Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / devs / networks / nForce / nforce.c
blob31b6d85009ff1d6631a81253154e2de1b7e02225
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>
45 #include <proto/oop.h>
46 #include <proto/exec.h>
47 #include <proto/dos.h>
48 #include <proto/battclock.h>
50 #include <hardware/intbits.h>
52 #include <stdlib.h>
54 #include "nforce.h"
55 #include "unit.h"
56 #include LC_LIBDEFS_FILE
58 /* A bit fixed linux stuff here :) */
60 #undef LIBBASE
61 #define LIBBASE (dev->nu_device)
63 #define net_device NFUnit
65 #define TIMER_RPROK 3599597124UL
67 static ULONG usec2tick(ULONG usec)
69 ULONG ret, timer_rpr = TIMER_RPROK;
70 asm volatile("movl $0,%%eax; divl %2":"=a"(ret):"d"(usec),"m"(timer_rpr));
71 return ret;
74 void udelay(LONG usec)
76 int oldtick, tick;
77 usec = usec2tick(usec);
79 BYTEOUT(0x43, 0x80);
80 oldtick = BYTEIN(0x42);
81 oldtick += BYTEIN(0x42) << 8;
83 while (usec > 0)
85 BYTEOUT(0x43, 0x80);
86 tick = BYTEIN(0x42);
87 tick += BYTEIN(0x42) << 8;
89 usec -= (oldtick - tick);
90 if (tick > oldtick) usec -= 0x10000;
91 oldtick = tick;
95 static ULONG readl(APTR base)
97 return *((volatile ULONG*)base);
99 static void writel(ULONG val, APTR base)
101 *((volatile ULONG*)base) = val;
104 static inline struct fe_priv *get_nvpriv(struct net_device *dev)
106 return dev->nu_fe_priv;
109 static inline UBYTE *get_hwbase(struct net_device *dev)
111 return (UBYTE*)dev->nu_BaseMem;
114 static inline void pci_push(UBYTE *base)
116 /* force out pending posted writes */
117 readl(base);
120 static inline ULONG nv_descr_getlength(struct ring_desc *prd, ULONG v)
122 return AROS_LE2LONG(prd->FlagLen)
123 & ((v == DESC_VER_1) ? LEN_MASK_V1 : LEN_MASK_V2);
126 static int reg_delay(struct net_device *dev, int offset, ULONG mask, ULONG target,
127 int delay, int delaymax, const char *msg)
129 UBYTE *base = get_hwbase(dev);
131 pci_push(base);
132 do {
133 udelay(delay);
134 delaymax -= delay;
135 if (delaymax < 0) {
136 if (msg)
137 D(bug(msg));
138 return 1;
140 } while ((readl(base + offset) & mask) != target);
141 return 0;
144 #define MII_READ (-1)
145 /* mii_rw: read/write a register on the PHY.
147 * Caller must guarantee serialization
149 static int mii_rw(struct net_device *dev, int addr, int miireg, int value)
151 UBYTE *base = get_hwbase(dev);
152 ULONG reg;
153 int retval;
155 writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus);
157 reg = readl(base + NvRegMIIControl);
158 if (reg & NVREG_MIICTL_INUSE) {
159 writel(NVREG_MIICTL_INUSE, base + NvRegMIIControl);
160 udelay(NV_MIIBUSY_DELAY);
163 reg = (addr << NVREG_MIICTL_ADDRSHIFT) | miireg;
164 if (value != MII_READ) {
165 writel(value, base + NvRegMIIData);
166 reg |= NVREG_MIICTL_WRITE;
168 writel(reg, base + NvRegMIIControl);
170 if (reg_delay(dev, NvRegMIIControl, NVREG_MIICTL_INUSE, 0,
171 NV_MIIPHY_DELAY, NV_MIIPHY_DELAYMAX, NULL)) {
172 D(bug("%s: mii_rw of reg %d at PHY %d timed out.\n",
173 dev->name, miireg, addr));
174 retval = -1;
175 } else if (value != MII_READ) {
176 /* it was a write operation - fewer failures are detectable */
177 D(bug("%s: mii_rw wrote 0x%x to reg %d at PHY %d\n",
178 dev->name, value, miireg, addr));
179 retval = 0;
180 } else if (readl(base + NvRegMIIStatus) & NVREG_MIISTAT_ERROR) {
181 D(bug("%s: mii_rw of reg %d at PHY %d failed.\n",
182 dev->name, miireg, addr));
183 retval = -1;
184 } else {
185 retval = readl(base + NvRegMIIData);
186 D(bug("%s: mii_rw read from reg %d at PHY %d: 0x%x.\n",
187 dev->name, miireg, addr, retval));
190 return retval;
193 static int phy_reset(struct net_device *dev)
195 struct fe_priv *np = get_nvpriv(dev);
196 ULONG miicontrol;
197 unsigned int tries = 0;
199 miicontrol = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
200 miicontrol |= BMCR_RESET;
201 if (mii_rw(dev, np->phyaddr, MII_BMCR, miicontrol)) {
202 return -1;
205 /* wait for 500ms */
206 Delay(25);
208 /* must wait till reset is deasserted */
209 while (miicontrol & BMCR_RESET) {
210 Delay(1);
211 miicontrol = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
212 /* FIXME: 100 tries seem excessive */
213 if (tries++ > 100)
214 return -1;
216 return 0;
219 static int phy_init(struct net_device *dev)
221 struct fe_priv *np = get_nvpriv(dev);
222 UBYTE *base = get_hwbase(dev);
223 ULONG phyinterface, phy_reserved, mii_status, mii_control, mii_control_1000,reg;
225 /* set advertise register */
226 reg = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
227 reg |= (ADVERTISE_10HALF|ADVERTISE_10FULL|ADVERTISE_100HALF|ADVERTISE_100FULL|0x800|0x400);
228 if (mii_rw(dev, np->phyaddr, MII_ADVERTISE, reg)) {
229 D(bug("%s: phy write to advertise failed.\n", dev->name));
230 return PHY_ERROR;
233 /* get phy interface type */
234 phyinterface = readl(base + NvRegPhyInterface);
236 /* see if gigabit phy */
237 mii_status = mii_rw(dev, np->phyaddr, MII_BMSR, MII_READ);
238 if (mii_status & PHY_GIGABIT) {
239 np->gigabit = PHY_GIGABIT;
240 mii_control_1000 = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ);
241 mii_control_1000 &= ~ADVERTISE_1000HALF;
242 if (phyinterface & PHY_RGMII)
243 mii_control_1000 |= ADVERTISE_1000FULL;
244 else
245 mii_control_1000 &= ~ADVERTISE_1000FULL;
247 if (mii_rw(dev, np->phyaddr, MII_1000BT_CR, mii_control_1000)) {
248 D(bug("%s: phy init failed.\n", dev->name));
249 return PHY_ERROR;
252 else
253 np->gigabit = 0;
255 /* reset the phy */
256 if (phy_reset(dev)) {
257 D(bug("%s: phy reset failed\n", dev->name));
258 return PHY_ERROR;
261 /* phy vendor specific configuration */
262 if ((np->phy_oui == PHY_OUI_CICADA) && (phyinterface & PHY_RGMII) ) {
263 phy_reserved = mii_rw(dev, np->phyaddr, MII_RESV1, MII_READ);
264 phy_reserved &= ~(PHY_INIT1 | PHY_INIT2);
265 phy_reserved |= (PHY_INIT3 | PHY_INIT4);
266 if (mii_rw(dev, np->phyaddr, MII_RESV1, phy_reserved)) {
267 D(bug("%s: phy init failed.\n", dev->name));
268 return PHY_ERROR;
270 phy_reserved = mii_rw(dev, np->phyaddr, MII_NCONFIG, MII_READ);
271 phy_reserved |= PHY_INIT5;
272 if (mii_rw(dev, np->phyaddr, MII_NCONFIG, phy_reserved)) {
273 D(bug("%s: phy init failed.\n", dev->name));
274 return PHY_ERROR;
277 if (np->phy_oui == PHY_OUI_CICADA) {
278 phy_reserved = mii_rw(dev, np->phyaddr, MII_SREVISION, MII_READ);
279 phy_reserved |= PHY_INIT6;
280 if (mii_rw(dev, np->phyaddr, MII_SREVISION, phy_reserved)) {
281 D(bug("%s: phy init failed.\n", dev->name));
282 return PHY_ERROR;
286 /* restart auto negotiation */
287 mii_control = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
288 mii_control |= (BMCR_ANRESTART | BMCR_ANENABLE);
289 if (mii_rw(dev, np->phyaddr, MII_BMCR, mii_control)) {
290 return PHY_ERROR;
293 return 0;
296 static void nv_start_rx(struct net_device *dev)
298 struct fe_priv *np = get_nvpriv(dev);
299 UBYTE *base = get_hwbase(dev);
301 D(bug("%s: nv_start_rx\n", dev->name));
302 /* Already running? Stop it. */
303 if (readl(base + NvRegReceiverControl) & NVREG_RCVCTL_START) {
304 writel(0, base + NvRegReceiverControl);
305 pci_push(base);
307 writel(np->linkspeed, base + NvRegLinkSpeed);
308 pci_push(base);
309 writel(NVREG_RCVCTL_START, base + NvRegReceiverControl);
310 D(bug("%s: nv_start_rx to duplex %d, speed 0x%08x.\n",
311 dev->name, np->duplex, np->linkspeed));
312 pci_push(base);
315 static void nv_stop_rx(struct net_device *dev)
317 UBYTE *base = get_hwbase(dev);
319 D(bug("%s: nv_stop_rx\n", dev->name));
320 writel(0, base + NvRegReceiverControl);
321 reg_delay(dev, NvRegReceiverStatus, NVREG_RCVSTAT_BUSY, 0,
322 NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX,
323 "nv_stop_rx: ReceiverStatus remained busy");
325 udelay(NV_RXSTOP_DELAY2);
326 writel(0, base + NvRegLinkSpeed);
329 static void nv_start_tx(struct net_device *dev)
331 UBYTE *base = get_hwbase(dev);
333 D(bug("%s: nv_start_tx\n", dev->name));
334 writel(NVREG_XMITCTL_START, base + NvRegTransmitterControl);
335 pci_push(base);
338 static void nv_stop_tx(struct net_device *dev)
340 UBYTE *base = get_hwbase(dev);
342 D(bug("%s: nv_stop_tx\n", dev->name));
343 writel(0, base + NvRegTransmitterControl);
344 reg_delay(dev, NvRegTransmitterStatus, NVREG_XMITSTAT_BUSY, 0,
345 NV_TXSTOP_DELAY1, NV_TXSTOP_DELAY1MAX,
346 "nv_stop_tx: TransmitterStatus remained busy");
348 udelay(NV_TXSTOP_DELAY2);
349 writel(0, base + NvRegUnknownTransmitterReg);
352 static void nv_txrx_reset(struct net_device *dev)
354 struct fe_priv *np = get_nvpriv(dev);
355 UBYTE *base = get_hwbase(dev);
357 D(bug("%s: nv_txrx_reset\n", dev->name));
358 writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->desc_ver, base + NvRegTxRxControl);
359 pci_push(base);
360 udelay(NV_TXRX_RESET_DELAY);
361 writel(NVREG_TXRXCTL_BIT2 | np->desc_ver, base + NvRegTxRxControl);
362 pci_push(base);
366 * nv_set_multicast: dev->set_multicast function
367 * Called with dev->xmit_lock held.
369 static void nv_set_multicast(struct net_device *dev)
371 struct fe_priv *np = get_nvpriv(dev);
372 UBYTE *base = get_hwbase(dev);
373 ULONG addr[2];
374 ULONG mask[2];
375 ULONG pff;
377 memset(addr, 0, sizeof(addr));
378 memset(mask, 0, sizeof(mask));
380 if (dev->flags & IFF_PROMISC) {
381 D(bug("%s: Promiscuous mode enabled.\n", dev->name));
382 pff = NVREG_PFF_PROMISC;
383 } else {
384 pff = NVREG_PFF_MYADDR;
386 if (dev->flags & IFF_ALLMULTI || dev->mc_list) {
387 ULONG alwaysOff[2];
388 ULONG alwaysOn[2];
390 alwaysOn[0] = alwaysOn[1] = alwaysOff[0] = alwaysOff[1] = 0xffffffff;
391 if (dev->flags & IFF_ALLMULTI) {
392 alwaysOn[0] = alwaysOn[1] = alwaysOff[0] = alwaysOff[1] = 0;
393 } else {
394 struct dev_mc_list *walk;
396 walk = dev->mc_list;
397 while (walk != NULL) {
398 ULONG a, b;
399 a = (walk->dmi_addr[0] << 0) |
400 (walk->dmi_addr[1] << 8) |
401 (walk->dmi_addr[2] << 16) |
402 (walk->dmi_addr[3] << 24);
403 b = (walk->dmi_addr[4] << 0) |
404 (walk->dmi_addr[5] << 8);
405 alwaysOn[0] &= a;
406 alwaysOff[0] &= ~a;
407 alwaysOn[1] &= b;
408 alwaysOff[1] &= ~b;
409 walk = walk->next;
412 addr[0] = alwaysOn[0];
413 addr[1] = alwaysOn[1];
414 mask[0] = alwaysOn[0] | alwaysOff[0];
415 mask[1] = alwaysOn[1] | alwaysOff[1];
418 addr[0] |= NVREG_MCASTADDRA_FORCE;
419 pff |= NVREG_PFF_ALWAYS;
420 ObtainSemaphore(&np->lock);
421 nv_stop_rx(dev);
422 writel(addr[0], base + NvRegMulticastAddrA);
423 writel(addr[1], base + NvRegMulticastAddrB);
424 writel(mask[0], base + NvRegMulticastMaskA);
425 writel(mask[1], base + NvRegMulticastMaskB);
426 writel(pff, base + NvRegPacketFilterFlags);
427 D(bug("%s: reconfiguration for multicast lists.\n",
428 dev->name));
429 nv_start_rx(dev);
430 ReleaseSemaphore(&np->lock);
433 static int nv_update_linkspeed(struct net_device *dev)
435 struct fe_priv *np = get_nvpriv(dev);
436 UBYTE *base = get_hwbase(dev);
437 int adv, lpa;
438 int newls = np->linkspeed;
439 int newdup = np->duplex;
440 int mii_status;
441 int retval = 0;
442 ULONG control_1000, status_1000, phyreg;
444 /* BMSR_LSTATUS is latched, read it twice:
445 * we want the current value.
447 mii_rw(dev, np->phyaddr, MII_BMSR, MII_READ);
448 mii_status = mii_rw(dev, np->phyaddr, MII_BMSR, MII_READ);
450 if (!(mii_status & BMSR_LSTATUS)) {
451 D(bug("%s: no link detected by phy - falling back to 10HD.\n",
452 dev->name));
453 newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
454 newdup = 0;
455 retval = 0;
456 goto set_speed;
459 if (np->autoneg == 0) {
460 D(bug("%s: nv_update_linkspeed: autoneg off, PHY set to 0x%04x.\n",
461 dev->name, np->fixed_mode));
462 if (np->fixed_mode & LPA_100FULL) {
463 newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_100;
464 newdup = 1;
465 } else if (np->fixed_mode & LPA_100HALF) {
466 newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_100;
467 newdup = 0;
468 } else if (np->fixed_mode & LPA_10FULL) {
469 newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
470 newdup = 1;
471 } else {
472 newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
473 newdup = 0;
475 retval = 1;
476 goto set_speed;
478 /* check auto negotiation is complete */
479 if (!(mii_status & BMSR_ANEGCOMPLETE)) {
480 /* still in autonegotiation - configure nic for 10 MBit HD and wait. */
481 newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
482 newdup = 0;
483 retval = 0;
484 D(bug("%s: autoneg not completed - falling back to 10HD.\n", dev->name));
485 goto set_speed;
488 retval = 1;
489 if (np->gigabit == PHY_GIGABIT) {
490 control_1000 = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ);
491 status_1000 = mii_rw(dev, np->phyaddr, MII_1000BT_SR, MII_READ);
493 if ((control_1000 & ADVERTISE_1000FULL) &&
494 (status_1000 & LPA_1000FULL)) {
495 D(bug("%s: nv_update_linkspeed: GBit ethernet detected.\n",
496 dev->name));
497 newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_1000;
498 newdup = 1;
499 goto set_speed;
503 adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
504 lpa = mii_rw(dev, np->phyaddr, MII_LPA, MII_READ);
505 D(bug("%s: nv_update_linkspeed: PHY advertises 0x%04x, lpa 0x%04x.\n",
506 dev->name, adv, lpa));
507 /* FIXME: handle parallel detection properly */
508 lpa = lpa & adv;
509 if (lpa & LPA_100FULL) {
510 newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_100;
511 newdup = 1;
512 } else if (lpa & LPA_100HALF) {
513 newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_100;
514 newdup = 0;
515 } else if (lpa & LPA_10FULL) {
516 newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
517 newdup = 1;
518 } else if (lpa & LPA_10HALF) {
519 newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
520 newdup = 0;
521 } else {
522 D(bug("%s: bad ability %04x - falling back to 10HD.\n", dev->name, lpa));
523 newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
524 newdup = 0;
527 set_speed:
528 if (np->duplex == newdup && np->linkspeed == newls)
529 return retval;
531 D(bug("%s: changing link setting from %d/%d to %d/%d.\n",
532 dev->name, np->linkspeed, np->duplex, newls, newdup));
534 np->duplex = newdup;
535 np->linkspeed = newls;
536 if (np->gigabit == PHY_GIGABIT) {
537 phyreg = readl(base + NvRegRandomSeed);
538 phyreg &= ~(0x3FF00);
539 if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_10)
540 phyreg |= NVREG_RNDSEED_FORCE3;
541 else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100)
542 phyreg |= NVREG_RNDSEED_FORCE2;
543 else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000)
544 phyreg |= NVREG_RNDSEED_FORCE;
545 writel(phyreg, base + NvRegRandomSeed);
548 phyreg = readl(base + NvRegPhyInterface);
549 phyreg &= ~(PHY_HALF|PHY_100|PHY_1000);
550 if (np->duplex == 0)
551 phyreg |= PHY_HALF;
552 if ((np->linkspeed & NVREG_LINKSPEED_MASK) == NVREG_LINKSPEED_100)
553 phyreg |= PHY_100;
554 else if ((np->linkspeed & NVREG_LINKSPEED_MASK) == NVREG_LINKSPEED_1000)
555 phyreg |= PHY_1000;
556 writel(phyreg, base + NvRegPhyInterface);
558 writel(NVREG_MISC1_FORCE | ( np->duplex ? 0 : NVREG_MISC1_HD),
559 base + NvRegMisc1);
560 pci_push(base);
561 writel(np->linkspeed, base + NvRegLinkSpeed);
562 pci_push(base);
564 return retval;
567 static void nv_linkchange(struct net_device *dev)
569 if (nv_update_linkspeed(dev)) {
570 if (netif_carrier_ok(dev)) {
571 nv_stop_rx(dev);
572 } else {
573 netif_carrier_on(dev);
574 D(bug("%s: link up.\n", dev->name));
576 nv_start_rx(dev);
577 } else {
578 if (netif_carrier_ok(dev)) {
579 netif_carrier_off(dev);
580 D(bug("%s: link down.\n", dev->name));
581 nv_stop_rx(dev);
586 static void nv_deinitialize(struct net_device *dev)
590 static void nv_initialize(struct net_device *dev)
592 struct fe_priv *np = dev->nu_fe_priv;
593 UBYTE *base = get_hwbase(dev);
594 int i;
596 np->rx_ring = HIDD_PCIDriver_AllocPCIMem(
597 dev->nu_PCIDriver,
598 sizeof(struct ring_desc) * (RX_RING + TX_RING));
600 np->ring_addr = (IPTR)np->rx_ring;
601 np->tx_ring = &np->rx_ring[RX_RING];
603 np->orig_mac[0] = readl(base + NvRegMacAddrA);
604 np->orig_mac[1] = readl(base + NvRegMacAddrB);
606 dev->dev_addr[0] = dev->org_addr[0] = (np->orig_mac[1] >> 8) & 0xff;
607 dev->dev_addr[1] = dev->org_addr[1] = (np->orig_mac[1] >> 0) & 0xff;
608 dev->dev_addr[2] = dev->org_addr[2] = (np->orig_mac[0] >> 24) & 0xff;
609 dev->dev_addr[3] = dev->org_addr[3] = (np->orig_mac[0] >> 16) & 0xff;
610 dev->dev_addr[4] = dev->org_addr[4] = (np->orig_mac[0] >> 8) & 0xff;
611 dev->dev_addr[5] = dev->org_addr[5] = (np->orig_mac[0] >> 0) & 0xff;
613 D(bug("%s: MAC Address %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name,
614 dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
615 dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]));
617 /* disable WOL */
618 writel(0, base + NvRegWakeUpFlags);
619 np->wolenabled = 0;
621 if (np->desc_ver == DESC_VER_1) {
622 np->tx_flags = NV_TX_LASTPACKET|NV_TX_VALID;
623 if (dev->nu_DriverFlags & DEV_NEED_LASTPACKET1)
624 np->tx_flags |= NV_TX_LASTPACKET1;
625 } else {
626 np->tx_flags = NV_TX2_LASTPACKET|NV_TX2_VALID;
627 if (dev->nu_DriverFlags & DEV_NEED_LASTPACKET1)
628 np->tx_flags |= NV_TX2_LASTPACKET1;
630 if (dev->nu_DriverFlags & DEV_IRQMASK_1)
631 np->irqmask = NVREG_IRQMASK_WANTED_1;
632 if (dev->nu_DriverFlags & DEV_IRQMASK_2)
633 np->irqmask = NVREG_IRQMASK_WANTED_2;
634 if (dev->nu_DriverFlags & DEV_NEED_TIMERIRQ)
635 np->irqmask |= NVREG_IRQ_TIMER;
636 if (dev->nu_DriverFlags & DEV_NEED_LINKTIMER) {
637 D(bug("%s: link timer on.\n", pci_name(dev)));
638 np->need_linktimer = 1;
639 np->link_timeout.tv_micro = LINK_TIMEOUT % 1000000;
640 np->link_timeout.tv_secs = LINK_TIMEOUT / 1000000;
641 } else {
642 D(bug("%s: link timer off.\n", pci_name(dev)));
643 np->need_linktimer = 0;
646 /* find a suitable phy */
647 for (i = 1; i < 32; i++) {
648 int id1, id2;
650 ObtainSemaphore(&np->lock);
651 id1 = mii_rw(dev, i, MII_PHYSID1, MII_READ);
652 ReleaseSemaphore(&np->lock);
653 if (id1 < 0 || id1 == 0xffff)
654 continue;
655 ObtainSemaphore(&np->lock);
656 id2 = mii_rw(dev, i, MII_PHYSID2, MII_READ);
657 ReleaseSemaphore(&np->lock);
658 if (id2 < 0 || id2 == 0xffff)
659 continue;
661 id1 = (id1 & PHYID1_OUI_MASK) << PHYID1_OUI_SHFT;
662 id2 = (id2 & PHYID2_OUI_MASK) >> PHYID2_OUI_SHFT;
663 D(bug("%s: open: Found PHY %04x:%04x at address %d.\n",
664 pci_name(dev), id1, id2, i));
665 np->phyaddr = i;
666 np->phy_oui = id1 | id2;
667 break;
670 if (i == 32) {
671 /* PHY in isolate mode? No phy attached and user wants to
672 * test loopback? Very odd, but can be correct.
674 D(bug("%s: open: Could not find a valid PHY.\n",
675 pci_name(dev)));
678 if (i != 32) {
679 /* reset it */
680 phy_init(dev);
683 /* set default link speed settings */
684 np->linkspeed = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
685 np->duplex = 0;
686 np->autoneg = 1;
689 static void nv_drain_tx(struct net_device *dev)
691 struct fe_priv *np = get_nvpriv(dev);
692 int i;
693 for (i = 0; i < TX_RING; i++) {
694 np->tx_ring[i].FlagLen = 0;
698 static void nv_drain_rx(struct net_device *dev)
700 struct fe_priv *np = get_nvpriv(dev);
701 int i;
702 for (i = 0; i < RX_RING; i++) {
703 np->rx_ring[i].FlagLen = 0;
708 static void drain_ring(struct net_device *dev)
710 nv_drain_tx(dev);
711 nv_drain_rx(dev);
714 static int request_irq(struct net_device *dev)
716 if (!dev->nu_IntsAdded)
718 AddIntServer(INTB_KERNEL + dev->nu_IRQ, &dev->nu_irqhandler);
719 AddIntServer(INTB_VERTB, &dev->nu_touthandler);
720 dev->nu_IntsAdded = TRUE;
723 return 0;
726 static void free_irq(struct net_device *dev)
728 if (dev->nu_IntsAdded)
730 RemIntServer(INTB_KERNEL + dev->nu_IRQ, &dev->nu_irqhandler);
731 RemIntServer(INTB_VERTB, &dev->nu_touthandler);
732 dev->nu_IntsAdded = FALSE;
736 static void nv_set_mac(struct net_device *dev)
738 UBYTE *base = get_hwbase(dev);
739 ULONG mac[2];
741 mac[0] = (dev->dev_addr[0] << 0) + (dev->dev_addr[1] << 8) +
742 (dev->dev_addr[2] << 16) + (dev->dev_addr[3] << 24);
743 mac[1] = (dev->dev_addr[4] << 0) + (dev->dev_addr[5] << 8);
745 writel(mac[0], base + NvRegMacAddrA);
746 writel(mac[1], base + NvRegMacAddrB);
750 * nv_alloc_rx: fill rx ring entries.
751 * Return 1 if the allocations for the skbs failed and the
752 * rx engine is without Available descriptors
754 static int nv_alloc_rx(struct net_device *dev)
756 struct fe_priv *np = get_nvpriv(dev);
757 unsigned int refill_rx = np->refill_rx;
758 int nr;
760 while (np->cur_rx != refill_rx) {
761 nr = refill_rx % RX_RING;
763 np->rx_ring[nr].FlagLen = AROS_LONG2LE(RX_NIC_BUFSIZE | NV_RX_AVAIL);
764 D(bug("%s: nv_alloc_rx: Packet %d marked as Available\n", dev->name, refill_rx));
765 refill_rx++;
767 np->refill_rx = refill_rx;
768 if (np->cur_rx - refill_rx == RX_RING)
769 return 1;
770 return 0;
774 static int nv_init_ring(struct net_device *dev)
776 struct fe_priv *np = get_nvpriv(dev);
777 int i;
779 np->next_tx = np->nic_tx = 0;
780 for (i = 0; i < TX_RING; i++)
781 np->tx_ring[i].FlagLen = 0;
783 np->cur_rx = RX_RING;
784 np->refill_rx = 0;
785 for (i = 0; i < RX_RING; i++)
786 np->rx_ring[i].FlagLen = 0;
787 return nv_alloc_rx(dev);
790 static int nv_open(struct net_device *dev)
792 struct fe_priv *np = get_nvpriv(dev);
793 UBYTE *base = get_hwbase(dev);
794 int ret, oom, i;
796 oom = 0;
798 np->rx_buffer = HIDD_PCIDriver_AllocPCIMem(
799 dev->nu_PCIDriver,
800 RX_RING * sizeof(struct eth_frame));
802 if (np->rx_buffer == NULL)
803 oom = 1;
805 np->tx_buffer = HIDD_PCIDriver_AllocPCIMem(
806 dev->nu_PCIDriver,
807 TX_RING * sizeof(struct eth_frame));
809 if (np->tx_buffer == NULL)
810 oom = 1;
812 for (i=0; i < TX_RING; i++)
813 np->tx_ring[i].PacketBuffer = (IPTR)&np->tx_buffer[i];
815 for (i=0; i < RX_RING; i++)
816 np->rx_ring[i].PacketBuffer = (IPTR)&np->rx_buffer[i];
818 D(bug("nv_open: begin\n"));
820 /* 1) erase previous misconfiguration */
821 /* 4.1-1: stop adapter: ignored, 4.3 seems to be overkill */
822 writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA);
823 writel(0, base + NvRegMulticastAddrB);
824 writel(0, base + NvRegMulticastMaskA);
825 writel(0, base + NvRegMulticastMaskB);
826 writel(0, base + NvRegPacketFilterFlags);
828 writel(0, base + NvRegTransmitterControl);
829 writel(0, base + NvRegReceiverControl);
831 writel(0, base + NvRegAdapterControl);
833 /* 2) initialize descriptor rings */
834 oom = nv_init_ring(dev);
836 writel(0, base + NvRegLinkSpeed);
837 writel(0, base + NvRegUnknownTransmitterReg);
838 nv_txrx_reset(dev);
839 writel(0, base + NvRegUnknownSetupReg6);
841 np->in_shutdown = 0;
843 /* 3) set mac address */
844 nv_set_mac(dev);
846 /* 4) give hw rings */
847 writel((ULONG) np->ring_addr, base + NvRegRxRingPhysAddr);
848 writel((ULONG) (np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
849 writel( ((RX_RING-1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING-1) << NVREG_RINGSZ_TXSHIFT),
850 base + NvRegRingSizes);
852 /* 5) continue setup */
853 writel(np->linkspeed, base + NvRegLinkSpeed);
854 writel(NVREG_UNKSETUP3_VAL1, base + NvRegUnknownSetupReg3);
855 writel(np->desc_ver, base + NvRegTxRxControl);
856 pci_push(base);
857 writel(NVREG_TXRXCTL_BIT1|np->desc_ver, base + NvRegTxRxControl);
858 reg_delay(dev, NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31, NVREG_UNKSETUP5_BIT31,
859 NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX,
860 "open: SetupReg5, Bit 31 remained off\n");
862 writel(0, base + NvRegUnknownSetupReg4);
863 writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
864 writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus);
866 /* 6) continue setup */
867 writel(NVREG_MISC1_FORCE | NVREG_MISC1_HD, base + NvRegMisc1);
868 writel(readl(base + NvRegTransmitterStatus), base + NvRegTransmitterStatus);
869 writel(NVREG_PFF_ALWAYS, base + NvRegPacketFilterFlags);
870 writel(NVREG_OFFLOAD_NORMAL, base + NvRegOffloadConfig);
872 writel(readl(base + NvRegReceiverStatus), base + NvRegReceiverStatus);
873 i = rand();
874 writel(NVREG_RNDSEED_FORCE | (i&NVREG_RNDSEED_MASK), base + NvRegRandomSeed);
875 writel(NVREG_UNKSETUP1_VAL, base + NvRegUnknownSetupReg1);
876 writel(NVREG_UNKSETUP2_VAL, base + NvRegUnknownSetupReg2);
877 writel(NVREG_POLL_DEFAULT, base + NvRegPollingInterval);
878 writel(NVREG_UNKSETUP6_VAL, base + NvRegUnknownSetupReg6);
879 writel((np->phyaddr << NVREG_ADAPTCTL_PHYSHIFT)|NVREG_ADAPTCTL_PHYVALID|NVREG_ADAPTCTL_RUNNING,
880 base + NvRegAdapterControl);
881 writel(NVREG_MIISPEED_BIT8|NVREG_MIIDELAY, base + NvRegMIISpeed);
882 writel(NVREG_UNKSETUP4_VAL, base + NvRegUnknownSetupReg4);
883 writel(NVREG_WAKEUPFLAGS_VAL, base + NvRegWakeUpFlags);
885 i = readl(base + NvRegPowerState);
886 if ( (i & NVREG_POWERSTATE_POWEREDUP) == 0)
887 writel(NVREG_POWERSTATE_POWEREDUP|i, base + NvRegPowerState);
889 pci_push(base);
890 udelay(10);
891 writel(readl(base + NvRegPowerState) | NVREG_POWERSTATE_VALID, base + NvRegPowerState);
893 writel(0, base + NvRegIrqMask);
894 pci_push(base);
895 writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus);
896 writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
897 pci_push(base);
899 ret = request_irq(dev);
900 if (ret)
901 goto out_drain;
903 /* ask for interrupts */
904 writel(np->irqmask, base + NvRegIrqMask);
906 ObtainSemaphore(&np->lock);
907 writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA);
908 writel(0, base + NvRegMulticastAddrB);
909 writel(0, base + NvRegMulticastMaskA);
910 writel(0, base + NvRegMulticastMaskB);
911 writel(NVREG_PFF_ALWAYS|NVREG_PFF_MYADDR, base + NvRegPacketFilterFlags);
912 /* One manual link speed update: Interrupts are enabled, future link
913 * speed changes cause interrupts and are handled by nv_link_irq().
916 D(ULONG miistat;)
917 D(miistat =) readl(base + NvRegMIIStatus);
918 writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus);
919 D(bug("startup: got 0x%08x.\n", miistat));
921 ret = nv_update_linkspeed(dev);
922 nv_start_rx(dev);
923 nv_start_tx(dev);
924 netif_start_queue(dev);
925 if (ret) {
926 netif_carrier_on(dev);
927 } else {
928 bug("%s: no link during initialization.\n", dev->name);
929 netif_carrier_off(dev);
931 if (oom) {
932 bug("%s: Out Of Memory. PANIC!\n", dev->name);
933 ret = 1;
934 goto out_drain;
937 ReleaseSemaphore(&np->lock);
938 dev->flags |= IFF_UP;
939 ReportEvents(LIBBASE, dev, S2EVENT_ONLINE);
941 return 0;
943 out_drain:
944 drain_ring(dev);
945 return ret;
948 static int nv_close(struct net_device *dev)
950 struct fe_priv *np = get_nvpriv(dev);
951 UBYTE *base;
953 dev->flags &= ~IFF_UP;
955 ObtainSemaphore(&np->lock);
956 np->in_shutdown = 1;
957 ReleaseSemaphore(&np->lock);
959 dev->nu_toutNEED = FALSE;
961 netif_stop_queue(dev);
962 ObtainSemaphore(&np->lock);
963 nv_stop_tx(dev);
964 nv_stop_rx(dev);
965 nv_txrx_reset(dev);
967 /* disable interrupts on the nic or we will lock up */
968 base = get_hwbase(dev);
969 writel(0, base + NvRegIrqMask);
970 pci_push(base);
971 D(bug("%s: Irqmask is zero again\n", dev->name));
973 ReleaseSemaphore(&np->lock);
975 free_irq(dev);
977 drain_ring(dev);
979 HIDD_PCIDriver_FreePCIMem(dev->nu_PCIDriver, np->rx_buffer);
980 HIDD_PCIDriver_FreePCIMem(dev->nu_PCIDriver, np->tx_buffer);
982 if (np->wolenabled)
983 nv_start_rx(dev);
985 /* FIXME: power down nic */
987 ReportEvents(LIBBASE, dev, S2EVENT_OFFLINE);
989 return 0;
992 static void nv_link_irq(struct net_device *dev)
994 UBYTE *base = get_hwbase(dev);
995 ULONG miistat;
997 miistat = readl(base + NvRegMIIStatus);
998 writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus);
999 D(bug("%s: link change irq, status 0x%x.\n", dev->name, miistat));
1001 if (miistat & (NVREG_MIISTAT_LINKCHANGE))
1002 dev->linkchange(dev);
1003 D(bug("%s: link change notification done.\n", dev->name));
1006 void nv_get_functions(struct net_device *Unit)
1008 Unit->initialize = nv_initialize;
1009 Unit->deinitialize = nv_deinitialize;
1010 Unit->start = nv_open;
1011 Unit->stop = nv_close;
1012 Unit->set_mac_address = nv_set_mac;
1013 Unit->linkchange = nv_linkchange;
1014 Unit->linkirq = nv_link_irq;
1015 Unit->descr_getlength = nv_descr_getlength;
1016 Unit->alloc_rx = nv_alloc_rx;
1017 Unit->set_multicast = nv_set_multicast;