use the override options if specified
[AROS.git] / arch / all-pc / boot / grub / netboot / fa311.c
blobdf92a6837b348a8454fef113ffaad7c416c68477
1 /*
2 Driver for the National Semiconductor DP83810 Ethernet controller.
4 Portions Copyright (C) 2001 Inprimis Technologies, Inc.
5 http://www.inprimis.com/
7 This driver is based (heavily) on the Linux driver for this chip
8 which is copyright 1999-2001 by Donald Becker.
10 This software has no warranties expressed or implied for any
11 purpose.
13 This software may be used and distributed according to the terms of
14 the GNU General Public License (GPL), incorporated herein by reference.
15 Drivers based on or derived from this code fall under the GPL and must
16 retain the authorship, copyright and license notice. This file is not
17 a complete program and may only be used when the entire operating
18 system is licensed under the GPL. License for under other terms may be
19 available. Contact the original author for details.
21 The original author may be reached as becker@scyld.com, or at
22 Scyld Computing Corporation
23 410 Severn Ave., Suite 210
24 Annapolis MD 21403
28 typedef unsigned char u8;
29 typedef signed char s8;
30 typedef unsigned short u16;
31 typedef signed short s16;
32 typedef unsigned int u32;
33 typedef signed int s32;
35 #include "etherboot.h"
36 #include "nic.h"
37 #include "pci.h"
39 #undef virt_to_bus
40 #define virt_to_bus(x) ((unsigned long)x)
41 #define cpu_to_le32(val) (val)
42 #define le32_to_cpu(val) (val)
43 #define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr))
44 #define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr))
46 #define TX_RING_SIZE 1
47 #define RX_RING_SIZE 4
48 #define TIME_OUT 1000000
49 #define PKT_BUF_SZ 1536
51 /* Offsets to the device registers. */
52 enum register_offsets {
53 ChipCmd=0x00, ChipConfig=0x04, EECtrl=0x08, PCIBusCfg=0x0C,
54 IntrStatus=0x10, IntrMask=0x14, IntrEnable=0x18,
55 TxRingPtr=0x20, TxConfig=0x24,
56 RxRingPtr=0x30, RxConfig=0x34,
57 WOLCmd=0x40, PauseCmd=0x44, RxFilterAddr=0x48, RxFilterData=0x4C,
58 BootRomAddr=0x50, BootRomData=0x54, StatsCtrl=0x5C, StatsData=0x60,
59 RxPktErrs=0x60, RxMissed=0x68, RxCRCErrs=0x64,
62 /* Bit in ChipCmd. */
63 enum ChipCmdBits {
64 ChipReset=0x100, RxReset=0x20, TxReset=0x10, RxOff=0x08, RxOn=0x04,
65 TxOff=0x02, TxOn=0x01,
68 /* Bits in the interrupt status/mask registers. */
69 enum intr_status_bits {
70 IntrRxDone=0x0001, IntrRxIntr=0x0002, IntrRxErr=0x0004, IntrRxEarly=0x0008,
71 IntrRxIdle=0x0010, IntrRxOverrun=0x0020,
72 IntrTxDone=0x0040, IntrTxIntr=0x0080, IntrTxErr=0x0100,
73 IntrTxIdle=0x0200, IntrTxUnderrun=0x0400,
74 StatsMax=0x0800, LinkChange=0x4000, WOLPkt=0x2000,
75 RxResetDone=0x1000000, TxResetDone=0x2000000,
76 IntrPCIErr=0x00f00000, IntrNormalSummary=0x0251, IntrAbnormalSummary=0xED20,
79 /* Bits in the RxMode register. */
80 enum rx_mode_bits {
81 AcceptErr=0x20, AcceptRunt=0x10, AcceptBroadcast=0xC0000000,
82 AcceptMulticast=0x00200000, AcceptAllMulticast=0x20000000,
83 AcceptAllPhys=0x10000000, AcceptMyPhys=0x08000000,
86 /* Bits in network_desc.status */
87 enum desc_status_bits {
88 DescOwn=0x80000000, DescMore=0x40000000, DescIntr=0x20000000,
89 DescNoCRC=0x10000000,
90 DescPktOK=0x08000000, RxTooLong=0x00400000,
93 /* The Rx and Tx buffer descriptors. */
94 struct netdev_desc {
95 u32 next_desc;
96 s32 cmd_status;
97 u32 addr;
100 static struct FA311_DEV {
101 unsigned int ioaddr;
102 unsigned short vendor;
103 unsigned short device;
104 unsigned int cur_rx;
105 unsigned int cur_tx;
106 unsigned int rx_buf_sz;
107 volatile struct netdev_desc *rx_head_desc;
108 volatile struct netdev_desc rx_ring[RX_RING_SIZE] __attribute__ ((aligned (4)));
109 volatile struct netdev_desc tx_ring[TX_RING_SIZE] __attribute__ ((aligned (4)));
110 } fa311_dev;
112 static int eeprom_read(long ioaddr, int location);
113 static void init_ring(struct FA311_DEV *dev);
114 static void fa311_reset(struct nic *nic);
115 static int fa311_poll(struct nic *nic);
116 static void fa311_transmit(struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p);
117 static void fa311_disable(struct nic *nic);
119 static char rx_packet[PKT_BUF_SZ * RX_RING_SIZE] __attribute__ ((aligned (4)));
120 static char tx_packet[PKT_BUF_SZ * TX_RING_SIZE] __attribute__ ((aligned (4)));
122 struct nic * fa311_probe(struct nic *nic, unsigned short *io_addrs, struct pci_device *pci)
124 int prev_eedata;
125 int i;
126 int duplex;
127 int tx_config;
128 int rx_config;
129 unsigned char macaddr[6];
130 unsigned char mactest;
131 unsigned char pci_bus = 0;
132 struct FA311_DEV* dev = &fa311_dev;
134 if (io_addrs == 0 || *io_addrs == 0)
135 return (0);
136 memset(dev, 0, sizeof(*dev));
137 dev->vendor = pci->vendor;
138 dev->device = pci->dev_id;
139 dev->ioaddr = pci->membase;
141 /* Work around the dropped serial bit. */
142 prev_eedata = eeprom_read(dev->ioaddr, 6);
143 for (i = 0; i < 3; i++) {
144 int eedata = eeprom_read(dev->ioaddr, i + 7);
145 macaddr[i*2] = (eedata << 1) + (prev_eedata >> 15);
146 macaddr[i*2+1] = eedata >> 7;
147 prev_eedata = eedata;
149 mactest = 0;
150 for (i = 0; i < 6; i++)
151 mactest |= macaddr[i];
152 if (mactest == 0)
153 return (0);
154 for (i = 0; i < 6; i++)
155 nic->node_addr[i] = macaddr[i];
156 printf("%! ", nic->node_addr);
158 adjust_pci_device(pci);
160 fa311_reset(nic);
162 nic->reset = fa311_reset;
163 nic->disable = fa311_disable;
164 nic->poll = fa311_poll;
165 nic->transmit = fa311_transmit;
167 init_ring(dev);
169 writel(virt_to_bus(dev->rx_ring), dev->ioaddr + RxRingPtr);
170 writel(virt_to_bus(dev->tx_ring), dev->ioaddr + TxRingPtr);
172 for (i = 0; i < 6; i += 2)
174 writel(i, dev->ioaddr + RxFilterAddr);
175 writew(macaddr[i] + (macaddr[i+1] << 8),
176 dev->ioaddr + RxFilterData);
179 /* Initialize other registers. */
180 /* Configure for standard, in-spec Ethernet. */
181 if (readl(dev->ioaddr + ChipConfig) & 0x20000000)
182 { /* Full duplex */
183 tx_config = 0xD0801002;
184 rx_config = 0x10000020;
186 else
188 tx_config = 0x10801002;
189 rx_config = 0x0020;
191 writel(tx_config, dev->ioaddr + TxConfig);
192 writel(rx_config, dev->ioaddr + RxConfig);
194 duplex = readl(dev->ioaddr + ChipConfig) & 0x20000000 ? 1 : 0;
195 if (duplex) {
196 rx_config |= 0x10000000;
197 tx_config |= 0xC0000000;
198 } else {
199 rx_config &= ~0x10000000;
200 tx_config &= ~0xC0000000;
202 writew(tx_config, dev->ioaddr + TxConfig);
203 writew(rx_config, dev->ioaddr + RxConfig);
205 writel(AcceptBroadcast | AcceptAllMulticast | AcceptMyPhys,
206 dev->ioaddr + RxFilterAddr);
208 writel(RxOn | TxOn, dev->ioaddr + ChipCmd);
209 writel(4, dev->ioaddr + StatsCtrl); /* Clear Stats */
210 return nic;
214 static void fa311_reset(struct nic *nic)
216 u32 chip_config;
217 struct FA311_DEV* dev = &fa311_dev;
219 /* Reset the chip to erase previous misconfiguration. */
220 outl(ChipReset, dev->ioaddr + ChipCmd);
222 if ((readl(dev->ioaddr + ChipConfig) & 0xe000) != 0xe000)
224 chip_config = readl(dev->ioaddr + ChipConfig);
228 static int fa311_poll(struct nic *nic)
230 s32 desc_status;
231 int to;
232 int entry;
233 int retcode;
234 struct FA311_DEV* dev = &fa311_dev;
236 retcode = 0;
237 entry = dev->cur_rx;
238 to = TIME_OUT;
239 while (to != 0)
241 desc_status = dev->rx_ring[entry].cmd_status;
242 if ((desc_status & DescOwn) != 0)
243 break;
244 else
245 --to;
247 if (to != 0)
249 readl(dev->ioaddr + IntrStatus); /* clear interrrupt bits */
250 /* driver owns the next entry it's a new packet. Send it up. */
251 if ((desc_status & (DescMore|DescPktOK|RxTooLong)) == DescPktOK)
253 nic->packetlen = (desc_status & 0x0fff) - 4; /* Omit CRC size. */
254 memcpy(nic->packet, (char*)(dev->rx_ring[entry].addr), nic->packetlen);
255 retcode = 1;
257 /* Give the descriptor back to the chip */
258 dev->rx_ring[entry].cmd_status = cpu_to_le32(dev->rx_buf_sz);
259 dev->cur_rx++;
260 if (dev->cur_rx >= RX_RING_SIZE)
261 dev->cur_rx = 0;
262 dev->rx_head_desc = &dev->rx_ring[dev->cur_rx];
264 /* Restart Rx engine if stopped. */
265 writel(RxOn, dev->ioaddr + ChipCmd);
266 return retcode;
269 static void fa311_transmit(struct nic *nic, const char *destaddr, unsigned int type, unsigned int len, const char *data)
271 unsigned short nstype;
272 s32 desc_status;
273 int to;
274 int entry;
275 char* txp;
276 unsigned char* s;
277 struct FA311_DEV* dev = &fa311_dev;
279 /* Calculate the next Tx descriptor entry. */
280 entry = dev->cur_tx;
281 txp = (char*)(dev->tx_ring[entry].addr);
283 memcpy(txp, destaddr, ETH_ALEN);
284 memcpy(txp + ETH_ALEN, nic->node_addr, ETH_ALEN);
285 nstype = htons(type);
286 memcpy(txp + 12, (char*)&nstype, 2);
287 memcpy(txp + ETH_HLEN, data, len);
288 len += ETH_HLEN;
289 /* pad frame */
290 if (len < ETH_ZLEN)
292 s = (unsigned char*)(txp+len);
293 while (s < (unsigned char*)(txp+ETH_ZLEN))
294 *s++ = 0;
295 len = ETH_ZLEN;
297 dev->tx_ring[entry].cmd_status = cpu_to_le32(DescOwn | len);
298 dev->cur_tx++;
299 if (dev->cur_tx >= TX_RING_SIZE)
300 dev->cur_tx = 0;
302 /* Wake the potentially-idle transmit channel. */
303 writel(TxOn, dev->ioaddr + ChipCmd);
305 /* wait for tranmission to complete */
306 to = TIME_OUT;
307 while (to != 0)
309 desc_status = dev->tx_ring[entry].cmd_status;
310 if ((desc_status & DescOwn) == 0)
311 break;
312 else
313 --to;
316 readl(dev->ioaddr + IntrStatus); /* clear interrrupt bits */
317 return;
320 static void fa311_disable(struct nic *nic)
322 struct FA311_DEV* dev = &fa311_dev;
324 /* Stop the chip's Tx and Rx processes. */
325 writel(RxOff | TxOff, dev->ioaddr + ChipCmd);
329 /* Read the EEPROM and MII Management Data I/O (MDIO) interfaces.
330 The EEPROM code is for the common 93c06/46 EEPROMs with 6 bit addresses. */
332 /* Delay between EEPROM clock transitions.
333 No extra delay is needed with 33Mhz PCI, but future 66Mhz access may need
334 a delay. Note that pre-2.0.34 kernels had a cache-alignment bug that
335 made udelay() unreliable.
336 The old method of using an ISA access as a delay, __SLOW_DOWN_IO__, is
337 depricated.
339 #define eeprom_delay(ee_addr) inl(ee_addr)
341 enum EEPROM_Ctrl_Bits {
342 EE_ShiftClk=0x04, EE_DataIn=0x01, EE_ChipSelect=0x08, EE_DataOut=0x02,
344 #define EE_Write0 (EE_ChipSelect)
345 #define EE_Write1 (EE_ChipSelect | EE_DataIn)
347 /* The EEPROM commands include the alway-set leading bit. */
348 enum EEPROM_Cmds {
349 EE_WriteCmd=(5 << 6), EE_ReadCmd=(6 << 6), EE_EraseCmd=(7 << 6),
353 static int eeprom_read(long addr, int location)
355 int i;
356 int retval = 0;
357 int ee_addr = addr + EECtrl;
358 int read_cmd = location | EE_ReadCmd;
359 writel(EE_Write0, ee_addr);
361 /* Shift the read command bits out. */
362 for (i = 10; i >= 0; i--) {
363 short dataval = (read_cmd & (1 << i)) ? EE_Write1 : EE_Write0;
364 writel(dataval, ee_addr);
365 eeprom_delay(ee_addr);
366 writel(dataval | EE_ShiftClk, ee_addr);
367 eeprom_delay(ee_addr);
369 writel(EE_ChipSelect, ee_addr);
370 eeprom_delay(ee_addr);
372 for (i = 0; i < 16; i++) {
373 writel(EE_ChipSelect | EE_ShiftClk, ee_addr);
374 eeprom_delay(ee_addr);
375 retval |= (readl(ee_addr) & EE_DataOut) ? 1 << i : 0;
376 writel(EE_ChipSelect, ee_addr);
377 eeprom_delay(ee_addr);
380 /* Terminate the EEPROM access. */
381 writel(EE_Write0, ee_addr);
382 writel(0, ee_addr);
383 return retval;
386 /* Initialize the Rx and Tx rings, along with various 'dev' bits. */
387 static void init_ring(struct FA311_DEV *dev)
389 int i;
391 dev->cur_rx = 0;
392 dev->cur_tx = 0;
394 dev->rx_buf_sz = PKT_BUF_SZ;
395 dev->rx_head_desc = &dev->rx_ring[0];
397 /* Initialize all Rx descriptors. */
398 for (i = 0; i < RX_RING_SIZE; i++) {
399 dev->rx_ring[i].next_desc = virt_to_le32desc(&dev->rx_ring[i+1]);
400 dev->rx_ring[i].cmd_status = DescOwn;
402 /* Mark the last entry as wrapping the ring. */
403 dev->rx_ring[i-1].next_desc = virt_to_le32desc(&dev->rx_ring[0]);
405 /* Fill in the Rx buffers. Handle allocation failure gracefully. */
406 for (i = 0; i < RX_RING_SIZE; i++) {
407 dev->rx_ring[i].addr = (u32)(&rx_packet[PKT_BUF_SZ * i]);
408 dev->rx_ring[i].cmd_status = cpu_to_le32(dev->rx_buf_sz);
411 for (i = 0; i < TX_RING_SIZE; i++) {
412 dev->tx_ring[i].next_desc = virt_to_le32desc(&dev->tx_ring[i+1]);
413 dev->tx_ring[i].cmd_status = 0;
415 dev->tx_ring[i-1].next_desc = virt_to_le32desc(&dev->tx_ring[0]);
417 for (i = 0; i < TX_RING_SIZE; i++)
418 dev->tx_ring[i].addr = (u32)(&tx_packet[PKT_BUF_SZ * i]);
419 return;