?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{BLAME START}

library

?curdirlinks? -

Blame information for rev 32

Line No. Rev Author Line
1 32 kaklik /*********************************************************************
2 *
3 * Medium Access Control (MAC) Layer for Microchip ENC624J600/424J600
4 * Module for Microchip TCP/IP Stack
5 * -Provides access to ENC424J600/624J600 Ethernet controller
6 * -Reference: ENC424J600/624J600 Data sheet (DS39935), IEEE 802.3
7 * Standard
8 *
9 *********************************************************************
10 * FileName: ENCX24J600.c
11 * Dependencies: ENCX24J600.h
12 * MAC.h
13 * string.h
14 * Helpers.h
15 * Delay.h
16 * Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
17 * Compiler: Microchip C32 v1.05 or higher
18 * Microchip C30 v3.12 or higher
19 * Microchip C18 v3.30 or higher
20 * HI-TECH PICC-18 PRO 9.63PL2 or higher
21 * Company: Microchip Technology, Inc.
22 *
23 * Software License Agreement
24 *
25 * Copyright (C) 2002-2009 Microchip Technology Inc. All rights
26 * reserved.
27 *
28 * Microchip licenses to you the right to use, modify, copy, and
29 * distribute:
30 * (i) the Software when embedded on a Microchip microcontroller or
31 * digital signal controller product ("Device") which is
32 * integrated into Licensee's product; or
33 * (ii) ONLY the Software driver source files ENC28J60.c, ENC28J60.h,
34 * ENCX24J600.c and ENCX24J600.h ported to a non-Microchip device
35 * used in conjunction with a Microchip ethernet controller for
36 * the sole purpose of interfacing with the ethernet controller.
37 *
38 * You should refer to the license agreement accompanying this
39 * Software for additional information regarding your rights and
40 * obligations.
41 *
42 * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
43 * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
44 * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
45 * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
46 * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
47 * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
48 * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
49 * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
50 * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
51 * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
52 * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
53 *
54 *
55 * Author Date Comment
56 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
57 * Howard Schlunder 12/07/07 Original
58 ********************************************************************/
59 #define __ENCX24J600_C
60  
61 #include "HardwareProfile.h"
62  
63 // Make sure that this hardware profile has an ENC424J600/624J600 in it
64 #if defined(ENC100_INTERFACE_MODE)
65  
66 #include "TCPIP Stack/TCPIP.h"
67 #include "TCPIP Stack/ENCX24J600.h"
68  
69 #include <stdarg.h>
70  
71 /** D E F I N I T I O N S ****************************************************/
72 #define ENC100_MAX_SPI_FREQ (14000000ul) // Hz
73  
74 // Configuration constants for diagnostics only. If you don't define any of
75 // these constants, auto-negotiation will be used (strongly recommended).
76 //#define ENC100_FORCE_10MBPS_HALF_DUPLEX
77 //#define ENC100_FORCE_10MBPS_FULL_DUPLEX
78 //#define ENC100_FORCE_100MBPS_HALF_DUPLEX
79 //#define ENC100_FORCE_100MBPS_FULL_DUPLEX
80  
81  
82 // Pseudo Functions - these should not need changing unless porting to a new
83 // processor type or speed.
84 // DelaySetupHold() should wait at least 75ns to meet Tpsp2 (RD to Data Valid)
85 #define DelaySetupHold() do{Nop();Nop();}while(0)
86 #if (GetInstructionClock() > 16000000ul)
87 #undef DelaySetupHold
88 #define DelaySetupHold() do{Nop();Nop();Nop();}while(0)
89 #endif
90 #if (GetInstructionClock() > 32000000ul)
91 #undef DelaySetupHold
92 #define DelaySetupHold() do{Nop();Nop();Nop();Nop();}while(0)
93 #endif
94 #if (GetInstructionClock() > 48000000ul)
95 #undef DelaySetupHold
96 #define DelaySetupHold() do{Nop();Nop();Nop();Nop();Nop();}while(0)
97 #endif
98 #if (GetInstructionClock() > 64000000ul)
99 #undef DelaySetupHold
100 #define DelaySetupHold() do{Nop();Nop();Nop();Nop();Nop();Nop();}while(0)
101 #endif
102  
103 #if defined(__PIC32MX__)
104 #define PMDIN1 PMDIN
105 #endif
106 #if (ENC100_INTERFACE_MODE >= 1) // Parallel mode
107 #if defined(ENC100_CS_TRIS)
108 #define AssertChipSelect() do{ENC100_CS_IO = 1;}while(0)
109 #define DeassertChipSelect() do{ENC100_CS_IO = 0;}while(0)
110 #else
111 #define AssertChipSelect()
112 #define DeassertChipSelect()
113 #endif
114 #else // SPI mode
115 #define AssertChipSelect() do{ENC100_CS_IO = 0;}while(0)
116 #define DeassertChipSelect() do{ENC100_CS_IO = 1;}while(0)
117  
118 #if defined (__18CXX)
119 #define ClearSPIDoneFlag() do{ENC100_SPI_IF = 0;}while(0)
120 #define WaitForDataByte() do{while(!ENC100_SPI_IF); ENC100_SPI_IF = 0;}while(0)
121 #elif defined(__C30__)
122 #define ClearSPIDoneFlag()
123 static inline __attribute__((__always_inline__)) void WaitForDataByte(void)
124 {
125 while ((ENC100_SPISTATbits.SPITBF == 1) || (ENC100_SPISTATbits.SPIRBF == 0));
126 }
127 #elif defined( __PIC32MX__ )
128 #define ClearSPIDoneFlag()
129 static inline __attribute__((__always_inline__)) void WaitForDataByte(void)
130 {
131 while (!ENC100_SPISTATbits.SPITBE || !ENC100_SPISTATbits.SPIRBF);
132 }
133 #else
134 #error Determine SPI flag mechanism
135 #endif
136 #endif
137  
138  
139 // Binary constant identifiers for ReadMemoryWindow() and WriteMemoryWindow()
140 // functions
141 #define UDA_WINDOW (0x1)
142 #define GP_WINDOW (0x2)
143 #define RX_WINDOW (0x4)
144  
145  
146 #define ETHER_IP ((WORD)0x00)
147 #define ETHER_ARP ((WORD)0x06)
148  
149  
150 // A header appended at the start of all RX frames by the hardware
151 typedef struct __attribute__((aligned(2), packed))
152 {
153 WORD NextPacketPointer;
154 RXSTATUS StatusVector;
155  
156 MAC_ADDR DestMACAddr;
157 MAC_ADDR SourceMACAddr;
158 WORD_VAL Type;
159 } ENC100_PREAMBLE;
160  
161  
162  
163 // Internal MAC level variables and flags.
164 static BYTE vCurrentBank;
165 static WORD wCurrentPacketPointer;
166 static WORD wNextPacketPointer;
167 static struct
168 {
169 unsigned char bWasDiscarded:1; // Status tracking bit indicating if the last received packet has been discarded via MACDiscardRx() or not.
170 unsigned char PoweredDown:1; // Local cached bit indicating CRYPTEN == ETHEN == 0 and PSLEEP == 1
171 unsigned char CryptoEnabled:1; // Local cached bit indicating CRYPTEN == 1
172 } ENC100Flags;
173  
174  
175 // Internal MAC level functions
176 void ENC100DumpState(void);
177 static void SendSystemReset(void);
178 static void ToggleCRYPTEN(void);
179 static WORD ReadReg(WORD wAddress);
180 static void WriteReg(WORD wAddress, WORD wValue);
181 static void BFSReg(WORD wAddress, WORD wBitMask);
182 static void BFCReg(WORD wAddress, WORD wBitMask);
183 static void ReadMemoryWindow(BYTE vWindow, BYTE *vData, WORD wLength);
184 static void WriteMemoryWindow(BYTE vWindow, BYTE *vData, WORD wLength);
185 #if ENC100_INTERFACE_MODE == 0
186 static void Execute0(BYTE vOpcode);
187 //static BYTE Execute1(BYTE vOpcode, BYTE wDataIn); // Not currently used
188 static WORD Execute2(BYTE vOpcode, WORD wDataIn);
189 static DWORD Execute3(BYTE vOpcode, DWORD dwDataIn);
190 static void ReadN(BYTE vOpcode, BYTE* vData, WORD wDataLen);
191 static void WriteN(BYTE vOpcode, BYTE* vData, WORD wDataLen);
192 #else
193 static void ReadMemory(WORD wAddress, BYTE *vData, WORD wLength);
194 static void WriteMemory(WORD wAddress, BYTE *vData, WORD wLength);
195 #endif
196  
197  
198  
199 // Compute some PMP register values
200 #if ENC100_INTERFACE_MODE == 1 // Parallel Mode 1: 8-bit demultiplexed (RD/WR)
201 #define PMP_ADRMUX 0x0 // Full demuxing of address and data
202 #define PMP_MODE16 0 // 8 bit
203 #define PMP_MODE 0x2 // Master mode 2: PMRD & PMWR, not PMRD/PMWR & PMENB
204 #define PMP_ADR_PINS ENC100_TRANSLATE_TO_PIN_ADDR(0x7FFF)
205 #elif ENC100_INTERFACE_MODE == 2 // Parallel Mode 2: 8-bit demultiplexed (RW/EN)
206 #define PMP_ADRMUX 0x0 // Full demuxing of address and data
207 #define PMP_MODE16 0 // 8 bit
208 #define PMP_MODE 0x3 // Master mode 1: PMRD/PMWR & PMENB, not PMRD & PMWR
209 #define PMP_ADR_PINS ENC100_TRANSLATE_TO_PIN_ADDR(0x7FFF)
210 #elif ENC100_INTERFACE_MODE == 3 // Parallel Mode 3: 16-bit demultiplexed (RD/WR)
211 #define PMP_ADRMUX 0x0 // Full demuxing of address and data
212 #define PMP_MODE16 1 // 16 bit
213 #define PMP_MODE 0x2 // Master mode 2: PMRD & PMWR, not PMRD/PMWR & PMENB
214 #define PMP_ADR_PINS ENC100_TRANSLATE_TO_PIN_ADDR(0x3FFF)
215 #elif ENC100_INTERFACE_MODE == 4 // Parallel Mode 4: 16-bit demultiplexed (RW/EN)
216 #define PMP_ADRMUX 0x0 // Full demuxing of address and data
217 #define PMP_MODE16 1 // 16 bit
218 #define PMP_MODE 0x3 // Master mode 1: PMRD/PMWR & PMENB, not PMRD & PMWR
219 #define PMP_ADR_PINS ENC100_TRANSLATE_TO_PIN_ADDR(0x3FFF)
220 #elif ENC100_INTERFACE_MODE == 5 // Parallel Mode 5: 8-bit multiplexed (RD/WR)
221 #define PMP_ADRMUX 0x1 // Partially multiplexed address and data
222 #define PMP_MODE16 0 // 8 bit
223 #define PMP_MODE 0x2 // Master mode 2: PMRD & PMWR, not PMRD/PMWR & PMENB
224 #define PMP_ADR_PINS (ENC100_TRANSLATE_TO_PIN_ADDR(0x7F00) | 0x0001)
225 #elif ENC100_INTERFACE_MODE == 6 // Parallel Mode 6: 8-bit multiplexed (RW/EN)
226 #define PMP_ADRMUX 0x1 // Partially multiplexed address and data
227 #define PMP_MODE16 0 // 8 bit
228 #define PMP_MODE 0x3 // Master mode 1: PMRD/PMWR & PMENB, not PMRD & PMWR
229 #define PMP_ADR_PINS (ENC100_TRANSLATE_TO_PIN_ADDR(0x7F00) | 0x0001)
230 #elif ENC100_INTERFACE_MODE == 9 // Parallel Mode 9: 16-bit multiplexed (RD/WR)
231 #define PMP_ADRMUX 0x3 // Fully multiplexed address and data
232 #define PMP_MODE16 1 // 16 bit
233 #define PMP_MODE 0x2 // Master mode 2: PMRD & PMWR, not PMRD/PMWR & PMENB
234 #define PMP_ADR_PINS 0x0001
235 #elif ENC100_INTERFACE_MODE == 10 // Parallel Mode 10: 16-bit multiplexed (RW/EN)
236 #define PMP_ADRMUX 0x3 // Fully multiplexed address and data
237 #define PMP_MODE16 1 // 16 bit
238 #define PMP_MODE 0x3 // Master mode 1: PMRD/PMWR & PMENB, not PMRD & PMWR
239 #define PMP_ADR_PINS 0x0001
240 #endif
241  
242 // Calculate the minimum number of wait states to ensure a 75ns or longer pulse width for READ and WRITE strobes
243 #if defined(__PIC32MX__) // PIC32 is offset by one (i.e. 0 = one wait state)
244 #define OPTIMAL_PMP_WAIT_STATES ((BYTE)((double)GetPeripheralClock()*0.000000075))
245 #else
246 #define OPTIMAL_PMP_WAIT_STATES ((BYTE)((double)GetPeripheralClock()*0.000000075 + 0.9999))
247 #endif
248  
249 #if ((ENC100_INTERFACE_MODE == 3) || (ENC100_INTERFACE_MODE == 4) || (ENC100_INTERFACE_MODE == 9) || (ENC100_INTERFACE_MODE == 10)) && !defined(ENC100_BIT_BANG_PMP)
250 #if !defined(__PIC32MX__)
251 #error "16-bit PMP mode is only available on PIC32. Use big bang mode or ENC100_INTERFACE_MODE of 1, 2, 5, or 6 (8-bit) instead."
252 #endif
253 #endif
254  
255  
256  
257 // Compute optimal SPI speed and define the ConfigureSPIModule() macro function
258 // to load it up quickly whenever we want to use the SPI
259 #if defined(__18CXX)
260 #define OPTIMAL_PRESCALE 0x00 // Default to divide by 4 setting
261 #if GetPeripheralClock() > ENC100_MAX_SPI_FREQ
262 #undef OPTIMAL_PRESCALE
263 #define OPTIMAL_PRESCALE 0x01 // Use divide by 16 setting
264 #endif
265 #if GetPeripheralClock()/16 > ENC100_MAX_SPI_FREQ
266 #undef OPTIMAL_PRESCALE
267 #define OPTIMAL_PRESCALE 0x02 // Use divide by 64 setting
268 #endif
269 #define ConfigureSPIModule() do{ \
270 ENC100_SPICON1 = 0; /* SSPEN = 0 */ \
271 ENC100_SPISTAT = 0x40; /* CKE = 1 (transmit data on rising edge), SMP = 0 (sample at middle of output time) */ \
272 ENC100_SPICON1 = OPTIMAL_PRESCALE | 0x20; /* SSPEN = 1, set clock speed */\
273 }while(0)
274 #define PMCONbits PMCONHbits // Remap for PMPEN bit accessed inline
275 #define ConfigurePMPModule() do{ \
276 PMCONHbits.PMPEN = 0; \
277 PMCONH = (PMP_ADRMUX<<3) | 0x03; /* PTWREN = 1, PTRDEN = 1 */ \
278 PMCONL = 0x23; /* ALP = 1, WRSP = 1, RDSP = 1 */ \
279 PMMODEH = (PMP_MODE16<<2) | (PMP_MODE); \
280 PMMODEL = (OPTIMAL_PMP_WAIT_STATES<<2); \
281 PMAENH = ((BYTE)(PMP_ADR_PINS>>8)); \
282 PMAENL = ((BYTE)PMP_ADR_PINS); \
283 PMCONHbits.PMPEN = 1; \
284 }while(0)
285 #elif defined(__C30__)
286 // Ensure SPI doesn't exceed processor limit
287 #if (defined(__PIC24F__) || defined(__PIC24FK__) || defined(__PIC24H__) || defined(__dsPIC33F__)) && ENC100_MAX_SPI_FREQ > 8000000
288 #undef ENC100_MAX_SPI_FREQ
289 #define ENC100_MAX_SPI_FREQ 8000000
290 #endif
291 #if defined(__dsPIC30F__) && ENC100_MAX_SPI_FREQ > 10000000
292 #undef ENC100_MAX_SPI_FREQ
293 #define ENC100_MAX_SPI_FREQ 10000000
294 #endif
295  
296 // Calculate optimal primary and secondary prescalers to make an SPI clock no faster than ENC100_MAX_SPI_FREQ
297 #define OPTIMAL_PRESCALE ((((~((GetPeripheralClock()/64+ENC100_MAX_SPI_FREQ-1)/ENC100_MAX_SPI_FREQ - 1)) & 0x7)<<2) | 0x0)
298 #if GetPeripheralClock()/8/16 <= ENC100_MAX_SPI_FREQ
299 #undef OPTIMAL_PRESCALE
300 #define OPTIMAL_PRESCALE ((((~((GetPeripheralClock()/16+ENC100_MAX_SPI_FREQ-1)/ENC100_MAX_SPI_FREQ - 1)) & 0x7)<<2) | 0x1)
301 #endif
302 #if GetPeripheralClock()/8/4 <= ENC100_MAX_SPI_FREQ
303 #undef OPTIMAL_PRESCALE
304 #define OPTIMAL_PRESCALE ((((~((GetPeripheralClock()/4+ENC100_MAX_SPI_FREQ-1)/ENC100_MAX_SPI_FREQ - 1)) & 0x7)<<2) | 0x2)
305 #endif
306 #if GetPeripheralClock()/8/1 <= ENC100_MAX_SPI_FREQ
307 #undef OPTIMAL_PRESCALE
308 #define OPTIMAL_PRESCALE ((((~((GetPeripheralClock()/1+ENC100_MAX_SPI_FREQ-1)/ENC100_MAX_SPI_FREQ - 1)) & 0x7)<<2) | 0x3)
309 #endif
310  
311 // Work around 1:1, 1:1 SPI errata on early PIC24FJ128GA010, PIC24HJ256GP610, dsPIC33FJ256GP710, etc. silicon where SCK stops running
312 #if (defined(__PIC24F__) || defined(__PIC24H__) || defined(__dsPIC33F__)) && (OPTIMAL_PRESCALE == 0x1F)
313 #undef OPTIMAL_PRESCALE
314 #define OPTIMAL_PRESCALE 0x1B
315 #endif
316  
317  
318 #define ConfigureSPIModule() do{ \
319 ENC100_SPISTAT = 0; /* Turn off SPI */ \
320 ENC100_SPICON1 = OPTIMAL_PRESCALE | 0x0100 | 0x0020; /* CKE = 1, MSTEN = 1 */ \
321 ENC100_SPICON2 = 0; /* Legacy non enhanced buffering */ \
322 ENC100_SPISTAT = 0x8000; /* Turn on SPI */ \
323 }while(0)
324  
325 #define ConfigurePMPModule() do{ \
326 PMCONbits.PMPEN = 0; \
327 PMCON = (PMP_ADRMUX<<11) | 0x0323; /* PTWREN = 1, PTRDEN = 1, ALP = 1, WRSP = 1, RDSP = 1 */ \
328 PMMODE = (PMP_MODE16<<10) | (PMP_MODE<<8) | (OPTIMAL_PMP_WAIT_STATES<<2); \
329 PMAEN = PMP_ADR_PINS; \
330 PADCFG1bits.PMPTTL = 0; /* Use schmitt trigger input buffers */ \
331 PMCONbits.PMPEN = 1; \
332 }while(0)
333 #elif defined(__C32__)
334 #define ConfigureSPIModule() do{ \
335 ENC100_SPICON1 = 0; /* Turn off SPI */ \
336 ENC100_SPIBRG = (GetPeripheralClock()-1ul)/2ul/ENC100_MAX_SPI_FREQ; \
337 ENC100_SPICON1 = 0x00008320; /* ON = 1, SMP = 1, CKE = 1, MSTEN = 1 */ \
338 }while(0)
339 #define ConfigurePMPModule() do{ \
340 PMCONbits.PMPEN = 0; \
341 PMCON = (PMP_ADRMUX<<11) | 0x0323; /* PMPTTL = 0, PTWREN = 1, PTRDEN = 1, ALP = 1, WRSP = 1, RDSP = 1 */ \
342 PMMODE = (PMP_MODE16<<10) | (PMP_MODE<<8) | (OPTIMAL_PMP_WAIT_STATES<<2); \
343 PMAEN = PMP_ADR_PINS; \
344 PMCONbits.PMPEN = 1; \
345 }while(0)
346 #endif
347  
348 /******************************************************************************
349 * Function: void ENC100Init(void)
350 *
351 * PreCondition: None
352 *
353 * Input: None
354 *
355 * Output: None
356 *
357 * Side Effects: None
358 *
359 * Overview: MACInit sets up the PIC's SPI module and all the
360 * registers in the ENCX24J600 so that normal operation can
361 * begin.
362 *
363 * Note: None
364 *****************************************************************************/
365 void MACInit(void)
366 {
367 WORD w;
368  
369 #if defined(ENC100_INT_TRIS) // Interrupt output from ENCx24J600
370 ENC100_INT_TRIS = 1;
371 #endif
372 #if defined(ENC100_MDIX_TRIS) // MDIX control pin from PIC
373 ENC100_MDIX_TRIS = 0;
374 ENC100_MDIX_IO = 0;
375 #endif
376  
377 #if defined(ENC100_CS_TRIS) // Chip Select line from PIC
378 DeassertChipSelect();
379 ENC100_CS_TRIS = 0;
380 #endif
381  
382 #if (ENC100_INTERFACE_MODE >= 1) && defined(ENC100_BIT_BANG_PMP) // Parallel bit-bang mode needs I/O pins to be configured. PMP will control pins automatically.
383 ENC100_SO_WR_B0SEL_EN_IO = 0;
384 ENC100_SO_WR_B0SEL_EN_TRIS = 0;
385 ENC100_SI_RD_RW_IO = 0;
386 ENC100_SI_RD_RW_TRIS = 0;
387 #if ENC100_INTERFACE_MODE >= 5 // If PSP address bus is multiplexed, then set Address Latch TRIS bit to output
388 ENC100_SCK_AL_IO = 0;
389 ENC100_SCK_AL_TRIS = 0;
390 #endif
391 #if (ENC100_INTERFACE_MODE == 3) || (ENC100_INTERFACE_MODE == 4) || (ENC100_INTERFACE_MODE == 9) || (ENC100_INTERFACE_MODE == 10) // If PSP data width is 16-bits, set Write High/Byte 1 select as output
392 ENC100_WRH_B1SEL_IO = 0;
393 ENC100_WRH_B1SEL_TRIS = 0;
394 #endif
395  
396 ENC100_INIT_PSP_BIT_BANG();
397 #elif (ENC100_INTERFACE_MODE == 0) // Use SPI interface
398 vCurrentBank = 0; // Needed for SPI only
399  
400 // Set up SPI pins on PIC18s
401 #if defined(__18CXX)
402 ENC100_SCK_AL_TRIS = 0;
403 ENC100_SI_RD_RW_TRIS = 0;
404 ENC100_SO_WR_B0SEL_EN_TRIS = 1;
405 ENC100_SPI_IF = 0;
406 #endif
407  
408 ConfigureSPIModule();
409 #endif
410  
411 // Perform a reliable reset
412 SendSystemReset();
413  
414 // Initialize RX tracking variables and other control state flags
415 wNextPacketPointer = RXSTART;
416 wCurrentPacketPointer = 0x0000;
417 ENC100Flags.bWasDiscarded = 1;
418 ENC100Flags.PoweredDown = 0;
419 ENC100Flags.CryptoEnabled = 0;
420  
421 // Set up TX/RX/UDA buffer addresses
422 WriteReg(ETXST, TXSTART);
423 WriteReg(ERXST, RXSTART);
424 WriteReg(ERXTAIL, ENC100_RAM_SIZE-2);
425 WriteReg(EUDAST, ENC100_RAM_SIZE);
426 WriteReg(EUDAND, ENC100_RAM_SIZE+1);
427  
428 // Use ENCx24J600 preprogrammed MAC address, if AppConfig is not already set
429 if(((AppConfig.MyMACAddr.v[0] == 0x00u) && (AppConfig.MyMACAddr.v[1] == 0x04u) && (AppConfig.MyMACAddr.v[2] == 0xA3u) && (AppConfig.MyMACAddr.v[3] == 0x00u) && (AppConfig.MyMACAddr.v[4] == 0x00u) && (AppConfig.MyMACAddr.v[5] == 0x00u)) ||
430 ((AppConfig.MyMACAddr.v[0] | AppConfig.MyMACAddr.v[1] | AppConfig.MyMACAddr.v[2] | AppConfig.MyMACAddr.v[3] | AppConfig.MyMACAddr.v[4] | AppConfig.MyMACAddr.v[5]) == 0x00u))
431 {
432 w = ReadReg(MAADR1);
433 AppConfig.MyMACAddr.v[0] = ((BYTE*)&w)[0];
434 AppConfig.MyMACAddr.v[1] = ((BYTE*)&w)[1];
435 w = ReadReg(MAADR2);
436 AppConfig.MyMACAddr.v[2] = ((BYTE*)&w)[0];
437 AppConfig.MyMACAddr.v[3] = ((BYTE*)&w)[1];
438 w = ReadReg(MAADR3);
439 AppConfig.MyMACAddr.v[4] = ((BYTE*)&w)[0];
440 AppConfig.MyMACAddr.v[5] = ((BYTE*)&w)[1];
441 }
442 else
443 {
444 ((BYTE*)&w)[0] = AppConfig.MyMACAddr.v[0];
445 ((BYTE*)&w)[1] = AppConfig.MyMACAddr.v[1];
446 WriteReg(MAADR1, w);
447 ((BYTE*)&w)[0] = AppConfig.MyMACAddr.v[2];
448 ((BYTE*)&w)[1] = AppConfig.MyMACAddr.v[3];
449 WriteReg(MAADR2, w);
450 ((BYTE*)&w)[0] = AppConfig.MyMACAddr.v[4];
451 ((BYTE*)&w)[1] = AppConfig.MyMACAddr.v[5];
452 WriteReg(MAADR3, w);
453 }
454  
455 // Set PHY Auto-negotiation to support 10BaseT Half duplex,
456 // 10BaseT Full duplex, 100BaseTX Half Duplex, 100BaseTX Full Duplex,
457 // and symmetric PAUSE capability
458 WritePHYReg(PHANA, PHANA_ADPAUS0 | PHANA_AD10FD | PHANA_AD10 | PHANA_AD100FD | PHANA_AD100 | PHANA_ADIEEE0);
459  
460 // Force operating mode, for debugging only. If none of these statements
461 // are executed, auto-negotiation/parallel detection is used which will
462 // always select the proper mode.
463 #if defined(ENC100_FORCE_10MBPS_HALF_DUPLEX)
464 WritePHYReg(PHCON1, 0x0000);
465 #elif defined(ENC100_FORCE_10MBPS_FULL_DUPLEX)
466 WritePHYReg(PHCON1, PHCON1_PFULDPX);
467 #elif defined(ENC100_FORCE_100MBPS_HALF_DUPLEX)
468 WritePHYReg(PHCON1, PHCON1_SPD100);
469 #elif defined(ENC100_FORCE_100MBPS_FULL_DUPLEX)
470 WritePHYReg(PHCON1, PHCON1_SPD100 | PHCON1_PFULDPX);
471 #endif
472  
473 // Enable RX packet reception
474 BFSReg(ECON1, ECON1_RXEN);
475 }//end MACInit
476  
477  
478 /******************************************************************************
479 * Function: BOOL MACIsLinked(void)
480 *
481 * PreCondition: None
482 *
483 * Input: None
484 *
485 * Output: TRUE: An Ethernet link is established
486 * FALSE: Ethernet link is not established
487 *
488 * Side Effects: None
489 *
490 * Overview: Returns the ESTAT<PHYLNK> bit.
491 *
492 * Note: None
493 *****************************************************************************/
494 BOOL MACIsLinked(void)
495 {
496 return (ReadReg(ESTAT) & ESTAT_PHYLNK) != 0u;
497 }
498  
499 /******************************************************************************
500 * Function: BOOL MACIsTxReady(void)
501 *
502 * PreCondition: None
503 *
504 * Input: None
505 *
506 * Output: TRUE: If no Ethernet transmission is in progress
507 * FALSE: If a previous transmission was started, and it has
508 * not completed yet. While FALSE, the data in the
509 * transmit buffer and the TXST/TXLEN pointers must not
510 * be changed.
511 *
512 * Side Effects: None
513 *
514 * Overview: Returns the ECON1<TXRTS> bit
515 *
516 * Note: None
517 *****************************************************************************/
518 BOOL MACIsTxReady(void)
519 {
520 return !(ReadReg(ECON1) & ECON1_TXRTS);
521 }
522  
523  
524 /******************************************************************************
525 * Function: void MACDiscardRx(void)
526 *
527 * PreCondition: None
528 *
529 * Input: None
530 *
531 * Output: None
532 *
533 * Side Effects: None
534 *
535 * Overview: Marks the last received packet (obtained using
536 * MACGetHeader())as being processed and frees the buffer
537 * memory associated with it
538 *
539 * Note: Is is safe to call this function multiple times between
540 * MACGetHeader() calls. Extra packets won't be thrown away
541 * until MACGetHeader() makes it available.
542 *****************************************************************************/
543 void MACDiscardRx(void)
544 {
545 WORD wNewRXTail;
546  
547 // Make sure the current packet was not already discarded
548 if(ENC100Flags.bWasDiscarded)
549 return;
550 ENC100Flags.bWasDiscarded = 1;
551  
552 // Decrement the next packet pointer before writing it into
553 // the ERXRDPT registers. RX buffer wrapping must be taken into account if the
554 // NextPacketLocation is precisely RXSTART.
555 wNewRXTail = wNextPacketPointer - 2;
556 if(wNextPacketPointer == RXSTART)
557 wNewRXTail = ENC100_RAM_SIZE - 2;
558  
559 // Decrement the RX packet counter register, EPKTCNT
560 BFSReg(ECON1, ECON1_PKTDEC);
561  
562 // Move the receive read pointer to unwrite-protect the memory used by the
563 // last packet. The writing order is important: set the low byte first,
564 // high byte last (handled automatically in WriteReg()).
565 WriteReg(ERXTAIL, wNewRXTail);
566 }
567  
568  
569 /******************************************************************************
570 * Function: WORD MACGetFreeRxSize(void)
571 *
572 * PreCondition: None
573 *
574 * Input: None
575 *
576 * Output: A WORD estimate of how much RX buffer space is free at
577 * the present time.
578 *
579 * Side Effects: None
580 *
581 * Overview: None
582 *
583 * Note: None
584 *****************************************************************************/
585 WORD MACGetFreeRxSize(void)
586 {
587 WORD wHeadPtr;
588  
589 wHeadPtr = ReadReg(ERXHEAD);
590  
591 // Calculate the difference between the pointers, taking care to account
592 // for buffer wrapping conditions
593 if(wHeadPtr > wCurrentPacketPointer)
594 return (RXSTOP - RXSTART) - (wHeadPtr - wCurrentPacketPointer);
595  
596 return wCurrentPacketPointer - wHeadPtr - 2;
597 }
598  
599  
600 /******************************************************************************
601 * Function: BOOL MACGetHeader(MAC_ADDR *remote, BYTE* type)
602 *
603 * PreCondition: None
604 *
605 * Input: *remote: Location to store the Source MAC address of the
606 * received frame.
607 * *type: Location of a BYTE to store the constant
608 * MAC_UNKNOWN, ETHER_IP, or ETHER_ARP, representing
609 * the contents of the Ethernet type field.
610 *
611 * Output: TRUE: If a packet was waiting in the RX buffer. The
612 * remote, and type values are updated.
613 * FALSE: If a packet was not pending. remote and type are
614 * not changed.
615 *
616 * Side Effects: Last packet is discarded if MACDiscardRx() hasn't already
617 * been called.
618 *
619 * Overview: None
620 *
621 * Note: None
622 *****************************************************************************/
623 BOOL MACGetHeader(MAC_ADDR *remote, BYTE* type)
624 {
625 ENC100_PREAMBLE header;
626  
627 // Test if at least one packet has been received and is waiting
628 if(!(ReadReg(EIR) & EIR_PKTIF))
629 {
630 // No packets are waiting. See if we are unlinked and need to process
631 // auto crossover timers.
632 #if defined(ENC100_MDIX_TRIS)
633 {
634 static WORD wMDIXTimer = 0;
635  
636 // See if it is time to swap MDI mode
637 if((WORD)(wMDIXTimer - (WORD)TickGetDiv256()) > (WORD)(2u*TICK_SECOND/256u))
638 {
639 // If we are linked, then we should simply reset the timer to a
640 // max of 1.3 seconds and do nothing
641 if(MACIsLinked())
642 {
643 wMDIXTimer = (WORD)TickGetDiv256() + (WORD)(13u*TICK_SECOND/256u/10u);
644 }
645 else
646 {
647 // We are unlinked and the MDI-X timer expired, lets swap MDI mode
648 ENC100_MDIX_IO ^= 1;
649  
650 // Set up new timer to expire sometime randomly between 1.0
651 // seconds and 1.55 seconds in the future. This needs to
652 // have randomness so that if you plug two similar devices
653 // into each other, you don't have a lock-step switching
654 // problem in which both devices swap MDI mode
655 // simultaneously and never link up.
656 wMDIXTimer = (WORD)TickGetDiv256() + (WORD)(TICK_SECOND/256u) + (WORD)(55ul*TICK_SECOND/256ul/100ul*(DWORD)rand()/(DWORD)RAND_MAX);
657  
658 //// Restart auto-negotiation
659 //WritePHYReg(PHCON1, PHCON1_ANEN | PHCON1_RENEG);
660 }
661 }
662 }
663 #endif
664  
665 return FALSE;
666 }
667  
668 // Discard the last packet, if the user application hasn't done so already
669 if(!ENC100Flags.bWasDiscarded)
670 {
671 MACDiscardRx();
672  
673 // Test again if at least one packet has been received and is waiting
674 if(!(ReadReg(EIR) & EIR_PKTIF))
675 return FALSE;
676 }
677  
678 // Set the RX Read Pointer to the beginning of the next unprocessed packet
679 wCurrentPacketPointer = wNextPacketPointer;
680 WriteReg(ERXRDPT, wCurrentPacketPointer);
681  
682 // Obtain the MAC header from the Ethernet buffer
683 ReadMemoryWindow(RX_WINDOW, (BYTE*)&header, sizeof(header));
684  
685 // The EtherType field, like most items transmitted on the Ethernet medium
686 // are in big endian.
687 header.Type.Val = swaps(header.Type.Val);
688  
689 // Validate the data returned from the ENC624J600 Family device. Random
690 // data corruption, such as if a single SPI/PSP bit error occurs while
691 // communicating or a momentary power glitch could cause this to occur
692 // in rare circumstances. Also, certain hardware bugs such as violations
693 // of the absolute maximum electrical specs can cause this. For example,
694 // if an MCU with a high slew rate were to access the interface, parasitic
695 // inductance in the traces could cause excessive voltage undershoot.
696 // If the voltage goes too far below ground, the ENCx24J600's internal
697 // ESD structure may activate and disrupt the communication. To prevent
698 // this, ensure that you have a clean board layout and consider adding
699 // resistors in series with the MCU output pins to limit the slew rate
700 // of signals going to the ENCx24J600. 100 Ohm resistors is a good value
701 // to start testing with.
702 if(header.NextPacketPointer > RXSTOP || ((BYTE_VAL*)(&header.NextPacketPointer))->bits.b0 ||
703 header.StatusVector.bits.Zero || header.StatusVector.bits.ZeroH ||
704 header.StatusVector.bits.CRCError ||
705 header.StatusVector.bits.ByteCount > 1522u ||
706 !header.StatusVector.bits.ReceiveOk)
707 {
708 //ENC100DumpState();
709 Nop();
710  
711 Reset();
712 }
713  
714 // Save the location where the hardware will write the next packet to
715 wNextPacketPointer = header.NextPacketPointer;
716  
717 // Return the Ethernet frame's Source MAC address field to the caller
718 // This parameter is useful for replying to requests without requiring an
719 // ARP cycle.
720 memcpy((void*)remote->v, (void*)header.SourceMACAddr.v, sizeof(*remote));
721  
722 // Return a simplified version of the EtherType field to the caller
723 *type = MAC_UNKNOWN;
724 if( (header.Type.v[1] == 0x08u) &&
725 ((header.Type.v[0] == (BYTE)ETHER_IP) || (header.Type.v[0] == (BYTE)ETHER_ARP)) )
726 {
727 *type = header.Type.v[0];
728 }
729  
730 // Mark this packet as discardable
731 ENC100Flags.bWasDiscarded = 0;
732 return TRUE;
733 }
734  
735  
736 /******************************************************************************
737 * Function: void MACPutHeader(MAC_ADDR *remote, BYTE type, WORD dataLen)
738 *
739 * PreCondition: MACIsTxReady() must return TRUE.
740 *
741 * Input: *remote: Pointer to memory which contains the destination
742 * MAC address (6 bytes)
743 * type: The constant ETHER_ARP or ETHER_IP, defining which
744 * value to write into the Ethernet header's type field.
745 * dataLen: Length of the Ethernet data payload
746 *
747 * Output: None
748 *
749 * Side Effects: None
750 *
751 * Overview: None
752 *
753 * Note: Because of the dataLen parameter, it is probably
754 * advantagous to call this function immediately before
755 * transmitting a packet rather than initially when the
756 * packet is first created. The order in which the packet
757 * is constructed (header first or data first) is not
758 * important.
759 *****************************************************************************/
760 void MACPutHeader(MAC_ADDR *remote, BYTE type, WORD dataLen)
761 {
762 WORD wEthernetType;
763  
764 wEthernetType = 0x08 | ((type == MAC_IP) ? (ETHER_IP<<8) : (ETHER_ARP<<8));
765  
766 // Set the Window Write Pointer to the beginning of the transmit buffer
767 WriteReg(EGPWRPT, TXSTART);
768 WriteReg(ETXLEN, dataLen + sizeof(ETHER_HEADER));
769  
770 // Write the Ethernet destination MAC address, our source MAC address,
771 // and the Ethernet Type field.
772 WriteMemoryWindow(GP_WINDOW, (BYTE*)remote, sizeof(*remote));
773 WriteMemoryWindow(GP_WINDOW, (BYTE*)&AppConfig.MyMACAddr, 6);
774 WriteMemoryWindow(GP_WINDOW, (BYTE*)&wEthernetType, 2);
775 }
776  
777  
778  
779 /******************************************************************************
780 * Function: void MACFlush(void)
781 *
782 * PreCondition: A packet has been created by calling MACPut() and
783 * MACPutHeader().
784 *
785 * Input: None
786 *
787 * Output: None
788 *
789 * Side Effects: None
790 *
791 * Overview: MACFlush causes the current TX packet to be sent out on
792 * the Ethernet medium. The hardware MAC will take control
793 * and handle CRC generation, collision retransmission and
794 * other details.
795 *
796 * Note: After transmission completes (MACIsTxReady() returns TRUE),
797 * the packet can be modified and transmitted again by calling
798 * MACFlush() again. Until MACPutHeader() or MACPut() is
799 * called (in the TX data area), the data in the TX buffer
800 * will not be corrupted.
801 *****************************************************************************/
802 void MACFlush(void)
803 {
804 WORD w;
805  
806 // Check to see if the duplex status has changed. This can
807 // change if the user unplugs the cable and plugs it into a
808 // different node. Auto-negotiation will automatically set
809 // the duplex in the PHY, but we must also update the MAC
810 // inter-packet gap timing and duplex state to match.
811 if(ReadReg(EIR) & EIR_LINKIF)
812 {
813 BFCReg(EIR, EIR_LINKIF);
814  
815 // Update MAC duplex settings to match PHY duplex setting
816 w = ReadReg(MACON2);
817 if(ReadReg(ESTAT) & ESTAT_PHYDPX)
818 {
819 // Switching to full duplex
820 WriteReg(MABBIPG, 0x15);
821 w |= MACON2_FULDPX;
822 }
823 else
824 {
825 // Switching to half duplex
826 WriteReg(MABBIPG, 0x12);
827 w &= ~MACON2_FULDPX;
828 }
829 WriteReg(MACON2, w);
830 }
831  
832  
833 // Start the transmission, but only if we are linked. Supressing
834 // transmissing when unlinked is necessary to avoid stalling the TX engine
835 // if we are in PHY energy detect power down mode and no link is present.
836 // A stalled TX engine won't do any harm in itself, but will cause the
837 // MACIsTXReady() function to continuously return FALSE, which will
838 // ultimately stall the Microchip TCP/IP stack since there is blocking code
839 // elsewhere in other files that expect the TX engine to always self-free
840 // itself very quickly.
841 if(ReadReg(ESTAT) & ESTAT_PHYLNK)
842 BFSReg(ECON1, ECON1_TXRTS);
843 }
844  
845  
846 /******************************************************************************
847 * Function: void MACSetReadPtrInRx(WORD offset)
848 *
849 * PreCondition: A packet has been obtained by calling MACGetHeader() and
850 * getting a TRUE result.
851 *
852 * Input: offset: WORD specifying how many bytes beyond the Ethernet
853 * header's type field to relocate the SPI read
854 * pointer.
855 *
856 * Output: None
857 *
858 * Side Effects: None
859 *
860 * Overview: SPI read pointer are updated. All calls to
861 * MACGet() and MACGetArray() will use these new values.
862 *
863 * Note: RXSTOP must be statically defined as being > RXSTART for
864 * this function to work correctly. In other words, do not
865 * define an RX buffer which spans the 0x1FFF->0x0000 memory
866 * boundary.
867 *****************************************************************************/
868 void MACSetReadPtrInRx(WORD offset)
869 {
870 WORD wReadPtr;
871  
872 // Determine the address of the beginning of the entire packet
873 // and adjust the address to the desired location
874 wReadPtr = wCurrentPacketPointer + sizeof(ENC100_PREAMBLE) + offset;
875  
876 // Since the receive buffer is circular, adjust if a wraparound is needed
877 if(wReadPtr > RXSTOP)
878 wReadPtr -= RXSIZE;
879  
880 // Set the RX Window Read pointer to the new calculated value
881 WriteReg(ERXRDPT, wReadPtr);
882 }
883  
884  
885 /******************************************************************************
886 * Function: PTR_BASE MACSetWritePtr(PTR_BASE address)
887 *
888 * PreCondition: None
889 *
890 * Input: Address: Address to seek to
891 *
892 * Output: WORD: Old EWRPT location
893 *
894 * Side Effects: None
895 *
896 * Overview: SPI write pointer is updated. All calls to
897 * MACPut() and MACPutArray() will use this new value.
898 *
899 * Note: None
900 *****************************************************************************/
901 PTR_BASE MACSetWritePtr(PTR_BASE address)
902 {
903 WORD wOldWritePtr;
904  
905 wOldWritePtr = ReadReg(EGPWRPT);
906  
907 // Set the TX Write Pointer to the new calculated value
908 WriteReg(EGPWRPT, address);
909  
910 return wOldWritePtr;
911 }
912  
913  
914 /******************************************************************************
915 * Function: PTR_BASE MACSetReadPtr(PTR_BASE Address)
916 *
917 * PreCondition: None
918 *
919 * Input: Address: Address to seek to
920 *
921 * Output: WORD: Old ERDPT value
922 *
923 * Side Effects: None
924 *
925 * Overview: SPI write pointer is updated. All calls to
926 * MACPut() and MACPutArray() will use this new value.
927 *
928 * Note: None
929 *****************************************************************************/
930 PTR_BASE MACSetReadPtr(PTR_BASE address)
931 {
932 WORD wOldReadPtr;
933  
934 wOldReadPtr = ReadReg(ERXRDPT);
935  
936 // Set the RX Read Pointer to the new calculated value
937 WriteReg(ERXRDPT, address);
938  
939 return wOldReadPtr;
940 }
941  
942  
943 /******************************************************************************
944 * Function: WORD MACCalcRxChecksum(WORD offset, WORD len)
945 *
946 * PreCondition: None
947 *
948 * Input: offset - Number of bytes beyond the beginning of the
949 * Ethernet data (first byte after the type field)
950 * where the checksum should begin
951 * len - Total number of bytes to include in the checksum
952 *
953 * Output: 16-bit checksum as defined by RFC 793.
954 *
955 * Side Effects: None
956 *
957 * Overview: This function performs a checksum calculation in the MAC
958 * buffer itself
959 *
960 * Note: None
961 *****************************************************************************/
962 WORD MACCalcRxChecksum(WORD offset, WORD len)
963 {
964 WORD wStartAddress;
965  
966 // Add the offset requested by firmware plus the Ethernet header
967 wStartAddress = wCurrentPacketPointer + sizeof(ENC100_PREAMBLE) + offset;
968 if(wStartAddress > RXSTOP)
969 wStartAddress -= RXSIZE;
970  
971 // If in power down, temporarily bring power up so we can use the DMA
972 if(ENC100Flags.PoweredDown)
973 BFSReg(ECON2, ECON2_ETHEN);
974  
975 // Calculate the checksum using the ENCX24J600 DMA engine
976 while(ReadReg(ECON1) & ECON1_DMAST);
977 WriteReg(EDMAST, wStartAddress);
978 WriteReg(EDMALEN, len);
979 BFCReg(ECON1, ECON1_DMACPY | ECON1_DMANOCS | ECON1_DMACSSD);
980 BFSReg(ECON1, ECON1_DMAST);
981 while(ReadReg(ECON1) & ECON1_DMAST);
982  
983 // Restore power down state, if applicable
984 if(ENC100Flags.PoweredDown)
985 BFCReg(ECON2, ECON2_ETHEN);
986  
987 return ReadReg(EDMACS);
988 }
989  
990 /******************************************************************************
991 * Function: WORD CalcIPBufferChecksum(WORD len)
992 *
993 * PreCondition: Read buffer pointer set to starting of checksum data
994 *
995 * Input: len: Total number of bytes to calculate the checksum over.
996 * The first byte included in the checksum is the byte
997 * pointed to by ERDPT, which is updated by calls to
998 * MACSetReadPtr(), MACGet(), MACGetArray(),
999 * MACGetHeader(), etc.
1000 *
1001 * Output: 16-bit checksum as defined by RFC 793
1002 *
1003 * Side Effects: None
1004 *
1005 * Overview: This function performs a checksum calculation in the MAC
1006 * buffer itself. The ENCx24J600 has a hardware DMA module
1007 * which can calculate the checksum faster than software, so
1008 * this function replaces the CaclIPBufferChecksum() function
1009 * defined in the helpers.c file. Through the use of
1010 * preprocessor defines, this replacement is automatic.
1011 *
1012 * Note: This function works either in the RX buffer area or the TX
1013 * buffer area. No validation is done on the len parameter.
1014 *****************************************************************************/
1015 WORD CalcIPBufferChecksum(WORD len)
1016 {
1017 // If in power down, temporarily bring power up so we can use the DMA
1018 if(ENC100Flags.PoweredDown)
1019 BFSReg(ECON2, ECON2_ETHEN);
1020  
1021 // Calculate the checksum using the ENCX24J600 DMA engine
1022 while(ReadReg(ECON1) & ECON1_DMAST);
1023 WriteReg(EDMAST, ReadReg(ERXRDPT));
1024 WriteReg(EDMALEN, len);
1025 BFCReg(ECON1, ECON1_DMACPY | ECON1_DMANOCS | ECON1_DMACSSD);
1026 BFSReg(ECON1, ECON1_DMAST);
1027 while(ReadReg(ECON1) & ECON1_DMAST);
1028  
1029 // Restore power down state, if applicable
1030 if(ENC100Flags.PoweredDown)
1031 BFCReg(ECON2, ECON2_ETHEN);
1032  
1033 return ReadReg(EDMACS);
1034 }
1035  
1036  
1037 /*****************************************************************************
1038 Function:
1039 void MACMemCopyAsync(PTR_BASE destAddr, PTR_BASE sourceAddr, WORD len)
1040  
1041 Summary:
1042 Asynchronously copies data from one address to another within the 24KB
1043 Ethernet memory.
1044  
1045 Description:
1046 Asynchronously copies data from one address to another within the 24KB
1047 Ethernet memory using the ENCX24J600 hardware DMA engine (very fast).
1048 Overlapped memory regions are allowed (with restrictions). The addresses
1049 do not have to be aligned.
1050  
1051 Precondition:
1052 SPI bus must be initialized (done in MACInit()).
1053  
1054 Parameters:
1055 destAddr - Destination address in the Ethernet memory to copy to. If
1056 (PTR_BASE)-1 is specified, the current EGPWRPT value will be used
1057 instead.
1058 sourceAddr - Source address to read from. If (PTR_BASE)-1 is specified,
1059 the current EGPRDPT value will be used instead.
1060 len - Number of bytes to copy
1061  
1062 Returns:
1063 None
1064  
1065 Remarks:
1066 Call MACIsMemCopyDone() to see when the transfer is complete.
1067  
1068 Copying to a destination region that overlaps with the source address
1069 is supported only if the destination start address is at a lower memory
1070 address (closer to 0x0000) than the source pointer. However, if they do
1071 overlap there must be at least 2 bytes of non-overlap to ensure correct
1072 results due to hardware DMA requirements. For example, destAddr = 0;
1073 sourceAddr = 1; is illegal while destAddr = 0; sourceAddr = 2; is fine.
1074  
1075 If a prior transfer is already in progress prior to calling this function,
1076 this function will block until it can start this transfer.
1077  
1078 If (PTR_BASE)-1 is used for the sourceAddr or destAddr parameters,
1079 then that pointer will get updated with the next address after the read or
1080 write.
1081 *****************************************************************************/
1082 void MACMemCopyAsync(PTR_BASE destAddr, PTR_BASE sourceAddr, WORD len)
1083 {
1084 WORD wNewReadPtr;
1085  
1086 // Decode destination and source addresses
1087 if(destAddr == (PTR_BASE)-1)
1088 {
1089 destAddr = ReadReg(EGPWRPT);
1090 WriteReg(EGPWRPT, destAddr + len);
1091 }
1092 if(sourceAddr == (PTR_BASE)-1)
1093 {
1094 sourceAddr = ReadReg(ERXRDPT);
1095 wNewReadPtr = sourceAddr + len;
1096 if(wNewReadPtr > RXSTOP)
1097 wNewReadPtr -= RXSIZE;
1098 WriteReg(ERXRDPT, wNewReadPtr);
1099 }
1100  
1101 // If in power down, temporarily bring power up so we can use the DMA
1102 if(ENC100Flags.PoweredDown)
1103 BFSReg(ECON2, ECON2_ETHEN);
1104  
1105 // Start the copy using the DMA
1106 while(ReadReg(ECON1) & ECON1_DMAST);
1107 WriteReg(EDMAST, sourceAddr);
1108 WriteReg(EDMADST, destAddr);
1109 WriteReg(EDMALEN, len);
1110 BFSReg(ECON1, ECON1_DMAST | ECON1_DMACPY);
1111 }
1112  
1113 BOOL MACIsMemCopyDone(void)
1114 {
1115 BOOL bDone;
1116  
1117 bDone = !(ReadReg(ECON1) & ECON1_DMAST);
1118  
1119 // Restore power down state, if applicable
1120 if(bDone && ENC100Flags.PoweredDown)
1121 BFCReg(ECON2, ECON2_ETHEN);
1122  
1123 return bDone;
1124 }
1125  
1126  
1127 /******************************************************************************
1128 * Function: BYTE MACGet()
1129 *
1130 * PreCondition: SPI bus must be initialized (done in MACInit()).
1131 * ERDPT must point to the place to read from.
1132 *
1133 * Input: None
1134 *
1135 * Output: Byte read from the ENCx24J600's RAM
1136 *
1137 * Side Effects: None
1138 *
1139 * Overview: MACGet returns the byte pointed to by ERDPT and
1140 * increments ERDPT so MACGet() can be called again. The
1141 * increment will follow the receive buffer wrapping boundary.
1142 *
1143 * Note: None
1144 *****************************************************************************/
1145 BYTE MACGet()
1146 {
1147 BYTE i;
1148  
1149 ReadMemoryWindow(RX_WINDOW, &i, 1);
1150 return i;
1151 }//end MACGet
1152  
1153  
1154 /******************************************************************************
1155 * Function: WORD MACGetArray(BYTE *val, WORD len)
1156 *
1157 * PreCondition: SPI bus must be initialized (done in MACInit()).
1158 * ERDPT must point to the place to read from.
1159 *
1160 * Input: *val: Pointer to storage location
1161 * len: Number of bytes to read from the data buffer.
1162 *
1163 * Output: Byte(s) of data read from the data buffer.
1164 *
1165 * Side Effects: None
1166 *
1167 * Overview: Burst reads several sequential bytes from the data buffer
1168 * and places them into local memory. With SPI burst support,
1169 * it performs much faster than multiple MACGet() calls.
1170 * ERDPT is incremented after each byte, following the same
1171 * rules as MACGet().
1172 *
1173 * Note: None
1174 *****************************************************************************/
1175 WORD MACGetArray(BYTE *val, WORD len)
1176 {
1177 WORD wNewReadPtr;
1178  
1179 if(val)
1180 {
1181 ReadMemoryWindow(RX_WINDOW, val, len);
1182 }
1183 else
1184 {
1185 wNewReadPtr = ReadReg(ERXRDPT) + len;
1186 if(wNewReadPtr > RXSTOP)
1187 wNewReadPtr -= RXSIZE;
1188 WriteReg(ERXRDPT, wNewReadPtr);
1189 }
1190  
1191 return len;
1192 }//end MACGetArray
1193  
1194  
1195 /******************************************************************************
1196 * Function: void MACPut(BYTE val)
1197 *
1198 * PreCondition: SPI bus must be initialized (done in MACInit()).
1199 * EWRPT must point to the location to begin writing.
1200 *
1201 * Input: Byte to write into the ENCx24J600 buffer memory
1202 *
1203 * Output: None
1204 *
1205 * Side Effects: None
1206 *
1207 * Overview: MACPut outputs the Write Buffer Memory opcode/constant
1208 * (8 bits) and data to write (8 bits) over the SPI.
1209 * EWRPT is incremented after the write.
1210 *
1211 * Note: None
1212 *****************************************************************************/
1213 void MACPut(BYTE val)
1214 {
1215 WriteMemoryWindow(GP_WINDOW, &val, 1);
1216 }//end MACPut
1217  
1218  
1219 /******************************************************************************
1220 * Function: void MACPutArray(BYTE *val, WORD len)
1221 *
1222 * PreCondition: SPI bus must be initialized (done in MACInit()).
1223 * EWRPT must point to the location to begin writing.
1224 *
1225 * Input: *val: Pointer to source of bytes to copy.
1226 * len: Number of bytes to write to the data buffer.
1227 *
1228 * Output: None
1229 *
1230 * Side Effects: None
1231 *
1232 * Overview: MACPutArray writes several sequential bytes to the
1233 * ENCx24J600 RAM. It performs faster than multiple MACPut()
1234 * calls. EWRPT is incremented by len.
1235 *
1236 * Note: None
1237 *****************************************************************************/
1238 void MACPutArray(BYTE *val, WORD len)
1239 {
1240 WriteMemoryWindow(GP_WINDOW, val, len);
1241 }//end MACPutArray
1242  
1243  
1244 #if defined(__18CXX)
1245 /******************************************************************************
1246 * Function: void MACPutROMArray(ROM BYTE *val, WORD len)
1247 *
1248 * PreCondition: SPI bus must be initialized (done in MACInit()).
1249 * EWRPT must point to the location to begin writing.
1250 *
1251 * Input: *val: Pointer to source of bytes to copy.
1252 * len: Number of bytes to write to the data buffer.
1253 *
1254 * Output: None
1255 *
1256 * Side Effects: None
1257 *
1258 * Overview: MACPutArray writes several sequential bytes to the
1259 * ENCx24J600 RAM. It performs faster than multiple MACPut()
1260 * calls. EWRPT is incremented by len.
1261 *
1262 * Note: None
1263 *****************************************************************************/
1264 void MACPutROMArray(ROM BYTE *val, WORD len)
1265 {
1266 WORD wChunkLen;
1267 BYTE vBuffer[12];
1268  
1269 while(len)
1270 {
1271 wChunkLen = sizeof(vBuffer);
1272 if(len < wChunkLen)
1273 wChunkLen = len;
1274  
1275 memcpypgm2ram((void*)vBuffer, (ROM void*)val, wChunkLen);
1276 WriteMemoryWindow(GP_WINDOW, vBuffer, wChunkLen);
1277  
1278 len -= wChunkLen;
1279 val += wChunkLen;
1280 }
1281 }//end MACPutROMArray
1282 #endif
1283  
1284  
1285 /******************************************************************************
1286 * Function: void MACPowerDown(void)
1287 *
1288 * PreCondition: SPI bus must be initialized (done in MACInit()).
1289 *
1290 * Input: None
1291 *
1292 * Output: None
1293 *
1294 * Side Effects: None
1295 *
1296 * Overview: MACPowerDown puts the ENCx24J600 in low power sleep mode. In
1297 * sleep mode, no packets can be transmitted or received.
1298 * All MAC and PHY registers should not be accessed.
1299 *
1300 * To exit power down, call MACPowerUp().
1301 *
1302 * Note: If a packet is being transmitted while this function is
1303 * called, this function will block until it is it complete.
1304 * If anything is being received, it will be completed.
1305 *****************************************************************************/
1306 void MACPowerDown(void)
1307 {
1308 // Disable packet reception
1309 BFCReg(ECON1, ECON1_RXEN);
1310  
1311 // Make sure any last packet which was in-progress when RXEN was cleared
1312 // is completed
1313 while(ReadReg(ESTAT) & ESTAT_RXBUSY);
1314  
1315 // If a packet is being transmitted, the DMA is operating, the Modular
1316 // Exponentiation or AES engine is running, wait for it to finish
1317 while(ReadReg(ECON1) & (ECON1_TXRTS | ECON1_DMAST | ECON1_MODEXST | ECON1_AESST));
1318  
1319 // Enter sleep mode
1320 ENC100Flags.PoweredDown = 1;
1321 ENC100Flags.CryptoEnabled = 0;
1322 if(ReadReg(EIR) & EIR_CRYPTEN) // Turn off ModdEx/AES clock
1323 ToggleCRYPTEN();
1324 WritePHYReg(PHCON1, PHCON1_PSLEEP); // Turn off the PHY
1325 BFCReg(ECON2, ECON2_ETHEN | ECON2_STRCH); // Turn off general internal clocks and LED stretching so they immediately turn off and don't get stuck on
1326 }//end MACPowerDown
1327  
1328  
1329 /******************************************************************************
1330 * Function: void MACEDPowerDown(void)
1331 *
1332 * PreCondition: SPI bus must be initialized (done in MACInit()).
1333 *
1334 * Input: None
1335 *
1336 * Output: None
1337 *
1338 * Side Effects: None
1339 *
1340 * Overview: MACEDPowerDown puts the ENCx24J600 PHY in Energy Detect
1341 * mode. In this mode, the PHY will passively listen for link
1342 * pulses and automatically link up, if detected. This can be
1343 * detected via the MACIsLinkned() function. This power state
1344 * will save power only when an Ethernet cable is unattached.
1345 *
1346 * To exit energy detect power down, call MACPowerUp().
1347 *
1348 * Note: The ENCx24J600 is fully operational when in energy detect
1349 * mode. If a Ethernet link is detected or already established,
1350 * full TX/RX activity will work as normal and no power saving
1351 * will occur.
1352 *****************************************************************************/
1353 void MACEDPowerDown(void)
1354 {
1355 // Put the PHY into energy detect mode
1356 WritePHYReg(PHCON2, PHCON2_EDPWRDN);
1357  
1358 // Go into general power down
1359 ENC100Flags.CryptoEnabled = 0;
1360 if(ReadReg(EIR) & EIR_CRYPTEN) // Turn off ModdEx/AES clock
1361 ToggleCRYPTEN();
1362 ENC100Flags.PoweredDown = 1;
1363 BFCReg(ECON2, ECON2_ETHEN | ECON2_STRCH);
1364 }//end MACEDPowerDown
1365  
1366 /******************************************************************************
1367 * Function: void MACPowerUp(void)
1368 *
1369 * PreCondition: SPI bus must be initialized (done in MACInit()).
1370 *
1371 * Input: None
1372 *
1373 * Output: None
1374 *
1375 * Side Effects: None
1376 *
1377 * Overview: MACPowerUp returns the ENCx24J600 back to normal operation
1378 * after a previous call to MACPowerDown(). Calling this
1379 * function when already powered up will have no effect.
1380 *
1381 * Note: If a link partner is present, it will take 10s of
1382 * milliseconds before a new link will be established after
1383 * waking up. While not linked, packets which are
1384 * transmitted will most likely be lost. MACIsLinked() can
1385 * be called to determine if a link is established.
1386 *****************************************************************************/
1387 void MACPowerUp(void)
1388 {
1389 // Start up general clocks and reenable LED stretching
1390 ENC100Flags.PoweredDown = 0;
1391 BFSReg(ECON2, ECON2_ETHEN | ECON2_STRCH);
1392  
1393 // Power PHY back up and put in auto-negotation mode to reestablish a link
1394 if(ReadPHYReg(PHCON1) & PHCON1_PSLEEP)
1395 WritePHYReg(PHCON1, PHCON1_ANEN);
1396  
1397 // Disable energy detect PHY power down
1398 WritePHYReg(PHCON2, 0x0000);
1399  
1400 // Ensure the PLL and PHY are ready
1401 while(!(ReadReg(ESTAT) & (ESTAT_PHYRDY | ESTAT_CLKRDY)));
1402  
1403 // Enable packet reception
1404 BFSReg(ECON1, ECON1_RXEN);
1405 }//end MACPowerUp
1406  
1407  
1408 /******************************************************************************
1409 * Function: void SetCLKOUT(BYTE NewConfig)
1410 *
1411 * PreCondition: SPI or Parallel bus must be initialized (done in MACInit()).
1412 *
1413 * Input: NewConfig - 0x00: CLKOUT disabled (pin driven low)
1414 * 0x01: 33.333 MHz
1415 * 0x02: 25.000 MHz
1416 * 0x03: 20.000 MHz
1417 * 0x04: 16.667 MHz
1418 * 0x05: 12.500 MHz
1419 * 0x06: 10.000 MHz
1420 * 0x07: 8.333 MHz
1421 * 0x08: 8.000 MHz (47.5% duty cycle)
1422 * 0x09: 6.250 MHz
1423 * 0x0A: 5.000 MHz
1424 * 0x0B: 4.000 MHz
1425 * 0x0C: 3.125 MHz
1426 * 0x0D: CLKOUT disabled (pin driven low)
1427 * 0x0E: 100.00 kHz
1428 * 0x0F: 50.00 kHz
1429 *
1430 * Output: None
1431 *
1432 * Side Effects: None
1433 *
1434 * Overview: Writes the value of NewConfig into the COCON bits of ECON2
1435 * register. The CLKOUT pin will beginning outputting the
1436 * new frequency immediately.
1437 *
1438 * Note:
1439 *****************************************************************************/
1440 void SetCLKOUT(BYTE NewConfig)
1441 {
1442 WORD w;
1443  
1444 w = ReadReg(ECON2) & 0xF0FF;
1445 ((BYTE*)&w)[1] |= (NewConfig & 0x0F);
1446 WriteReg(ECON2, w);
1447 }//end SetCLKOUT
1448  
1449  
1450 /******************************************************************************
1451 * Function: BYTE GetCLKOUT(void)
1452 *
1453 * PreCondition: SPI or Parallel bus must be initialized (done in MACInit()).
1454 *
1455 * Input: None
1456 *
1457 * Output: BYTE - 0x00: CLKOUT disabled (pin driven low)
1458 * 0x01: 33.333 MHz
1459 * 0x02: 25.000 MHz
1460 * 0x03: 20.000 MHz
1461 * 0x04: 16.667 MHz
1462 * 0x05: 12.500 MHz
1463 * 0x06: 10.000 MHz
1464 * 0x07: 8.333 MHz
1465 * 0x08: 8.000 MHz (47.5% duty cycle)
1466 * 0x09: 6.250 MHz
1467 * 0x0A: 5.000 MHz
1468 * 0x0B: 4.000 MHz
1469 * 0x0C: 3.125 MHz
1470 * 0x0D: CLKOUT disabled (pin driven low)
1471 * 0x0E: 100.00 kHz
1472 * 0x0F: 50.00 kHz
1473 *
1474 * Side Effects: None
1475 *
1476 * Overview: Returns the current value of the COCON bits of ECON2
1477 * register.
1478 *
1479 * Note: None
1480 *****************************************************************************/
1481 BYTE GetCLKOUT(void)
1482 {
1483 WORD w;
1484  
1485 w = ReadReg(ECON2);
1486  
1487 return ((BYTE*)&w)[1] & 0x0F;
1488 }//end GetCLKOUT
1489  
1490  
1491 /******************************************************************************
1492 * Function: void SetRXHashTableEntry(MAC_ADDR DestMACAddr)
1493 *
1494 * PreCondition: SPI bus must be initialized (done in MACInit()).
1495 *
1496 * Input: DestMACAddr: 6 byte group destination MAC address to allow
1497 * through the Hash Table Filter
1498 *
1499 * Output: Sets the appropriate bit in the EHT* registers to allow
1500 * packets sent to DestMACAddr to be received if the Hash
1501 * Table receive filter is enabled
1502 *
1503 * Side Effects: None
1504 *
1505 * Overview: Calculates a CRC-32 using polynomial 0x4C11DB7 and then,
1506 * using bits 28:23 of the CRC, sets the appropriate bit in
1507 * the EHT* registers
1508 *
1509 * Note: This code is commented out to save code space on systems
1510 * that do not need this function. Change the "#if 0" line
1511 * to "#if 1" to uncomment it.
1512 *****************************************************************************/
1513 #if 0
1514 void SetRXHashTableEntry(MAC_ADDR DestMACAddr)
1515 {
1516 DWORD_VAL CRC = {0xFFFFFFFF};
1517 WORD HTRegister;
1518 BYTE i, j;
1519  
1520 // Calculate a CRC-32 over the 6 byte MAC address
1521 // using polynomial 0x4C11DB7
1522 for(i = 0; i < sizeof(MAC_ADDR); i++)
1523 {
1524 BYTE crcnext;
1525  
1526 // shift in 8 bits
1527 for(j = 0; j < 8; j++)
1528 {
1529 crcnext = 0;
1530 if(((BYTE_VAL*)&(CRC.v[3]))->bits.b7)
1531 crcnext = 1;
1532 crcnext ^= (((BYTE_VAL*)&DestMACAddr.v[i])->bits.b0);
1533  
1534 CRC.Val <<= 1;
1535 if(crcnext)
1536 CRC.Val ^= 0x4C11DB7;
1537 // next bit
1538 DestMACAddr.v[i] >>= 1;
1539 }
1540 }
1541  
1542 // CRC-32 calculated, now extract bits 28:23
1543 // Bits 25:23 define where within the Hash Table byte the bit needs to be set
1544 // Bits 28:26 define which of the 8 Hash Table bytes that bits 25:23 apply to
1545 i = CRC.v[3] & 0x1F;
1546 HTRegister = (i >> 2) + EHT1;
1547 i = (i << 1) & 0x06;
1548 ((BYTE_VAL*)&i)->bits.b0 = ((BYTE_VAL*)&CRC.v[2])->bits.b7;
1549  
1550 // Set the proper bit in the Hash Table
1551 BFSReg(HTRegister, 1<<i);
1552 }
1553 #endif
1554  
1555 /******************************************************************************
1556 * Function: static void SendSystemReset(void)
1557 *
1558 * PreCondition: SPI or PSP bus must be initialized (done in MACInit()).
1559 *
1560 * Input: None
1561 *
1562 * Output: None
1563 *
1564 * Side Effects: None
1565 *
1566 * Overview: SendSystemReset reliably resets the Ethernet controller.
1567 * It resets all register contents (except for COCON bits of
1568 * ECON2) and returns the device to the power on default state.
1569 * This function should be called instead of directly
1570 * attempting to perform a reset via the ECON2<ETHRST> bit.
1571 * If using the PSP, SendSystemReset also does basic checks to
1572 * look for unsoldered pins or solder bridges on the PSP pins.
1573 *
1574 * Note: This function is a blocking function and will lock up the
1575 * application if a non-recoverable problem is present.
1576 * Possible non-recoverable problems include:
1577 * - SPI module not configured correctly
1578 * - PMP module not configured correctly
1579 * - HardwareProfile pins not defined correctly
1580 * - Solder bridge on SPI/PSP/PMP lines
1581 * - Unsoldered pins on SPI/PSP/PMP lines
1582 * - 25MHz Ethernet oscillator not running
1583 * - Vdd lower than ENCX24J600 operating range
1584 * - I/O levels out of range (for example if the PIC is at
1585 * 2V without level shifting)
1586 * - Bus contention on SPI/PSP/PMP lines with other slaves
1587 * - One or more Vdd or Vss pins are not connected.
1588 *****************************************************************************/
1589 static void SendSystemReset(void)
1590 {
1591 // Power cycle the ENCx24J600 device, if any sort of POR pin is defined
1592 #if defined(ENC100_POR_IO)
1593 ENC100_POR_IO = 0;
1594 ENC100_POR_TRIS = 0;
1595 DelayMs(2);
1596  
1597 // If the INT/SPISEL signal is connected, force it to the correct state
1598 // for latching SPI or PSP mode.
1599 #if defined(ENC100_INT_TRIS)
1600 #if ENC100_INTERFACE_MODE == 0 // SPI
1601 ENC100_INT_IO = 1;
1602 #else // PSP
1603 ENC100_INT_IO = 0;
1604 #endif
1605 ENC100_INT_TRIS = 0;
1606 #endif
1607  
1608 // Turn on power and wait for interface latching to occur
1609 ENC100_POR_IO = 1;
1610 vCurrentBank = 0;
1611 Delay10us(40);
1612  
1613 // Tri-state interrupt GPIO so that we don't cause bus contention.
1614 #if defined(ENC100_INT_TRIS)
1615 ENC100_INT_TRIS = 1;
1616 #endif
1617 #endif
1618  
1619 // Perform a reset via the SPI/PSP interface
1620 do
1621 {
1622 // Set and clear a few bits that clears themselves upon reset.
1623 // If EUDAST cannot be written to and your code gets stuck in this
1624 // loop, you have a hardware problem of some sort (SPI or PMP not
1625 // initialized correctly, I/O pins aren't connected or are
1626 // shorted to something, power isn't available, etc.)
1627 do
1628 {
1629 WriteReg(EUDAST, 0x1234);
1630 } while(ReadReg(EUDAST) != 0x1234u);
1631  
1632 // Issue a reset and wait for it to complete
1633 BFSReg(ECON2, ECON2_ETHRST);
1634 vCurrentBank = 0;
1635 while((ReadReg(ESTAT) & (ESTAT_CLKRDY | ESTAT_RSTDONE | ESTAT_PHYRDY)) != (ESTAT_CLKRDY | ESTAT_RSTDONE | ESTAT_PHYRDY));
1636 Delay10us(3);
1637  
1638 // Check to see if the reset operation was successful by
1639 // checking if EUDAST went back to its reset default. This test
1640 // should always pass, but certain special conditions might make
1641 // this test fail, such as a PSP pin shorted to logic high.
1642 } while(ReadReg(EUDAST) != 0x0000u);
1643  
1644  
1645 // Really ensure reset is done and give some time for power to be stable
1646 DelayMs(1);
1647  
1648  
1649 // If using PSP, verify all address and data lines are working
1650 #if (ENC100_INTERFACE_MODE >= 1) && (ENC100_INTERFACE_MODE < 9) && defined(ENC100_PSP_USE_INDIRECT_RAM_ADDRESSING)
1651 {
1652 BYTE i;
1653 WORD wTestWriteData, wTestReadData;
1654  
1655 // If we have a PSP interface, but are using indirect addressing, we
1656 // can't use the ReadMemory()/WriteMemory() functions directly to access
1657 // RAM. Instead, lets do a simple test to verify all data lines only.
1658  
1659 // Check marching zero data pattern, then marching one data pattern
1660 wTestWriteData = 0xFFFE;
1661 for(i = 0; i < 34u; i++)
1662 {
1663 WriteReg(EHT1, wTestWriteData);
1664 wTestReadData = ReadReg(EHT1);
1665  
1666 // See if the data matches. If your application gets stuck here,
1667 // it means you have a hardware failure. Check all of your PSP
1668 // address and data lines.
1669 if(wTestWriteData != wTestReadData)
1670 while(1);
1671  
1672 // March the data over left by one bit
1673 wTestWriteData <<= 1;
1674 if(i == 16u)
1675 wTestWriteData = 0x0001;
1676 else if(i < 16u)
1677 wTestWriteData |= 0x0001;
1678 }
1679 }
1680 #elif (ENC100_INTERFACE_MODE >= 1) // Parallel direct addressing
1681 {
1682 WORD w;
1683 WORD wTestWriteData, wTestReadData;
1684  
1685 // Initialize RAM contents with a random pattern and read back to verify
1686 // This step is critical if using a PSP interface since some functionality
1687 // may appear to work while a solder bridge or disconnect will cause
1688 // certain memory ranges to fail.
1689  
1690 // Generate and write random pattern
1691 srand(600);
1692 for(w = 0; w < ENC100_RAM_SIZE; w += sizeof(wTestWriteData))
1693 {
1694 wTestWriteData = rand() + rand();
1695 WriteMemory(w, (BYTE*)&wTestWriteData, sizeof(wTestWriteData));
1696 ReadMemory(w, (BYTE*)&wTestReadData, sizeof(wTestReadData));
1697  
1698 // See if the data matches. If your application gets stuck here,
1699 // it means you have a hardware failure. Check all of your PSP
1700 // address and data lines.
1701 if(wTestWriteData != wTestReadData)
1702 while(1);
1703 }
1704  
1705 // Read back and verify random pattern
1706 srand(600);
1707 for(w = 0; w < ENC100_RAM_SIZE; w += sizeof(wTestWriteData))
1708 {
1709 wTestWriteData = rand() + rand();
1710 ReadMemory(w, (BYTE*)&wTestReadData, sizeof(wTestReadData));
1711  
1712 // See if the data matches. If your application gets stuck here,
1713 // it means you have a hardware failure. Check all of your PSP
1714 // address and data lines.
1715 if(wTestWriteData != wTestReadData)
1716 while(1);
1717 }
1718 }
1719 #endif
1720  
1721 }//end SendSystemReset
1722  
1723  
1724 #if ENC100_INTERFACE_MODE // WriteMemory() is not currently needed in SPI mode
1725 /******************************************************************************
1726 * Function: void WriteMemory(WORD wAddress, BYTE *vData, WORD wLength)
1727 *
1728 * PreCondition: None
1729 *
1730 * Input: wAddress: ENCX24J600 RAM or SFR address to write to
1731 * *vData: Pointer to local PIC RAM which needs to be written
1732 * to the ENCX24J600
1733 * wLength: Number of bytes to copy from vData to wAddress
1734 *
1735 * Output: None
1736 *
1737 * Side Effects: None
1738 *
1739 * Overview: Copys 0 or more bytes to the ENCX24J600 RAM
1740 *
1741 * Note: Can be used to access SFRs and ESFRs when using PSP
1742 *****************************************************************************/
1743 void WriteMemory(WORD wAddress, BYTE *vData, WORD wLength)
1744 {
1745 BOOL bISREnabled;
1746  
1747 if(wLength == 0u)
1748 return;
1749  
1750 #if defined(ENC100_ISR_ENABLE) && defined(ENC100_INT_TRIS)
1751 bISREnabled = ENC100_ISR_ENABLE;
1752 ENC100_ISR_ENABLE = 0;
1753 #endif
1754  
1755 #if !defined(ENC100_BIT_BANG_PMP) && ((ENC100_INTERFACE_MODE == 1) || (ENC100_INTERFACE_MODE == 2) || (ENC100_INTERFACE_MODE == 5) || (ENC100_INTERFACE_MODE == 6))
1756 {
1757 ConfigurePMPModule();
1758 AssertChipSelect();
1759 while(wLength--)
1760 {
1761 PMADDR = wAddress++; // NOTE: Performance might be improvable if you use PMP address increment
1762 while(PMMODEbits.BUSY);
1763 PMDIN1 = *vData++;
1764 }
1765 while(PMMODEbits.BUSY);
1766 DeassertChipSelect();
1767 PMCONbits.PMPEN = 0;
1768 }
1769 #elif !defined(ENC100_BIT_BANG_PMP) && ((ENC100_INTERFACE_MODE == 3) || (ENC100_INTERFACE_MODE == 4) || (ENC100_INTERFACE_MODE == 9) || (ENC100_INTERFACE_MODE == 10))
1770 {
1771 WORD wWORDAddress;
1772 volatile WORD wDummy;
1773  
1774 wWORDAddress = wAddress>>1;
1775 ConfigurePMPModule();
1776 AssertChipSelect();
1777 if(wAddress & 0x1)
1778 {
1779 PMADDR = wWORDAddress++;
1780 wDummy = PMDIN1; // Can't write to a single byte address by itself, so we will do a read-modify-write
1781 wLength--;
1782 ((BYTE*)&wDummy)[1] = *vData++;
1783 while(PMMODEbits.BUSY);
1784 ((BYTE*)&wDummy)[0] = ((BYTE*)&PMDIN1)[0];
1785 while(PMMODEbits.BUSY);
1786 PMDIN1 = wDummy;
1787 }
1788 while(wLength >= 2u)
1789 {
1790 PMADDR = wWORDAddress++; // NOTE: Performance might be improvable if you use PMP address increment
1791 wLength -= 2;
1792 ((BYTE*)&wDummy)[0] = *vData++;
1793 ((BYTE*)&wDummy)[1] = *vData++;
1794 while(PMMODEbits.BUSY);
1795 PMDIN1 = wDummy;
1796 }
1797 if(wLength)
1798 {
1799 PMADDR = wWORDAddress;
1800 wDummy = PMDIN1; // Can't write to a single byte address by itself, so we will do a read-modify-write
1801 ((BYTE*)&wDummy)[0] = *vData++;
1802 while(PMMODEbits.BUSY);
1803 ((BYTE*)&wDummy)[1] = ((BYTE*)&PMDIN1)[1];
1804 while(PMMODEbits.BUSY);
1805 PMDIN1 = wDummy;
1806 }
1807 while(PMMODEbits.BUSY);
1808 DeassertChipSelect();
1809 PMCONbits.PMPEN = 0;
1810 }
1811 #elif ENC100_INTERFACE_MODE == 1
1812 ENC100_SET_ADDR_TRIS_OUT();
1813 ENC100_SET_AD_TRIS_OUT();
1814 AssertChipSelect();
1815 while(wLength--)
1816 {
1817 ENC100_SET_ADDR_IO(wAddress++);
1818 ENC100_SET_AD_IO(*vData++);
1819 ENC100_SO_WR_B0SEL_EN_IO = 1;
1820 ENC100_SO_WR_B0SEL_EN_IO = 0;
1821 }
1822 DeassertChipSelect();
1823 #elif ENC100_INTERFACE_MODE == 2
1824 ENC100_SET_ADDR_TRIS_OUT();
1825 ENC100_SET_AD_TRIS_OUT();
1826 AssertChipSelect();
1827 ENC100_SI_RD_RW_IO = 0;
1828 while(wLength--)
1829 {
1830 ENC100_SET_ADDR_IO(wAddress++);
1831 ENC100_SET_AD_IO(*vData++);
1832 ENC100_SO_WR_B0SEL_EN_IO = 1;
1833 ENC100_SO_WR_B0SEL_EN_IO = 0;
1834 }
1835 DeassertChipSelect();
1836 #elif ENC100_INTERFACE_MODE == 3
1837 {
1838 WORD wData;
1839  
1840 ENC100_SET_ADDR_TRIS_OUT();
1841 ENC100_SET_AD_TRIS_OUT();
1842 AssertChipSelect();
1843 if(wAddress & 0x1) // Write high byte to odd address, if not WORD aligned
1844 {
1845 ENC100_SET_ADDR_IO(wAddress>>1);
1846 #if 1 // ENC100_WRH_B1SEL_IO == ENC100_SO_WR_B0SEL_EN_IO // Word writes only -- need to perform read-modify-write
1847 ENC100_SET_AD_TRIS_IN();
1848 ENC100_SI_RD_RW_IO = 1;
1849 DelaySetupHold();
1850 ((BYTE*)&wData)[0] = ENC100_GET_AD_IOL();
1851 ENC100_SI_RD_RW_IO = 0;
1852 ENC100_SET_AD_TRIS_OUT();
1853 #endif
1854 ((BYTE*)&wData)[1] = *vData++;
1855 ENC100_SET_AD_IO(wData);
1856 ENC100_WRH_B1SEL_IO = 1;
1857 ENC100_WRH_B1SEL_IO = 0;
1858 wAddress++;
1859 wLength--;
1860 }
1861 while(wLength >= 2u) // Write all possible WORDs
1862 {
1863 ENC100_SET_ADDR_IO(wAddress>>1);
1864 ((BYTE*)&wData)[0] = *vData++;
1865 ((BYTE*)&wData)[1] = *vData++;
1866 ENC100_SET_AD_IO(wData);
1867 ENC100_SO_WR_B0SEL_EN_IO = 1;
1868 ENC100_WRH_B1SEL_IO = 1;
1869 ENC100_SO_WR_B0SEL_EN_IO = 0;
1870 ENC100_WRH_B1SEL_IO = 0;
1871 wAddress += 2;
1872 wLength -= 2;
1873 }
1874 if(wLength) // Write final byte to low byte address, if needed
1875 {
1876 ENC100_SET_ADDR_IO(wAddress>>1);
1877 #if 1 // ENC100_WRH_B1SEL_IO == ENC100_SO_WR_B0SEL_EN_IO // Word writes only -- need to perform read-modify-write
1878 ENC100_SET_AD_TRIS_IN();
1879 ENC100_SI_RD_RW_IO = 1;
1880 DelaySetupHold();
1881 ((BYTE*)&wData)[1] = ENC100_GET_AD_IOH();
1882 ENC100_SI_RD_RW_IO = 0;
1883 ENC100_SET_AD_TRIS_OUT();
1884 #endif
1885 ((BYTE*)&wData)[0] = *vData++;
1886 ENC100_SET_AD_IO(wData);
1887 ENC100_SO_WR_B0SEL_EN_IO = 1;
1888 ENC100_SO_WR_B0SEL_EN_IO = 0;
1889 }
1890 DeassertChipSelect();
1891 }
1892 #elif ENC100_INTERFACE_MODE == 4
1893 {
1894 WORD wData;
1895  
1896 ENC100_SET_ADDR_TRIS_OUT();
1897 ENC100_SET_AD_TRIS_OUT();
1898 AssertChipSelect();
1899 ENC100_SI_RD_RW_IO = 0;
1900 if(wAddress & 0x1) // Write high byte to odd address, if not WORD aligned
1901 {
1902 ENC100_SET_ADDR_IO(wAddress>>1);
1903 #if 1 // ENC100_WRH_B1SEL_IO == ENC100_SO_WR_B0SEL_EN_IO // Word writes only -- need to perform read-modify-write
1904 ENC100_SET_AD_TRIS_IN();
1905 ENC100_SI_RD_RW_IO = 1;
1906 ENC100_SO_WR_B0SEL_EN_IO = 1;
1907 DelaySetupHold();
1908 ((BYTE*)&wData)[0] = ENC100_GET_AD_IOL();
1909 ENC100_SO_WR_B0SEL_EN_IO = 0;
1910 ENC100_SI_RD_RW_IO = 0;
1911 ENC100_SET_AD_TRIS_OUT();
1912 #endif
1913 ((BYTE*)&wData)[1] = *vData++;
1914 ENC100_SET_AD_IO(wData);
1915 ENC100_WRH_B1SEL_IO = 1;
1916 ENC100_WRH_B1SEL_IO = 0;
1917 wAddress++;
1918 wLength--;
1919 }
1920 while(wLength >= 2u) // Write all possible WORDs
1921 {
1922 ENC100_SET_ADDR_IO(wAddress>>1);
1923 ((BYTE*)&wData)[0] = *vData++;
1924 ((BYTE*)&wData)[1] = *vData++;
1925 ENC100_SET_AD_IO(wData);
1926 ENC100_SO_WR_B0SEL_EN_IO = 1;
1927 ENC100_WRH_B1SEL_IO = 1;
1928 ENC100_SO_WR_B0SEL_EN_IO = 0;
1929 ENC100_WRH_B1SEL_IO = 0;
1930 wAddress += 2;
1931 wLength -= 2;
1932 }
1933 if(wLength) // Write final byte to low byte address, if needed
1934 {
1935 ENC100_SET_ADDR_IO(wAddress>>1);
1936 #if 1 // ENC100_WRH_B1SEL_IO == ENC100_SO_WR_B0SEL_EN_IO // Word writes only -- need to perform read-modify-write
1937 ENC100_SET_AD_TRIS_IN();
1938 ENC100_SI_RD_RW_IO = 1;
1939 ENC100_SO_WR_B0SEL_EN_IO = 1;
1940 DelaySetupHold();
1941 ((BYTE*)&wData)[1] = ENC100_GET_AD_IOH();
1942 ENC100_SO_WR_B0SEL_EN_IO = 0;
1943 ENC100_SI_RD_RW_IO = 0;
1944 ENC100_SET_AD_TRIS_OUT();
1945 #endif
1946 ((BYTE*)&wData)[0] = *vData++;
1947 ENC100_SET_AD_IO(wData);
1948 ENC100_SO_WR_B0SEL_EN_IO = 1;
1949 ENC100_SO_WR_B0SEL_EN_IO = 0;
1950 }
1951 DeassertChipSelect();
1952 }
1953 #elif ENC100_INTERFACE_MODE == 5
1954 {
1955 ENC100_SET_AD_TRIS_OUT();
1956 AssertChipSelect();
1957 while(wLength--)
1958 {
1959 ENC100_SET_AD_IO(wAddress);
1960 ENC100_SCK_AL_IO = 1;
1961 ENC100_SCK_AL_IO = 0;
1962 ENC100_SET_AD_IOL(*vData++);
1963 wAddress++;
1964 ENC100_SO_WR_B0SEL_EN_IO = 1;
1965 ENC100_SO_WR_B0SEL_EN_IO = 0;
1966 }
1967 DeassertChipSelect();
1968 }
1969 #elif ENC100_INTERFACE_MODE == 6
1970 {
1971 ENC100_SET_AD_TRIS_OUT();
1972 AssertChipSelect();
1973 ENC100_SI_RD_RW_IO = 0;
1974 while(wLength--)
1975 {
1976 ENC100_SET_AD_IO(wAddress);
1977 ENC100_SCK_AL_IO = 1;
1978 ENC100_SCK_AL_IO = 0;
1979 ENC100_SET_AD_IOL(*vData++);
1980 wAddress++;
1981 ENC100_SO_WR_B0SEL_EN_IO = 1;
1982 ENC100_SO_WR_B0SEL_EN_IO = 0;
1983 }
1984 DeassertChipSelect();
1985 }
1986 #elif ENC100_INTERFACE_MODE == 9
1987 {
1988 WORD wData;
1989  
1990 ENC100_SET_AD_TRIS_OUT();
1991 AssertChipSelect();
1992 if(wAddress & 0x1) // Write high byte to odd address, if not WORD aligned
1993 {
1994 ENC100_SET_AD_IO(wAddress>>1);
1995 ENC100_SCK_AL_IO = 1;
1996 ENC100_SCK_AL_IO = 0;
1997 #if 1 // ENC100_WRH_B1SEL_IO == ENC100_SO_WR_B0SEL_EN_IO // Word writes only -- need to perform read-modify-write
1998 ENC100_SET_AD_TRIS_IN();
1999 ENC100_SI_RD_RW_IO = 1;
2000 DelaySetupHold();
2001 ((BYTE*)&wData)[0] = ENC100_GET_AD_IOL();
2002 ENC100_SI_RD_RW_IO = 0;
2003 ENC100_SET_AD_TRIS_OUT();
2004 #endif
2005 ((BYTE*)&wData)[1] = *vData++;
2006 ENC100_SET_AD_IO(wData);
2007 ENC100_WRH_B1SEL_IO = 1;
2008 wAddress++;
2009 wLength--;
2010 DelaySetupHold();
2011 ENC100_WRH_B1SEL_IO = 0;
2012 }
2013 while(wLength >= 2u) // Write all possible WORDs
2014 {
2015 ENC100_SET_AD_IO(wAddress>>1);
2016 ENC100_SCK_AL_IO = 1;
2017 ENC100_SCK_AL_IO = 0;
2018 ((BYTE*)&wData)[0] = *vData++;
2019 ((BYTE*)&wData)[1] = *vData++;
2020 ENC100_SET_AD_IO(wData);
2021 ENC100_SO_WR_B0SEL_EN_IO = 1;
2022 ENC100_WRH_B1SEL_IO = 1;
2023 wAddress += 2;
2024 wLength -= 2;
2025 DelaySetupHold();
2026 ENC100_SO_WR_B0SEL_EN_IO = 0;
2027 ENC100_WRH_B1SEL_IO = 0;
2028 }
2029 if(wLength) // Write final byte to low byte address, if needed
2030 {
2031 ENC100_SET_AD_IO(wAddress>>1);
2032 ENC100_SCK_AL_IO = 1;
2033 ENC100_SCK_AL_IO = 0;
2034 #if 1 // ENC100_WRH_B1SEL_IO == ENC100_SO_WR_B0SEL_EN_IO // Word writes only -- need to perform read-modify-write
2035 ENC100_SET_AD_TRIS_IN();
2036 ENC100_SI_RD_RW_IO = 1;
2037 DelaySetupHold();
2038 ((BYTE*)&wData)[1] = ENC100_GET_AD_IOH();
2039 ENC100_SI_RD_RW_IO = 0;
2040 ENC100_SET_AD_TRIS_OUT();
2041 #endif
2042 ((BYTE*)&wData)[0] = *vData++;
2043 ENC100_SET_AD_IO(wData);
2044 ENC100_SO_WR_B0SEL_EN_IO = 1;
2045 DelaySetupHold();
2046 ENC100_SO_WR_B0SEL_EN_IO = 0;
2047 }
2048 DeassertChipSelect();
2049 }
2050 #elif ENC100_INTERFACE_MODE == 10
2051 {
2052 WORD wData;
2053  
2054 ENC100_SET_AD_TRIS_OUT();
2055 AssertChipSelect();
2056 if(wAddress & 0x1) // Write high byte to odd address, if not WORD aligned
2057 {
2058 ENC100_SET_AD_IO(wAddress>>1);
2059 ENC100_SCK_AL_IO = 1;
2060 ENC100_SCK_AL_IO = 0;
2061 #if 1 // ENC100_WRH_B1SEL_IO == ENC100_SO_WR_B0SEL_EN_IO // Word writes only -- need to perform read-modify-write
2062 ENC100_SET_AD_TRIS_IN();
2063 ENC100_SI_RD_RW_IO = 1;
2064 ENC100_SO_WR_B0SEL_EN_IO = 1;
2065 DelaySetupHold();
2066 ((BYTE*)&wData)[0] = ENC100_GET_AD_IOL();
2067 ENC100_SO_WR_B0SEL_EN_IO = 0;
2068 ENC100_SET_AD_TRIS_OUT();
2069 #endif
2070 ENC100_SI_RD_RW_IO = 0;
2071 ((BYTE*)&wData)[1] = *vData++;
2072 ENC100_SET_AD_IO(wData);
2073 ENC100_WRH_B1SEL_IO = 1;
2074 wAddress++;
2075 wLength--;
2076 DelaySetupHold();
2077 ENC100_WRH_B1SEL_IO = 0;
2078 }
2079 ENC100_SI_RD_RW_IO = 0;
2080 while(wLength >= 2u) // Write all possible WORDs
2081 {
2082 ENC100_SET_AD_IO(wAddress>>1);
2083 ENC100_SCK_AL_IO = 1;
2084 ENC100_SCK_AL_IO = 0;
2085 ((BYTE*)&wData)[0] = *vData++;
2086 ((BYTE*)&wData)[1] = *vData++;
2087 ENC100_SET_AD_IO(wData);
2088 ENC100_SO_WR_B0SEL_EN_IO = 1;
2089 ENC100_WRH_B1SEL_IO = 1;
2090 wAddress += 2;
2091 wLength -= 2;
2092 DelaySetupHold();
2093 ENC100_SO_WR_B0SEL_EN_IO = 0;
2094 ENC100_WRH_B1SEL_IO = 0;
2095 }
2096 if(wLength) // Write final byte to low byte address, if needed
2097 {
2098 ENC100_SET_AD_IO(wAddress>>1);
2099 ENC100_SCK_AL_IO = 1;
2100 ENC100_SCK_AL_IO = 0;
2101 #if 1 // ENC100_WRH_B1SEL_IO == ENC100_SO_WR_B0SEL_EN_IO // Word writes only -- need to perform read-modify-write
2102 ENC100_SET_AD_TRIS_IN();
2103 ENC100_SI_RD_RW_IO = 1;
2104 ENC100_SO_WR_B0SEL_EN_IO = 1;
2105 DelaySetupHold();
2106 ((BYTE*)&wData)[1] = ENC100_GET_AD_IOH();
2107 ENC100_SO_WR_B0SEL_EN_IO = 0;
2108 ENC100_SET_AD_TRIS_OUT();
2109 #endif
2110 ENC100_SI_RD_RW_IO = 0;
2111 ((BYTE*)&wData)[0] = *vData++;
2112 ENC100_SET_AD_IO(wData);
2113 ENC100_SO_WR_B0SEL_EN_IO = 1;
2114 DelaySetupHold();
2115 ENC100_SO_WR_B0SEL_EN_IO = 0;
2116 }
2117 DeassertChipSelect();
2118 }
2119 #else // SPI mode
2120 {
2121 WORD w;
2122  
2123 // Use RX window
2124 w = Execute2(RRXWRPT, 0x0000);
2125 Execute2(WRXWRPT, wAddress);
2126 WriteN(WBMRX, vData, wLength);
2127 Execute2(WRXWRPT, w);
2128 }
2129 #endif
2130  
2131 #if defined(ENC100_ISR_ENABLE) && defined(ENC100_INT_TRIS)
2132 ENC100_ISR_ENABLE = bISREnabled;
2133 #endif
2134 }
2135 #endif
2136  
2137  
2138 /******************************************************************************
2139 * Function: void WriteMemoryWindow(BYTE vWindow, BYTE *vData, WORD wLength)
2140 *
2141 * PreCondition: None
2142 *
2143 * Input: vWindow: UDA_WINDOW, GP_WINDOW, or RX_WINDOW corresponding
2144 * to the window register to write to
2145 * *vData: Pointer to local PIC RAM which contains the
2146 * source data
2147 * wLength: Number of bytes to copy from vData to window
2148 *
2149 * Output: None
2150 *
2151 * Side Effects: None
2152 *
2153 * Overview: Copys 0 or more bytes from CPU RAM to the ENCX24J600
2154 * Family RAM using one of the UDA, TX, or RX write window
2155 * pointers. This pointer is incremented by the number of
2156 * bytes writen.
2157 *
2158 * Note: None
2159 *****************************************************************************/
2160 void WriteMemoryWindow(BYTE vWindow, BYTE *vData, WORD wLength)
2161 {
2162 BOOL bISREnabled;
2163  
2164 #if (ENC100_INTERFACE_MODE >= 1) // Parallel mode
2165 WORD wAddress;
2166 #endif
2167  
2168 // If we are in the middle of a SPI/PSP read/write operation, an interrupt
2169 // cannot be immediately processed (which would also require SPI/PSP
2170 // read/write operations). Therefore, we must disable the Ethernet
2171 // interrupt temporarily to ensure this illegal reentrancy doesn't occur.
2172 #if defined(ENC100_ISR_ENABLE) && defined(ENC100_INT_TRIS)
2173 bISREnabled = ENC100_ISR_ENABLE;
2174 ENC100_ISR_ENABLE = 0;
2175 #endif
2176  
2177 // Decode the vWindow handle to the litteral SFR address to read/write from/to
2178 #if (ENC100_INTERFACE_MODE == 1) || (ENC100_INTERFACE_MODE == 2) || (ENC100_INTERFACE_MODE == 5) || (ENC100_INTERFACE_MODE == 6)
2179 wAddress = EUDADATA;
2180 if(vWindow & GP_WINDOW)
2181 wAddress = EGPDATA;
2182 if(vWindow & RX_WINDOW)
2183 wAddress = ERXDATA;
2184 #elif (ENC100_INTERFACE_MODE == 3) || (ENC100_INTERFACE_MODE == 4) || (ENC100_INTERFACE_MODE == 9) || (ENC100_INTERFACE_MODE == 10)
2185 wAddress = (EUDADATA>>1);
2186 if(vWindow & GP_WINDOW)
2187 wAddress = (EGPDATA>>1);
2188 if(vWindow & RX_WINDOW)
2189 wAddress = (ERXDATA>>1);
2190 #endif
2191  
2192 #if (ENC100_INTERFACE_MODE >= 1) && !defined(ENC100_BIT_BANG_PMP) // PMP under hardware control
2193 {
2194 ConfigurePMPModule();
2195 AssertChipSelect();
2196 PMADDR = wAddress;
2197 while(wLength--)
2198 {
2199 while(PMMODEbits.BUSY);
2200 PMDIN1 = *vData++;
2201 }
2202 while(PMMODEbits.BUSY);
2203 DeassertChipSelect();
2204 PMCONbits.PMPEN = 0;
2205 }
2206 #elif ENC100_INTERFACE_MODE == 1 // Bit bang PMP
2207 ENC100_SET_ADDR_TRIS_OUT();
2208 ENC100_SET_AD_TRIS_OUT();
2209 AssertChipSelect();
2210 ENC100_SET_ADDR_IO(wAddress);
2211 while(wLength--)
2212 {
2213 ENC100_SET_AD_IO(*vData++);
2214 ENC100_SO_WR_B0SEL_EN_IO = 1;
2215 ENC100_SO_WR_B0SEL_EN_IO = 0;
2216 }
2217 DeassertChipSelect();
2218 #elif ENC100_INTERFACE_MODE == 2 // Bit bang PMP
2219 ENC100_SET_ADDR_TRIS_OUT();
2220 ENC100_SET_AD_TRIS_OUT();
2221 AssertChipSelect();
2222 ENC100_SI_RD_RW_IO = 0;
2223 ENC100_SET_ADDR_IO(wAddress);
2224 while(wLength--)
2225 {
2226 ENC100_SET_AD_IO(*vData++);
2227 ENC100_SO_WR_B0SEL_EN_IO = 1;
2228 ENC100_SO_WR_B0SEL_EN_IO = 0;
2229 }
2230 DeassertChipSelect();
2231 #elif ENC100_INTERFACE_MODE == 3 // Bit bang PMP
2232 {
2233 ENC100_SET_ADDR_TRIS_OUT();
2234 ENC100_SET_AD_TRIS_OUT();
2235 AssertChipSelect();
2236 ENC100_SET_ADDR_IO(wAddress);
2237 while(wLength--)
2238 {
2239 ENC100_SET_AD_IOL(*vData++);
2240 ENC100_SO_WR_B0SEL_EN_IO = 1;
2241 ENC100_SO_WR_B0SEL_EN_IO = 0;
2242 }
2243 DeassertChipSelect();
2244 }
2245 #elif ENC100_INTERFACE_MODE == 4 // Bit bang PMP
2246 {
2247 ENC100_SET_ADDR_TRIS_OUT();
2248 ENC100_SET_AD_TRIS_OUT();
2249 AssertChipSelect();
2250 ENC100_SI_RD_RW_IO = 0;
2251 ENC100_SET_ADDR_IO(wAddress);
2252 while(wLength--)
2253 {
2254 ENC100_SET_AD_IOL(*vData++);
2255 ENC100_SO_WR_B0SEL_EN_IO = 1;
2256 ENC100_SO_WR_B0SEL_EN_IO = 0;
2257 }
2258 DeassertChipSelect();
2259 }
2260 #elif ENC100_INTERFACE_MODE == 5 // Bit bang PMP
2261 {
2262 ENC100_SET_AD_TRIS_OUT();
2263 AssertChipSelect();
2264 ENC100_SET_AD_IO(wAddress);
2265 ENC100_SCK_AL_IO = 1;
2266 ENC100_SCK_AL_IO = 0;
2267 while(wLength--)
2268 {
2269 ENC100_SET_AD_IO(*vData++);
2270 ENC100_SO_WR_B0SEL_EN_IO = 1;
2271 ENC100_SO_WR_B0SEL_EN_IO = 0;
2272 }
2273 DeassertChipSelect();
2274 }
2275 #elif ENC100_INTERFACE_MODE == 6 // Bit bang PMP
2276 {
2277 ENC100_SET_AD_TRIS_OUT();
2278 AssertChipSelect();
2279 ENC100_SI_RD_RW_IO = 0;
2280 ENC100_SET_AD_IO(wAddress);
2281 ENC100_SCK_AL_IO = 1;
2282 ENC100_SCK_AL_IO = 0;
2283 while(wLength--)
2284 {
2285 ENC100_SET_AD_IO(*vData++);
2286 ENC100_SO_WR_B0SEL_EN_IO = 1;
2287 ENC100_SO_WR_B0SEL_EN_IO = 0;
2288 }
2289 DeassertChipSelect();
2290 }
2291 #elif ENC100_INTERFACE_MODE == 9 // Bit bang PMP
2292 {
2293 ENC100_SET_AD_TRIS_OUT();
2294 AssertChipSelect();
2295 ENC100_SET_AD_IO(wAddress);
2296 ENC100_SCK_AL_IO = 1;
2297 ENC100_SCK_AL_IO = 0;
2298 while(wLength--)
2299 {
2300 ENC100_SET_AD_IOL(*vData++);
2301 ENC100_SO_WR_B0SEL_EN_IO = 1;
2302 DelaySetupHold();
2303 ENC100_SO_WR_B0SEL_EN_IO = 0;
2304 }
2305 DeassertChipSelect();
2306 }
2307 #elif ENC100_INTERFACE_MODE == 10 // Bit bang PMP
2308 {
2309 ENC100_SET_AD_TRIS_OUT();
2310 AssertChipSelect();
2311 ENC100_SI_RD_RW_IO = 0;
2312 ENC100_SET_AD_IO(wAddress);
2313 ENC100_SCK_AL_IO = 1;
2314 ENC100_SCK_AL_IO = 0;
2315 while(wLength--)
2316 {
2317 ENC100_SET_AD_IOL(*vData++);
2318 ENC100_SO_WR_B0SEL_EN_IO = 1;
2319 DelaySetupHold();
2320 ENC100_SO_WR_B0SEL_EN_IO = 0;
2321 }
2322 DeassertChipSelect();
2323 }
2324 #else // SPI mode
2325 {
2326 BYTE vOpcode;
2327  
2328 vOpcode = WBMUDA;
2329 if(vWindow & GP_WINDOW)
2330 vOpcode = WBMGP;
2331 if(vWindow & RX_WINDOW)
2332 vOpcode = WBMRX;
2333  
2334 WriteN(vOpcode, vData, wLength);
2335 }
2336 #endif
2337  
2338 #if defined(ENC100_ISR_ENABLE) && defined(ENC100_INT_TRIS)
2339 ENC100_ISR_ENABLE = bISREnabled;
2340 #endif
2341 }
2342  
2343  
2344 #if ENC100_INTERFACE_MODE // ReadMemory() is not currently needed in SPI mode
2345 /******************************************************************************
2346 * Function: void ReadMemory(WORD wAddress, BYTE *vData, WORD wLength)
2347 *
2348 * PreCondition: None
2349 *
2350 * Input: wAddress: ENCX24J600 RAM or SFR address to read from
2351 * *vData: Pointer to local PIC RAM which will be written
2352 * with data from the ENCX24J600.
2353 * wLength: Number of bytes to copy from wAddress to vData
2354 *
2355 * Output: None
2356 *
2357 * Side Effects: None
2358 *
2359 * Overview: Copys 0 or more bytes from the ENCX24J600 RAM
2360 *
2361 * Note: Can be used to access SFRs and ESFRs when using PSP
2362 *****************************************************************************/
2363 void ReadMemory(WORD wAddress, BYTE *vData, WORD wLength)
2364 {
2365 BOOL bISREnabled;
2366  
2367 if(wLength == 0u)
2368 return;
2369  
2370 #if defined(ENC100_ISR_ENABLE) && defined(ENC100_INT_TRIS)
2371 bISREnabled = ENC100_ISR_ENABLE;
2372 ENC100_ISR_ENABLE = 0;
2373 #endif
2374  
2375 #if !defined(ENC100_BIT_BANG_PMP) && ((ENC100_INTERFACE_MODE == 1) || (ENC100_INTERFACE_MODE == 2) || (ENC100_INTERFACE_MODE == 5) || (ENC100_INTERFACE_MODE == 6))
2376 {
2377 volatile BYTE vDummy;
2378  
2379 ConfigurePMPModule();
2380 AssertChipSelect();
2381 PMADDR = wAddress++;
2382 vDummy = PMDIN1;
2383 while(--wLength)
2384 {
2385 PMADDR = wAddress++;
2386 while(PMMODEbits.BUSY);
2387 *vData++ = PMDIN1;
2388 }
2389 while(PMMODEbits.BUSY);
2390 DeassertChipSelect();
2391 *vData = PMDIN1;
2392 PMCONbits.PMPEN = 0;
2393 }
2394 #elif !defined(ENC100_BIT_BANG_PMP) && ((ENC100_INTERFACE_MODE == 3) || (ENC100_INTERFACE_MODE == 4) || (ENC100_INTERFACE_MODE == 9) || (ENC100_INTERFACE_MODE == 10))
2395 {
2396 WORD wWORDAddress;
2397 volatile WORD wDummy;
2398  
2399 wWORDAddress = wAddress>>1;
2400 ConfigurePMPModule();
2401 AssertChipSelect();
2402 PMADDR = wWORDAddress++;
2403 wDummy = PMDIN1;
2404 if(wAddress & 0x1)
2405 {
2406 PMADDR = wWORDAddress++;
2407 wLength--;
2408 while(PMMODEbits.BUSY);
2409 *vData++ = ((BYTE*)&PMDIN1)[1];
2410 }
2411 while(wLength >= 2)
2412 {
2413 PMADDR = wWORDAddress++;
2414 wLength -= 2;
2415 while(PMMODEbits.BUSY);
2416 wDummy = PMDIN1;
2417 *vData++ = ((BYTE*)&wDummy)[0];
2418 *vData++ = ((BYTE*)&wDummy)[1];
2419 }
2420 if(wLength)
2421 {
2422 while(PMMODEbits.BUSY);
2423 *vData = ((BYTE*)&PMDIN1)[0];
2424 }
2425 DeassertChipSelect();
2426 PMCONbits.PMPEN = 0;
2427 }
2428 #elif ENC100_INTERFACE_MODE == 1
2429 ENC100_SET_ADDR_TRIS_OUT();
2430 ENC100_SET_AD_TRIS_IN();
2431 AssertChipSelect();
2432 while(wLength--)
2433 {
2434 ENC100_SET_ADDR_IO(wAddress);
2435 ENC100_SI_RD_RW_IO = 1;
2436 wAddress++;
2437 DelaySetupHold();
2438 *vData++ = ENC100_GET_AD_IO();
2439 ENC100_SI_RD_RW_IO = 0;
2440 }
2441 DeassertChipSelect();
2442  
2443 #elif ENC100_INTERFACE_MODE == 2
2444 ENC100_SET_ADDR_TRIS_OUT();
2445 ENC100_SET_AD_TRIS_IN();
2446 AssertChipSelect();
2447 ENC100_SI_RD_RW_IO = 1;
2448 while(wLength--)
2449 {
2450 ENC100_SET_ADDR_IO(wAddress);
2451 ENC100_SO_WR_B0SEL_EN_IO = 1;
2452 wAddress++;
2453 DelaySetupHold();
2454 *vData++ = ENC100_GET_AD_IO();
2455 ENC100_SO_WR_B0SEL_EN_IO = 0;
2456 }
2457 DeassertChipSelect();
2458  
2459 #elif ENC100_INTERFACE_MODE == 3
2460 ENC100_SET_ADDR_TRIS_OUT();
2461 ENC100_SET_AD_TRIS_IN();
2462 AssertChipSelect();
2463 if(wAddress & 0x1) // Read from high byte if not WORD aligned
2464 {
2465 ENC100_SET_ADDR_IO(wAddress>>1);
2466 ENC100_SI_RD_RW_IO = 1;
2467 DelaySetupHold();
2468 wAddress++;
2469 wLength--;
2470 *vData++ = ENC100_GET_AD_IOH();
2471 ENC100_SI_RD_RW_IO = 0;
2472 }
2473 while(wLength >= 2u) // Read all necessary WORDs
2474 {
2475 ENC100_SET_ADDR_IO(wAddress>>1);
2476 ENC100_SI_RD_RW_IO = 1;
2477 DelaySetupHold();
2478 wLength -= 2;
2479 wAddress += 2;
2480 *vData++ = ENC100_GET_AD_IOL();
2481 *vData++ = ENC100_GET_AD_IOH();
2482 ENC100_SI_RD_RW_IO = 0;
2483 }
2484 if(wLength) // Read final low byte, if needed
2485 {
2486 ENC100_SET_ADDR_IO(wAddress>>1);
2487 ENC100_SI_RD_RW_IO = 1;
2488 DelaySetupHold();
2489 *vData = ENC100_GET_AD_IOL();
2490 ENC100_SI_RD_RW_IO = 0;
2491 }
2492 DeassertChipSelect();
2493  
2494 #elif ENC100_INTERFACE_MODE == 4
2495 ENC100_SET_ADDR_TRIS_OUT();
2496 ENC100_SET_AD_TRIS_IN();
2497 AssertChipSelect();
2498 ENC100_SI_RD_RW_IO = 1;
2499 if(wAddress & 0x1) // Read from high byte if not WORD aligned
2500 {
2501 ENC100_SET_ADDR_IO(wAddress>>1);
2502 ENC100_SO_WR_B0SEL_EN_IO = 1;
2503 DelaySetupHold();
2504 wAddress++;
2505 wLength--;
2506 *vData++ = ENC100_GET_AD_IOH();
2507 ENC100_SO_WR_B0SEL_EN_IO = 0;
2508 }
2509 while(wLength >= 2u) // Read all necessary WORDs
2510 {
2511 ENC100_SET_ADDR_IO(wAddress>>1);
2512 ENC100_SO_WR_B0SEL_EN_IO = 1;
2513 DelaySetupHold();
2514 wLength -= 2;
2515 wAddress += 2;
2516 *vData++ = ENC100_GET_AD_IOL();
2517 *vData++ = ENC100_GET_AD_IOH();
2518 ENC100_SO_WR_B0SEL_EN_IO = 0;
2519 }
2520 if(wLength) // Read final low byte, if needed
2521 {
2522 ENC100_SET_ADDR_IO(wAddress>>1);
2523 ENC100_SO_WR_B0SEL_EN_IO = 1;
2524 DelaySetupHold();
2525 *vData = ENC100_GET_AD_IOL();
2526 ENC100_SO_WR_B0SEL_EN_IO = 0;
2527 }
2528  
2529 DeassertChipSelect();
2530  
2531 #elif ENC100_INTERFACE_MODE == 5
2532 AssertChipSelect();
2533 while(wLength--)
2534 {
2535 ENC100_SET_AD_TRIS_OUT();
2536 ENC100_SET_AD_IO(wAddress);
2537 ENC100_SCK_AL_IO = 1;
2538 ENC100_SCK_AL_IO = 0;
2539 ENC100_SET_AD_TRIS_IN();
2540 ENC100_SI_RD_RW_IO = 1;
2541 DelaySetupHold();
2542 wAddress++;
2543 *vData++ = ENC100_GET_AD_IO();
2544 ENC100_SI_RD_RW_IO = 0;
2545 }
2546 DeassertChipSelect();
2547  
2548 #elif ENC100_INTERFACE_MODE == 6
2549 AssertChipSelect();
2550 ENC100_SI_RD_RW_IO = 1;
2551 while(wLength--)
2552 {
2553 ENC100_SET_AD_TRIS_OUT();
2554 ENC100_SET_AD_IO(wAddress);
2555 ENC100_SCK_AL_IO = 1;
2556 ENC100_SCK_AL_IO = 0;
2557 ENC100_SET_AD_TRIS_IN();
2558 ENC100_SO_WR_B0SEL_EN_IO = 1;
2559 DelaySetupHold();
2560 wAddress++;
2561 *vData++ = ENC100_GET_AD_IO();
2562 ENC100_SO_WR_B0SEL_EN_IO = 0;
2563 }
2564 DeassertChipSelect();
2565  
2566 #elif ENC100_INTERFACE_MODE == 9
2567 {
2568 AssertChipSelect();
2569 if(wAddress & 0x1) // Read from high byte if not WORD aligned
2570 {
2571 ENC100_SET_AD_TRIS_OUT();
2572 ENC100_SET_AD_IO(wAddress>>1);
2573 ENC100_SCK_AL_IO = 1;
2574 ENC100_SCK_AL_IO = 0;
2575 ENC100_SET_AD_TRIS_IN();
2576 ENC100_SI_RD_RW_IO = 1;
2577 DelaySetupHold();
2578 wAddress++;
2579 wLength--;
2580 *vData++ = ENC100_GET_AD_IOH();
2581 ENC100_SI_RD_RW_IO = 0;
2582 }
2583 while(wLength >= 2u) // Read all necessary WORDs
2584 {
2585 ENC100_SET_AD_TRIS_OUT();
2586 ENC100_SET_AD_IO(wAddress>>1);
2587 ENC100_SCK_AL_IO = 1;
2588 ENC100_SCK_AL_IO = 0;
2589 ENC100_SET_AD_TRIS_IN();
2590 ENC100_SI_RD_RW_IO = 1;
2591 DelaySetupHold();
2592 wAddress += 2;
2593 wLength -= 2;
2594 *vData++ = ENC100_GET_AD_IOL();
2595 *vData++ = ENC100_GET_AD_IOH();
2596 ENC100_SI_RD_RW_IO = 0;
2597 }
2598 if(wLength) // Read final low byte, if needed
2599 {
2600 ENC100_SET_AD_TRIS_OUT();
2601 ENC100_SET_AD_IO(wAddress>>1);
2602 ENC100_SCK_AL_IO = 1;
2603 ENC100_SCK_AL_IO = 0;
2604 ENC100_SET_AD_TRIS_IN();
2605 ENC100_SI_RD_RW_IO = 1;
2606 DelaySetupHold();
2607 *vData++ = ENC100_GET_AD_IOL();
2608 ENC100_SI_RD_RW_IO = 0;
2609 }
2610 DeassertChipSelect();
2611 }
2612 #elif ENC100_INTERFACE_MODE == 10
2613 {
2614 AssertChipSelect();
2615 ENC100_SI_RD_RW_IO = 1;
2616 if(wAddress & 0x1) // Read from high byte if not WORD aligned
2617 {
2618 ENC100_SET_AD_TRIS_OUT();
2619 ENC100_SET_AD_IO(wAddress>>1);
2620 ENC100_SCK_AL_IO = 1;
2621 ENC100_SCK_AL_IO = 0;
2622 ENC100_SET_AD_TRIS_IN();
2623 ENC100_SO_WR_B0SEL_EN_IO = 1;
2624 DelaySetupHold();
2625 wAddress++;
2626 wLength--;
2627 *vData++ = ENC100_GET_AD_IOH();
2628 ENC100_SO_WR_B0SEL_EN_IO = 0;
2629 }
2630 while(wLength >= 2u) // Read all necessary WORDs
2631 {
2632 ENC100_SET_AD_TRIS_OUT();
2633 ENC100_SET_AD_IO(wAddress>>1);
2634 ENC100_SCK_AL_IO = 1;
2635 ENC100_SCK_AL_IO = 0;
2636 ENC100_SET_AD_TRIS_IN();
2637 ENC100_SO_WR_B0SEL_EN_IO = 1;
2638 DelaySetupHold();
2639 wAddress += 2;
2640 wLength -= 2;
2641 *vData++ = ENC100_GET_AD_IOL();
2642 *vData++ = ENC100_GET_AD_IOH();
2643 ENC100_SO_WR_B0SEL_EN_IO = 0;
2644 }
2645 if(wLength) // Read final low byte, if needed
2646 {
2647 ENC100_SET_AD_TRIS_OUT();
2648 ENC100_SET_AD_IO(wAddress>>1);
2649 ENC100_SCK_AL_IO = 1;
2650 ENC100_SCK_AL_IO = 0;
2651 ENC100_SET_AD_TRIS_IN();
2652 ENC100_SO_WR_B0SEL_EN_IO = 1;
2653 DelaySetupHold();
2654 *vData++ = ENC100_GET_AD_IOL();
2655 ENC100_SO_WR_B0SEL_EN_IO = 0;
2656 }
2657 DeassertChipSelect();
2658 }
2659 #else // SPI mode
2660 {
2661 WORD w;
2662  
2663 // Use RX pointer
2664 w = Execute2(RRXRDPT, 0x0000);
2665 Execute2(WRXRDPT, wAddress);
2666 ReadN(RBMRX, vData, wLength);
2667 Execute2(WRXRDPT, w);
2668 }
2669 #endif
2670  
2671 #if defined(ENC100_ISR_ENABLE) && defined(ENC100_INT_TRIS)
2672 ENC100_ISR_ENABLE = bISREnabled;
2673 #endif
2674 }
2675 #endif
2676  
2677 /******************************************************************************
2678 * Function: void ReadMemoryWindow(BYTE vWindow, BYTE *vData, WORD wLength)
2679 *
2680 * PreCondition: None
2681 *
2682 * Input: vWindow: UDA_WINDOW, GP_WINDOW, or RX_WINDOW corresponding
2683 * to the window register to read from
2684 * *vData: Pointer to local PIC RAM which will be written
2685 * with data from the ENC624J600 Family.
2686 * wLength: Number of bytes to copy from window to vData
2687 *
2688 * Output: None
2689 *
2690 * Side Effects: None
2691 *
2692 * Overview: Copys 0 or more bytes from the ENC624J600 Family RAM using
2693 * one of the UDA, TX, or RX read window pointers. This
2694 * pointer is incremented by the number of bytes read.
2695 * However, if using a 16-bit parallel interface, the pointer
2696 * will be incremented by 1 extra if the length parameter is
2697 * odd to ensure 16-bit alignment.
2698 *
2699 * Note: None
2700 *****************************************************************************/
2701 void ReadMemoryWindow(BYTE vWindow, BYTE *vData, WORD wLength)
2702 {
2703 BOOL bISREnabled;
2704  
2705 #if (ENC100_INTERFACE_MODE >= 1) // Parallel mode
2706 WORD wAddress;
2707 #endif
2708  
2709 if(wLength == 0u)
2710 return;
2711  
2712 #if defined(ENC100_ISR_ENABLE) && defined(ENC100_INT_TRIS)
2713 bISREnabled = ENC100_ISR_ENABLE;
2714 ENC100_ISR_ENABLE = 0;
2715 #endif
2716  
2717 #if (ENC100_INTERFACE_MODE == 1) || (ENC100_INTERFACE_MODE == 2) || (ENC100_INTERFACE_MODE == 5) || (ENC100_INTERFACE_MODE == 6)
2718 wAddress = EUDADATA;
2719 if(vWindow & GP_WINDOW)
2720 wAddress = EGPDATA;
2721 if(vWindow & RX_WINDOW)
2722 wAddress = ERXDATA;
2723 #elif (ENC100_INTERFACE_MODE == 3) || (ENC100_INTERFACE_MODE == 4) || (ENC100_INTERFACE_MODE == 9) || (ENC100_INTERFACE_MODE == 10)
2724 wAddress = (EUDADATA>>1);
2725 if(vWindow & GP_WINDOW)
2726 wAddress = (EGPDATA>>1);
2727 if(vWindow & RX_WINDOW)
2728 wAddress = (ERXDATA>>1);
2729 #endif
2730  
2731 #if (ENC100_INTERFACE_MODE >= 1) && !defined(ENC100_BIT_BANG_PMP)
2732 {
2733 volatile BYTE vDummy;
2734  
2735 ConfigurePMPModule();
2736 AssertChipSelect();
2737 PMADDR = wAddress;
2738 vDummy = PMDIN1;
2739 while(--wLength)
2740 {
2741 while(PMMODEbits.BUSY);
2742 *vData++ = PMDIN1;
2743 }
2744 while(PMMODEbits.BUSY);
2745 DeassertChipSelect();
2746 PMCONbits.PMPEN = 0;
2747 *vData = PMDIN1;
2748 }
2749 #elif ENC100_INTERFACE_MODE == 1
2750 ENC100_SET_ADDR_TRIS_OUT();
2751 ENC100_SET_AD_TRIS_IN();
2752 AssertChipSelect();
2753 ENC100_SET_ADDR_IO(wAddress);
2754 while(wLength--)
2755 {
2756 ENC100_SI_RD_RW_IO = 1;
2757 DelaySetupHold();
2758 *vData++ = ENC100_GET_AD_IO();
2759 ENC100_SI_RD_RW_IO = 0;
2760 }
2761 DeassertChipSelect();
2762 #elif ENC100_INTERFACE_MODE == 2
2763 ENC100_SET_ADDR_TRIS_OUT();
2764 ENC100_SET_AD_TRIS_IN();
2765 AssertChipSelect();
2766 ENC100_SI_RD_RW_IO = 1;
2767 ENC100_SET_ADDR_IO(wAddress);
2768 while(wLength--)
2769 {
2770 ENC100_SO_WR_B0SEL_EN_IO = 1;
2771 DelaySetupHold();
2772 *vData++ = ENC100_GET_AD_IO();
2773 ENC100_SO_WR_B0SEL_EN_IO = 0;
2774 }
2775 DeassertChipSelect();
2776 #elif ENC100_INTERFACE_MODE == 3
2777 ENC100_SET_ADDR_TRIS_OUT();
2778 ENC100_SET_AD_TRIS_IN();
2779 AssertChipSelect();
2780 ENC100_SET_ADDR_IO(wAddress);
2781 while(wLength--)
2782 {
2783 ENC100_SI_RD_RW_IO = 1;
2784 DelaySetupHold();
2785 *vData++ = ENC100_GET_AD_IOL();
2786 ENC100_SI_RD_RW_IO = 0;
2787 }
2788 DeassertChipSelect();
2789 #elif ENC100_INTERFACE_MODE == 4
2790 ENC100_SET_ADDR_TRIS_OUT();
2791 ENC100_SET_AD_TRIS_IN();
2792 AssertChipSelect();
2793 ENC100_SI_RD_RW_IO = 1;
2794 ENC100_SET_ADDR_IO(wAddress);
2795 while(wLength--)
2796 {
2797 ENC100_SO_WR_B0SEL_EN_IO = 1;
2798 DelaySetupHold();
2799 *vData++ = ENC100_GET_AD_IOL();
2800 ENC100_SO_WR_B0SEL_EN_IO = 0;
2801 }
2802 DeassertChipSelect();
2803 #elif ENC100_INTERFACE_MODE == 5
2804 AssertChipSelect();
2805 ENC100_SET_AD_TRIS_OUT();
2806 ENC100_SET_AD_IO(wAddress);
2807 ENC100_SCK_AL_IO = 1;
2808 ENC100_SCK_AL_IO = 0;
2809 ENC100_SET_AD_TRIS_IN();
2810 while(wLength--)
2811 {
2812 ENC100_SI_RD_RW_IO = 1;
2813 DelaySetupHold();
2814 *vData++ = ENC100_GET_AD_IO();
2815 ENC100_SI_RD_RW_IO = 0;
2816 }
2817 DeassertChipSelect();
2818 #elif ENC100_INTERFACE_MODE == 6
2819 AssertChipSelect();
2820 ENC100_SI_RD_RW_IO = 1;
2821 ENC100_SET_AD_TRIS_OUT();
2822 ENC100_SET_AD_IO(wAddress);
2823 ENC100_SCK_AL_IO = 1;
2824 ENC100_SCK_AL_IO = 0;
2825 ENC100_SET_AD_TRIS_IN();
2826 while(wLength--)
2827 {
2828 ENC100_SO_WR_B0SEL_EN_IO = 1;
2829 DelaySetupHold();
2830 *vData++ = ENC100_GET_AD_IO();
2831 ENC100_SO_WR_B0SEL_EN_IO = 0;
2832 }
2833 DeassertChipSelect();
2834 #elif ENC100_INTERFACE_MODE == 9
2835 AssertChipSelect();
2836 ENC100_SET_AD_TRIS_OUT();
2837 ENC100_SET_AD_IO(wAddress);
2838 ENC100_SCK_AL_IO = 1;
2839 ENC100_SCK_AL_IO = 0;
2840 ENC100_SET_AD_TRIS_IN();
2841 while(wLength--)
2842 {
2843 ENC100_SI_RD_RW_IO = 1;
2844 DelaySetupHold();
2845 *vData++ = ENC100_GET_AD_IOL();
2846 ENC100_SI_RD_RW_IO = 0;
2847 }
2848 DeassertChipSelect();
2849 #elif ENC100_INTERFACE_MODE == 10
2850 AssertChipSelect();
2851 ENC100_SI_RD_RW_IO = 1;
2852 ENC100_SET_AD_TRIS_OUT();
2853 ENC100_SET_AD_IO(wAddress);
2854 ENC100_SCK_AL_IO = 1;
2855 ENC100_SCK_AL_IO = 0;
2856 ENC100_SET_AD_TRIS_IN();
2857 while(wLength--)
2858 {
2859 ENC100_SO_WR_B0SEL_EN_IO = 1;
2860 DelaySetupHold();
2861 *vData++ = ENC100_GET_AD_IOL();
2862 ENC100_SO_WR_B0SEL_EN_IO = 0;
2863 }
2864 DeassertChipSelect();
2865 #else // SPI mode
2866 {
2867 BYTE vOpcode;
2868  
2869 vOpcode = RBMUDA;
2870 if(vWindow & GP_WINDOW)
2871 vOpcode = RBMGP;
2872 if(vWindow & RX_WINDOW)
2873 vOpcode = RBMRX;
2874  
2875 ReadN(vOpcode, vData, wLength);
2876 }
2877 #endif
2878  
2879 #if defined(ENC100_ISR_ENABLE) && defined(ENC100_INT_TRIS)
2880 ENC100_ISR_ENABLE = bISREnabled;
2881 #endif
2882 }
2883  
2884  
2885  
2886 #if (ENC100_INTERFACE_MODE == 0) // These are SPI only functions
2887 /******************************************************************************
2888 * Function: void Execute0(BYTE vOpcode)
2889 *
2890 * PreCondition: SPI bus must be initialized (done in MACInit()).
2891 *
2892 * Input: None
2893 *
2894 * Output: None
2895 *
2896 * Side Effects: None
2897 *
2898 * Overview: Sends a single byte command with no parameters
2899 *
2900 * Note: None
2901 *****************************************************************************/
2902 static void Execute0(BYTE vOpcode)
2903 {
2904 volatile BYTE vDummy;
2905 BOOL bISREnabled;
2906  
2907 #if defined(ENC100_ISR_ENABLE) && defined(ENC100_INT_TRIS)
2908 bISREnabled = ENC100_ISR_ENABLE;
2909 ENC100_ISR_ENABLE = 0;
2910 #endif
2911  
2912 AssertChipSelect();
2913 ClearSPIDoneFlag();
2914 ENC100_SSPBUF = vOpcode; // Send the command/opcode
2915 WaitForDataByte();
2916 vDummy = ENC100_SSPBUF;
2917 DeassertChipSelect();
2918  
2919 #if defined(ENC100_ISR_ENABLE) && defined(ENC100_INT_TRIS)
2920 ENC100_ISR_ENABLE = bISREnabled;
2921 #endif
2922 }//end Execute0
2923  
2924 // This Execute1 function is not currently used
2925 //static BYTE Execute1(BYTE vOpcode, BYTE vData)
2926 //{
2927 // volatile BYTE vReturn;
2928 // BOOL bISREnabled;
2929 //
2930 // #if defined(ENC100_ISR_ENABLE) && defined(ENC100_INT_TRIS)
2931 // bISREnabled = ENC100_ISR_ENABLE;
2932 // ENC100_ISR_ENABLE = 0;
2933 // #endif
2934 //
2935 // AssertChipSelect();
2936 // ClearSPIDoneFlag();
2937 // ENC100_SSPBUF = vOpcode; // Send the command/opcode
2938 // WaitForDataByte();
2939 // vReturn = ENC100_SSPBUF;
2940 // ENC100_SSPBUF = vData; // Send the data
2941 // WaitForDataByte();
2942 // vReturn = ENC100_SSPBUF;
2943 // DeassertChipSelect();
2944 //
2945 // #if defined(ENC100_ISR_ENABLE) && defined(ENC100_INT_TRIS)
2946 // ENC100_ISR_ENABLE = bISREnabled;
2947 // #endif
2948 //
2949 // return vReturn;
2950 //}//end Execute1
2951  
2952 static WORD Execute2(BYTE vOpcode, WORD wData)
2953 {
2954 volatile WORD wReturn;
2955 BOOL bISREnabled;
2956  
2957 #if defined(ENC100_ISR_ENABLE) && defined(ENC100_INT_TRIS)
2958 bISREnabled = ENC100_ISR_ENABLE;
2959 ENC100_ISR_ENABLE = 0;
2960 #endif
2961  
2962 AssertChipSelect();
2963 ClearSPIDoneFlag();
2964 ENC100_SSPBUF = vOpcode; // Send the command/opcode
2965 WaitForDataByte();
2966 ((BYTE*)&wReturn)[0] = ENC100_SSPBUF;
2967 ENC100_SSPBUF = ((BYTE*)&wData)[0]; // Send low byte of data
2968 WaitForDataByte();
2969 ((BYTE*)&wReturn)[0] = ENC100_SSPBUF;
2970 ENC100_SSPBUF = ((BYTE*)&wData)[1]; // Send high byte of data
2971 WaitForDataByte();
2972 ((BYTE*)&wReturn)[1] = ENC100_SSPBUF;
2973 DeassertChipSelect();
2974  
2975 #if defined(ENC100_ISR_ENABLE) && defined(ENC100_INT_TRIS)
2976 ENC100_ISR_ENABLE = bISREnabled;
2977 #endif
2978  
2979 return wReturn;
2980 }//end Execute2
2981  
2982 static DWORD Execute3(BYTE vOpcode, DWORD dwData)
2983 {
2984 volatile DWORD dwReturn;
2985 BOOL bISREnabled;
2986  
2987 #if defined(ENC100_ISR_ENABLE) && defined(ENC100_INT_TRIS)
2988 bISREnabled = ENC100_ISR_ENABLE;
2989 ENC100_ISR_ENABLE = 0;
2990 #endif
2991  
2992 AssertChipSelect();
2993 ClearSPIDoneFlag();
2994 ENC100_SSPBUF = vOpcode; // Send the command/opcode
2995 ((BYTE*)&dwReturn)[3] = 0x00;
2996 WaitForDataByte();
2997 ((BYTE*)&dwReturn)[0] = ENC100_SSPBUF;
2998 ENC100_SSPBUF = ((BYTE*)&dwData)[0]; // Send byte 0 of data
2999 WaitForDataByte();
3000 ((BYTE*)&dwReturn)[0] = ENC100_SSPBUF;
3001 ENC100_SSPBUF = ((BYTE*)&dwData)[1]; // Send byte 1 of data
3002 WaitForDataByte();
3003 ((BYTE*)&dwReturn)[1] = ENC100_SSPBUF;
3004 ENC100_SSPBUF = ((BYTE*)&dwData)[2]; // Send byte 2 of data
3005 WaitForDataByte();
3006 ((BYTE*)&dwReturn)[2] = ENC100_SSPBUF;
3007 DeassertChipSelect();
3008  
3009 #if defined(ENC100_ISR_ENABLE) && defined(ENC100_INT_TRIS)
3010 ENC100_ISR_ENABLE = bISREnabled;
3011 #endif
3012  
3013 return dwReturn;
3014 }//end Execute2
3015  
3016 static void ReadN(BYTE vOpcode, BYTE* vData, WORD wDataLen)
3017 {
3018 volatile BYTE vDummy;
3019 BOOL bISREnabled;
3020  
3021 #if defined(ENC100_ISR_ENABLE) && defined(ENC100_INT_TRIS)
3022 bISREnabled = ENC100_ISR_ENABLE;
3023 ENC100_ISR_ENABLE = 0;
3024 #endif
3025  
3026 AssertChipSelect();
3027 ClearSPIDoneFlag();
3028 ENC100_SSPBUF = vOpcode; // Send the command/opcode
3029 WaitForDataByte();
3030 vDummy = ENC100_SSPBUF;
3031 while(wDataLen--)
3032 {
3033 ENC100_SSPBUF = 0x00;
3034 WaitForDataByte();
3035 *vData++ = ENC100_SSPBUF;
3036 }
3037 DeassertChipSelect();
3038  
3039 #if defined(ENC100_ISR_ENABLE) && defined(ENC100_INT_TRIS)
3040 ENC100_ISR_ENABLE = bISREnabled;
3041 #endif
3042 }
3043  
3044 static void WriteN(BYTE vOpcode, BYTE* vData, WORD wDataLen)
3045 {
3046 volatile BYTE vDummy;
3047 BOOL bISREnabled;
3048  
3049 #if defined(ENC100_ISR_ENABLE) && defined(ENC100_INT_TRIS)
3050 bISREnabled = ENC100_ISR_ENABLE;
3051 ENC100_ISR_ENABLE = 0;
3052 #endif
3053  
3054 AssertChipSelect();
3055 ClearSPIDoneFlag();
3056 ENC100_SSPBUF = vOpcode; // Send the command/opcode
3057 WaitForDataByte();
3058 vDummy = ENC100_SSPBUF;
3059  
3060 while(wDataLen--)
3061 {
3062 ENC100_SSPBUF = *vData++;
3063 WaitForDataByte();
3064 vDummy = ENC100_SSPBUF;
3065 }
3066 DeassertChipSelect();
3067  
3068 #if defined(ENC100_ISR_ENABLE) && defined(ENC100_INT_TRIS)
3069 ENC100_ISR_ENABLE = bISREnabled;
3070 #endif
3071 }
3072  
3073 #endif
3074  
3075 /******************************************************************************
3076 * Function: WORD ReadReg(WORD wAddress)
3077 *
3078 * PreCondition: SPI/PSP bus must be initialized (done in MACInit()).
3079 *
3080 * Input: wAddress: Address of SFR register to read from.
3081 * The LSb is ignored and treated as '0' always.
3082 *
3083 * Output: WORD value of register contents
3084 *
3085 * Side Effects: None
3086 *
3087 * Overview: Selects the correct bank (if needed), and reads the
3088 * corresponding 16-bit register
3089 *
3090 * Note: This routine cannot be used to read PHY registers.
3091 * Use the ReadPHYReg() function to read from PHY registers.
3092 *****************************************************************************/
3093 static WORD ReadReg(WORD wAddress)
3094 {
3095 #if (ENC100_INTERFACE_MODE >= 1) // Parallel mode
3096 {
3097 WORD w;
3098  
3099 ReadMemory(wAddress, (BYTE*)&w, 2);
3100 return w;
3101 }
3102 #else // SPI mode
3103 {
3104 WORD w;
3105 BYTE vBank;
3106  
3107 // See if we need to change register banks
3108 vBank = ((BYTE)wAddress) & 0xE0;
3109 if(vBank <= (0x3u<<5))
3110 {
3111 if(vBank != vCurrentBank)
3112 {
3113 if(vBank == (0x0u<<5))
3114 Execute0(B0SEL);
3115 else if(vBank == (0x1u<<5))
3116 Execute0(B1SEL);
3117 else if(vBank == (0x2u<<5))
3118 Execute0(B2SEL);
3119 else if(vBank == (0x3u<<5))
3120 Execute0(B3SEL);
3121  
3122 vCurrentBank = vBank;
3123 }
3124  
3125 w = Execute2(RCR | (wAddress & 0x1F), 0x0000);
3126 }
3127 else
3128 {
3129 DWORD dw = Execute3(RCRU, (DWORD)wAddress);
3130 ((BYTE*)&w)[0] = ((BYTE*)&dw)[1];
3131 ((BYTE*)&w)[1] = ((BYTE*)&dw)[2];
3132 }
3133  
3134 return w;
3135 }
3136 #endif
3137 }//end ReadReg
3138  
3139  
3140 /******************************************************************************
3141 * Function: void WriteReg(WORD wAddress, WORD wValue)
3142 *
3143 * PreCondition: SPI/PSP bus must be initialized (done in MACInit()).
3144 *
3145 * Input: wAddress: Address of the SFR register to write to.
3146 * 16-bit WORD to be written into the register.
3147 *
3148 * Output: None
3149 *
3150 * Side Effects: None
3151 *
3152 * Overview: Selects the correct bank (if using the SPI and needed), and
3153 * writes the corresponding 16-bit register with wValue.
3154 *
3155 * Note: This routine cannot write to PHY registers. Use the
3156 * WritePHYReg() function for writing to PHY registers.
3157 *****************************************************************************/
3158 static void WriteReg(WORD wAddress, WORD wValue)
3159 {
3160 #if (ENC100_INTERFACE_MODE >= 1) // Parallel mode
3161 {
3162 WriteMemory(wAddress, (BYTE*)&wValue, 2);
3163 }
3164 #else // SPI mode
3165 {
3166 BYTE vBank;
3167  
3168 // See if we need to change register banks
3169 vBank = ((BYTE)wAddress) & 0xE0;
3170 if(vBank <= (0x3u<<5))
3171 {
3172 if(vBank != vCurrentBank)
3173 {
3174 if(vBank == (0x0u<<5))
3175 Execute0(B0SEL);
3176 else if(vBank == (0x1u<<5))
3177 Execute0(B1SEL);
3178 else if(vBank == (0x2u<<5))
3179 Execute0(B2SEL);
3180 else if(vBank == (0x3u<<5))
3181 Execute0(B3SEL);
3182  
3183 vCurrentBank = vBank;
3184 }
3185  
3186 Execute2(WCR | (wAddress & 0x1F), wValue);
3187 }
3188 else
3189 {
3190 DWORD dw;
3191 ((BYTE*)&dw)[0] = (BYTE)wAddress;
3192 ((BYTE*)&dw)[1] = ((BYTE*)&wValue)[0];
3193 ((BYTE*)&dw)[2] = ((BYTE*)&wValue)[1];
3194 Execute3(WCRU, dw);
3195 }
3196  
3197 }
3198 #endif
3199 }//end WriteReg
3200  
3201  
3202 /******************************************************************************
3203 * Function: void BFSReg(WORD wAddress, WORD wBitMask)
3204 * void BFCReg(WORD wAddress, WORD wBitMask)
3205 *
3206 * PreCondition: None
3207 *
3208 * Input: 7 bit address of the register to write to.
3209 * 16-bit WORD bitmask to set/clear in the register.
3210 *
3211 * Output: None
3212 *
3213 * Side Effects: None
3214 *
3215 * Overview: Sets/clears bits in Ethernet SFR registers
3216 *
3217 * Note: These functions cannot be used to access ESFR registers.
3218 *****************************************************************************/
3219 static void BFSReg(WORD wAddress, WORD wBitMask)
3220 {
3221 #if (ENC100_INTERFACE_MODE >= 1) // Parallel mode
3222 {
3223 WriteMemory(wAddress+SET_OFFSET, (BYTE*)&wBitMask, 2);
3224 }
3225 #else // SPI mode
3226 {
3227 BYTE vBank;
3228  
3229 // See if we need to change register banks
3230 vBank = ((BYTE)wAddress) & 0xE0;
3231 if(vBank != vCurrentBank)
3232 {
3233 if(vBank == (0x0u<<5))
3234 Execute0(B0SEL);
3235 else if(vBank == (0x1u<<5))
3236 Execute0(B1SEL);
3237 else if(vBank == (0x2u<<5))
3238 Execute0(B2SEL);
3239 else if(vBank == (0x3u<<5))
3240 Execute0(B3SEL);
3241  
3242 vCurrentBank = vBank;
3243 }
3244  
3245 Execute2(BFS | (wAddress & 0x1F), wBitMask);
3246 }
3247 #endif
3248 }//end BFSReg
3249  
3250 static void BFCReg(WORD wAddress, WORD wBitMask)
3251 {
3252 #if (ENC100_INTERFACE_MODE >= 1) // Parallel mode
3253 {
3254 WriteMemory(wAddress+CLR_OFFSET, (BYTE*)&wBitMask, 2);
3255 }
3256 #else // SPI mode
3257 {
3258 BYTE vBank;
3259  
3260 // See if we need to change register banks
3261 vBank = ((BYTE)wAddress) & 0xE0;
3262 if(vBank != vCurrentBank)
3263 {
3264 if(vBank == (0x0u<<5))
3265 Execute0(B0SEL);
3266 else if(vBank == (0x1u<<5))
3267 Execute0(B1SEL);
3268 else if(vBank == (0x2u<<5))
3269 Execute0(B2SEL);
3270 else if(vBank == (0x3u<<5))
3271 Execute0(B3SEL);
3272  
3273 vCurrentBank = vBank;
3274 }
3275  
3276 Execute2(BFC | (wAddress & 0x1F), wBitMask);
3277 }
3278 #endif
3279 }//end BFCReg
3280  
3281  
3282 /******************************************************************************
3283 * Function: WORD ReadPHYReg(BYTE Register)
3284 *
3285 * PreCondition: SPI bus must be initialized (done in MACInit()).
3286 *
3287 * Input: Address of the PHY register to read from.
3288 *
3289 * Output: 16 bits of data read from the PHY register.
3290 *
3291 * Side Effects: None
3292 *
3293 * Overview: ReadPHYReg performs an MII read operation. While in
3294 * progress, it simply polls the MII BUSY bit wasting time
3295 * (25.6us).
3296 *
3297 * Note: None
3298 *****************************************************************************/
3299 WORD ReadPHYReg(BYTE Register)
3300 {
3301 WORD wResult;
3302  
3303 // Set the right address and start the register read operation
3304 WriteReg(MIREGADR, 0x0100 | Register);
3305 WriteReg(MICMD, MICMD_MIIRD);
3306  
3307 // Loop to wait until the PHY register has been read through the MII
3308 // This requires 25.6us
3309 while(ReadReg(MISTAT) & MISTAT_BUSY);
3310  
3311 // Stop reading
3312 WriteReg(MICMD, 0x0000);
3313  
3314 // Obtain results and return
3315 wResult = ReadReg(MIRD);
3316  
3317 return wResult;
3318 }//end ReadPHYReg
3319  
3320 /******************************************************************************
3321 * Function: WritePHYReg
3322 *
3323 * PreCondition: SPI bus must be initialized (done in MACInit()).
3324 *
3325 * Input: Address of the PHY register to write to.
3326 * 16 bits of data to write to PHY register.
3327 *
3328 * Output: None
3329 *
3330 * Side Effects: None
3331 *
3332 * Overview: WritePHYReg performs an MII write operation. While in
3333 * progress, it simply polls the MII BUSY bit wasting time.
3334 *
3335 * Note: None
3336 *****************************************************************************/
3337 void WritePHYReg(BYTE Register, WORD Data)
3338 {
3339 // Write the register address
3340 WriteReg(MIREGADR, 0x0100 | Register);
3341  
3342 // Write the data
3343 WriteReg(MIWR, Data);
3344  
3345 // Wait until the PHY register has been written
3346 while(ReadReg(MISTAT) & MISTAT_BUSY);
3347 }//end WritePHYReg
3348  
3349  
3350  
3351 /*****************************************************************************
3352 Function:
3353 static void ToggleCRYPTEN(void)
3354  
3355 Summary:
3356 Toggles the CRYPTEN (EIR<15>) cryptographic enable bit in an errata safe
3357 way.
3358  
3359 Description:
3360 Due to an ENC424J600/624J600 Rev. A2 silicon errata, it is not possible to
3361 set or clear the CRYPTEN bit (EIR<15>) by using the BFSReg() or BFCReg()
3362 functions. Instead a register write to the volatile EIR interrupt flags
3363 register is required. This function reads EIR, toggles the CRYPTEN state,
3364 and writes the value back to EIR in a manner that does not destroy or
3365 glitch the interrupt states.
3366  
3367 Precondition:
3368 None
3369  
3370 Parameters:
3371 None
3372  
3373 Returns:
3374 None
3375 ***************************************************************************/
3376 static void ToggleCRYPTEN(void)
3377 {
3378 WORD wLinkStat;
3379 WORD wInterruptEnable;
3380  
3381 // About to do read-modify-write to interrupt flags - disable interrupts
3382 // temporarily.
3383 wInterruptEnable = ReadReg(EIE);
3384 if(wInterruptEnable & EIE_INTIE)
3385 BFCReg(EIE, EIE_INTIE);
3386  
3387 // Get current link status so that we can regenerate LINKIF if it is missed
3388 wLinkStat = ReadReg(ESTAT);
3389  
3390 #if(ENC100_INTERFACE_MODE == 0) // SPI
3391 {
3392 BYTE i;
3393  
3394 ReadN(RCR | EIRH, &i, 1); // Read EIR high byte only
3395 i ^= 0x80; // Modify - toggle CRYPTEN
3396 WriteN(WCR | EIRH, &i, 1); // Write EIR high byte only
3397 }
3398 #elif(ENC100_INTERFACE_MODE == 1) || (ENC100_INTERFACE_MODE == 2) || (ENC100_INTERFACE_MODE == 5) || (ENC100_INTERFACE_MODE == 6) // 8-bit PSP modes
3399 {
3400 BYTE i;
3401  
3402 ReadMemory(EIRH, &i, 1); // Read EIR high byte only
3403 i ^= 0x80; // Modify - toggle CRYPTEN
3404 WriteMemory(EIRH, &i, 1); // Write EIR high byte only
3405 }
3406 #else // 16-bit PSP
3407 {
3408 WORD w;
3409  
3410 // Wait for any pending transmit and DMA operations to complete so that
3411 // the interrupt flags get set appropriately
3412 while(ReadReg(ECON1) & (ECON1_DMAST | ECON1_TXRTS));
3413  
3414 // Turn on/off crypto enable
3415 ReadMemory(EIR, (BYTE*)&w, 2); // Read EIR
3416 w ^= EIR_CRYPTEN; // Modify - set CRYPTEN
3417 WriteMemory(EIR, (BYTE*)&w, 2); // Write EIR - has to be 16 bits
3418  
3419 // Regenerate packet counter full interrupt flag, PCFULIF, if it was
3420 // missed (unlikley but possible)
3421 if((ReadReg(ESTAT) & 0xFFu) == 0xFFu)
3422 BFSReg(EIR, EIR_PCFULIF);
3423 }
3424 #endif
3425  
3426 // Generate link change interrupt if the status has changed while we were
3427 // doing the read-modify-write operation (unlikely but possible)
3428 if((ReadReg(ESTAT) ^ wLinkStat) & ESTAT_PHYLNK)
3429 BFSReg(EIR, EIR_LINKIF);
3430  
3431 // Restore interrupts
3432 if(wInterruptEnable & EIE_INTIE)
3433 BFSReg(EIE, EIE_INTIE);
3434 }
3435  
3436  
3437 /****************************************************************************
3438 Section:
3439 Global RSA Variables
3440 ***************************************************************************/
3441 #if defined(STACK_USE_SSL_SERVER) || defined(STACK_USE_SSL_CLIENT)
3442  
3443 static SM_RSA smRSA; // State machine variable
3444 static BYTE keyLength; // Length of the input key
3445 static BYTE* vOutput; // Where output should be stored
3446  
3447 extern ROM BYTE SSL_N[SSL_RSA_KEY_SIZE/8], SSL_D[SSL_RSA_KEY_SIZE/8];
3448  
3449  
3450 /****************************************************************************
3451 Section:
3452 Function Implementations
3453 ***************************************************************************/
3454  
3455 /*****************************************************************************
3456 Function:
3457 void RSAInit(void)
3458  
3459 Deleted Only
3460 ***************************************************************************/
3461 void RSAInit(void)
3462 {
3463 smRSA = SM_RSA_IDLE;
3464 }
3465  
3466 /*****************************************************************************
3467 Function:
3468 BOOL RSABeginUsage(RSA_OP op, BYTE vKeyByteLen)
3469  
3470 Same
3471 ***************************************************************************/
3472 BOOL RSABeginUsage(RSA_OP op, BYTE vKeyByteLen)
3473 {
3474 if(smRSA != SM_RSA_IDLE)
3475 return FALSE;
3476  
3477 keyLength = vKeyByteLen;
3478  
3479 // ENCX24J600 modular exponentiation engine only supports 1024 bit, 768 bit,
3480 // and 512 bit modulos. Other values could cause the incorrect behavior so
3481 // must be avoided.
3482 if(!((keyLength == 1024u/8u) || (keyLength == 768u/8u) || (keyLength == 512u/8u)))
3483 return FALSE;
3484  
3485 // Set up the state machine
3486 if(op == RSA_OP_ENCRYPT)
3487 {
3488 smRSA = SM_RSA_ENCRYPT_START;
3489  
3490 // Turn on Modular Exponentiation hardware engine
3491 if(!(ReadReg(EIR) & EIR_CRYPTEN))
3492 ToggleCRYPTEN();
3493 }
3494 #if defined(STACK_USE_SSL_SERVER) || defined(STACK_USE_RSA_DECRYPT)
3495 else if(op == RSA_OP_DECRYPT)
3496 {
3497 WORD oldPtr;
3498  
3499 smRSA = SM_RSA_DECRYPT_START;
3500  
3501 // Turn on Modular Exponentiation hardware engine
3502 if(!(ReadReg(EIR) & EIR_CRYPTEN))
3503 ToggleCRYPTEN();
3504  
3505 // Copy the decryption key and DMA into palce
3506 oldPtr = MACSetWritePtr(BASE_CRYPTOB_ADDR);
3507 MACPutROMArray(SSL_D, keyLength);
3508 MACMemCopyAsync(ENC100_MODEX_E, BASE_CRYPTOB_ADDR, 128);
3509 while(!MACIsMemCopyDone());
3510  
3511 // Copy the modulus and DMA into palce
3512 MACSetWritePtr(BASE_CRYPTOB_ADDR);
3513 MACPutROMArray(SSL_N, keyLength);
3514 MACMemCopyAsync(ENC100_MODEX_M, BASE_CRYPTOB_ADDR, 128);
3515 while(!MACIsMemCopyDone());
3516  
3517 // Restore the write pointer
3518 MACSetWritePtr(oldPtr);
3519 }
3520 #endif
3521 else
3522 return FALSE;
3523  
3524 return TRUE;
3525 }
3526  
3527 /*****************************************************************************
3528 Function:
3529 void RSAEndUsage(void)
3530  
3531 Same
3532 Need to clear MODEXST to cancel
3533 ***************************************************************************/
3534 void RSAEndUsage(void)
3535 {
3536 smRSA = SM_RSA_IDLE;
3537  
3538 // Turn off Modular Exponentiation hardware engine to save power
3539 if(ReadReg(EIR) & EIR_CRYPTEN)
3540 ToggleCRYPTEN();
3541 }
3542  
3543 /*****************************************************************************
3544 Function:
3545 void RSASetData(BYTE* data, BYTE len, RSA_DATA_FORMAT format)
3546  
3547 Replaced
3548 ***************************************************************************/
3549 void RSASetData(BYTE* data, BYTE len, RSA_DATA_FORMAT format)
3550 {
3551 WORD oldPtr;
3552 BYTE i;
3553  
3554 // Little-endian input is not supported for ENC624 hardware crypto
3555 if(format == RSA_LITTLE_ENDIAN)
3556 while(1);
3557  
3558 // Set the write pointer to reserved crypto area
3559 oldPtr = MACSetWritePtr(BASE_CRYPTOB_ADDR);
3560  
3561 // Pad the input data according to PKCS #1 Block 2 if doing an encryption
3562 // operation
3563 #if defined(STACK_USE_SSL_CLIENT) || defined(STACK_USE_RSA_ENCRYPT)
3564 {
3565 BYTE j;
3566  
3567 if(smRSA == SM_RSA_ENCRYPT_START)
3568 {
3569 if(len < keyLength-4)
3570 {
3571 MACPut(0x00);
3572 MACPut(0x02);
3573 for(i = len + 3; i < keyLength; i++)
3574 {
3575 do
3576 {
3577 j = RandomGet();
3578 } while(j == 0x00u);
3579 MACPut(j);
3580 }
3581 MACPut(0x00);
3582 }
3583 }
3584 }
3585 #endif
3586  
3587 // Left zero-pad the input for decrypt operations
3588 if(smRSA == SM_RSA_DECRYPT_START)
3589 {
3590 for(i = len; i < keyLength; i++)
3591 MACPut(0x00);
3592 }
3593  
3594 // Copy data into ENCX24J600 and DMA into ModEx engine
3595 MACPutArray(data, len);
3596 MACMemCopyAsync(ENC100_MODEX_X, BASE_CRYPTOB_ADDR, 128);
3597  
3598 // Restore the write pointer
3599 MACSetWritePtr(oldPtr);
3600  
3601 // Decrypt operations happen in place
3602 if(smRSA == SM_RSA_DECRYPT_START)
3603 RSASetResult(data, format);
3604  
3605 // Wait for DMA engine to finish copying data into ModEx engine
3606 while(!MACIsMemCopyDone());
3607 }
3608  
3609 /*****************************************************************************
3610 Function:
3611 void RSASetResult(BYTE* data, RSA_DATA_FORMAT format)
3612  
3613 Replaced
3614 ***************************************************************************/
3615 void RSASetResult(BYTE* data, RSA_DATA_FORMAT format)
3616 {
3617 // Little-endian input is not supported for ENC624 hardware crypto
3618 if(format == RSA_LITTLE_ENDIAN)
3619 while(1);
3620  
3621 vOutput = data;
3622 }
3623  
3624 /*****************************************************************************
3625 Function:
3626 void RSASetE(BYTE *data, BYTE len, RSA_DATA_FORMAT format)
3627  
3628 Replace
3629 ***************************************************************************/
3630 #if defined(STACK_USE_RSA_ENCRYPT)
3631 void RSASetE(BYTE* data, BYTE len, RSA_DATA_FORMAT format)
3632 {
3633 WORD oldPtr;
3634 BYTE i;
3635  
3636 // Little-endian input is not supported for ENC624 hardware crypto
3637 if(format == RSA_LITTLE_ENDIAN)
3638 while(1);
3639  
3640 // Set the write pointer to reserved crypto area
3641 oldPtr = MACSetWritePtr(BASE_CRYPTOB_ADDR);
3642  
3643 // Zero-pad the input, copy data, and DMA into palce
3644 for(i = len; i < keyLength; i++)
3645 MACPut(0x00);
3646 MACPutArray(data, len);
3647 MACMemCopyAsync(ENC100_MODEX_E, BASE_CRYPTOB_ADDR, 128);
3648  
3649 // Restore the write pointer
3650 MACSetWritePtr(oldPtr);
3651  
3652 // Wait for DMA copy to ModEx to complete
3653 while(!MACIsMemCopyDone());
3654 }
3655 #endif
3656  
3657 /*****************************************************************************
3658 Function:
3659 void RSASetN(BYTE* data, RSA_DATA_FORMAT format)
3660  
3661 Replace
3662 ***************************************************************************/
3663 #if defined(STACK_USE_RSA_ENCRYPT)
3664 void RSASetN(BYTE* data, RSA_DATA_FORMAT format)
3665 {
3666 WORD oldPtr;
3667  
3668 // Little-endian input is not supported for ENC624 hardware crypto
3669 if(format == RSA_LITTLE_ENDIAN)
3670 while(1);
3671  
3672 // Set the write pointer to reserved crypto area
3673 oldPtr = MACSetWritePtr(BASE_CRYPTOB_ADDR);
3674  
3675 // Copy data and DMA into palce
3676 MACPutArray(data, keyLength);
3677 MACMemCopyAsync(ENC100_MODEX_M, BASE_CRYPTOB_ADDR, 128);
3678  
3679 // Restore the write pointer
3680 MACSetWritePtr(oldPtr);
3681  
3682 // Wait for DMA copy to ModEx to complete
3683 while(!MACIsMemCopyDone());
3684 }
3685 #endif
3686  
3687 /*****************************************************************************
3688 Function:
3689 RSA_STATUS RSAStep(void)
3690  
3691 Replace
3692 ***************************************************************************/
3693 RSA_STATUS RSAStep(void)
3694 {
3695 WORD oldPtr;
3696  
3697 switch(smRSA)
3698 {
3699 case SM_RSA_ENCRYPT_START:
3700 case SM_RSA_DECRYPT_START:
3701 // Set the correct key length
3702 BFCReg(ECON2, ECON2_MODLEN1 | ECON2_MODLEN0);
3703 if(keyLength == 1024u/8u)
3704 BFSReg(ECON2, ECON2_MODLEN1);
3705 if(keyLength == 768u/8u)
3706 BFSReg(ECON2, ECON2_MODLEN0);
3707  
3708 // Start the engine
3709 BFSReg(ECON1, ECON1_MODEXST);
3710  
3711 // Advance state machine to SM_RSA_ENCRYPT. With the ENCX24J600
3712 // Modular Exponentiation engine, the finishing of decryption is
3713 // identical to the finishing of encryption.
3714 smRSA = SM_RSA_ENCRYPT;
3715 break;
3716  
3717 case SM_RSA_ENCRYPT: // Also used to finish decryption
3718 // Check if operation is complete
3719 if(ReadReg(ECON1) & ECON1_MODEXST)
3720 break;
3721  
3722 // Copy the data out
3723 MACMemCopyAsync(BASE_CRYPTOB_ADDR, ENC100_MODEX_Y, 128);
3724 oldPtr = MACSetReadPtr(BASE_CRYPTOB_ADDR);
3725 while(!MACIsMemCopyDone());
3726 MACGetArray(vOutput, keyLength);
3727 MACSetReadPtr(oldPtr);
3728  
3729 // Indicate that we're finished
3730 smRSA = SM_RSA_DONE;
3731 return RSA_DONE;
3732  
3733 default:
3734 // Unknown state
3735 return RSA_DONE;
3736 }
3737  
3738 // Indicate that we're still working
3739 return RSA_WORKING;
3740  
3741 }
3742  
3743  
3744 /****************************************************************************
3745 Section:
3746 Fundamental RSA Operations
3747 ***************************************************************************/
3748  
3749 /*****************************************************************************
3750 Function:
3751 static BOOL _RSAModExpROM(BIGINT* y, BIGINT* x, BIGINT_ROM* e,
3752 BIGINT_ROM* n)
3753  
3754 Not Needed
3755 ***************************************************************************/
3756  
3757 /*****************************************************************************
3758 Function:
3759 static BOOL _RSAModExp(BIGINT* y, BIGINT* x, BIGINT* e, BIGINT* n)
3760  
3761 Not Needed
3762 ***************************************************************************/
3763  
3764 #endif
3765  
3766  
3767  
3768 /* // A function potentially useful for debugging, but a waste of code otherwise
3769 void ENC100DumpState(void)
3770 {
3771 WORD w;
3772 BYTE a[32];
3773 BYTE i;
3774  
3775 printf("\r\n Current Packet Address = 0x%04hX", wCurrentPacketPointer);
3776 printf("\r\n EIR = 0x%04hX", ReadReg(EIR));
3777 printf("\r\n ERXST = 0x%04hX", ReadReg(ERXST));
3778 printf("\r\n EUDAST = 0x%04hX", ReadReg(EUDAST));
3779 printf("\r\n EUDAND = 0x%04hX", ReadReg(EUDAND));
3780 printf("\r\n ERXTAIL = 0x%04hX", ReadReg(ERXTAIL));
3781 printf("\r\n ERXHEAD = 0x%04hX", ReadReg(ERXHEAD));
3782 w = ReadReg(ESTAT);
3783 printf("\r\n ESTAT = 0x%04hX (Packet Count = %hhu)", w, (BYTE)w);
3784 printf("\r\n ERXFCON = 0x%04hX", ReadReg(ERXFCON));
3785 printf("\r\n MACON1 = 0x%04hX", ReadReg(MACON1));
3786 printf("\r\n MACON2 = 0x%04hX", ReadReg(MACON2));
3787 printf("\r\n ECON1 = 0x%04hX", ReadReg(ECON1));
3788 printf("\r\n ECON2 = 0x%04hX", ReadReg(ECON2));
3789 printf("\r\n ETXST = 0x%04hX", ReadReg(ETXST));
3790 printf("\r\n ETXLEN = 0x%04hX", ReadReg(ETXLEN));
3791 printf("\r\n EDMAST = 0x%04hX", ReadReg(EDMAST));
3792 printf("\r\n EDMALEN = 0x%04hX", ReadReg(EDMALEN));
3793 printf("\r\n EDMADST = 0x%04hX", ReadReg(EDMADST));
3794 printf("\r\n EDMACS = 0x%04hX", ReadReg(EDMACS));
3795  
3796 for(w = 0; w < ENC100_RAM_SIZE; w += 16)
3797 {
3798 ReadMemory(w, a, 16);
3799  
3800 for(i = 0; i < 16u; i++)
3801 {
3802 if((a[i] >= 0x20) && (a[i] <= 0x7E))
3803 a[i+16] = a[i];
3804 else
3805 a[i+16] = '.';
3806 }
3807  
3808 printf("\r\n%04hx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %hhc%hhc%hhc%hhc%hhc%hhc%hhc%hhc %hhc%hhc%hhc%hhc%hhc%hhc%hhc%hhc", w, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], a[16], a[17], a[18], a[19], a[20], a[21], a[22], a[23], a[24], a[25], a[26], a[27], a[28], a[29], a[30], a[31]);
3809 }
3810 printf("\r\n\r\n");
3811 }
3812 */
3813  
3814 #endif //#if defined(ENC100_INTERFACE_MODE)
{BLAME END}
{FOOTER START}

Powered by WebSVN v2.8.3