|
|
1.1 root 1: /**************************************************************************
2: * ns83820.c: Etherboot device driver for the National Semiconductor 83820
3: * Written 2004 by Timothy Legge <[email protected]>
4: *
5: * This program is free software; you can redistribute it and/or modify
6: * it under the terms of the GNU General Public License as published by
7: * the Free Software Foundation; either version 2 of the License, or
8: * (at your option) any later version.
9: *
10: * This program is distributed in the hope that it will be useful,
11: * but WITHOUT ANY WARRANTY; without even the implied warranty of
12: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13: * GNU General Public License for more details.
14: *
15: * You should have received a copy of the GNU General Public License
16: * along with this program; if not, write to the Free Software
17: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18: *
19: * Portions of this code based on:
20: * ns83820.c by Benjamin LaHaise with contributions
21: * for Linux kernel 2.4.x.
22: *
23: * Linux Driver Version 0.20, 20020610
24: *
25: * This development of this Etherboot driver was funded by:
26: *
27: * NXTV: http://www.nxtv.com/
28: *
29: * REVISION HISTORY:
30: * ================
31: *
32: * v1.0 02-16-2004 timlegge Initial port of Linux driver
33: * v1.1 02-19-2004 timlegge More rohbust transmit and poll
34: *
35: * Indent Options: indent -kr -i8
36: ***************************************************************************/
37:
38: FILE_LICENCE ( GPL2_OR_LATER );
39:
40: /* to get some global routines like printf */
41: #include "etherboot.h"
42: /* to get the interface to the body of the program */
43: #include "nic.h"
44: /* to get the PCI support functions, if this is a PCI NIC */
45: #include <ipxe/pci.h>
46:
47: #if ARCH == ia64 /* Support 64-bit addressing */
48: #define USE_64BIT_ADDR
49: #endif
50:
51: #define HZ 100
52:
53: /* Condensed operations for readability. */
54: #define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr))
55: #define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr))
56:
57: /* NIC specific static variables go here */
58:
59: /* Global parameters. See MODULE_PARM near the bottom. */
60: // static int ihr = 2;
61: static int reset_phy = 0;
62: static int lnksts = 0; /* CFG_LNKSTS bit polarity */
63:
64: #if defined(CONFIG_HIGHMEM64G) || defined(__ia64__)
65: #define USE_64BIT_ADDR "+"
66: #endif
67:
68: #if defined(USE_64BIT_ADDR)
69: #define TRY_DAC 1
70: #else
71: #define TRY_DAC 0
72: #endif
73:
74: /* tunables */
75: #define RX_BUF_SIZE 1500 /* 8192 */
76:
77: /* Must not exceed ~65000. */
78: #define NR_RX_DESC 64
79: #define NR_TX_DESC 1
80:
81: /* not tunable *//* Extra 6 bytes for 64 bit alignment (divisable by 8) */
82: #define REAL_RX_BUF_SIZE (RX_BUF_SIZE + 14 + 6) /* rx/tx mac addr + type */
83:
84: #define MIN_TX_DESC_FREE 8
85:
86: /* register defines */
87: #define CFGCS 0x04
88:
89: #define CR_TXE 0x00000001
90: #define CR_TXD 0x00000002
91: /* Ramit : Here's a tip, don't do a RXD immediately followed by an RXE
92: * The Receive engine skips one descriptor and moves
93: * onto the next one!! */
94: #define CR_RXE 0x00000004
95: #define CR_RXD 0x00000008
96: #define CR_TXR 0x00000010
97: #define CR_RXR 0x00000020
98: #define CR_SWI 0x00000080
99: #define CR_RST 0x00000100
100:
101: #define PTSCR_EEBIST_FAIL 0x00000001
102: #define PTSCR_EEBIST_EN 0x00000002
103: #define PTSCR_EELOAD_EN 0x00000004
104: #define PTSCR_RBIST_FAIL 0x000001b8
105: #define PTSCR_RBIST_DONE 0x00000200
106: #define PTSCR_RBIST_EN 0x00000400
107: #define PTSCR_RBIST_RST 0x00002000
108:
109: #define MEAR_EEDI 0x00000001
110: #define MEAR_EEDO 0x00000002
111: #define MEAR_EECLK 0x00000004
112: #define MEAR_EESEL 0x00000008
113: #define MEAR_MDIO 0x00000010
114: #define MEAR_MDDIR 0x00000020
115: #define MEAR_MDC 0x00000040
116:
117: #define ISR_TXDESC3 0x40000000
118: #define ISR_TXDESC2 0x20000000
119: #define ISR_TXDESC1 0x10000000
120: #define ISR_TXDESC0 0x08000000
121: #define ISR_RXDESC3 0x04000000
122: #define ISR_RXDESC2 0x02000000
123: #define ISR_RXDESC1 0x01000000
124: #define ISR_RXDESC0 0x00800000
125: #define ISR_TXRCMP 0x00400000
126: #define ISR_RXRCMP 0x00200000
127: #define ISR_DPERR 0x00100000
128: #define ISR_SSERR 0x00080000
129: #define ISR_RMABT 0x00040000
130: #define ISR_RTABT 0x00020000
131: #define ISR_RXSOVR 0x00010000
132: #define ISR_HIBINT 0x00008000
133: #define ISR_PHY 0x00004000
134: #define ISR_PME 0x00002000
135: #define ISR_SWI 0x00001000
136: #define ISR_MIB 0x00000800
137: #define ISR_TXURN 0x00000400
138: #define ISR_TXIDLE 0x00000200
139: #define ISR_TXERR 0x00000100
140: #define ISR_TXDESC 0x00000080
141: #define ISR_TXOK 0x00000040
142: #define ISR_RXORN 0x00000020
143: #define ISR_RXIDLE 0x00000010
144: #define ISR_RXEARLY 0x00000008
145: #define ISR_RXERR 0x00000004
146: #define ISR_RXDESC 0x00000002
147: #define ISR_RXOK 0x00000001
148:
149: #define TXCFG_CSI 0x80000000
150: #define TXCFG_HBI 0x40000000
151: #define TXCFG_MLB 0x20000000
152: #define TXCFG_ATP 0x10000000
153: #define TXCFG_ECRETRY 0x00800000
154: #define TXCFG_BRST_DIS 0x00080000
155: #define TXCFG_MXDMA1024 0x00000000
156: #define TXCFG_MXDMA512 0x00700000
157: #define TXCFG_MXDMA256 0x00600000
158: #define TXCFG_MXDMA128 0x00500000
159: #define TXCFG_MXDMA64 0x00400000
160: #define TXCFG_MXDMA32 0x00300000
161: #define TXCFG_MXDMA16 0x00200000
162: #define TXCFG_MXDMA8 0x00100000
163:
164: #define CFG_LNKSTS 0x80000000
165: #define CFG_SPDSTS 0x60000000
166: #define CFG_SPDSTS1 0x40000000
167: #define CFG_SPDSTS0 0x20000000
168: #define CFG_DUPSTS 0x10000000
169: #define CFG_TBI_EN 0x01000000
170: #define CFG_MODE_1000 0x00400000
171: /* Ramit : Dont' ever use AUTO_1000, it never works and is buggy.
172: * Read the Phy response and then configure the MAC accordingly */
173: #define CFG_AUTO_1000 0x00200000
174: #define CFG_PINT_CTL 0x001c0000
175: #define CFG_PINT_DUPSTS 0x00100000
176: #define CFG_PINT_LNKSTS 0x00080000
177: #define CFG_PINT_SPDSTS 0x00040000
178: #define CFG_TMRTEST 0x00020000
179: #define CFG_MRM_DIS 0x00010000
180: #define CFG_MWI_DIS 0x00008000
181: #define CFG_T64ADDR 0x00004000
182: #define CFG_PCI64_DET 0x00002000
183: #define CFG_DATA64_EN 0x00001000
184: #define CFG_M64ADDR 0x00000800
185: #define CFG_PHY_RST 0x00000400
186: #define CFG_PHY_DIS 0x00000200
187: #define CFG_EXTSTS_EN 0x00000100
188: #define CFG_REQALG 0x00000080
189: #define CFG_SB 0x00000040
190: #define CFG_POW 0x00000020
191: #define CFG_EXD 0x00000010
192: #define CFG_PESEL 0x00000008
193: #define CFG_BROM_DIS 0x00000004
194: #define CFG_EXT_125 0x00000002
195: #define CFG_BEM 0x00000001
196:
197: #define EXTSTS_UDPPKT 0x00200000
198: #define EXTSTS_TCPPKT 0x00080000
199: #define EXTSTS_IPPKT 0x00020000
200:
201: #define SPDSTS_POLARITY (CFG_SPDSTS1 | CFG_SPDSTS0 | CFG_DUPSTS | (lnksts ? CFG_LNKSTS : 0))
202:
203: #define MIBC_MIBS 0x00000008
204: #define MIBC_ACLR 0x00000004
205: #define MIBC_FRZ 0x00000002
206: #define MIBC_WRN 0x00000001
207:
208: #define PCR_PSEN (1 << 31)
209: #define PCR_PS_MCAST (1 << 30)
210: #define PCR_PS_DA (1 << 29)
211: #define PCR_STHI_8 (3 << 23)
212: #define PCR_STLO_4 (1 << 23)
213: #define PCR_FFHI_8K (3 << 21)
214: #define PCR_FFLO_4K (1 << 21)
215: #define PCR_PAUSE_CNT 0xFFFE
216:
217: #define RXCFG_AEP 0x80000000
218: #define RXCFG_ARP 0x40000000
219: #define RXCFG_STRIPCRC 0x20000000
220: #define RXCFG_RX_FD 0x10000000
221: #define RXCFG_ALP 0x08000000
222: #define RXCFG_AIRL 0x04000000
223: #define RXCFG_MXDMA512 0x00700000
224: #define RXCFG_DRTH 0x0000003e
225: #define RXCFG_DRTH0 0x00000002
226:
227: #define RFCR_RFEN 0x80000000
228: #define RFCR_AAB 0x40000000
229: #define RFCR_AAM 0x20000000
230: #define RFCR_AAU 0x10000000
231: #define RFCR_APM 0x08000000
232: #define RFCR_APAT 0x07800000
233: #define RFCR_APAT3 0x04000000
234: #define RFCR_APAT2 0x02000000
235: #define RFCR_APAT1 0x01000000
236: #define RFCR_APAT0 0x00800000
237: #define RFCR_AARP 0x00400000
238: #define RFCR_MHEN 0x00200000
239: #define RFCR_UHEN 0x00100000
240: #define RFCR_ULM 0x00080000
241:
242: #define VRCR_RUDPE 0x00000080
243: #define VRCR_RTCPE 0x00000040
244: #define VRCR_RIPE 0x00000020
245: #define VRCR_IPEN 0x00000010
246: #define VRCR_DUTF 0x00000008
247: #define VRCR_DVTF 0x00000004
248: #define VRCR_VTREN 0x00000002
249: #define VRCR_VTDEN 0x00000001
250:
251: #define VTCR_PPCHK 0x00000008
252: #define VTCR_GCHK 0x00000004
253: #define VTCR_VPPTI 0x00000002
254: #define VTCR_VGTI 0x00000001
255:
256: #define CR 0x00
257: #define CFG 0x04
258: #define MEAR 0x08
259: #define PTSCR 0x0c
260: #define ISR 0x10
261: #define IMR 0x14
262: #define IER 0x18
263: #define IHR 0x1c
264: #define TXDP 0x20
265: #define TXDP_HI 0x24
266: #define TXCFG 0x28
267: #define GPIOR 0x2c
268: #define RXDP 0x30
269: #define RXDP_HI 0x34
270: #define RXCFG 0x38
271: #define PQCR 0x3c
272: #define WCSR 0x40
273: #define PCR 0x44
274: #define RFCR 0x48
275: #define RFDR 0x4c
276:
277: #define SRR 0x58
278:
279: #define VRCR 0xbc
280: #define VTCR 0xc0
281: #define VDR 0xc4
282: #define CCSR 0xcc
283:
284: #define TBICR 0xe0
285: #define TBISR 0xe4
286: #define TANAR 0xe8
287: #define TANLPAR 0xec
288: #define TANER 0xf0
289: #define TESR 0xf4
290:
291: #define TBICR_MR_AN_ENABLE 0x00001000
292: #define TBICR_MR_RESTART_AN 0x00000200
293:
294: #define TBISR_MR_LINK_STATUS 0x00000020
295: #define TBISR_MR_AN_COMPLETE 0x00000004
296:
297: #define TANAR_PS2 0x00000100
298: #define TANAR_PS1 0x00000080
299: #define TANAR_HALF_DUP 0x00000040
300: #define TANAR_FULL_DUP 0x00000020
301:
302: #define GPIOR_GP5_OE 0x00000200
303: #define GPIOR_GP4_OE 0x00000100
304: #define GPIOR_GP3_OE 0x00000080
305: #define GPIOR_GP2_OE 0x00000040
306: #define GPIOR_GP1_OE 0x00000020
307: #define GPIOR_GP3_OUT 0x00000004
308: #define GPIOR_GP1_OUT 0x00000001
309:
310: #define LINK_AUTONEGOTIATE 0x01
311: #define LINK_DOWN 0x02
312: #define LINK_UP 0x04
313:
314:
315: #define __kick_rx() writel(CR_RXE, ns->base + CR)
316:
317: #define kick_rx() do { \
318: DBG("kick_rx: maybe kicking\n"); \
319: writel(virt_to_le32desc(&rx_ring[ns->cur_rx]), ns->base + RXDP); \
320: if (ns->next_rx == ns->next_empty) \
321: printf("uh-oh: next_rx == next_empty???\n"); \
322: __kick_rx(); \
323: } while(0)
324:
325:
326: #ifdef USE_64BIT_ADDR
327: #define HW_ADDR_LEN 8
328: #else
329: #define HW_ADDR_LEN 4
330: #endif
331:
332: #define CMDSTS_OWN 0x80000000
333: #define CMDSTS_MORE 0x40000000
334: #define CMDSTS_INTR 0x20000000
335: #define CMDSTS_ERR 0x10000000
336: #define CMDSTS_OK 0x08000000
337: #define CMDSTS_LEN_MASK 0x0000ffff
338:
339: #define CMDSTS_DEST_MASK 0x01800000
340: #define CMDSTS_DEST_SELF 0x00800000
341: #define CMDSTS_DEST_MULTI 0x01000000
342:
343: #define DESC_SIZE 8 /* Should be cache line sized */
344:
345: #ifdef USE_64BIT_ADDR
346: struct ring_desc {
347: uint64_t link;
348: uint64_t bufptr;
349: u32 cmdsts;
350: u32 extsts; /* Extended status field */
351: };
352: #else
353: struct ring_desc {
354: u32 link;
355: u32 bufptr;
356: u32 cmdsts;
357: u32 extsts; /* Extended status field */
358: };
359: #endif
360:
361: /* Private Storage for the NIC */
362: static struct ns83820_private {
363: u8 *base;
364: int up;
365: long idle;
366: u32 *next_rx_desc;
367: u16 next_rx, next_empty;
368: u32 cur_rx;
369: u32 *descs;
370: unsigned ihr;
371: u32 CFG_cache;
372: u32 MEAR_cache;
373: u32 IMR_cache;
374: int linkstate;
375: u16 tx_done_idx;
376: u16 tx_idx;
377: u16 tx_intr_idx;
378: u32 phy_descs;
379: u32 *tx_descs;
380:
381: } nsx;
382: static struct ns83820_private *ns;
383:
384: /* Define the TX and RX Descriptor and Buffers */
385: struct {
386: struct ring_desc tx_ring[NR_TX_DESC] __attribute__ ((aligned(8)));
387: unsigned char txb[NR_TX_DESC * REAL_RX_BUF_SIZE];
388: struct ring_desc rx_ring[NR_RX_DESC] __attribute__ ((aligned(8)));
389: unsigned char rxb[NR_RX_DESC * REAL_RX_BUF_SIZE]
390: __attribute__ ((aligned(8)));
391: } ns83820_bufs __shared;
392: #define tx_ring ns83820_bufs.tx_ring
393: #define rx_ring ns83820_bufs.rx_ring
394: #define txb ns83820_bufs.txb
395: #define rxb ns83820_bufs.rxb
396:
397: static void phy_intr(struct nic *nic __unused)
398: {
399: static char *speeds[] =
400: { "10", "100", "1000", "1000(?)", "1000F" };
401: u32 cfg, new_cfg;
402: u32 tbisr, tanar, tanlpar;
403: int speed, fullduplex, newlinkstate;
404:
405: cfg = readl(ns->base + CFG) ^ SPDSTS_POLARITY;
406: if (ns->CFG_cache & CFG_TBI_EN) {
407: /* we have an optical transceiver */
408: tbisr = readl(ns->base + TBISR);
409: tanar = readl(ns->base + TANAR);
410: tanlpar = readl(ns->base + TANLPAR);
411: DBG("phy_intr: tbisr=%hX, tanar=%hX, tanlpar=%hX\n",
412: tbisr, tanar, tanlpar);
413:
414: if ((fullduplex = (tanlpar & TANAR_FULL_DUP)
415: && (tanar & TANAR_FULL_DUP))) {
416:
417: /* both of us are full duplex */
418: writel(readl(ns->base + TXCFG)
419: | TXCFG_CSI | TXCFG_HBI | TXCFG_ATP,
420: ns->base + TXCFG);
421: writel(readl(ns->base + RXCFG) | RXCFG_RX_FD,
422: ns->base + RXCFG);
423: /* Light up full duplex LED */
424: writel(readl(ns->base + GPIOR) | GPIOR_GP1_OUT,
425: ns->base + GPIOR);
426:
427: } else if (((tanlpar & TANAR_HALF_DUP)
428: && (tanar & TANAR_HALF_DUP))
429: || ((tanlpar & TANAR_FULL_DUP)
430: && (tanar & TANAR_HALF_DUP))
431: || ((tanlpar & TANAR_HALF_DUP)
432: && (tanar & TANAR_FULL_DUP))) {
433:
434: /* one or both of us are half duplex */
435: writel((readl(ns->base + TXCFG)
436: & ~(TXCFG_CSI | TXCFG_HBI)) | TXCFG_ATP,
437: ns->base + TXCFG);
438: writel(readl(ns->base + RXCFG) & ~RXCFG_RX_FD,
439: ns->base + RXCFG);
440: /* Turn off full duplex LED */
441: writel(readl(ns->base + GPIOR) & ~GPIOR_GP1_OUT,
442: ns->base + GPIOR);
443: }
444:
445: speed = 4; /* 1000F */
446:
447: } else {
448: /* we have a copper transceiver */
449: new_cfg =
450: ns->CFG_cache & ~(CFG_SB | CFG_MODE_1000 | CFG_SPDSTS);
451:
452: if (cfg & CFG_SPDSTS1)
453: new_cfg |= CFG_MODE_1000;
454: else
455: new_cfg &= ~CFG_MODE_1000;
456:
457: speed = ((cfg / CFG_SPDSTS0) & 3);
458: fullduplex = (cfg & CFG_DUPSTS);
459:
460: if (fullduplex)
461: new_cfg |= CFG_SB;
462:
463: if ((cfg & CFG_LNKSTS) &&
464: ((new_cfg ^ ns->CFG_cache) & CFG_MODE_1000)) {
465: writel(new_cfg, ns->base + CFG);
466: ns->CFG_cache = new_cfg;
467: }
468:
469: ns->CFG_cache &= ~CFG_SPDSTS;
470: ns->CFG_cache |= cfg & CFG_SPDSTS;
471: }
472:
473: newlinkstate = (cfg & CFG_LNKSTS) ? LINK_UP : LINK_DOWN;
474:
475: if (newlinkstate & LINK_UP && ns->linkstate != newlinkstate) {
476: printf("link now %s mbps, %s duplex and up.\n",
477: speeds[speed], fullduplex ? "full" : "half");
478: } else if (newlinkstate & LINK_DOWN
479: && ns->linkstate != newlinkstate) {
480: printf("link now down.\n");
481: }
482: ns->linkstate = newlinkstate;
483: }
484: static void ns83820_set_multicast(struct nic *nic __unused);
485: static void ns83820_setup_rx(struct nic *nic)
486: {
487: unsigned i;
488: ns->idle = 1;
489: ns->next_rx = 0;
490: ns->next_rx_desc = ns->descs;
491: ns->next_empty = 0;
492: ns->cur_rx = 0;
493:
494:
495: for (i = 0; i < NR_RX_DESC; i++) {
496: rx_ring[i].link = virt_to_le32desc(&rx_ring[i + 1]);
497: rx_ring[i].bufptr =
498: virt_to_le32desc(&rxb[i * REAL_RX_BUF_SIZE]);
499: rx_ring[i].cmdsts = cpu_to_le32(REAL_RX_BUF_SIZE);
500: rx_ring[i].extsts = cpu_to_le32(0);
501: }
502: // No need to wrap the ring
503: // rx_ring[i].link = virt_to_le32desc(&rx_ring[0]);
504: writel(0, ns->base + RXDP_HI);
505: writel(virt_to_le32desc(&rx_ring[0]), ns->base + RXDP);
506:
507: DBG("starting receiver\n");
508:
509: writel(0x0001, ns->base + CCSR);
510: writel(0, ns->base + RFCR);
511: writel(0x7fc00000, ns->base + RFCR);
512: writel(0xffc00000, ns->base + RFCR);
513:
514: ns->up = 1;
515:
516: phy_intr(nic);
517:
518: /* Okay, let it rip */
519: ns->IMR_cache |= ISR_PHY;
520: ns->IMR_cache |= ISR_RXRCMP;
521: //dev->IMR_cache |= ISR_RXERR;
522: //dev->IMR_cache |= ISR_RXOK;
523: ns->IMR_cache |= ISR_RXORN;
524: ns->IMR_cache |= ISR_RXSOVR;
525: ns->IMR_cache |= ISR_RXDESC;
526: ns->IMR_cache |= ISR_RXIDLE;
527: ns->IMR_cache |= ISR_TXDESC;
528: ns->IMR_cache |= ISR_TXIDLE;
529:
530: // No reason to enable interupts...
531: // writel(ns->IMR_cache, ns->base + IMR);
532: // writel(1, ns->base + IER);
533: ns83820_set_multicast(nic);
534: kick_rx();
535: }
536:
537:
538: static void ns83820_do_reset(struct nic *nic __unused, u32 which)
539: {
540: DBG("resetting chip...\n");
541: writel(which, ns->base + CR);
542: do {
543:
544: } while (readl(ns->base + CR) & which);
545: DBG("okay!\n");
546: }
547:
548: static void ns83820_reset(struct nic *nic)
549: {
550: unsigned i;
551: DBG("ns83820_reset\n");
552:
553: writel(0, ns->base + PQCR);
554:
555: ns83820_setup_rx(nic);
556:
557: for (i = 0; i < NR_TX_DESC; i++) {
558: tx_ring[i].link = 0;
559: tx_ring[i].bufptr = 0;
560: tx_ring[i].cmdsts = cpu_to_le32(0);
561: tx_ring[i].extsts = cpu_to_le32(0);
562: }
563:
564: ns->tx_idx = 0;
565: ns->tx_done_idx = 0;
566: writel(0, ns->base + TXDP_HI);
567: return;
568: }
569: static void ns83820_getmac(struct nic *nic __unused, u8 * mac)
570: {
571: unsigned i;
572: for (i = 0; i < 3; i++) {
573: u32 data;
574: /* Read from the perfect match memory: this is loaded by
575: * the chip from the EEPROM via the EELOAD self test.
576: */
577: writel(i * 2, ns->base + RFCR);
578: data = readl(ns->base + RFDR);
579: *mac++ = data;
580: *mac++ = data >> 8;
581: }
582: }
583:
584: static void ns83820_set_multicast(struct nic *nic __unused)
585: {
586: u8 *rfcr = ns->base + RFCR;
587: u32 and_mask = 0xffffffff;
588: u32 or_mask = 0;
589: u32 val;
590:
591: /* Support Multicast */
592: and_mask &= ~(RFCR_AAU | RFCR_AAM);
593: or_mask |= RFCR_AAM;
594: val = (readl(rfcr) & and_mask) | or_mask;
595: /* Ramit : RFCR Write Fix doc says RFEN must be 0 modify other bits */
596: writel(val & ~RFCR_RFEN, rfcr);
597: writel(val, rfcr);
598:
599: }
600: static void ns83820_run_bist(struct nic *nic __unused, const char *name,
601: u32 enable, u32 done, u32 fail)
602: {
603: int timed_out = 0;
604: long start;
605: u32 status;
606: int loops = 0;
607:
608: DBG("start %s\n", name);
609:
610: start = currticks();
611:
612: writel(enable, ns->base + PTSCR);
613: for (;;) {
614: loops++;
615: status = readl(ns->base + PTSCR);
616: if (!(status & enable))
617: break;
618: if (status & done)
619: break;
620: if (status & fail)
621: break;
622: if ((currticks() - start) >= HZ) {
623: timed_out = 1;
624: break;
625: }
626: }
627:
628: if (status & fail)
629: printf("%s failed! (0x%hX & 0x%hX)\n", name, (unsigned int) status,
630: (unsigned int) fail);
631: else if (timed_out)
632: printf("run_bist %s timed out! (%hX)\n", name, (unsigned int) status);
633: DBG("done %s in %d loops\n", name, loops);
634: }
635:
636: /*************************************
637: Check Link
638: *************************************/
639: static void ns83820_check_intr(struct nic *nic) {
640: int i;
641: u32 isr = readl(ns->base + ISR);
642: if(ISR_PHY & isr)
643: phy_intr(nic);
644: if(( ISR_RXIDLE | ISR_RXDESC | ISR_RXERR) & isr)
645: kick_rx();
646: for (i = 0; i < NR_RX_DESC; i++) {
647: if (rx_ring[i].cmdsts == CMDSTS_OWN) {
648: // rx_ring[i].link = virt_to_le32desc(&rx_ring[i + 1]);
649: rx_ring[i].cmdsts = cpu_to_le32(REAL_RX_BUF_SIZE);
650: }
651: }
652: }
653: /**************************************************************************
654: POLL - Wait for a frame
655: ***************************************************************************/
656: static int ns83820_poll(struct nic *nic, int retrieve)
657: {
658: /* return true if there's an ethernet packet ready to read */
659: /* nic->packet should contain data on return */
660: /* nic->packetlen should contain length of data */
661: u32 cmdsts;
662: int entry = ns->cur_rx;
663:
664: ns83820_check_intr(nic);
665:
666: cmdsts = le32_to_cpu(rx_ring[entry].cmdsts);
667:
668: if ( ! ( (CMDSTS_OWN & (cmdsts)) && (cmdsts != (CMDSTS_OWN)) ) )
669: return 0;
670:
671: if ( ! retrieve ) return 1;
672:
673: if (! (CMDSTS_OK & cmdsts) )
674: return 0;
675:
676: nic->packetlen = cmdsts & 0xffff;
677: memcpy(nic->packet,
678: rxb + (entry * REAL_RX_BUF_SIZE),
679: nic->packetlen);
680: // rx_ring[entry].link = 0;
681: rx_ring[entry].cmdsts = cpu_to_le32(CMDSTS_OWN);
682:
683: ns->cur_rx = (ns->cur_rx + 1) % NR_RX_DESC;
684:
685: if (ns->cur_rx == 0) /* We have wrapped the ring */
686: kick_rx();
687:
688: return 1;
689: }
690:
691: static inline void kick_tx(struct nic *nic __unused)
692: {
693: DBG("kick_tx\n");
694: writel(CR_TXE, ns->base + CR);
695: }
696:
697: /**************************************************************************
698: TRANSMIT - Transmit a frame
699: ***************************************************************************/
700: static void ns83820_transmit(struct nic *nic, const char *d, /* Destination */
701: unsigned int t, /* Type */
702: unsigned int s, /* size */
703: const char *p)
704: { /* Packet */
705: /* send the packet to destination */
706:
707: u16 nstype;
708: u32 cmdsts, extsts;
709: int cur_tx = 0;
710: u32 isr = readl(ns->base + ISR);
711: if (ISR_TXIDLE & isr)
712: kick_tx(nic);
713: /* point to the current txb incase multiple tx_rings are used */
714: memcpy(txb, d, ETH_ALEN);
715: memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN);
716: nstype = htons((u16) t);
717: memcpy(txb + 2 * ETH_ALEN, (u8 *) & nstype, 2);
718: memcpy(txb + ETH_HLEN, p, s);
719: s += ETH_HLEN;
720: s &= 0x0FFF;
721: while (s < ETH_ZLEN)
722: txb[s++] = '\0';
723:
724: /* Setup the transmit descriptor */
725: extsts = 0;
726: extsts |= EXTSTS_UDPPKT;
727:
728: tx_ring[cur_tx].bufptr = virt_to_le32desc(&txb);
729: tx_ring[cur_tx].extsts = cpu_to_le32(extsts);
730:
731: cmdsts = cpu_to_le32(0);
732: cmdsts |= cpu_to_le32(CMDSTS_OWN | s);
733: tx_ring[cur_tx].cmdsts = cpu_to_le32(cmdsts);
734:
735: writel(virt_to_le32desc(&tx_ring[0]), ns->base + TXDP);
736: kick_tx(nic);
737: }
738:
739: /**************************************************************************
740: DISABLE - Turn off ethernet interface
741: ***************************************************************************/
742: static void ns83820_disable ( struct nic *nic ) {
743:
744: /* put the card in its initial state */
745: /* This function serves 3 purposes.
746: * This disables DMA and interrupts so we don't receive
747: * unexpected packets or interrupts from the card after
748: * etherboot has finished.
749: * This frees resources so etherboot may use
750: * this driver on another interface
751: * This allows etherboot to reinitialize the interface
752: * if something is something goes wrong.
753: */
754: /* disable interrupts */
755: writel(0, ns->base + IMR);
756: writel(0, ns->base + IER);
757: readl(ns->base + IER);
758:
759: ns->up = 0;
760:
761: ns83820_do_reset(nic, CR_RST);
762:
763: ns->IMR_cache &=
764: ~(ISR_RXOK | ISR_RXDESC | ISR_RXERR | ISR_RXEARLY |
765: ISR_RXIDLE);
766: writel(ns->IMR_cache, ns->base + IMR);
767:
768: /* touch the pci bus... */
769: readl(ns->base + IMR);
770:
771: /* assumes the transmitter is already disabled and reset */
772: writel(0, ns->base + RXDP_HI);
773: writel(0, ns->base + RXDP);
774: }
775:
776: /**************************************************************************
777: IRQ - Enable, Disable, or Force interrupts
778: ***************************************************************************/
779: static void ns83820_irq(struct nic *nic __unused, irq_action_t action __unused)
780: {
781: switch ( action ) {
782: case DISABLE :
783: break;
784: case ENABLE :
785: break;
786: case FORCE :
787: break;
788: }
789: }
790:
791: static struct nic_operations ns83820_operations = {
792: .connect = dummy_connect,
793: .poll = ns83820_poll,
794: .transmit = ns83820_transmit,
795: .irq = ns83820_irq,
796:
797: };
798:
799: static struct pci_device_id ns83820_nics[] = {
800: PCI_ROM(0x100b, 0x0022, "ns83820", "National Semiconductor 83820", 0),
801: };
802:
803: PCI_DRIVER ( ns83820_driver, ns83820_nics, PCI_NO_CLASS );
804:
805: /**************************************************************************
806: PROBE - Look for an adapter, this routine's visible to the outside
807: ***************************************************************************/
808:
809: #define board_found 1
810: #define valid_link 0
811: static int ns83820_probe ( struct nic *nic, struct pci_device *pci ) {
812:
813: long addr;
814: int using_dac = 0;
815:
816: if (pci->ioaddr == 0)
817: return 0;
818:
819: printf("ns83820.c: Found %s, vendor=0x%hX, device=0x%hX\n",
820: pci->id->name, pci->vendor, pci->device);
821:
822: /* point to private storage */
823: ns = &nsx;
824:
825: adjust_pci_device(pci);
826:
827: addr = pci_bar_start(pci, PCI_BASE_ADDRESS_1);
828:
829: ns->base = ioremap(addr, (1UL << 12));
830:
831: if (!ns->base)
832: return 0;
833:
834: nic->irqno = 0;
835: nic->ioaddr = pci->ioaddr & ~3;
836:
837: /* disable interrupts */
838: writel(0, ns->base + IMR);
839: writel(0, ns->base + IER);
840: readl(ns->base + IER);
841:
842: ns->IMR_cache = 0;
843:
844: ns83820_do_reset(nic, CR_RST);
845:
846: /* Must reset the ram bist before running it */
847: writel(PTSCR_RBIST_RST, ns->base + PTSCR);
848: ns83820_run_bist(nic, "sram bist", PTSCR_RBIST_EN,
849: PTSCR_RBIST_DONE, PTSCR_RBIST_FAIL);
850: ns83820_run_bist(nic, "eeprom bist", PTSCR_EEBIST_EN, 0,
851: PTSCR_EEBIST_FAIL);
852: ns83820_run_bist(nic, "eeprom load", PTSCR_EELOAD_EN, 0, 0);
853:
854: /* I love config registers */
855: ns->CFG_cache = readl(ns->base + CFG);
856:
857: if ((ns->CFG_cache & CFG_PCI64_DET)) {
858: printf("%s: detected 64 bit PCI data bus.\n", pci->id->name);
859: /*dev->CFG_cache |= CFG_DATA64_EN; */
860: if (!(ns->CFG_cache & CFG_DATA64_EN))
861: printf
862: ("%s: EEPROM did not enable 64 bit bus. Disabled.\n",
863: pci->id->name);
864: } else
865: ns->CFG_cache &= ~(CFG_DATA64_EN);
866:
867: ns->CFG_cache &= (CFG_TBI_EN | CFG_MRM_DIS | CFG_MWI_DIS |
868: CFG_T64ADDR | CFG_DATA64_EN | CFG_EXT_125 |
869: CFG_M64ADDR);
870: ns->CFG_cache |=
871: CFG_PINT_DUPSTS | CFG_PINT_LNKSTS | CFG_PINT_SPDSTS |
872: CFG_EXTSTS_EN | CFG_EXD | CFG_PESEL;
873: ns->CFG_cache |= CFG_REQALG;
874: ns->CFG_cache |= CFG_POW;
875: ns->CFG_cache |= CFG_TMRTEST;
876:
877: /* When compiled with 64 bit addressing, we must always enable
878: * the 64 bit descriptor format.
879: */
880: #ifdef USE_64BIT_ADDR
881: ns->CFG_cache |= CFG_M64ADDR;
882: #endif
883:
884: //FIXME: Enable section on dac or remove this
885: if (using_dac)
886: ns->CFG_cache |= CFG_T64ADDR;
887:
888: /* Big endian mode does not seem to do what the docs suggest */
889: ns->CFG_cache &= ~CFG_BEM;
890:
891: /* setup optical transceiver if we have one */
892: if (ns->CFG_cache & CFG_TBI_EN) {
893: DBG("%s: enabling optical transceiver\n", pci->id->name);
894: writel(readl(ns->base + GPIOR) | 0x3e8, ns->base + GPIOR);
895:
896: /* setup auto negotiation feature advertisement */
897: writel(readl(ns->base + TANAR)
898: | TANAR_HALF_DUP | TANAR_FULL_DUP,
899: ns->base + TANAR);
900:
901: /* start auto negotiation */
902: writel(TBICR_MR_AN_ENABLE | TBICR_MR_RESTART_AN,
903: ns->base + TBICR);
904: writel(TBICR_MR_AN_ENABLE, ns->base + TBICR);
905: ns->linkstate = LINK_AUTONEGOTIATE;
906:
907: ns->CFG_cache |= CFG_MODE_1000;
908: }
909: writel(ns->CFG_cache, ns->base + CFG);
910: DBG("CFG: %hX\n", ns->CFG_cache);
911:
912: /* FIXME: reset_phy is defaulted to 0, should we reset anyway? */
913: if (reset_phy) {
914: DBG("%s: resetting phy\n", pci->id->name);
915: writel(ns->CFG_cache | CFG_PHY_RST, ns->base + CFG);
916: writel(ns->CFG_cache, ns->base + CFG);
917: }
918: #if 0 /* Huh? This sets the PCI latency register. Should be done via
919: * the PCI layer. FIXME.
920: */
921: if (readl(dev->base + SRR))
922: writel(readl(dev->base + 0x20c) | 0xfe00,
923: dev->base + 0x20c);
924: #endif
925:
926: /* Note! The DMA burst size interacts with packet
927: * transmission, such that the largest packet that
928: * can be transmitted is 8192 - FLTH - burst size.
929: * If only the transmit fifo was larger...
930: */
931: /* Ramit : 1024 DMA is not a good idea, it ends up banging
932: * some DELL and COMPAQ SMP systems */
933: writel(TXCFG_CSI | TXCFG_HBI | TXCFG_ATP | TXCFG_MXDMA512
934: | ((1600 / 32) * 0x100), ns->base + TXCFG);
935:
936: /* Set Rx to full duplex, don't accept runt, errored, long or length
937: * range errored packets. Use 512 byte DMA.
938: */
939: /* Ramit : 1024 DMA is not a good idea, it ends up banging
940: * some DELL and COMPAQ SMP systems
941: * Turn on ALP, only we are accpeting Jumbo Packets */
942: writel(RXCFG_AEP | RXCFG_ARP | RXCFG_AIRL | RXCFG_RX_FD
943: | RXCFG_STRIPCRC
944: //| RXCFG_ALP
945: | (RXCFG_MXDMA512) | 0, ns->base + RXCFG);
946:
947: /* Disable priority queueing */
948: writel(0, ns->base + PQCR);
949:
950: /* Enable IP checksum validation and detetion of VLAN headers.
951: * Note: do not set the reject options as at least the 0x102
952: * revision of the chip does not properly accept IP fragments
953: * at least for UDP.
954: */
955: /* Ramit : Be sure to turn on RXCFG_ARP if VLAN's are enabled, since
956: * the MAC it calculates the packetsize AFTER stripping the VLAN
957: * header, and if a VLAN Tagged packet of 64 bytes is received (like
958: * a ping with a VLAN header) then the card, strips the 4 byte VLAN
959: * tag and then checks the packet size, so if RXCFG_ARP is not enabled,
960: * it discrards it!. These guys......
961: */
962: writel(VRCR_IPEN | VRCR_VTDEN, ns->base + VRCR);
963:
964: /* Enable per-packet TCP/UDP/IP checksumming */
965: writel(VTCR_PPCHK, ns->base + VTCR);
966:
967: /* Ramit : Enable async and sync pause frames */
968: // writel(0, ns->base + PCR);
969: writel((PCR_PS_MCAST | PCR_PS_DA | PCR_PSEN | PCR_FFLO_4K |
970: PCR_FFHI_8K | PCR_STLO_4 | PCR_STHI_8 | PCR_PAUSE_CNT),
971: ns->base + PCR);
972:
973: /* Disable Wake On Lan */
974: writel(0, ns->base + WCSR);
975:
976: ns83820_getmac(nic, nic->node_addr);
977:
978: if (using_dac) {
979: DBG("%s: using 64 bit addressing.\n", pci->id->name);
980: }
981:
982: DBG("%s: DP83820 %d.%d: io=%#04lx\n",
983: pci->id->name,
984: (unsigned) readl(ns->base + SRR) >> 8,
985: (unsigned) readl(ns->base + SRR) & 0xff,
986: pci->ioaddr);
987:
988: #ifdef PHY_CODE_IS_FINISHED
989: ns83820_probe_phy(dev);
990: #endif
991:
992: ns83820_reset(nic);
993: /* point to NIC specific routines */
994: nic->nic_op = &ns83820_operations;
995: return 1;
996: }
997:
998: DRIVER ( "NS83820/PCI", nic_driver, pci_driver, ns83820_driver,
999: ns83820_probe, ns83820_disable );
1000:
1001: /*
1002: * Local variables:
1003: * c-basic-offset: 8
1004: * c-indent-level: 8
1005: * tab-width: 8
1006: * End:
1007: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.