/[H8]/trunk/PIC/TCP-IP stack/Mac.c
ViewVC logotype

Contents of /trunk/PIC/TCP-IP stack/Mac.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 54 - (show annotations) (download)
Fri Apr 27 08:42:17 2007 UTC (17 years ago) by hedin
File MIME type: text/plain
File size: 16008 byte(s)
Added basic project
1 /*********************************************************************
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