Updated PCI IDs to latest snapshot.
[tangerine.git] / workbench / devs / networks / nForce / nforce.c
blobfac0ae7335edc2e8d58dc5c64f3df0560f465fd1
1 /*
2 * $Id$
3 */
5 /*
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
19 MA 02111-1307, USA.
22 #define DEBUG 0
24 #include <exec/types.h>
25 #include <exec/resident.h>
26 #include <exec/io.h>
27 #include <exec/ports.h>
29 #include <aros/libcall.h>
30 #include <aros/debug.h>
31 #include <aros/macros.h>
32 #include <aros/io.h>
34 #include <oop/oop.h>
36 #include <devices/sana2.h>
37 #include <devices/sana2specialstats.h>
39 #include <utility/utility.h>
40 #include <utility/tagitem.h>
41 #include <utility/hooks.h>
43 #include <hidd/pci.h>
44 #include <hidd/irq.h>
46 #include <proto/oop.h>
47 #include <proto/exec.h>
48 #include <proto/dos.h>
49 #include <proto/battclock.h>
51 #include <stdlib.h>
53 #include "nforce.h"
54 #include "unit.h"
55 #include LC_LIBDEFS_FILE
57 /* A bit fixed linux stuff here :) */
59 #undef LIBBASE
60 #define LIBBASE (dev->nu_device)
62 #define net_device NFUnit
64 #define TIMER_RPROK 3599597124UL
66 static ULONG usec2tick(ULONG usec)
68 ULONG ret, timer_rpr = TIMER_RPROK;
69 asm volatile("movl $0,%%eax; divl %2":"=a"(ret):"d"(usec),"m"(timer_rpr));
70 return ret;
73 void udelay(LONG usec)
75 int oldtick, tick;
76 usec = usec2tick(usec);
78 BYTEOUT(0x43, 0x80);
79 oldtick = BYTEIN(0x42);
80 oldtick += BYTEIN(0x42) << 8;
82 while (usec > 0)
84 BYTEOUT(0x43, 0x80);
85 tick = BYTEIN(0x42);
86 tick += BYTEIN(0x42) << 8;
88 usec -= (oldtick - tick);
89 if (tick > oldtick) usec -= 0x10000;
90 oldtick = tick;
94 static volatile ULONG readl(APTR base)
96 return *((ULONG*)base);
98 static volatile void writel(ULONG val, APTR base)
100 *((ULONG*)base) = val;
103 static inline struct fe_priv *get_nvpriv(struct net_device *dev)
105 return dev->nu_fe_priv;
108 static inline UBYTE *get_hwbase(struct net_device *dev)
110 return (UBYTE*)dev->nu_BaseMem;
113 static inline void pci_push(UBYTE *base)
115 /* force out pending posted writes */
116 readl(base);
119 static inline ULONG nv_descr_getlength(struct ring_desc *prd, ULONG v)
121 return AROS_LE2LONG(prd->FlagLen)
122 & ((v == DESC_VER_1) ? LEN_MASK_V1 : LEN_MASK_V2);
125 static int reg_delay(struct net_device *dev, int offset, ULONG mask, ULONG target,
126 int delay, int delaymax, const char *msg)
128 UBYTE *base = get_hwbase(dev);
130 pci_push(base);
131 do {
132 udelay(delay);
133 delaymax -= delay;
134 if (delaymax < 0) {
135 if (msg)
136 D(bug(msg));
137 return 1;
139 } while ((readl(base + offset) & mask) != target);
140 return 0;
143 #define MII_READ (-1)
144 /* mii_rw: read/write a register on the PHY.
146 * Caller must guarantee serialization
148 static int mii_rw(struct net_device *dev, int addr, int miireg, int value)
150 UBYTE *base = get_hwbase(dev);
151 ULONG reg;
152 int retval;
154 writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus);
156 reg = readl(base + NvRegMIIControl);
157 if (reg & NVREG_MIICTL_INUSE) {
158 writel(NVREG_MIICTL_INUSE, base + NvRegMIIControl);
159 udelay(NV_MIIBUSY_DELAY);
162 reg = (addr << NVREG_MIICTL_ADDRSHIFT) | miireg;
163 if (value != MII_READ) {
164 writel(value, base + NvRegMIIData);
165 reg |= NVREG_MIICTL_WRITE;
167 writel(reg, base + NvRegMIIControl);
169 if (reg_delay(dev, NvRegMIIControl, NVREG_MIICTL_INUSE, 0,
170 NV_MIIPHY_DELAY, NV_MIIPHY_DELAYMAX, NULL)) {
171 D(bug("%s: mii_rw of reg %d at PHY %d timed out.\n",
172 dev->name, miireg, addr));
173 retval = -1;
174 } else if (value != MII_READ) {
175 /* it was a write operation - fewer failures are detectable */
176 D(bug("%s: mii_rw wrote 0x%x to reg %d at PHY %d\n",
177 dev->name, value, miireg, addr));
178 retval = 0;
179 } else if (readl(base + NvRegMIIStatus) & NVREG_MIISTAT_ERROR) {
180 D(bug("%s: mii_rw of reg %d at PHY %d failed.\n",
181 dev->name, miireg, addr));
182 retval = -1;
183 } else {
184 retval = readl(base + NvRegMIIData);
185 D(bug("%s: mii_rw read from reg %d at PHY %d: 0x%x.\n",
186 dev->name, miireg, addr, retval));
189 return retval;
192 static int phy_reset(struct net_device *dev)
194 struct fe_priv *np = get_nvpriv(dev);
195 ULONG miicontrol;
196 unsigned int tries = 0;
198 miicontrol = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
199 miicontrol |= BMCR_RESET;
200 if (mii_rw(dev, np->phyaddr, MII_BMCR, miicontrol)) {
201 return -1;
204 /* wait for 500ms */
205 Delay(25);
207 /* must wait till reset is deasserted */
208 while (miicontrol & BMCR_RESET) {
209 Delay(1);
210 miicontrol = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
211 /* FIXME: 100 tries seem excessive */
212 if (tries++ > 100)
213 return -1;
215 return 0;
218 static int phy_init(struct net_device *dev)
220 struct fe_priv *np = get_nvpriv(dev);
221 UBYTE *base = get_hwbase(dev);
222 ULONG phyinterface, phy_reserved, mii_status, mii_control, mii_control_1000,reg;
224 /* set advertise register */
225 reg = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
226 reg |= (ADVERTISE_10HALF|ADVERTISE_10FULL|ADVERTISE_100HALF|ADVERTISE_100FULL|0x800|0x400);
227 if (mii_rw(dev, np->phyaddr, MII_ADVERTISE, reg)) {
228 D(bug("%s: phy write to advertise failed.\n", dev->name));
229 return PHY_ERROR;
232 /* get phy interface type */
233 phyinterface = readl(base + NvRegPhyInterface);
235 /* see if gigabit phy */
236 mii_status = mii_rw(dev, np->phyaddr, MII_BMSR, MII_READ);
237 if (mii_status & PHY_GIGABIT) {
238 np->gigabit = PHY_GIGABIT;
239 mii_control_1000 = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ);
240 mii_control_1000 &= ~ADVERTISE_1000HALF;
241 if (phyinterface & PHY_RGMII)
242 mii_control_1000 |= ADVERTISE_1000FULL;
243 else
244 mii_control_1000 &= ~ADVERTISE_1000FULL;
246 if (mii_rw(dev, np->phyaddr, MII_1000BT_CR, mii_control_1000)) {
247 D(bug("%s: phy init failed.\n", dev->name));
248 return PHY_ERROR;
251 else
252 np->gigabit = 0;
254 /* reset the phy */
255 if (phy_reset(dev)) {
256 D(bug("%s: phy reset failed\n", dev->name));
257 return PHY_ERROR;
260 /* phy vendor specific configuration */
261 if ((np->phy_oui == PHY_OUI_CICADA) && (phyinterface & PHY_RGMII) ) {
262 phy_reserved = mii_rw(dev, np->phyaddr, MII_RESV1, MII_READ);
263 phy_reserved &= ~(PHY_INIT1 | PHY_INIT2);
264 phy_reserved |= (PHY_INIT3 | PHY_INIT4);
265 if (mii_rw(dev, np->phyaddr, MII_RESV1, phy_reserved)) {
266 D(bug("%s: phy init failed.\n", dev->name));
267 return PHY_ERROR;
269 phy_reserved = mii_rw(dev, np->phyaddr, MII_NCONFIG, MII_READ);
270 phy_reserved |= PHY_INIT5;
271 if (mii_rw(dev, np->phyaddr, MII_NCONFIG, phy_reserved)) {
272 D(bug("%s: phy init failed.\n", dev->name));
273 return PHY_ERROR;
276 if (np->phy_oui == PHY_OUI_CICADA) {
277 phy_reserved = mii_rw(dev, np->phyaddr, MII_SREVISION, MII_READ);
278 phy_reserved |= PHY_INIT6;
279 if (mii_rw(dev, np->phyaddr, MII_SREVISION, phy_reserved)) {
280 D(bug("%s: phy init failed.\n", dev->name));
281 return PHY_ERROR;
285 /* restart auto negotiation */
286 mii_control = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
287 mii_control |= (BMCR_ANRESTART | BMCR_ANENABLE);
288 if (mii_rw(dev, np->phyaddr, MII_BMCR, mii_control)) {
289 return PHY_ERROR;
292 return 0;
295 static void nv_start_rx(struct net_device *dev)
297 struct fe_priv *np = get_nvpriv(dev);
298 UBYTE *base = get_hwbase(dev);
300 D(bug("%s: nv_start_rx\n", dev->name));
301 /* Already running? Stop it. */
302 if (readl(base + NvRegReceiverControl) & NVREG_RCVCTL_START) {
303 writel(0, base + NvRegReceiverControl);
304 pci_push(base);
306 writel(np->linkspeed, base + NvRegLinkSpeed);
307 pci_push(base);
308 writel(NVREG_RCVCTL_START, base + NvRegReceiverControl);
309 D(bug("%s: nv_start_rx to duplex %d, speed 0x%08x.\n",
310 dev->name, np->duplex, np->linkspeed));
311 pci_push(base);
314 static void nv_stop_rx(struct net_device *dev)
316 UBYTE *base = get_hwbase(dev);
318 D(bug("%s: nv_stop_rx\n", dev->name));
319 writel(0, base + NvRegReceiverControl);
320 reg_delay(dev, NvRegReceiverStatus, NVREG_RCVSTAT_BUSY, 0,
321 NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX,
322 "nv_stop_rx: ReceiverStatus remained busy");
324 udelay(NV_RXSTOP_DELAY2);
325 writel(0, base + NvRegLinkSpeed);
328 static void nv_start_tx(struct net_device *dev)
330 UBYTE *base = get_hwbase(dev);
332 D(bug("%s: nv_start_tx\n", dev->name));
333 writel(NVREG_XMITCTL_START, base + NvRegTransmitterControl);
334 pci_push(base);
337 static void nv_stop_tx(struct net_device *dev)
339 UBYTE *base = get_hwbase(dev);
341 D(bug("%s: nv_stop_tx\n", dev->name));
342 writel(0, base + NvRegTransmitterControl);
343 reg_delay(dev, NvRegTransmitterStatus, NVREG_XMITSTAT_BUSY, 0,
344 NV_TXSTOP_DELAY1, NV_TXSTOP_DELAY1MAX,
345 "nv_stop_tx: TransmitterStatus remained busy");
347 udelay(NV_TXSTOP_DELAY2);
348 writel(0, base + NvRegUnknownTransmitterReg);
351 static void nv_txrx_reset(struct net_device *dev)
353 struct fe_priv *np = get_nvpriv(dev);
354 UBYTE *base = get_hwbase(dev);
356 D(bug("%s: nv_txrx_reset\n", dev->name));
357 writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->desc_ver, base + NvRegTxRxControl);
358 pci_push(base);
359 udelay(NV_TXRX_RESET_DELAY);
360 writel(NVREG_TXRXCTL_BIT2 | np->desc_ver, base + NvRegTxRxControl);
361 pci_push(base);
365 * nv_set_multicast: dev->set_multicast function
366 * Called with dev->xmit_lock held.
368 static void nv_set_multicast(struct net_device *dev)
370 struct fe_priv *np = get_nvpriv(dev);
371 UBYTE *base = get_hwbase(dev);
372 ULONG addr[2];
373 ULONG mask[2];
374 ULONG pff;
376 memset(addr, 0, sizeof(addr));
377 memset(mask, 0, sizeof(mask));
379 if (dev->flags & IFF_PROMISC) {
380 D(bug("%s: Promiscuous mode enabled.\n", dev->name));
381 pff = NVREG_PFF_PROMISC;
382 } else {
383 pff = NVREG_PFF_MYADDR;
385 if (dev->flags & IFF_ALLMULTI || dev->mc_list) {
386 ULONG alwaysOff[2];
387 ULONG alwaysOn[2];
389 alwaysOn[0] = alwaysOn[1] = alwaysOff[0] = alwaysOff[1] = 0xffffffff;
390 if (dev->flags & IFF_ALLMULTI) {
391 alwaysOn[0] = alwaysOn[1] = alwaysOff[0] = alwaysOff[1] = 0;
392 } else {
393 struct dev_mc_list *walk;
395 walk = dev->mc_list;
396 while (walk != NULL) {
397 ULONG a, b;
398 a = AROS_LE2LONG(*(ULONG *) walk->dmi_addr);
399 b = AROS_LE2WORD(*(UWORD *) (&walk->dmi_addr[4]));
400 alwaysOn[0] &= a;
401 alwaysOff[0] &= ~a;
402 alwaysOn[1] &= b;
403 alwaysOff[1] &= ~b;
404 walk = walk->next;
407 addr[0] = alwaysOn[0];
408 addr[1] = alwaysOn[1];
409 mask[0] = alwaysOn[0] | alwaysOff[0];
410 mask[1] = alwaysOn[1] | alwaysOff[1];
413 addr[0] |= NVREG_MCASTADDRA_FORCE;
414 pff |= NVREG_PFF_ALWAYS;
415 ObtainSemaphore(&np->lock);
416 nv_stop_rx(dev);
417 writel(addr[0], base + NvRegMulticastAddrA);
418 writel(addr[1], base + NvRegMulticastAddrB);
419 writel(mask[0], base + NvRegMulticastMaskA);
420 writel(mask[1], base + NvRegMulticastMaskB);
421 writel(pff, base + NvRegPacketFilterFlags);
422 D(bug("%s: reconfiguration for multicast lists.\n",
423 dev->name));
424 nv_start_rx(dev);
425 ReleaseSemaphore(&np->lock);
428 static int nv_update_linkspeed(struct net_device *dev)
430 struct fe_priv *np = get_nvpriv(dev);
431 UBYTE *base = get_hwbase(dev);
432 int adv, lpa;
433 int newls = np->linkspeed;
434 int newdup = np->duplex;
435 int mii_status;
436 int retval = 0;
437 ULONG control_1000, status_1000, phyreg;
439 /* BMSR_LSTATUS is latched, read it twice:
440 * we want the current value.
442 mii_rw(dev, np->phyaddr, MII_BMSR, MII_READ);
443 mii_status = mii_rw(dev, np->phyaddr, MII_BMSR, MII_READ);
445 if (!(mii_status & BMSR_LSTATUS)) {
446 D(bug("%s: no link detected by phy - falling back to 10HD.\n",
447 dev->name));
448 newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
449 newdup = 0;
450 retval = 0;
451 goto set_speed;
454 if (np->autoneg == 0) {
455 D(bug("%s: nv_update_linkspeed: autoneg off, PHY set to 0x%04x.\n",
456 dev->name, np->fixed_mode));
457 if (np->fixed_mode & LPA_100FULL) {
458 newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_100;
459 newdup = 1;
460 } else if (np->fixed_mode & LPA_100HALF) {
461 newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_100;
462 newdup = 0;
463 } else if (np->fixed_mode & LPA_10FULL) {
464 newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
465 newdup = 1;
466 } else {
467 newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
468 newdup = 0;
470 retval = 1;
471 goto set_speed;
473 /* check auto negotiation is complete */
474 if (!(mii_status & BMSR_ANEGCOMPLETE)) {
475 /* still in autonegotiation - configure nic for 10 MBit HD and wait. */
476 newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
477 newdup = 0;
478 retval = 0;
479 D(bug("%s: autoneg not completed - falling back to 10HD.\n", dev->name));
480 goto set_speed;
483 retval = 1;
484 if (np->gigabit == PHY_GIGABIT) {
485 control_1000 = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ);
486 status_1000 = mii_rw(dev, np->phyaddr, MII_1000BT_SR, MII_READ);
488 if ((control_1000 & ADVERTISE_1000FULL) &&
489 (status_1000 & LPA_1000FULL)) {
490 D(bug("%s: nv_update_linkspeed: GBit ethernet detected.\n",
491 dev->name));
492 newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_1000;
493 newdup = 1;
494 goto set_speed;
498 adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
499 lpa = mii_rw(dev, np->phyaddr, MII_LPA, MII_READ);
500 D(bug("%s: nv_update_linkspeed: PHY advertises 0x%04x, lpa 0x%04x.\n",
501 dev->name, adv, lpa));
502 /* FIXME: handle parallel detection properly */
503 lpa = lpa & adv;
504 if (lpa & LPA_100FULL) {
505 newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_100;
506 newdup = 1;
507 } else if (lpa & LPA_100HALF) {
508 newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_100;
509 newdup = 0;
510 } else if (lpa & LPA_10FULL) {
511 newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
512 newdup = 1;
513 } else if (lpa & LPA_10HALF) {
514 newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
515 newdup = 0;
516 } else {
517 D(bug("%s: bad ability %04x - falling back to 10HD.\n", dev->name, lpa));
518 newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
519 newdup = 0;
522 set_speed:
523 if (np->duplex == newdup && np->linkspeed == newls)
524 return retval;
526 D(bug("%s: changing link setting from %d/%d to %d/%d.\n",
527 dev->name, np->linkspeed, np->duplex, newls, newdup));
529 np->duplex = newdup;
530 np->linkspeed = newls;
531 if (np->gigabit == PHY_GIGABIT) {
532 phyreg = readl(base + NvRegRandomSeed);
533 phyreg &= ~(0x3FF00);
534 if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_10)
535 phyreg |= NVREG_RNDSEED_FORCE3;
536 else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100)
537 phyreg |= NVREG_RNDSEED_FORCE2;
538 else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000)
539 phyreg |= NVREG_RNDSEED_FORCE;
540 writel(phyreg, base + NvRegRandomSeed);
543 phyreg = readl(base + NvRegPhyInterface);
544 phyreg &= ~(PHY_HALF|PHY_100|PHY_1000);
545 if (np->duplex == 0)
546 phyreg |= PHY_HALF;
547 if ((np->linkspeed & NVREG_LINKSPEED_MASK) == NVREG_LINKSPEED_100)
548 phyreg |= PHY_100;
549 else if ((np->linkspeed & NVREG_LINKSPEED_MASK) == NVREG_LINKSPEED_1000)
550 phyreg |= PHY_1000;
551 writel(phyreg, base + NvRegPhyInterface);
553 writel(NVREG_MISC1_FORCE | ( np->duplex ? 0 : NVREG_MISC1_HD),
554 base + NvRegMisc1);
555 pci_push(base);
556 writel(np->linkspeed, base + NvRegLinkSpeed);
557 pci_push(base);
559 return retval;
562 static void nv_linkchange(struct net_device *dev)
564 if (nv_update_linkspeed(dev)) {
565 if (netif_carrier_ok(dev)) {
566 nv_stop_rx(dev);
567 } else {
568 netif_carrier_on(dev);
569 D(bug("%s: link up.\n", dev->name));
571 nv_start_rx(dev);
572 } else {
573 if (netif_carrier_ok(dev)) {
574 netif_carrier_off(dev);
575 D(bug("%s: link down.\n", dev->name));
576 nv_stop_rx(dev);
581 static void nv_deinitialize(struct net_device *dev)
585 static void nv_initialize(struct net_device *dev)
587 struct fe_priv *np = dev->nu_fe_priv;
588 UBYTE *base = get_hwbase(dev);
589 int i;
591 np->rx_ring = HIDD_PCIDriver_AllocPCIMem(
592 dev->nu_PCIDriver,
593 sizeof(struct ring_desc) * (RX_RING + TX_RING));
595 np->ring_addr = (IPTR)np->rx_ring;
596 np->tx_ring = &np->rx_ring[RX_RING];
598 np->orig_mac[0] = readl(base + NvRegMacAddrA);
599 np->orig_mac[1] = readl(base + NvRegMacAddrB);
601 dev->dev_addr[0] = dev->org_addr[0] = (np->orig_mac[1] >> 8) & 0xff;
602 dev->dev_addr[1] = dev->org_addr[1] = (np->orig_mac[1] >> 0) & 0xff;
603 dev->dev_addr[2] = dev->org_addr[2] = (np->orig_mac[0] >> 24) & 0xff;
604 dev->dev_addr[3] = dev->org_addr[3] = (np->orig_mac[0] >> 16) & 0xff;
605 dev->dev_addr[4] = dev->org_addr[4] = (np->orig_mac[0] >> 8) & 0xff;
606 dev->dev_addr[5] = dev->org_addr[5] = (np->orig_mac[0] >> 0) & 0xff;
608 D(bug("%s: MAC Address %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name,
609 dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
610 dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]));
612 /* disable WOL */
613 writel(0, base + NvRegWakeUpFlags);
614 np->wolenabled = 0;
616 if (np->desc_ver == DESC_VER_1) {
617 np->tx_flags = NV_TX_LASTPACKET|NV_TX_VALID;
618 if (dev->nu_DriverFlags & DEV_NEED_LASTPACKET1)
619 np->tx_flags |= NV_TX_LASTPACKET1;
620 } else {
621 np->tx_flags = NV_TX2_LASTPACKET|NV_TX2_VALID;
622 if (dev->nu_DriverFlags & DEV_NEED_LASTPACKET1)
623 np->tx_flags |= NV_TX2_LASTPACKET1;
625 if (dev->nu_DriverFlags & DEV_IRQMASK_1)
626 np->irqmask = NVREG_IRQMASK_WANTED_1;
627 if (dev->nu_DriverFlags & DEV_IRQMASK_2)
628 np->irqmask = NVREG_IRQMASK_WANTED_2;
629 if (dev->nu_DriverFlags & DEV_NEED_TIMERIRQ)
630 np->irqmask |= NVREG_IRQ_TIMER;
631 if (dev->nu_DriverFlags & DEV_NEED_LINKTIMER) {
632 D(bug("%s: link timer on.\n", pci_name(dev)));
633 np->need_linktimer = 1;
634 np->link_timeout.tv_micro = LINK_TIMEOUT % 1000000;
635 np->link_timeout.tv_secs = LINK_TIMEOUT / 1000000;
636 } else {
637 D(bug("%s: link timer off.\n", pci_name(dev)));
638 np->need_linktimer = 0;
641 /* find a suitable phy */
642 for (i = 1; i < 32; i++) {
643 int id1, id2;
645 ObtainSemaphore(&np->lock);
646 id1 = mii_rw(dev, i, MII_PHYSID1, MII_READ);
647 ReleaseSemaphore(&np->lock);
648 if (id1 < 0 || id1 == 0xffff)
649 continue;
650 ObtainSemaphore(&np->lock);
651 id2 = mii_rw(dev, i, MII_PHYSID2, MII_READ);
652 ReleaseSemaphore(&np->lock);
653 if (id2 < 0 || id2 == 0xffff)
654 continue;
656 id1 = (id1 & PHYID1_OUI_MASK) << PHYID1_OUI_SHFT;
657 id2 = (id2 & PHYID2_OUI_MASK) >> PHYID2_OUI_SHFT;
658 D(bug("%s: open: Found PHY %04x:%04x at address %d.\n",
659 pci_name(dev), id1, id2, i));
660 np->phyaddr = i;
661 np->phy_oui = id1 | id2;
662 break;
665 if (i == 32) {
666 /* PHY in isolate mode? No phy attached and user wants to
667 * test loopback? Very odd, but can be correct.
669 D(bug("%s: open: Could not find a valid PHY.\n",
670 pci_name(dev)));
673 if (i != 32) {
674 /* reset it */
675 phy_init(dev);
678 /* set default link speed settings */
679 np->linkspeed = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
680 np->duplex = 0;
681 np->autoneg = 1;
684 static void nv_drain_tx(struct net_device *dev)
686 struct fe_priv *np = get_nvpriv(dev);
687 int i;
688 for (i = 0; i < TX_RING; i++) {
689 np->tx_ring[i].FlagLen = 0;
693 static void nv_drain_rx(struct net_device *dev)
695 struct fe_priv *np = get_nvpriv(dev);
696 int i;
697 for (i = 0; i < RX_RING; i++) {
698 np->rx_ring[i].FlagLen = 0;
703 static void drain_ring(struct net_device *dev)
705 nv_drain_tx(dev);
706 nv_drain_rx(dev);
709 static int request_irq(struct net_device *dev)
711 OOP_Object *irq = OOP_NewObject(NULL, CLID_Hidd_IRQ, NULL);
712 BOOL ret;
714 if (irq)
716 ret = HIDD_IRQ_AddHandler(irq, dev->nu_irqhandler, dev->nu_IRQ);
717 HIDD_IRQ_AddHandler(irq, dev->nu_touthandler, vHidd_IRQ_Timer);
719 OOP_DisposeObject(irq);
721 if (ret)
723 return 0;
726 return 1;
729 static void free_irq(struct net_device *dev)
731 OOP_Object *irq = OOP_NewObject(NULL, CLID_Hidd_IRQ, NULL);
732 if (irq)
734 HIDD_IRQ_RemHandler(irq, dev->nu_irqhandler);
735 HIDD_IRQ_RemHandler(irq, dev->nu_touthandler);
736 OOP_DisposeObject(irq);
740 static void nv_set_mac(struct net_device *dev)
742 UBYTE *base = get_hwbase(dev);
743 ULONG mac[2];
745 mac[0] = (dev->dev_addr[0] << 0) + (dev->dev_addr[1] << 8) +
746 (dev->dev_addr[2] << 16) + (dev->dev_addr[3] << 24);
747 mac[1] = (dev->dev_addr[4] << 0) + (dev->dev_addr[5] << 8);
749 writel(mac[0], base + NvRegMacAddrA);
750 writel(mac[1], base + NvRegMacAddrB);
754 * nv_alloc_rx: fill rx ring entries.
755 * Return 1 if the allocations for the skbs failed and the
756 * rx engine is without Available descriptors
758 static int nv_alloc_rx(struct net_device *dev)
760 struct fe_priv *np = get_nvpriv(dev);
761 unsigned int refill_rx = np->refill_rx;
762 int nr;
764 while (np->cur_rx != refill_rx) {
765 nr = refill_rx % RX_RING;
767 np->rx_ring[nr].FlagLen = AROS_LONG2LE(RX_NIC_BUFSIZE | NV_RX_AVAIL);
768 D(bug("%s: nv_alloc_rx: Packet %d marked as Available\n", dev->name, refill_rx));
769 refill_rx++;
771 np->refill_rx = refill_rx;
772 if (np->cur_rx - refill_rx == RX_RING)
773 return 1;
774 return 0;
778 static int nv_init_ring(struct net_device *dev)
780 struct fe_priv *np = get_nvpriv(dev);
781 int i;
783 np->next_tx = np->nic_tx = 0;
784 for (i = 0; i < TX_RING; i++)
785 np->tx_ring[i].FlagLen = 0;
787 np->cur_rx = RX_RING;
788 np->refill_rx = 0;
789 for (i = 0; i < RX_RING; i++)
790 np->rx_ring[i].FlagLen = 0;
791 return nv_alloc_rx(dev);
794 static int nv_open(struct net_device *dev)
796 struct fe_priv *np = get_nvpriv(dev);
797 UBYTE *base = get_hwbase(dev);
798 int ret, oom, i;
800 oom = 0;
802 np->rx_buffer = HIDD_PCIDriver_AllocPCIMem(
803 dev->nu_PCIDriver,
804 RX_RING * sizeof(struct eth_frame));
806 if (np->rx_buffer == NULL)
807 oom = 1;
809 np->tx_buffer = HIDD_PCIDriver_AllocPCIMem(
810 dev->nu_PCIDriver,
811 TX_RING * sizeof(struct eth_frame));
813 if (np->tx_buffer == NULL)
814 oom = 1;
816 for (i=0; i < TX_RING; i++)
817 np->tx_ring[i].PacketBuffer = (IPTR)&np->tx_buffer[i];
819 for (i=0; i < RX_RING; i++)
820 np->rx_ring[i].PacketBuffer = (IPTR)&np->rx_buffer[i];
822 D(bug("nv_open: begin\n"));
824 /* 1) erase previous misconfiguration */
825 /* 4.1-1: stop adapter: ignored, 4.3 seems to be overkill */
826 writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA);
827 writel(0, base + NvRegMulticastAddrB);
828 writel(0, base + NvRegMulticastMaskA);
829 writel(0, base + NvRegMulticastMaskB);
830 writel(0, base + NvRegPacketFilterFlags);
832 writel(0, base + NvRegTransmitterControl);
833 writel(0, base + NvRegReceiverControl);
835 writel(0, base + NvRegAdapterControl);
837 /* 2) initialize descriptor rings */
838 oom = nv_init_ring(dev);
840 writel(0, base + NvRegLinkSpeed);
841 writel(0, base + NvRegUnknownTransmitterReg);
842 nv_txrx_reset(dev);
843 writel(0, base + NvRegUnknownSetupReg6);
845 np->in_shutdown = 0;
847 /* 3) set mac address */
848 nv_set_mac(dev);
850 /* 4) give hw rings */
851 writel((ULONG) np->ring_addr, base + NvRegRxRingPhysAddr);
852 writel((ULONG) (np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
853 writel( ((RX_RING-1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING-1) << NVREG_RINGSZ_TXSHIFT),
854 base + NvRegRingSizes);
856 /* 5) continue setup */
857 writel(np->linkspeed, base + NvRegLinkSpeed);
858 writel(NVREG_UNKSETUP3_VAL1, base + NvRegUnknownSetupReg3);
859 writel(np->desc_ver, base + NvRegTxRxControl);
860 pci_push(base);
861 writel(NVREG_TXRXCTL_BIT1|np->desc_ver, base + NvRegTxRxControl);
862 reg_delay(dev, NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31, NVREG_UNKSETUP5_BIT31,
863 NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX,
864 "open: SetupReg5, Bit 31 remained off\n");
866 writel(0, base + NvRegUnknownSetupReg4);
867 writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
868 writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus);
870 /* 6) continue setup */
871 writel(NVREG_MISC1_FORCE | NVREG_MISC1_HD, base + NvRegMisc1);
872 writel(readl(base + NvRegTransmitterStatus), base + NvRegTransmitterStatus);
873 writel(NVREG_PFF_ALWAYS, base + NvRegPacketFilterFlags);
874 writel(NVREG_OFFLOAD_NORMAL, base + NvRegOffloadConfig);
876 writel(readl(base + NvRegReceiverStatus), base + NvRegReceiverStatus);
877 i = random();
878 writel(NVREG_RNDSEED_FORCE | (i&NVREG_RNDSEED_MASK), base + NvRegRandomSeed);
879 writel(NVREG_UNKSETUP1_VAL, base + NvRegUnknownSetupReg1);
880 writel(NVREG_UNKSETUP2_VAL, base + NvRegUnknownSetupReg2);
881 writel(NVREG_POLL_DEFAULT, base + NvRegPollingInterval);
882 writel(NVREG_UNKSETUP6_VAL, base + NvRegUnknownSetupReg6);
883 writel((np->phyaddr << NVREG_ADAPTCTL_PHYSHIFT)|NVREG_ADAPTCTL_PHYVALID|NVREG_ADAPTCTL_RUNNING,
884 base + NvRegAdapterControl);
885 writel(NVREG_MIISPEED_BIT8|NVREG_MIIDELAY, base + NvRegMIISpeed);
886 writel(NVREG_UNKSETUP4_VAL, base + NvRegUnknownSetupReg4);
887 writel(NVREG_WAKEUPFLAGS_VAL, base + NvRegWakeUpFlags);
889 i = readl(base + NvRegPowerState);
890 if ( (i & NVREG_POWERSTATE_POWEREDUP) == 0)
891 writel(NVREG_POWERSTATE_POWEREDUP|i, base + NvRegPowerState);
893 pci_push(base);
894 udelay(10);
895 writel(readl(base + NvRegPowerState) | NVREG_POWERSTATE_VALID, base + NvRegPowerState);
897 writel(0, base + NvRegIrqMask);
898 pci_push(base);
899 writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus);
900 writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
901 pci_push(base);
903 ret = request_irq(dev);
904 if (ret)
905 goto out_drain;
907 /* ask for interrupts */
908 writel(np->irqmask, base + NvRegIrqMask);
910 ObtainSemaphore(&np->lock);
911 writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA);
912 writel(0, base + NvRegMulticastAddrB);
913 writel(0, base + NvRegMulticastMaskA);
914 writel(0, base + NvRegMulticastMaskB);
915 writel(NVREG_PFF_ALWAYS|NVREG_PFF_MYADDR, base + NvRegPacketFilterFlags);
916 /* One manual link speed update: Interrupts are enabled, future link
917 * speed changes cause interrupts and are handled by nv_link_irq().
920 ULONG miistat;
921 miistat = readl(base + NvRegMIIStatus);
922 writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus);
923 D(bug("startup: got 0x%08x.\n", miistat));
925 ret = nv_update_linkspeed(dev);
926 nv_start_rx(dev);
927 nv_start_tx(dev);
928 netif_start_queue(dev);
929 if (ret) {
930 netif_carrier_on(dev);
931 } else {
932 bug("%s: no link during initialization.\n", dev->name);
933 netif_carrier_off(dev);
935 if (oom) {
936 bug("%s: Out Of Memory. PANIC!\n", dev->name);
937 ret = 1;
938 goto out_drain;
941 ReleaseSemaphore(&np->lock);
942 dev->flags |= IFF_UP;
943 ReportEvents(LIBBASE, dev, S2EVENT_ONLINE);
945 return 0;
947 out_drain:
948 drain_ring(dev);
949 return ret;
952 static int nv_close(struct net_device *dev)
954 struct fe_priv *np = get_nvpriv(dev);
955 UBYTE *base;
957 dev->flags &= ~IFF_UP;
959 ObtainSemaphore(&np->lock);
960 np->in_shutdown = 1;
961 ReleaseSemaphore(&np->lock);
963 dev->nu_toutNEED = FALSE;
965 netif_stop_queue(dev);
966 ObtainSemaphore(&np->lock);
967 nv_stop_tx(dev);
968 nv_stop_rx(dev);
969 nv_txrx_reset(dev);
971 /* disable interrupts on the nic or we will lock up */
972 base = get_hwbase(dev);
973 writel(0, base + NvRegIrqMask);
974 pci_push(base);
975 D(bug("%s: Irqmask is zero again\n", dev->name));
977 ReleaseSemaphore(&np->lock);
979 free_irq(dev);
981 drain_ring(dev);
983 HIDD_PCIDriver_FreePCIMem(dev->nu_PCIDriver, np->rx_buffer);
984 HIDD_PCIDriver_FreePCIMem(dev->nu_PCIDriver, np->tx_buffer);
986 if (np->wolenabled)
987 nv_start_rx(dev);
989 /* FIXME: power down nic */
991 ReportEvents(LIBBASE, dev, S2EVENT_OFFLINE);
993 return 0;
996 static void nv_link_irq(struct net_device *dev)
998 UBYTE *base = get_hwbase(dev);
999 ULONG miistat;
1001 miistat = readl(base + NvRegMIIStatus);
1002 writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus);
1003 D(bug("%s: link change irq, status 0x%x.\n", dev->name, miistat));
1005 if (miistat & (NVREG_MIISTAT_LINKCHANGE))
1006 dev->linkchange(dev);
1007 D(bug("%s: link change notification done.\n", dev->name));
1010 void nv_get_functions(struct net_device *Unit)
1012 Unit->initialize = nv_initialize;
1013 Unit->deinitialize = nv_deinitialize;
1014 Unit->start = nv_open;
1015 Unit->stop = nv_close;
1016 Unit->set_mac_address = nv_set_mac;
1017 Unit->linkchange = nv_linkchange;
1018 Unit->linkirq = nv_link_irq;
1019 Unit->descr_getlength = nv_descr_getlength;
1020 Unit->alloc_rx = nv_alloc_rx;
1021 Unit->set_multicast = nv_set_multicast;