Index: if_ex.c =================================================================== RCS file: /home/ncvs/src/sys/dev/ex/if_ex.c,v retrieving revision 1.29 diff -u -r1.29 if_ex.c --- if_ex.c 2000/04/19 14:57:16 1.29 +++ if_ex.c 2000/04/26 07:31:34 @@ -90,8 +90,11 @@ struct ifmedia ifmedia; device_t dev; + int port_rid; + int irq_rid; struct resource *ioport; struct resource *irq; + void * sc_ih; u_int iobase; /* I/O base address. */ u_short irq_no; /* IRQ number. */ @@ -399,7 +402,6 @@ int unit = device_get_unit(dev); int error; int rid; - void * ih; u_int16_t temp; DODEBUG(Start_End, device_printf(dev, "start\n");); @@ -423,7 +425,7 @@ } error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET, - ex_intr, (void *)sc, &ih); + ex_intr, (void *)sc, &sc->sc_ih); if (error) { device_printf(dev, "bus_setup_intr() failed!\n"); @@ -624,7 +626,7 @@ struct mbuf * opkt; struct mbuf * m; - DODEBUG(Start_End, printf("ex_start%d: start\n", unit);); + DODEBUG(Start_End, printf("ex_start%d: start\n", ifp->if_unit);); s = splimp(); @@ -789,7 +791,7 @@ splx(s); - DODEBUG(Start_End, printf("ex_start%d: finish\n", unit);); + DODEBUG(Start_End, printf("ex_start%d: finish\n", ifp->if_unit);); } static void @@ -797,7 +799,7 @@ { int iobase = sc->iobase; - DODEBUG(Start_End, printf("ex_stop%d: start\n", unit);); + DODEBUG(Start_End, printf("ex_stop%d: start\n", device_get_unit(sc->dev));); /* * Disable card operation: @@ -817,7 +819,7 @@ outb(iobase + CMD_REG, Reset_CMD); DELAY(200); - DODEBUG(Start_End, printf("ex_stop%d: finish\n", unit);); + DODEBUG(Start_End, printf("ex_stop%d: finish\n", device_get_unit(sc->dev));); return; } @@ -831,7 +833,7 @@ int iobase = sc->iobase; int int_status, send_pkts; - DODEBUG(Start_End, printf("ex_intr%d: start\n", unit);); + DODEBUG(Start_End, printf("ex_intr%d: start\n", device_get_unit(sc->dev));); #ifdef EXDEBUG if (++exintr_count != 1) @@ -865,7 +867,7 @@ exintr_count--; #endif - DODEBUG(Start_End, printf("ex_intr%d: finish\n", unit);); + DODEBUG(Start_End, printf("ex_intr%d: finish\n", device_get_unit(sc->dev));); return; } @@ -877,7 +879,7 @@ int iobase = sc->iobase; int tx_status; - DODEBUG(Start_End, printf("ex_tx_intr%d: start\n", unit);); + DODEBUG(Start_End, printf("ex_tx_intr%d: start\n", device_get_unit(sc->dev));); /* * - Cancel the watchdog. @@ -913,7 +915,7 @@ ifp->if_flags &= ~IFF_OACTIVE; DODEBUG(Status, printf("OIDLE tx_intr\n");); - DODEBUG(Start_End, printf("ex_tx_intr%d: finish\n", unit);); + DODEBUG(Start_End, printf("ex_tx_intr%d: finish\n", device_get_unit(sc->dev));); return; } @@ -930,7 +932,7 @@ struct mbuf * ipkt; struct ether_header * eh; - DODEBUG(Start_End, printf("ex_rx_intr%d: start\n", unit);); + DODEBUG(Start_End, printf("ex_rx_intr%d: start\n", device_get_unit(sc->dev));); /* * For all packets received since last receive interrupt: @@ -1037,7 +1039,7 @@ else outw(iobase + RCV_STOP_REG, sc->rx_head - 2); - DODEBUG(Start_End, printf("ex_rx_intr%d: finish\n", unit);); + DODEBUG(Start_End, printf("ex_rx_intr%d: finish\n", device_get_unit(sc->dev));); return; } @@ -1109,7 +1111,7 @@ { int s; - DODEBUG(Start_End, printf("ex_reset%d: start\n", unit);); + DODEBUG(Start_End, printf("ex_reset%d: start\n", device_get_unit(sc->dev));); s = splimp(); @@ -1118,7 +1120,7 @@ splx(s); - DODEBUG(Start_End, printf("ex_reset%d: finish\n", unit);); + DODEBUG(Start_End, printf("ex_reset%d: finish\n", device_get_unit(sc->dev));); return; } @@ -1202,3 +1204,246 @@ outb(iobase + CMD_REG, Bank0_Sel); return(data); } + +/* + * PC-Card (PCMCIA) specific code by iwasaki@FreeBSD.org + */ + +#include + +static void +ex_deactivate(device_t dev) +{ + struct ex_softc * sc = device_get_softc(dev); + + if (sc->sc_ih) { + bus_teardown_intr(dev, sc->irq, sc->sc_ih); + sc->sc_ih = NULL; + } + + if (sc->ioport) { + bus_release_resource(dev, SYS_RES_IOPORT, sc->port_rid, + sc->ioport); + sc->ioport = NULL; + } + + if (sc->irq) { + bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, + sc->irq); + sc->irq = NULL; + } + + return; +} + +static int +ex_activate(device_t dev) +{ + struct ex_softc * sc = device_get_softc(dev); + int error; + + sc->port_rid = 0; + sc->ioport = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->port_rid, + 0, ~0, EX_IOSIZE, RF_ACTIVE); + if (!sc->ioport) { + device_printf(dev, "No I/O space?!\n"); + return(ENOMEM); + } + + sc->irq_rid = 0; + sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid, + 0, ~0, 1, RF_ACTIVE); + if (!sc->irq) { + device_printf(dev, "No IRQ?!\n"); + ex_deactivate(dev); + return(ENOMEM); + } + + error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET, + ex_intr, (void *)sc, &sc->sc_ih); + if (error) { + device_printf(dev, "bus_setup_intr() failed!\n"); + ex_deactivate(dev); + return(error); + } + + return(0); +} + +static int +ex_pccard_probe(device_t dev) +{ + struct ex_softc * sc = device_get_softc(dev); + int error; + u_int iobase; + u_int irq; + + DODEBUG(Start_End, printf("ex_probe: start\n");); + + error = ex_activate(dev); + if (error) { + return(error); + } + + iobase = rman_get_start(sc->ioport); + if (!iobase) { + printf("ex: no iobase?\n"); + ex_deactivate(dev); + return(ENXIO); + } + + if (!look_for_card(iobase)) { + printf("ex: no card found at 0x%03x\n", iobase); + ex_deactivate(dev); + return(ENXIO); + } + + if (bootverbose) + printf("ex: ex_pccard_probe() found card at 0x%03x\n", iobase); + + irq = rman_get_start(sc->irq); + + if (irq == 0) { + printf("ex: invalid IRQ.\n"); + ex_deactivate(dev); + return(ENXIO); + } + + DODEBUG(Start_End, printf("ex_probe: finish\n");); + + ex_deactivate(dev); + return(0); +} + +static int +ex_pccard_attach(device_t dev) +{ + struct ex_softc * sc = device_get_softc(dev); + struct ifnet * ifp = &sc->arpcom.ac_if; + struct ifmedia * ifm; + int unit = device_get_unit(dev); + int error; + int i; + u_int16_t temp; + u_char sum; + u_char ether_addr[ETHER_ADDR_LEN]; + + DODEBUG(Start_End, device_printf(dev, "start\n");); + + error = ex_activate(dev); + if (error) { + goto bad; + } + + ex_stop(sc); + + /* + * Fill in several fields of the softc structure: + * - I/O base address. + * - Hardware Ethernet address. + * - IRQ number (if not supplied in config file, read it from EEPROM). + * - Connector type. + */ + sc->dev = dev; + sc->iobase = rman_get_start(sc->ioport); + sc->irq_no = rman_get_start(sc->irq); + + pccard_get_ether(dev, ether_addr); + for (i = 0, sum = 0; i < ETHER_ADDR_LEN; i++) + sum |= ether_addr[i]; + if (sum) + bcopy(ether_addr, sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); + + /* work out which set of irq <-> internal tables to use */ + if (ex_card_type(sc->arpcom.ac_enaddr) == CARD_TYPE_EX_10_PLUS) { + sc->irq2ee = plus_irq2eemap; + sc->ee2irq = plus_ee2irqmap; + } else { + sc->irq2ee = irq2eemap; + sc->ee2irq = ee2irqmap; + } + + sc->mem_size = CARD_RAM_SIZE; /* XXX This should be read from the card itself. */ + + /* + * Initialize the ifnet structure. + */ + ifp->if_softc = sc; + ifp->if_unit = unit; + ifp->if_name = "ex"; + ifp->if_mtu = ETHERMTU; + ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST /* XXX not done yet. | IFF_MULTICAST */; + ifp->if_output = ether_output; + ifp->if_start = ex_start; + ifp->if_ioctl = ex_ioctl; + ifp->if_watchdog = ex_watchdog; + ifp->if_init = ex_init; + ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; + + ifmedia_init(&sc->ifmedia, 0, ex_ifmedia_upd, ex_ifmedia_sts); + + temp = eeprom_read(sc->iobase, EE_W5); + if (temp & EE_W5_PORT_TPE) + ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL); + if (temp & EE_W5_PORT_BNC) + ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_2, 0, NULL); + if (temp & EE_W5_PORT_AUI) + ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_5, 0, NULL); + + ifmedia_set(&sc->ifmedia, ex_get_media(sc->iobase)); + + ifm = &sc->ifmedia; + ifm->ifm_media = ifm->ifm_cur->ifm_media; + ex_ifmedia_upd(ifp); + + /* + * Attach the interface. + */ + if_attach(ifp); + ether_ifattach(ifp); + + device_printf(sc->dev, "Ethernet address %6D\n", + sc->arpcom.ac_enaddr, ":"); + /* + * If BPF is in the kernel, call the attach for it + */ + bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header)); + DODEBUG(Start_End, printf("ex_pccard_attach%d: finish\n", unit);); + + return(0); +bad: + + ex_deactivate(dev); + + return (-1); +} + +static int +ex_pccard_detach(device_t dev) +{ + struct ex_softc *sc = device_get_softc(dev); + struct ifnet *ifp = &sc->arpcom.ac_if; + + ex_stop(sc); + ifp->if_flags &= ~IFF_RUNNING; + if_detach(ifp); + ex_deactivate(dev); + return (0); +} + +static device_method_t ex_pccard_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ex_pccard_probe), + DEVMETHOD(device_attach, ex_pccard_attach), + DEVMETHOD(device_detach, ex_pccard_detach), + + { 0, 0 } +}; + +static driver_t ex_pccard_driver = { + "ex", + ex_pccard_methods, + sizeof(struct ex_softc), +}; + +DRIVER_MODULE(ex, pccard, ex_pccard_driver, ex_devclass, 0, 0);