/[H8]/trunk/docs/MCHPStack2.20/Source/Mac.c
ViewVC logotype

Annotation of /trunk/docs/MCHPStack2.20/Source/Mac.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 62 - (hide annotations) (download)
Tue May 1 08:17:39 2007 UTC (17 years, 1 month ago) by hedin
File MIME type: text/plain
File size: 16008 byte(s)
Removed tcpip stack 4.02 and added tcpip stack 2.20.
1 hedin 62 /*********************************************************************
2     *
3     * MAC Module for Microchip TCP/IP Stack
4     *
5     *********************************************************************
6     * FileName: MAC.c
7     * Dependencies: string.h
8     * stacktsk.h
9     * helpers.h
10     * mac.h
11     * Processor: PIC18
12     * Complier: MCC18 v1.00.50 or higher
13     * HITECH PICC-18 V8.10PL1 or higher
14     * Company: Microchip Technology, Inc.
15     *
16     * Software License Agreement
17     *
18     * The software supplied herewith by Microchip Technology Incorporated
19     * (the “Company”) for its PICmicro® Microcontroller is intended and
20     * supplied to you, the Company’s customer, for use solely and
21     * exclusively on Microchip PICmicro Microcontroller products. The
22     * software is owned by the Company and/or its supplier, and is
23     * protected under applicable copyright laws. All rights are reserved.
24     * Any use in violation of the foregoing restrictions may subject the
25     * user to criminal sanctions under applicable laws, as well as to
26     * civil liability for the breach of the terms and conditions of this
27     * license.
28     *
29     * THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
30     * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
31     * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
32     * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
33     * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
34     * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
35     *
36     *
37     * HiTech PICC18 Compiler Options excluding device selection:
38     * -FAKELOCAL -G -O -Zg -E -C
39     *
40     *
41     *
42     *
43     * Author Date Comment
44     *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
45     * Nilesh Rajbharti 4/27/00 Original (Rev 1.0)
46     * Nilesh Rajbharti 2/9/02 Cleanup
47     * Nilesh Rajbharti 5/22/02 Rev 2.0 (See version.log for detail)
48     * Nilesh Rajbharti 3/21/03 Fixed MACIsTxReady() bug where upon
49     * certain bus collision, this would always
50     * return FLASE causing Stack to not handle
51     * any incoming packets at all.
52     ********************************************************************/
53     #define THIS_IS_MAC_LAYER
54    
55     #include <string.h>
56     #include "stacktsk.h"
57     #include "helpers.h"
58     #include "mac.h"
59     #include "delay.h"
60    
61    
62     #if defined(STACK_USE_SLIP)
63     #error Unexpected module is detected.
64     #error This file must be linked when SLIP module is not in use.
65     #endif
66    
67    
68     /*
69     * Hardware interface to NIC.
70     */
71     #define NIC_CTRL_TRIS (TRISE)
72     #define NIC_RESET_IO (PORTE_RE2)
73     #define NIC_IOW_IO (PORTE_RE1)
74     #define NIC_IOR_IO (PORTE_RE0)
75     #define NIC_ADDR_IO (PORTB)
76     #define NIC_DATA_IO (PORTD)
77    
78     #define NIC_DATAPORT (0x10)
79     #define NIC_RESET (0x1f)
80    
81     /* Ethernet definitions.. */
82     #define MINFRAME 60
83     #define MINFRAMEC 64
84     #define CRCLEN 4
85     #define MAXFRAME 1514
86     #define MAXFRAMEC 1518
87    
88     /* 8390 Network Interface Controller (NIC) page0 register offsets */
89     #define CMDR 0x00 /* command register for read & write */
90     #define PSTART 0x01 /* page start register for write */
91     #define PSTOP 0x02 /* page stop register for write */
92     #define BNRY 0x03 /* boundary reg for rd and wr */
93     #define TPSR 0x04 /* tx start page start reg for wr */
94     #define TXSTAT TPSR
95     #define TBCR0 0x05 /* tx byte count 0 reg for wr */
96     #define TBCR1 0x06 /* tx byte count 1 reg for wr */
97     #define ISR 0x07 /* interrupt status reg for rd and wr */
98     #define RSAR0 0x08 /* low byte of remote start addr */
99     #define RSAR1 0x09 /* hi byte of remote start addr */
100     #define RBCR0 0x0A /* remote byte count reg 0 for wr */
101     #define RBCR1 0x0B /* remote byte count reg 1 for wr */
102     #define RCR 0x0C /* rx configuration reg for wr */
103     #define TCR 0x0D /* tx configuration reg for wr */
104     #define DCR 0x0E /* data configuration reg for wr */
105     #define IMR 0x0F /* interrupt mask reg for wr */
106    
107     /* NIC page 1 register offsets */
108     #define PAR0 0x01 /* physical addr reg 0 for rd and wr */
109     #define CURRP 0x07 /* current page reg for rd and wr */
110     #define MAR0 0x08 /* multicast addr reg 0 for rd and WR */
111    
112     /* NIC page 3 register offsets */
113     #define RTL9346CR 0x01 /* RTL 9346 command reg */
114     #define RTL3 0x06 /* RTL config reg 3 */
115    
116    
117     #define NIC_PAGE_SIZE (256)
118    
119     /* NIC RAM definitions */
120     #define RAMPAGES 0x20 /* Total number of 256-byte RAM pages */
121     #define TXSTART 0x40 /* Tx buffer start page - NE2000 mode */
122     #define TXPAGES (MAC_TX_BUFFER_COUNT * (MAC_TX_BUFFER_SIZE/NIC_PAGE_SIZE))
123     #define RXSTART (TXSTART+TXPAGES) /* Rx buffer start page */
124     #define RXSTOP (TXSTART+RAMPAGES-1) /* Last Rx buffer page */
125     #define DCRVAL 0x48 /* Value for data config reg */
126     /* 8-bit DMA, big-endian, 1 DMA, Normal */
127    
128     #define RXPAGES (RXSTOP - RXSTART)
129    
130    
131     #define SET_NIC_READ() (TRISD = 0xff)
132     #define SET_NIC_WRITE() (TRISD = 0x00)
133    
134     #define WRITE_NIC_ADDR(a) NIC_ADDR_IO = a; \
135     TRISB = 0xe0
136    
137     typedef struct _IEEE_HEADER
138     {
139     MAC_ADDR DestMACAddr;
140     MAC_ADDR SourceMACAddr;
141     WORD_VAL Len;
142     BYTE LSAPControl[3];
143     BYTE OUI[3];
144     WORD_VAL Protocol;
145     } IEEE_HEADER;
146    
147     #define ETHER_IP (0x00)
148     #define ETHER_ARP (0x06)
149    
150    
151     typedef struct _DATA_BUFFER
152     {
153     BYTE Index;
154     BOOL bFree;
155     } DATA_BUFFER;
156    
157    
158    
159     static DATA_BUFFER TxBuffers[(TXPAGES*NIC_PAGE_SIZE)/MAC_TX_BUFFER_SIZE];
160     #define MAX_DATA_BUFFERS (sizeof(TxBuffers)/sizeof(TxBuffers[0]))
161    
162     typedef struct _ETHER_HEADER
163     {
164     MAC_ADDR DestMACAddr;
165     MAC_ADDR SourceMACAddr;
166     WORD_VAL Type;
167     } ETHER_HEADER;
168    
169    
170     typedef struct _NE_RCR
171     {
172     unsigned int PRX:1;
173     unsigned int CRC:1;
174     unsigned int FAE:1;
175     unsigned int FO:1;
176     unsigned int MPA:1;
177     unsigned int PHY:1;
178     unsigned int DIS:1;
179     unsigned int DFR:1;
180     } NE_RCR;
181    
182    
183    
184     typedef struct _NE_PREAMBLE
185     {
186     NE_RCR Status;
187     BYTE NextPacketPointer;
188     WORD ReceivedBytes;
189    
190     MAC_ADDR DestMACAddr;
191     MAC_ADDR SourceMACAddr;
192     WORD_VAL Type;
193     } NE_PREAMBLE;
194    
195    
196     BYTE NICReadPtr; // Next page that will be used by NIC to load new packet.
197     BYTE NICCurrentRdPtr; // Page that is being read...
198     BYTE NICCurrentTxBuffer;
199    
200    
201     static void NICReset(void);
202     static void NICPut(BYTE reg, BYTE val);
203     static BYTE NICGet(BYTE reg);
204     static void NICSetAddr(WORD addr);
205     static void Delay(BYTE val);
206    
207    
208    
209     void MACInit(void)
210     {
211     BYTE i;
212    
213     // On Init, all transmit buffers are free.
214     for ( i = 0; i < MAX_DATA_BUFFERS; i++ )
215     {
216     TxBuffers[i].Index = TXSTART + (i * (MAC_TX_BUFFER_SIZE/NIC_PAGE_SIZE));
217     TxBuffers[i].bFree = TRUE;
218     }
219     NICCurrentTxBuffer = 0;
220    
221     NICReset();
222     DelayMs(2);
223     NICPut(NIC_RESET, NICGet(NIC_RESET));
224     // mimimum Delay of 1.6 ms
225     DelayMs(2);
226    
227     // Continue only if reset state is entered.
228     if ( (NICGet(ISR) & 0x80) != 0 )
229     {
230     // Select Page 0
231     NICPut(CMDR, 0x21);
232     DelayMs(2);
233    
234     // Initialize Data Configuration Register
235     NICPut(DCR, DCRVAL);
236    
237     // Clear Remote Byte Count Registers
238     NICPut(RBCR0, 0);
239     NICPut(RBCR1, 0);
240    
241     // Initialize Receive Configuration Register
242     NICPut(RCR, 0x04);
243    
244     // Place NIC in LOOPBACK mode 1
245     NICPut(TCR, 0x02);
246    
247     // Initialize Transmit buffer queue
248     NICPut(TPSR, TxBuffers[NICCurrentTxBuffer].Index);
249    
250     // Initialize Receive Buffer Ring
251     NICPut(PSTART, RXSTART);
252     NICPut(PSTOP, RXSTOP);
253     NICPut(BNRY, (BYTE)(RXSTOP-1));
254    
255     // Initialize Interrupt Mask Register
256     // Clear all status bits
257     NICPut(ISR, 0xff);
258     // No interrupt enabled.
259     NICPut(IMR, 0x00);
260    
261     // Select Page 1
262     NICPut(CMDR, 0x61);
263    
264     // Initialize Physical Address Registers
265     NICPut(PAR0, MY_MAC_BYTE1);
266     NICPut(PAR0+1, MY_MAC_BYTE2);
267     NICPut(PAR0+2, MY_MAC_BYTE3);
268     NICPut(PAR0+3, MY_MAC_BYTE4);
269     NICPut(PAR0+4, MY_MAC_BYTE5);
270     NICPut(PAR0+5, MY_MAC_BYTE6);
271    
272     // Initialize Multicast registers
273     for ( i = 0; i < 8; i++ )
274     NICPut(MAR0+i, 0xff);
275    
276     // Initialize CURRent pointer
277     NICPut(CURRP, RXSTART);
278    
279     // Remember current receive page
280     NICReadPtr = RXSTART;
281    
282     // Page 0, Abort Remote DMA and Activate the transmitter.
283     NICPut(CMDR, 0x22);
284    
285     // Set Normal Mode
286     NICPut(TCR, 0x00);
287    
288     }
289    
290     }
291    
292    
293    
294     BOOL MACIsTxReady(void)
295     {
296     // NICCurrentTxBuffer always points to free buffer, if there is any.
297     // If there is none, NICCurrentTxBuffer will be a in 'Use' state.
298     //return TxBuffers[NICCurrentTxBuffer].bFree;
299     // Check to see if previous transmission was successful or not.
300     return !(NICGet(CMDR) & 0x04);
301     }
302    
303    
304     void MACPut(BYTE val)
305     {
306     NICPut(RBCR0, 1);
307     NICPut(RBCR1, 0);
308     NICPut(CMDR, 0x12);
309     NICPut(NIC_DATAPORT, val);
310     }
311    
312    
313     void MACPutArray(BYTE *val, WORD len)
314     {
315     WORD_VAL t;
316    
317     t.Val = len + (len & 1);
318    
319     NICPut(ISR, 0x40);
320     NICPut(RBCR0, t.v[0]);
321     NICPut(RBCR1, t.v[1]);
322     NICPut(CMDR, 0x12);
323    
324     while ( len-- > 0 )
325     NICPut(NIC_DATAPORT, *val++);
326    
327     // Make sure that DMA is complete.
328     len = 255;
329     while( len && (NICGet(ISR) & 0x40) == 0 )
330     len--;
331    
332     }
333    
334    
335     BYTE MACGet(void)
336     {
337     NICPut(RBCR0, 1);
338     NICPut(RBCR1, 0);
339     NICPut(CMDR, 0x0a);
340     return NICGet(NIC_DATAPORT);
341     }
342    
343    
344     WORD MACGetArray(BYTE *val, WORD len)
345     {
346     WORD_VAL t;
347    
348     t.Val = len;
349    
350     NICPut(ISR, 0x40);
351     NICPut(RBCR0, t.v[0]);
352     NICPut(RBCR1, t.v[1]);
353     NICPut(CMDR, 0x0a);
354    
355     while( len-- > 0 )
356     {
357     *val++ = NICGet(NIC_DATAPORT);
358     }
359    
360     return t.Val;
361     }
362    
363     void MACReserveTxBuffer(BUFFER buffer)
364     {
365     TxBuffers[buffer].bFree = FALSE;
366     }
367    
368    
369     void MACDiscardTx(BUFFER buffer)
370     {
371     TxBuffers[buffer].bFree = TRUE;
372     NICCurrentTxBuffer = buffer;
373     }
374    
375     void MACDiscardRx(void)
376     {
377     BYTE newBoundary;
378    
379     newBoundary = NICReadPtr - 1;
380     if ( newBoundary < RXSTART )
381     newBoundary = RXSTOP - 1;
382     NICPut(CMDR, 0x20); // Select PAGE 0
383     NICPut(BNRY, newBoundary);
384     return;
385     }
386    
387    
388     WORD MACGetFreeRxSize(void)
389     {
390     BYTE NICWritePtr;
391     BYTE temp;
392     WORD_VAL tempVal;
393    
394     NICPut(CMDR, 0x60);
395     NICWritePtr = NICGet(CURRP);
396     NICPut(CMDR, 0x20);
397    
398     if ( NICWritePtr < NICCurrentRdPtr )
399     temp = (RXSTOP - NICCurrentRdPtr) + NICWritePtr;
400     else
401     temp = NICWritePtr - NICCurrentRdPtr;
402    
403     temp = RXPAGES - temp;
404     tempVal.v[1] = temp;
405     tempVal.v[0] = 0;
406     return tempVal.Val;
407     }
408    
409    
410     BOOL MACIsLinked(void)
411     {
412     BYTE_VAL temp;
413    
414     // Select Page 3
415     NICPut(CMDR, 0xe0);
416    
417     // Read CONFIG0.
418     temp.Val = NICGet(0x03);
419    
420     // Reset to page 0.
421     NICPut(CMDR, 0x20);
422    
423     // Bit 2 "BNC" will be '0' if LINK is established.
424     return (temp.bits.b2 == 0);
425     }
426    
427     BOOL MACGetHeader(MAC_ADDR *remote, BYTE* type)
428     {
429     NE_PREAMBLE header;
430     BYTE NICWritePtr;
431     WORD_VAL temp;
432    
433    
434     *type = MAC_UNKNOWN;
435    
436     // Reset NIC if overrun has occured.
437     if ( NICGet(ISR) & 0x10 )
438     {
439     #if 1
440     NICPut(CMDR, 0x21);
441     Delay(0xff);
442     NICPut(RBCR0, 0);
443     NICPut(RBCR1, 0);
444     NICPut(TCR, 0x02);
445     NICPut(CMDR, 0x20);
446     MACDiscardRx();
447     NICPut(ISR, 0xff);
448     NICPut(TCR, 0x00);
449     return FALSE;
450     #else
451     MACInit();
452     return FALSE;
453     #endif
454     }
455    
456     NICPut(CMDR, 0x60);
457     NICWritePtr = NICGet(CURRP);
458     NICPut(CMDR, 0x20);
459    
460     if ( NICWritePtr != NICReadPtr )
461     {
462     temp.v[1] = NICReadPtr;
463     temp.v[0] = 0;
464     NICSetAddr(temp.Val);
465    
466     MACGetArray((BYTE*)&header, sizeof(header));
467    
468     // Validate packet length and status.
469     if ( header.Status.PRX && (header.ReceivedBytes >= MINFRAMEC) && (header.ReceivedBytes <= MAXFRAMEC) )
470     {
471     header.Type.Val = swaps(header.Type.Val);
472    
473     memcpy((void*)remote->v, (void*)header.SourceMACAddr.v, sizeof(*remote));
474    
475     if ( (header.Type.v[1] == 0x08) && ((header.Type.v[0] == ETHER_IP) || (header.Type.v[0] == ETHER_ARP)) )
476     *type = header.Type.v[0];
477    
478     }
479    
480     NICCurrentRdPtr = NICReadPtr;
481     NICReadPtr = header.NextPacketPointer;
482    
483     return TRUE;
484     }
485     return FALSE;
486    
487     }
488    
489    
490    
491     void MACPutHeader(MAC_ADDR *remote,
492     BYTE type,
493     WORD dataLen)
494     {
495     WORD_VAL mytemp;
496     BYTE etherType;
497    
498     NICPut(ISR, 0x0a);
499    
500     mytemp.v[1] = TxBuffers[NICCurrentTxBuffer].Index;
501     mytemp.v[0] = 0;
502    
503     NICSetAddr(mytemp.Val);
504    
505     MACPutArray((BYTE*)remote, sizeof(*remote));
506    
507     MACPut(MY_MAC_BYTE1);
508     MACPut(MY_MAC_BYTE2);
509     MACPut(MY_MAC_BYTE3);
510     MACPut(MY_MAC_BYTE4);
511     MACPut(MY_MAC_BYTE5);
512     MACPut(MY_MAC_BYTE6);
513    
514     if ( type == MAC_IP )
515     etherType = ETHER_IP;
516     else
517     etherType = ETHER_ARP;
518    
519     MACPut(0x08);
520     MACPut(etherType);
521    
522     dataLen += (WORD)sizeof(ETHER_HEADER);
523     if ( dataLen < MINFRAME ) // 64 ) // NKR 4/23/02
524     dataLen = 64; // MINFRAME;
525     mytemp.Val = dataLen;
526    
527     NICPut(TBCR0, mytemp.v[0]);
528     NICPut(TBCR1, mytemp.v[1]);
529    
530     }
531    
532     void MACFlush(void)
533     {
534     BYTE i;
535    
536     NICPut(TPSR, TxBuffers[NICCurrentTxBuffer].Index);
537    
538     NICPut(CMDR, 0x24);
539    
540     // After every transmission, adjust transmit pointer to
541     // next free transmit buffer.
542     for ( i = 0; i < MAX_DATA_BUFFERS; i++ )
543     {
544     if ( TxBuffers[i].bFree )
545     {
546     NICCurrentTxBuffer = i;
547     return;
548     }
549     }
550     }
551    
552     static void NICReset(void)
553     {
554     SET_NIC_READ();
555     WRITE_NIC_ADDR(0);
556     INTCON2_RBPU = 0;
557    
558     NIC_IOW_IO = 1;
559     NIC_IOR_IO = 1;
560     NIC_RESET_IO = 1;
561     NIC_CTRL_TRIS = 0x00;
562    
563     // Reset pulse must be at least 800 ns.
564     Delay10us(1);
565    
566     NIC_RESET_IO = 0;
567     }
568    
569     static void NICPut(BYTE reg, BYTE val)
570     {
571     WRITE_NIC_ADDR(reg);
572     NIC_DATA_IO = val;
573     SET_NIC_WRITE();
574     NIC_IOW_IO = 0;
575     NIC_IOW_IO = 1;
576     SET_NIC_READ();
577     }
578    
579     static BYTE NICGet(BYTE reg)
580     {
581     BYTE val;
582    
583     SET_NIC_READ();
584     WRITE_NIC_ADDR(reg);
585     NIC_IOR_IO = 0;
586     val = NIC_DATA_IO;
587     NIC_IOR_IO = 1;
588     return val;
589     }
590    
591    
592     static void NICSetAddr(WORD addr)
593     {
594     WORD_VAL t;
595    
596     t.Val = addr;
597     NICPut(ISR, 0x40);
598     NICPut(RSAR0, t.v[0]);
599     NICPut(RSAR1, t.v[1]);
600     }
601    
602     static void Delay(BYTE val)
603     {
604     WORD_VAL t;
605    
606     t.v[1] = val;
607     t.v[0] = 0;
608    
609     while( t.Val-- > 0);
610     }
611    
612     void MACSetRxBuffer(WORD offset)
613     {
614     WORD_VAL t;
615    
616     t.v[1] = NICCurrentRdPtr;
617     t.v[0] = sizeof(NE_PREAMBLE);
618    
619     t.Val += offset;
620    
621     NICSetAddr(t.Val);
622     }
623    
624     void MACSetTxBuffer(BUFFER buffer, WORD offset)
625     {
626     WORD_VAL t;
627    
628     NICCurrentTxBuffer = buffer;
629     t.v[1] = TxBuffers[NICCurrentTxBuffer].Index;
630     t.v[0] = sizeof(ETHER_HEADER);
631    
632     t.Val += offset;
633    
634     NICSetAddr(t.Val);
635     }
636    
637     WORD MACGetOffset(void)
638     {
639     WORD_VAL t;
640    
641     t.v[1] = NICGet(RSAR1);
642     t.v[0] = NICGet(RSAR0);
643    
644     return t.Val;
645     }
646    

  ViewVC Help
Powered by ViewVC 1.1.20