summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormdodd <mdodd@FreeBSD.org>1999-09-26 06:42:36 +0000
committermdodd <mdodd@FreeBSD.org>1999-09-26 06:42:36 +0000
commit5272c65210119098f91f9749539447f2945f26a9 (patch)
tree1686bbf05ff020787377386cdef3689839bbc67f
parent07038f1e994b4a14bbf31e08277be3a83b8b95d1 (diff)
downloadFreeBSD-src-5272c65210119098f91f9749539447f2945f26a9.zip
FreeBSD-src-5272c65210119098f91f9749539447f2945f26a9.tar.gz
- Split out the ISA and PCCARD specific code.
- Split out the prototypes, externs and struct decls from if_epreg.h into if_epvar.h. - Add support for MCA based Etherlink III (3c529) devices. None of this code is used right now; the old if_ep driver is still in place and used. I will eventually get around to converting if_ep_isa.c to newbus once I've had a talk with Peter and DFR about the DEVICE_IDENTIFY() method. I have tested this code on my PS/2. It works. I would like EISA and ISA testers since my example hardware hasn't arrived yet. Add: dev/ep/if_ep.c optional ep dev/ep/if_ep_isa.c optional ep isa dev/ep/if_ep_eisa.c optional ep eisa dev/ep/if_ep_mca.c optional ep mca dev/ep/if_ep_pccard.c optional ep card to sys/conf/files Remove: i386/eisa/3c5x9.c optional ep i386/isa/if_ep.c optional ep from sys/i386/conf/files.i386 PCCARD testers wanted! I will switch off and cvs rm the old driver in favor of this copy once I've had positive feedback or have the hardware to verify that it works.
-rw-r--r--sys/dev/ep/if_ep.c556
-rw-r--r--sys/dev/ep/if_ep_isa.c344
-rw-r--r--sys/dev/ep/if_ep_mca.c219
-rw-r--r--sys/dev/ep/if_ep_pccard.c245
-rw-r--r--sys/dev/ep/if_epreg.h81
-rw-r--r--sys/dev/ep/if_epvar.h78
6 files changed, 918 insertions, 605 deletions
diff --git a/sys/dev/ep/if_ep.c b/sys/dev/ep/if_ep.c
index 4ee050d..7202bf9 100644
--- a/sys/dev/ep/if_ep.c
+++ b/sys/dev/ep/if_ep.c
@@ -59,270 +59,45 @@
#include "ep.h"
#if NEP > 0
-#include "opt_inet.h"
-#include "opt_ipx.h"
-
#include <sys/param.h>
-#if defined(__FreeBSD__)
#include <sys/kernel.h>
#include <sys/systm.h>
-#endif
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/sockio.h>
-#if defined(__NetBSD__)
-#include <sys/select.h>
-#endif
#include <net/ethernet.h>
#include <net/if.h>
-
#include <netinet/in.h>
#include <netinet/if_ether.h>
-
#include <net/bpf.h>
-#if defined(__FreeBSD__)
#include <machine/clock.h>
-#endif
-#include <i386/isa/isa_device.h>
-#include <i386/isa/if_epreg.h>
#include <i386/isa/elink.h>
-
-/* DELAY_MULTIPLE: How much to boost "base" delays, except
- * for the inter-bit delays in get_eeprom_data. A cyrix Media GX needed this.
- */
-#define DELAY_MULTIPLE 10
-#define BIT_DELAY_MULTIPLE 10
+#include <dev/ep/if_epreg.h>
+#include <dev/ep/if_epvar.h>
/* Exported variables */
-u_long ep_unit;
+struct ep_softc * ep_softc[NEP];
+struct ep_board ep_board[EP_MAX_BOARDS + 1];
int ep_boards;
-struct ep_board ep_board[EP_MAX_BOARDS + 1];
-
-static int eeprom_rdy __P((struct ep_softc *sc));
-
-static int ep_isa_probe __P((struct isa_device *));
-static struct ep_board * ep_look_for_board_at __P((struct isa_device *is));
-static int ep_isa_attach __P((struct isa_device *));
-static int epioctl __P((struct ifnet * ifp, u_long, caddr_t));
-
-static void epinit __P((void *));
-static ointhand2_t epintr;
-static void epread __P((struct ep_softc *));
-void epreset __P((int));
-static void epstart __P((struct ifnet *));
-static void epstop __P((struct ep_softc *));
-static void epwatchdog __P((struct ifnet *));
-
-#if 0
-static int send_ID_sequence __P((int));
-#endif
-static int get_eeprom_data __P((int, int));
-
-static struct ep_softc* ep_softc[NEP];
-static int ep_current_tag = EP_LAST_TAG + 1;
-static char *ep_conn_type[] = {"UTP", "AUI", "???", "BNC"};
-
-#define ep_ftst(f) (sc->stat&(f))
-#define ep_fset(f) (sc->stat|=(f))
-#define ep_frst(f) (sc->stat&=~(f))
-
-struct isa_driver epdriver = {
- ep_isa_probe,
- ep_isa_attach,
- "ep",
- 0
-};
-
-#include "card.h"
-
-#if NCARD > 0
-#include <sys/select.h>
-#include <sys/module.h>
-#include <pccard/cardinfo.h>
-#include <pccard/slot.h>
-
-/*
- * PC-Card (PCMCIA) specific code.
- */
-static int ep_pccard_init __P((struct pccard_devinfo *));
-static int ep_pccard_attach __P((struct pccard_devinfo *));
-static void ep_unload __P((struct pccard_devinfo *));
-static int card_intr __P((struct pccard_devinfo *));
-static int ep_pccard_identify (struct ep_board *epb, int unit);
-
-PCCARD_MODULE(ep, ep_pccard_init, ep_unload, card_intr, 0, net_imask);
-
-/*
- * Initialize the device - called from Slot manager.
- */
-static int
-ep_pccard_init(devi)
- struct pccard_devinfo *devi;
-{
- struct isa_device *is = &devi->isahd;
- struct ep_softc *sc = ep_softc[is->id_unit];
- struct ep_board *epb;
- int i;
-
- epb = &ep_board[is->id_unit];
-
- if (sc == 0) {
- if ((sc = ep_alloc(is->id_unit, epb)) == 0) {
- return (ENXIO);
- }
- ep_unit++;
- }
-
- /* get_e() requires these. */
- sc->ep_io_addr = is->id_iobase;
- sc->unit = is->id_unit;
- epb->epb_addr = is->id_iobase;
- epb->epb_used = 1;
-
- /*
- * XXX - Certain (newer?) 3Com cards need epb->cmd_off == 2. Sadly,
- * you need to have a correct cmd_off in order to identify the card.
- * So we have to hit it with both and cross our virtual fingers. There's
- * got to be a better way to do this. jyoung@accessus.net 09/11/1999
- */
-
- epb->cmd_off = 0;
- epb->prod_id = get_e(sc, EEPROM_PROD_ID);
- if (!ep_pccard_identify(epb, is->id_unit)) {
- if (bootverbose) printf("ep%d: Pass 1 of 2 detection failed (nonfatal)\n", is->id_unit);
- epb->cmd_off = 2;
- epb->prod_id = get_e(sc, EEPROM_PROD_ID);
- if (!ep_pccard_identify(epb, is->id_unit)) {
- if (bootverbose) printf("ep%d: Pass 2 of 2 detection failed (fatal!)\n", is->id_unit);
- printf("ep%d: Unit failed to come ready or product ID unknown! (id 0x%x)\n", is->id_unit, epb->prod_id);
- return (ENXIO);
- }
- }
-
- epb->res_cfg = get_e(sc, EEPROM_RESOURCE_CFG);
- for (i = 0; i < 3; i++)
- sc->epb->eth_addr[i] = get_e(sc, EEPROM_NODE_ADDR_0 + i);
-
- if (ep_pccard_attach(devi) == 0)
- return (ENXIO);
-
- sc->arpcom.ac_if.if_snd.ifq_maxlen = ifqmaxlen;
- return (0);
-}
-
-static int
-ep_pccard_identify(epb, unit)
- struct ep_board *epb;
- int unit;
-{
- /* Determine device type and associated MII capabilities */
- switch (epb->prod_id) {
- case 0x6055: /* 3C556 */
- if (bootverbose) printf("ep%d: 3Com 3C556\n", unit);
- epb->mii_trans = 1;
- return (1);
- break; /* NOTREACHED */
- case 0x4057: /* 3C574 */
- if (bootverbose) printf("ep%d: 3Com 3C574\n", unit);
- epb->mii_trans = 1;
- return (1);
- break; /* NOTREACHED */
- case 0x4b57: /* 3C574B */
- if (bootverbose) printf("ep%d: 3Com 3C574B, Megahertz 3CCFE574BT or Fast Etherlink 3C574-TX\n", unit);
- epb->mii_trans = 1;
- return (1);
- break; /* NOTREACHED */
- case 0x9058: /* 3C589 */
- if (bootverbose) printf("ep%d: 3Com Etherlink III 3C589[B/C/D]\n", unit);
- epb->mii_trans = 0;
- return (1);
- break; /* NOTREACHED */
- }
- return (0);
-}
-
-static int
-ep_pccard_attach(devi)
- struct pccard_devinfo *devi;
-{
- struct isa_device *is = &devi->isahd;
- struct ep_softc *sc = ep_softc[is->id_unit];
- u_short config;
-
- sc->ep_connectors = 0;
- config = inw(IS_BASE + EP_W0_CONFIG_CTRL);
- if (config & IS_BNC) {
- sc->ep_connectors |= BNC;
- }
- if (config & IS_UTP) {
- sc->ep_connectors |= UTP;
- }
- if (!(sc->ep_connectors & 7))
- /* (Apparently) non-fatal */
- if(bootverbose) printf("ep%d: No connectors or MII.\n", is->id_unit);
-
- sc->ep_connector = inw(BASE + EP_W0_ADDRESS_CFG) >> ACF_CONNECTOR_BITS;
-
- /* ROM size = 0, ROM base = 0 */
- /* For now, ignore AUTO SELECT feature of 3C589B and later. */
- outw(BASE + EP_W0_ADDRESS_CFG, get_e(sc, EEPROM_ADDR_CFG) & 0xc000);
-
- /* Fake IRQ must be 3 */
- outw(BASE + EP_W0_RESOURCE_CFG, (sc->epb->res_cfg & 0x0fff) | 0x3000);
-
- outw(BASE + EP_W0_PRODUCT_ID, sc->epb->prod_id);
-
- if (sc->epb->mii_trans) {
- /*
- * turn on the MII transciever
- */
- GO_WINDOW(3);
- outw(BASE + EP_W3_OPTIONS, 0x8040);
- DELAY(1000);
- outw(BASE + EP_W3_OPTIONS, 0xc040);
- outw(BASE + EP_COMMAND, RX_RESET);
- outw(BASE + EP_COMMAND, TX_RESET);
- while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
- DELAY(1000);
- outw(BASE + EP_W3_OPTIONS, 0x8040);
- }
+u_long ep_unit;
- ep_attach(sc);
+static char * ep_conn_type[] = {"UTP", "AUI", "???", "BNC"};
- return 1;
-}
+static int eeprom_rdy __P((struct ep_softc *sc));
+static int epioctl __P((struct ifnet * ifp, u_long, caddr_t));
+static void epinit __P((void *));
+static void epread __P((struct ep_softc *));
+static void epstart __P((struct ifnet *));
+static void epstop __P((struct ep_softc *));
+static void epwatchdog __P((struct ifnet *));
-static void
-ep_unload(devi)
- struct pccard_devinfo *devi;
-{
- struct ep_softc *sc = ep_softc[devi->isahd.id_unit];
-
- if (sc->gone) {
- printf("ep%d: already unloaded\n", devi->isahd.id_unit);
- return;
- }
- sc->arpcom.ac_if.if_flags &= ~IFF_RUNNING;
- sc->gone = 1;
- printf("ep%d: unload\n", devi->isahd.id_unit);
-}
-
-/*
- * card_intr - Shared interrupt called from
- * front end of PC-Card handler.
- */
-static int
-card_intr(devi)
- struct pccard_devinfo *devi;
-{
- epintr(devi->isahd.id_unit);
- return(1);
-}
-#endif /* NCARD > 0 */
+#define EP_FTST(sc, f) (sc->stat&(f))
+#define EP_FSET(sc, f) (sc->stat|=(f))
+#define EP_FRST(sc, f) (sc->stat&=~(f))
static int
eeprom_rdy(sc)
@@ -339,120 +114,6 @@ eeprom_rdy(sc)
return (1);
}
-static struct ep_board *
-ep_look_for_board_at(is)
- struct isa_device *is;
-{
- int data, i, j, id_port = ELINK_ID_PORT;
- int count = 0;
-
- if (ep_current_tag == (EP_LAST_TAG + 1)) {
- /* Come here just one time */
-
- ep_current_tag--;
-
- /* Look for the ISA boards. Init and leave them actived */
- outb(id_port, 0);
- outb(id_port, 0);
-
- elink_idseq(0xCF);
-
- elink_reset();
- DELAY(DELAY_MULTIPLE * 10000);
- for (i = 0; i < EP_MAX_BOARDS; i++) {
- outb(id_port, 0);
- outb(id_port, 0);
- elink_idseq(0xCF);
-
- data = get_eeprom_data(id_port, EEPROM_MFG_ID);
- if (data != MFG_ID)
- break;
-
- /* resolve contention using the Ethernet address */
-
- for (j = 0; j < 3; j++)
- get_eeprom_data(id_port, j);
-
- /* and save this address for later use */
-
- for (j = 0; j < 3; j++)
- ep_board[ep_boards].eth_addr[j] = get_eeprom_data(id_port, j);
-
- ep_board[ep_boards].res_cfg =
- get_eeprom_data(id_port, EEPROM_RESOURCE_CFG);
-
- ep_board[ep_boards].prod_id =
- get_eeprom_data(id_port, EEPROM_PROD_ID);
-
- ep_board[ep_boards].epb_used = 0;
-#ifdef PC98
- ep_board[ep_boards].epb_addr =
- (get_eeprom_data(id_port, EEPROM_ADDR_CFG) & 0x1f) * 0x100 + 0x40d0;
-#else
- ep_board[ep_boards].epb_addr =
- (get_eeprom_data(id_port, EEPROM_ADDR_CFG) & 0x1f) * 0x10 + 0x200;
-
- if (ep_board[ep_boards].epb_addr > 0x3E0)
- /* Board in EISA configuration mode */
- continue;
-#endif /* PC98 */
-
- outb(id_port, ep_current_tag); /* tags board */
- outb(id_port, ACTIVATE_ADAPTER_TO_CONFIG);
- ep_boards++;
- count++;
- ep_current_tag--;
- }
-
- ep_board[ep_boards].epb_addr = 0;
- if (count) {
- printf("%d 3C5x9 board(s) on ISA found at", count);
- for (j = 0; ep_board[j].epb_addr; j++)
- if (ep_board[j].epb_addr <= 0x3E0)
- printf(" 0x%x", ep_board[j].epb_addr);
- printf("\n");
- }
- }
-
- /* we have two cases:
- *
- * 1. Device was configured with 'port ?'
- * In this case we search for the first unused card in list
- *
- * 2. Device was configured with 'port xxx'
- * In this case we search for the unused card with that address
- *
- */
-
- if (IS_BASE == -1) { /* port? */
- for (i = 0; ep_board[i].epb_addr && ep_board[i].epb_used; i++)
- ;
- if (ep_board[i].epb_addr == 0)
- return 0;
-
- IS_BASE = ep_board[i].epb_addr;
- ep_board[i].epb_used = 1;
-
- return &ep_board[i];
- } else {
- for (i = 0;
- ep_board[i].epb_addr && ep_board[i].epb_addr != IS_BASE;
- i++)
- ;
-
- if (ep_board[i].epb_used || ep_board[i].epb_addr != IS_BASE)
- return 0;
-
- if (inw(IS_BASE + EP_W0_EEPROM_COMMAND) & EEPROM_TST_MODE) {
- printf("ep%d: 3c5x9 at 0x%x in PnP mode. Disable PnP mode!\n",
- is->id_unit, IS_BASE);
- }
- ep_board[i].epb_used = 1;
-
- return &ep_board[i];
- }
-}
-
/*
* get_e: gets a 16 bits word from the EEPROM. we must have set the window
* before
@@ -472,8 +133,8 @@ get_e(sc, offset)
struct ep_softc *
ep_alloc(unit, epb)
- int unit;
- struct ep_board *epb;
+ int unit;
+ struct ep_board *epb;
{
struct ep_softc *sc;
@@ -515,108 +176,6 @@ ep_free(sc)
}
int
-ep_isa_probe(is)
- struct isa_device *is;
-{
- struct ep_softc *sc;
- struct ep_board *epb;
- u_short k;
-
- if ((epb = ep_look_for_board_at(is)) == 0)
- return (0);
-
- /*
- * Allocate a storage area for us
- */
- sc = ep_alloc(ep_unit, epb);
- if (!sc)
- return (0);
-
- is->id_unit = ep_unit++;
-
- /*
- * The iobase was found and MFG_ID was 0x6d50. PROD_ID should be
- * 0x9[0-f]50 (IBM-PC)
- * 0x9[0-f]5[0-f] (PC-98)
- */
- GO_WINDOW(0);
- k = sc->epb->prod_id;
-#ifdef PC98
- if ((k & 0xf0f0) != (PROD_ID & 0xf0f0)) {
-#else
- if ((k & 0xf0ff) != (PROD_ID & 0xf0ff)) {
-#endif
- printf("ep_isa_probe: ignoring model %04x\n", k);
- ep_free(sc);
- return (0);
- }
-
- k = sc->epb->res_cfg;
-
- k >>= 12;
-
- /* Now we have two cases again:
- *
- * 1. Device was configured with 'irq?'
- * In this case we use irq read from the board
- *
- * 2. Device was configured with 'irq xxx'
- * In this case we set up the board to use specified interrupt
- *
- */
-
- if (is->id_irq == 0) { /* irq? */
- is->id_irq = 1 << ((k == 2) ? 9 : k);
- }
-
- sc->stat = 0; /* 16 bit access */
-
- /* By now, the adapter is already activated */
-
- return (EP_IOSIZE); /* 16 bytes of I/O space used. */
-}
-
-static int
-ep_isa_attach(is)
- struct isa_device *is;
-{
- struct ep_softc *sc = ep_softc[is->id_unit];
- u_short config;
- int irq;
-
- is->id_ointr = epintr;
- sc->ep_connectors = 0;
- config = inw(IS_BASE + EP_W0_CONFIG_CTRL);
- if (config & IS_AUI) {
- sc->ep_connectors |= AUI;
- }
- if (config & IS_BNC) {
- sc->ep_connectors |= BNC;
- }
- if (config & IS_UTP) {
- sc->ep_connectors |= UTP;
- }
- if (!(sc->ep_connectors & 7))
- printf("no connectors!");
- sc->ep_connector = inw(BASE + EP_W0_ADDRESS_CFG) >> ACF_CONNECTOR_BITS;
- /*
- * Write IRQ value to board
- */
-
- irq = ffs(is->id_irq) - 1;
- if (irq == -1) {
- printf(" invalid irq... cannot attach\n");
- return 0;
- }
-
- GO_WINDOW(0);
- SET_IRQ(BASE, irq);
-
- ep_attach(sc);
- return 1;
-}
-
-int
ep_attach(sc)
struct ep_softc *sc;
{
@@ -680,7 +239,7 @@ ep_attach(sc)
sc->rx_bpf_disc = sc->rx_overrunf = sc->rx_overrunl =
sc->tx_underrun = 0;
#endif
- ep_fset(F_RX_FIRST);
+ EP_FSET(sc, F_RX_FIRST);
sc->top = sc->mcur = 0;
if (!attached) {
@@ -819,7 +378,7 @@ epinit(xsc)
sc->rx_bpf_disc = sc->rx_overrunf = sc->rx_overrunl =
sc->tx_underrun = 0;
#endif
- ep_fset(F_RX_FIRST);
+ EP_FSET(sc, F_RX_FIRST);
if (sc->top) {
m_freem(sc->top);
sc->top = sc->mcur = 0;
@@ -901,7 +460,7 @@ startagain:
outw(BASE + EP_W1_TX_PIO_WR_1, 0x0); /* Second dword meaningless */
for (top = m; m != 0; m = m->m_next)
- if (ep_ftst(F_ACCESS_32_BITS)) {
+ if (EP_FTST(sc, F_ACCESS_32_BITS)) {
outsl(BASE + EP_W1_TX_PIO_WR_1, mtod(m, caddr_t),
m->m_len / 4);
if (m->m_len & 3)
@@ -945,19 +504,6 @@ readcheck:
goto startagain;
}
-static void
-epintr(unit)
- int unit;
-{
- register struct ep_softc *sc = ep_softc[unit];
-
- if (sc->gone) {
- return;
- }
-
- ep_intr(sc);
-}
-
void
ep_intr(arg)
void *arg;
@@ -1095,7 +641,7 @@ read_again:
* expect
*/
#ifdef EP_LOCAL_STATS
- if (ep_ftst(F_RX_FIRST))
+ if (EP_FTST(sc, F_RX_FIRST))
sc->rx_overrunf++;
else
sc->rx_overrunl++;
@@ -1105,7 +651,7 @@ read_again:
}
rx_fifo = rx_fifo2 = status & RX_BYTES_MASK;
- if (ep_ftst(F_RX_FIRST)) {
+ if (EP_FTST(sc, F_RX_FIRST)) {
MGETHDR(m, M_DONTWAIT, MT_DATA);
if (!m)
goto out;
@@ -1143,7 +689,7 @@ read_again:
mcur->m_next = m;
lenthisone = min(rx_fifo, M_TRAILINGSPACE(m));
}
- if (ep_ftst(F_ACCESS_32_BITS)) { /* default for EISA configured cards*/
+ if (EP_FTST(sc, F_ACCESS_32_BITS)) { /* default for EISA configured cards*/
insl(BASE + EP_W1_RX_PIO_RD_1, mtod(m, caddr_t) + m->m_len,
lenthisone / 4);
m->m_len += (lenthisone & ~3);
@@ -1168,7 +714,7 @@ read_again:
#ifdef EP_LOCAL_STATS
sc->rx_no_first++; /* to know how often we come here */
#endif
- ep_frst(F_RX_FIRST);
+ EP_FRST(sc, F_RX_FIRST);
if (!((status = inw(BASE + EP_W1_RX_STATUS)) & ERR_RX_INCOMPLETE)) {
/* we see if by now, the packet has completly arrived */
goto read_again;
@@ -1178,7 +724,7 @@ read_again:
}
outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
++ifp->if_ipackets;
- ep_fset(F_RX_FIRST);
+ EP_FSET(sc, F_RX_FIRST);
top->m_pkthdr.rcvif = &sc->arpcom.ac_if;
top->m_pkthdr.len = sc->cur_len;
@@ -1201,7 +747,7 @@ read_again:
m_freem(sc->top);
sc->top = 0;
}
- ep_fset(F_RX_FIRST);
+ EP_FSET(sc, F_RX_FIRST);
#ifdef EP_LOCAL_STATS
sc->rx_bpf_disc++;
#endif
@@ -1228,7 +774,7 @@ out:
sc->rx_no_mbuf++;
#endif
}
- ep_fset(F_RX_FIRST);
+ EP_FSET(sc, F_RX_FIRST);
while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | RX_INIT_EARLY_THRESH);
}
@@ -1338,50 +884,4 @@ epstop(sc)
outw(BASE + EP_COMMAND, SET_RX_FILTER);
}
-
-#if 0
-static int
-send_ID_sequence(port)
- int port;
-{
- int cx, al;
-
- for (al = 0xff, cx = 0; cx < 255; cx++) {
- outb(port, al);
- al <<= 1;
- if (al & 0x100)
- al ^= 0xcf;
- }
- return (1);
-}
-#endif
-
-
-/*
- * We get eeprom data from the id_port given an offset into the eeprom.
- * Basically; after the ID_sequence is sent to all of the cards; they enter
- * the ID_CMD state where they will accept command requests. 0x80-0xbf loads
- * the eeprom data. We then read the port 16 times and with every read; the
- * cards check for contention (ie: if one card writes a 0 bit and another
- * writes a 1 bit then the host sees a 0. At the end of the cycle; each card
- * compares the data on the bus; if there is a difference then that card goes
- * into ID_WAIT state again). In the meantime; one bit of data is returned in
- * the AX register which is conveniently returned to us by inb(). Hence; we
- * read 16 times getting one bit of data with each read.
- */
-
-static int
-get_eeprom_data(id_port, offset)
- int id_port;
- int offset;
-{
- int i, data = 0;
- outb(id_port, 0x80 + offset);
- for (i = 0; i < 16; i++) {
- DELAY(BIT_DELAY_MULTIPLE * 1000);
- data = (data << 1) | (inw(id_port) & 1);
- }
- return (data);
-}
-
#endif /* NEP > 0 */
diff --git a/sys/dev/ep/if_ep_isa.c b/sys/dev/ep/if_ep_isa.c
new file mode 100644
index 0000000..b36ff57
--- /dev/null
+++ b/sys/dev/ep/if_ep_isa.c
@@ -0,0 +1,344 @@
+/*
+ * Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Herb Peyerl.
+ * 4. The name of Herb Peyerl may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include <machine/clock.h>
+
+#include <i386/isa/isa_device.h>
+
+#include <dev/ep/if_epreg.h>
+#include <dev/ep/if_epvar.h>
+#include <i386/isa/elink.h>
+
+static int ep_isa_probe (struct isa_device *);
+static int ep_isa_attach (struct isa_device *);
+static struct ep_board *ep_look_for_board_at (struct isa_device *is);
+static int get_eeprom_data (int, int);
+static void epintr (int);
+
+#if 0
+static int send_ID_sequence (int);
+#endif
+
+static int ep_current_tag = EP_LAST_TAG + 1;
+
+struct isa_driver epdriver = {
+ ep_isa_probe,
+ ep_isa_attach,
+ "ep",
+ 0
+};
+
+int
+ep_isa_probe(is)
+ struct isa_device *is;
+{
+ struct ep_softc *sc;
+ struct ep_board *epb;
+ u_short k;
+
+ if ((epb = ep_look_for_board_at(is)) == 0)
+ return (0);
+
+ /*
+ * Allocate a storage area for us
+ */
+ sc = ep_alloc(ep_unit, epb);
+ if (!sc)
+ return (0);
+
+ is->id_unit = ep_unit++;
+
+ /*
+ * The iobase was found and MFG_ID was 0x6d50. PROD_ID should be
+ * 0x9[0-f]50 (IBM-PC)
+ * 0x9[0-f]5[0-f] (PC-98)
+ */
+ GO_WINDOW(0);
+ k = sc->epb->prod_id;
+#ifdef PC98
+ if ((k & 0xf0f0) != (PROD_ID & 0xf0f0)) {
+#else
+ if ((k & 0xf0ff) != (PROD_ID & 0xf0ff)) {
+#endif
+ printf("ep_isa_probe: ignoring model %04x\n", k);
+ ep_free(sc);
+ return (0);
+ }
+
+ k = sc->epb->res_cfg;
+
+ k >>= 12;
+
+ /* Now we have two cases again:
+ *
+ * 1. Device was configured with 'irq?'
+ * In this case we use irq read from the board
+ *
+ * 2. Device was configured with 'irq xxx'
+ * In this case we set up the board to use specified interrupt
+ *
+ */
+
+ if (is->id_irq == 0) { /* irq? */
+ is->id_irq = 1 << ((k == 2) ? 9 : k);
+ }
+
+ sc->stat = 0; /* 16 bit access */
+
+ /* By now, the adapter is already activated */
+
+ return (EP_IOSIZE); /* 16 bytes of I/O space used. */
+}
+
+static int
+ep_isa_attach(is)
+ struct isa_device *is;
+{
+ struct ep_softc *sc = ep_softc[is->id_unit];
+ u_short config;
+ int irq;
+
+ is->id_ointr = epintr;
+ sc->ep_connectors = 0;
+ config = inw(IS_BASE + EP_W0_CONFIG_CTRL);
+ if (config & IS_AUI) {
+ sc->ep_connectors |= AUI;
+ }
+ if (config & IS_BNC) {
+ sc->ep_connectors |= BNC;
+ }
+ if (config & IS_UTP) {
+ sc->ep_connectors |= UTP;
+ }
+ if (!(sc->ep_connectors & 7))
+ printf("no connectors!");
+ sc->ep_connector = inw(BASE + EP_W0_ADDRESS_CFG) >> ACF_CONNECTOR_BITS;
+ /*
+ * Write IRQ value to board
+ */
+
+ irq = ffs(is->id_irq) - 1;
+ if (irq == -1) {
+ printf(" invalid irq... cannot attach\n");
+ return 0;
+ }
+
+ GO_WINDOW(0);
+ SET_IRQ(BASE, irq);
+
+ ep_attach(sc);
+ return 1;
+}
+
+static struct ep_board *
+ep_look_for_board_at(is)
+ struct isa_device *is;
+{
+ int data, i, j, id_port = ELINK_ID_PORT;
+ int count = 0;
+
+ if (ep_current_tag == (EP_LAST_TAG + 1)) {
+ /* Come here just one time */
+
+ ep_current_tag--;
+
+ /* Look for the ISA boards. Init and leave them actived */
+ outb(id_port, 0);
+ outb(id_port, 0);
+
+ elink_idseq(0xCF);
+
+ elink_reset();
+ DELAY(DELAY_MULTIPLE * 10000);
+ for (i = 0; i < EP_MAX_BOARDS; i++) {
+ outb(id_port, 0);
+ outb(id_port, 0);
+ elink_idseq(0xCF);
+
+ data = get_eeprom_data(id_port, EEPROM_MFG_ID);
+ if (data != MFG_ID)
+ break;
+
+ /* resolve contention using the Ethernet address */
+
+ for (j = 0; j < 3; j++)
+ get_eeprom_data(id_port, j);
+
+ /* and save this address for later use */
+
+ for (j = 0; j < 3; j++)
+ ep_board[ep_boards].eth_addr[j] = get_eeprom_data(id_port, j);
+
+ ep_board[ep_boards].res_cfg =
+ get_eeprom_data(id_port, EEPROM_RESOURCE_CFG);
+
+ ep_board[ep_boards].prod_id =
+ get_eeprom_data(id_port, EEPROM_PROD_ID);
+
+ ep_board[ep_boards].epb_used = 0;
+#ifdef PC98
+ ep_board[ep_boards].epb_addr =
+ (get_eeprom_data(id_port, EEPROM_ADDR_CFG) & 0x1f) *
+ 0x100 + 0x40d0;
+#else
+ ep_board[ep_boards].epb_addr =
+ (get_eeprom_data(id_port, EEPROM_ADDR_CFG) & 0x1f) *
+ 0x10 + 0x200;
+
+ if (ep_board[ep_boards].epb_addr > 0x3E0)
+ /* Board in EISA configuration mode */
+ continue;
+#endif /* PC98 */
+
+ outb(id_port, ep_current_tag); /* tags board */
+ outb(id_port, ACTIVATE_ADAPTER_TO_CONFIG);
+ ep_boards++;
+ count++;
+ ep_current_tag--;
+ }
+
+ ep_board[ep_boards].epb_addr = 0;
+ if (count) {
+ printf("%d 3C5x9 board(s) on ISA found at", count);
+ for (j = 0; ep_board[j].epb_addr; j++)
+ if (ep_board[j].epb_addr <= 0x3E0)
+ printf(" 0x%x", ep_board[j].epb_addr);
+ printf("\n");
+ }
+ }
+
+ /* we have two cases:
+ *
+ * 1. Device was configured with 'port ?'
+ * In this case we search for the first unused card in list
+ *
+ * 2. Device was configured with 'port xxx'
+ * In this case we search for the unused card with that address
+ *
+ */
+
+ if (IS_BASE == -1) { /* port? */
+ for (i = 0; ep_board[i].epb_addr && ep_board[i].epb_used; i++)
+ ;
+ if (ep_board[i].epb_addr == 0)
+ return 0;
+
+ IS_BASE = ep_board[i].epb_addr;
+ ep_board[i].epb_used = 1;
+
+ return &ep_board[i];
+ } else {
+ for (i = 0;
+ ep_board[i].epb_addr && ep_board[i].epb_addr != IS_BASE;
+ i++)
+ ;
+
+ if (ep_board[i].epb_used || ep_board[i].epb_addr != IS_BASE)
+ return 0;
+
+ if (inw(IS_BASE + EP_W0_EEPROM_COMMAND) & EEPROM_TST_MODE) {
+ printf("ep%d: 3c5x9 at 0x%x in PnP mode. Disable PnP mode!\n",
+ is->id_unit, IS_BASE);
+ }
+ ep_board[i].epb_used = 1;
+
+ return &ep_board[i];
+ }
+}
+
+/*
+ * We get eeprom data from the id_port given an offset into the eeprom.
+ * Basically; after the ID_sequence is sent to all of the cards; they enter
+ * the ID_CMD state where they will accept command requests. 0x80-0xbf loads
+ * the eeprom data. We then read the port 16 times and with every read; the
+ * cards check for contention (ie: if one card writes a 0 bit and another
+ * writes a 1 bit then the host sees a 0. At the end of the cycle; each card
+ * compares the data on the bus; if there is a difference then that card goes
+ * into ID_WAIT state again). In the meantime; one bit of data is returned in
+ * the AX register which is conveniently returned to us by inb(). Hence; we
+ * read 16 times getting one bit of data with each read.
+ */
+
+static int
+get_eeprom_data(id_port, offset)
+ int id_port;
+ int offset;
+{
+ int i, data = 0;
+ outb(id_port, 0x80 + offset);
+ for (i = 0; i < 16; i++) {
+ DELAY(BIT_DELAY_MULTIPLE * 1000);
+ data = (data << 1) | (inw(id_port) & 1);
+ }
+ return (data);
+}
+
+void
+epintr(unit)
+ int unit;
+{
+ register struct ep_softc *sc = ep_softc[unit];
+
+ ep_intr(sc);
+
+ return;
+}
+
+#if 0
+static int
+send_ID_sequence(port)
+ int port;
+{
+ int cx, al;
+
+ for (al = 0xff, cx = 0; cx < 255; cx++) {
+ outb(port, al);
+ al <<= 1;
+ if (al & 0x100)
+ al ^= 0xcf;
+ }
+ return (1);
+}
+#endif
diff --git a/sys/dev/ep/if_ep_mca.c b/sys/dev/ep/if_ep_mca.c
new file mode 100644
index 0000000..6e0b9e3
--- /dev/null
+++ b/sys/dev/ep/if_ep_mca.c
@@ -0,0 +1,219 @@
+/*-
+ * Copyright (c) 1999 Matthew N. Dodd <winter@jurai.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+
+#include <machine/clock.h>
+#include <machine/cpufunc.h>
+#include <machine/md_var.h>
+
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <net/if.h>
+#include <net/if_mib.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include <dev/mca/mca_busreg.h>
+#include <dev/mca/mca_busvar.h>
+
+#include <dev/ep/if_epreg.h>
+#include <dev/ep/if_epvar.h>
+
+#define EP_MCA_627C 0x627C
+#define EP_MCA_627D 0x627D
+#define EP_MCA_62DB 0x62db
+#define EP_MCA_62F6 0x62f6
+#define EP_MCA_62F7 0x62f7
+
+static struct mca_ident ep_mca_devs[] = {
+ { EP_MCA_627C, "3Com 3C529 Network Adapter" },
+ { EP_MCA_627D, "3Com 3C529-TP Network Adapter" },
+
+ /*
+ * These are from the linux 3c509 driver.
+ * I have not seen the ADFs for them and have
+ * not tested or even seen the hardware.
+ * Someone with the ADFs should replace the names with
+ * whatever is in the AdapterName field of the ADF.
+ * (and fix the media setup for the cards as well.)
+ */
+ { EP_MCA_62DB, "3Com 3c529 EtherLink III (test mode)" },
+ { EP_MCA_62F6, "3Com 3c529 EtherLink III (TP or coax)" },
+ { EP_MCA_62F7, "3Com 3c529 EtherLink III (TP)" },
+
+ { 0, NULL },
+};
+
+#define EP_MCA_IOPORT_POS MCA_ADP_POS(MCA_POS2)
+#define EP_MCA_IOPORT_MASK 0xfc
+#define EP_MCA_IOPORT_SIZE 0x0f
+#define EP_MCA_IOPORT(pos) ((((u_int32_t)pos & EP_MCA_IOPORT_MASK) \
+ | 0x02) << 8)
+
+#define EP_MCA_IRQ_POS MCA_ADP_POS(MCA_POS3)
+#define EP_MCA_IRQ_MASK 0x0f
+#define EP_MCA_IRQ(pos) (pos & EP_MCA_IRQ_MASK)
+
+#define EP_MCA_MEDIA_POS MCA_ADP_POS(MCA_POS2)
+#define EP_MCA_MEDIA_MASK 0x03
+#define EP_MCA_MEDIA(pos) (pos & EP_MCA_MEDIA_MASK)
+
+static int
+ep_mca_probe (device_t dev)
+{
+ const char * desc;
+ u_int32_t iobase = 0;
+ u_int8_t irq = 0;
+ u_int8_t pos;
+
+ desc = mca_match_id(mca_get_id(dev), ep_mca_devs);
+ if (!desc)
+ return (ENXIO);
+ device_set_desc(dev, desc);
+
+ pos = mca_pos_read(dev, EP_MCA_IOPORT_POS);
+ iobase = EP_MCA_IOPORT(pos);
+
+ pos = mca_pos_read(dev, EP_MCA_IRQ_POS);
+ irq = EP_MCA_IRQ(pos);
+
+ mca_add_iospace(dev, iobase, EP_MCA_IOPORT_SIZE);
+ mca_add_irq(dev, irq);
+
+ return (0);
+}
+
+static int
+ep_mca_attach (device_t dev)
+{
+ struct ep_softc * sc;
+ struct ep_board * epb;
+ struct resource * io = 0;
+ struct resource * irq = 0;
+ u_int8_t pos;
+ int unit = device_get_unit(dev);
+ int i, rid;
+ void * ih;
+
+ rid = 0;
+ io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
+ 0, ~0, 1, RF_ACTIVE);
+ if (!io) {
+ device_printf(dev, "No I/O space?!\n");
+ goto bad;
+ }
+
+ rid = 0;
+ irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
+ 0, ~0, 1, RF_ACTIVE);
+ if (!irq) {
+ device_printf(dev, "No irq?!\n");
+ goto bad;
+ }
+
+ epb = &ep_board[ep_boards];
+
+ epb->epb_addr = rman_get_start(io);
+ epb->epb_used = 1;
+
+ if(!(sc = ep_alloc(unit, epb)))
+ goto bad;
+
+ ep_boards++;
+
+ sc->stat = F_ACCESS_32_BITS;
+
+ switch(mca_get_id(dev)) {
+ case EP_MCA_627C:
+ sc->ep_connectors = BNC|AUI;
+ break;
+ case EP_MCA_627D:
+ sc->ep_connectors = UTP|AUI;
+ break;
+ default:
+ break;
+ }
+ pos = mca_pos_read(dev, EP_MCA_MEDIA_POS);
+ sc->ep_connector = EP_MCA_MEDIA(pos);
+
+ /*
+ * Retrieve our ethernet address
+ */
+ GO_WINDOW(0);
+ for(i = 0; i < 3; i++)
+ sc->epb->eth_addr[i] = get_e(sc, i);
+
+ GO_WINDOW(0);
+ SET_IRQ(BASE, rman_get_start(irq));
+
+ ep_attach(sc);
+
+ bus_setup_intr(dev, irq, INTR_TYPE_NET, ep_intr, sc, &ih);
+
+ return (0);
+
+bad:
+ if (io)
+ bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
+ if (irq)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, irq);
+
+ return (-1);
+}
+
+static device_method_t ep_mca_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ep_mca_probe),
+ DEVMETHOD(device_attach, ep_mca_attach),
+
+ { 0, 0 }
+};
+
+static driver_t ep_mca_driver = {
+ "ep",
+ ep_mca_methods,
+ 1, /* unusep */
+};
+
+static devclass_t ep_devclass;
+
+DRIVER_MODULE(ep, mca, ep_mca_driver, ep_devclass, 0, 0);
diff --git a/sys/dev/ep/if_ep_pccard.c b/sys/dev/ep/if_ep_pccard.c
new file mode 100644
index 0000000..4b18497
--- /dev/null
+++ b/sys/dev/ep/if_ep_pccard.c
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Herb Peyerl.
+ * 4. The name of Herb Peyerl may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Pccard support for 3C589 by:
+ * HAMADA Naoki
+ * nao@tom-yam.or.jp
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include <machine/clock.h>
+
+#include <sys/select.h>
+#include <sys/module.h>
+#include <pccard/cardinfo.h>
+#include <pccard/slot.h>
+
+#include <dev/ep/if_epreg.h>
+#include <dev/ep/if_epvar.h>
+
+/*
+ * PC-Card (PCMCIA) specific code.
+ */
+static int ep_pccard_init (struct pccard_devinfo *);
+static int ep_pccard_attach ((struct pccard_devinfo *);
+static void ep_pccard_unload (struct pccard_devinfo *);
+static int ep_pccard_intr (struct pccard_devinfo *);
+static int ep_pccard_identify (struct ep_board *epb, int unit);
+
+PCCARD_MODULE(ep, ep_pccard_init, ep_pccard_unload, ep_pccard_intr, 0, net_imask);
+
+/*
+ * Initialize the device - called from Slot manager.
+ */
+static int
+ep_pccard_init(devi)
+ struct pccard_devinfo *devi;
+{
+ struct isa_device *is = &devi->isahd;
+ struct ep_softc *sc = ep_softc[is->id_unit];
+ struct ep_board *epb;
+ int i;
+
+ epb = &ep_board[is->id_unit];
+
+ if (sc == 0) {
+ if ((sc = ep_alloc(is->id_unit, epb)) == 0) {
+ return (ENXIO);
+ }
+ ep_unit++;
+ }
+
+ /* get_e() requires these. */
+ sc->ep_io_addr = is->id_iobase;
+ sc->unit = is->id_unit;
+ epb->epb_addr = is->id_iobase;
+ epb->epb_used = 1;
+
+ /*
+ * XXX - Certain (newer?) 3Com cards need epb->cmd_off == 2. Sadly,
+ * you need to have a correct cmd_off in order to identify the card.
+ * So we have to hit it with both and cross our virtual fingers. There's
+ * got to be a better way to do this. jyoung@accessus.net 09/11/1999
+ */
+
+ epb->cmd_off = 0;
+ epb->prod_id = get_e(sc, EEPROM_PROD_ID);
+ if (!ep_pccard_identify(epb, is->id_unit)) {
+ if (bootverbose) printf("ep%d: Pass 1 of 2 detection failed (nonfatal)\n", is->id_unit);
+ epb->cmd_off = 2;
+ epb->prod_id = get_e(sc, EEPROM_PROD_ID);
+ if (!ep_pccard_identify(epb, is->id_unit)) {
+ if (bootverbose) printf("ep%d: Pass 2 of 2 detection failed (fatal!)\n", is->id_unit);
+ printf("ep%d: Unit failed to come ready or product ID unknown! (id 0x%x)\n", is->id_unit, epb->prod_id);
+ return (ENXIO);
+ }
+ }
+
+ epb->res_cfg = get_e(sc, EEPROM_RESOURCE_CFG);
+ for (i = 0; i < 3; i++)
+ sc->epb->eth_addr[i] = get_e(sc, EEPROM_NODE_ADDR_0 + i);
+
+ if (ep_pccard_attach(devi) == 0)
+ return (ENXIO);
+
+ sc->arpcom.ac_if.if_snd.ifq_maxlen = ifqmaxlen;
+ return (0);
+}
+
+static int
+ep_pccard_identify(epb, unit)
+ struct ep_board *epb;
+ int unit;
+{
+ /* Determine device type and associated MII capabilities */
+ switch (epb->prod_id) {
+ case 0x6055: /* 3C556 */
+ if (bootverbose) printf("ep%d: 3Com 3C556\n", unit);
+ epb->mii_trans = 1;
+ return (1);
+ break; /* NOTREACHED */
+ case 0x4057: /* 3C574 */
+ if (bootverbose) printf("ep%d: 3Com 3C574\n", unit);
+ epb->mii_trans = 1;
+ return (1);
+ break; /* NOTREACHED */
+ case 0x4b57: /* 3C574B */
+ if (bootverbose) printf("ep%d: 3Com 3C574B, Megahertz 3CCFE574BT or Fast Etherlink 3C574-TX\n", unit);
+ epb->mii_trans = 1;
+ return (1);
+ break; /* NOTREACHED */
+ case 0x9058: /* 3C589 */
+ if (bootverbose) printf("ep%d: 3Com Etherlink III 3C589[B/C/D]\n", unit);
+ epb->mii_trans = 0;
+ return (1);
+ break; /* NOTREACHED */
+ }
+ return (0);
+}
+
+static int
+ep_pccard_attach(devi)
+ struct pccard_devinfo *devi;
+{
+ struct isa_device *is = &devi->isahd;
+ struct ep_softc *sc = ep_softc[is->id_unit];
+ u_short config;
+
+ sc->ep_connectors = 0;
+ config = inw(IS_BASE + EP_W0_CONFIG_CTRL);
+ if (config & IS_BNC) {
+ sc->ep_connectors |= BNC;
+ }
+ if (config & IS_UTP) {
+ sc->ep_connectors |= UTP;
+ }
+ if (!(sc->ep_connectors & 7))
+ /* (Apparently) non-fatal */
+ if(bootverbose) printf("ep%d: No connectors or MII.\n", is->id_unit);
+
+ sc->ep_connector = inw(BASE + EP_W0_ADDRESS_CFG) >> ACF_CONNECTOR_BITS;
+
+ /* ROM size = 0, ROM base = 0 */
+ /* For now, ignore AUTO SELECT feature of 3C589B and later. */
+ outw(BASE + EP_W0_ADDRESS_CFG, get_e(sc, EEPROM_ADDR_CFG) & 0xc000);
+
+ /* Fake IRQ must be 3 */
+ outw(BASE + EP_W0_RESOURCE_CFG, (sc->epb->res_cfg & 0x0fff) | 0x3000);
+
+ outw(BASE + EP_W0_PRODUCT_ID, sc->epb->prod_id);
+
+ if (sc->epb->mii_trans) {
+ /*
+ * turn on the MII transciever
+ */
+ GO_WINDOW(3);
+ outw(BASE + EP_W3_OPTIONS, 0x8040);
+ DELAY(1000);
+ outw(BASE + EP_W3_OPTIONS, 0xc040);
+ outw(BASE + EP_COMMAND, RX_RESET);
+ outw(BASE + EP_COMMAND, TX_RESET);
+ while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
+ DELAY(1000);
+ outw(BASE + EP_W3_OPTIONS, 0x8040);
+ }
+
+ ep_attach(sc);
+
+ return 1;
+}
+
+static void
+ep_pccard_unload(devi)
+ struct pccard_devinfo *devi;
+{
+ struct ep_softc *sc = ep_softc[devi->isahd.id_unit];
+
+ if (sc->gone) {
+ printf("ep%d: already unloaded\n", devi->isahd.id_unit);
+ return;
+ }
+ sc->arpcom.ac_if.if_flags &= ~IFF_RUNNING;
+ sc->gone = 1;
+ printf("ep%d: unload\n", devi->isahd.id_unit);
+}
+
+/*
+ * card_intr - Shared interrupt called from
+ * front end of PC-Card handler.
+ */
+static int
+ep_pccard_intr(devi)
+ struct pccard_devinfo *devi;
+{
+ struct ep_softc *sc = ep_softc[devi->isahd.id_unit];
+
+ if (sc->gone) {
+ return;
+ }
+
+ ep_intr((void *)sc);
+
+ return(1);
+}
diff --git a/sys/dev/ep/if_epreg.h b/sys/dev/ep/if_epreg.h
index 08ff37b..fb729cb 100644
--- a/sys/dev/ep/if_epreg.h
+++ b/sys/dev/ep/if_epreg.h
@@ -19,78 +19,15 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * if_epreg.h,v 1.4 1994/11/13 10:12:37 gibbs Exp Modified by:
- *
- October 2, 1994
-
- Modified by: Andres Vega Garcia
-
- INRIA - Sophia Antipolis, France
- e-mail: avega@sophia.inria.fr
- finger: avega@pax.inria.fr
-
- */
-/*
* $FreeBSD$
- *
- * Promiscuous mode added and interrupt logic slightly changed
- * to reduce the number of adapter failures. Transceiver select
- * logic changed to use value from EEPROM. Autoconfiguration
- * features added.
- * Done by:
- * Serge Babkin
- * Chelindbank (Chelyabinsk, Russia)
- * babkin@hq.icb.chel.su
- */
-
-/*
- * Pccard support for 3C589 by:
- * HAMADA Naoki
- * nao@tom-yam.or.jp
*/
/*
- * Ethernet software status per interface.
+ * DELAY_MULTIPLE: How much to boost "base" delays, except
+ * for the inter-bit delays in get_eeprom_data. A cyrix Media GX needed this.
*/
-struct ep_softc {
- struct arpcom arpcom; /* Ethernet common part */
- int ep_io_addr; /* i/o bus address */
- struct mbuf *top, *mcur;
- short cur_len;
- u_short ep_connectors; /* Connectors on this card. */
- u_char ep_connector; /* Configured connector. */
- int stat; /* some flags */
- int gone; /* adapter is not present (for PCCARD) */
-#define F_RX_FIRST 0x1
-#define F_PROMISC 0x8
-
-#define F_ACCESS_32_BITS 0x100
-
- struct ep_board *epb;
-
- int unit;
-
-#ifdef EP_LOCAL_STATS
- short tx_underrun;
- short rx_no_first;
- short rx_no_mbuf;
- short rx_bpf_disc;
- short rx_overrunf;
- short rx_overrunl;
-#endif
-};
-
-struct ep_board {
- int epb_addr; /* address of this board */
- char epb_used; /* was this entry already used for configuring ? */
- /* data from EEPROM for later use */
- u_short eth_addr[3]; /* Ethernet address */
- u_short prod_id; /* product ID */
- int cmd_off; /* command offset (bit shift) */
- int mii_trans; /* activate MII transiever */
- u_short res_cfg; /* resource configuration */
-};
-
+#define DELAY_MULTIPLE 10
+#define BIT_DELAY_MULTIPLE 10
/*
* Some global constants
@@ -455,16 +392,6 @@ struct ep_board {
#define RX_BYTES_MASK (u_short) (0x07ff)
-extern struct ep_board ep_board[];
-extern int ep_boards;
-extern u_long ep_unit;
-extern struct ep_softc *ep_alloc __P((int unit, struct ep_board *epb));
-extern void ep_free __P((struct ep_softc *sc));
-extern void ep_intr __P((void *sc));
-extern int ep_attach __P((struct ep_softc *sc));
-
-extern u_int16_t get_e __P((struct ep_softc *sc, int offset));
-
/*
* Config flags
*/
diff --git a/sys/dev/ep/if_epvar.h b/sys/dev/ep/if_epvar.h
new file mode 100644
index 0000000..4ad224f
--- /dev/null
+++ b/sys/dev/ep/if_epvar.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 1993 Herb Peyerl (hpeyerl@novatel.ca) All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2. The name
+ * of the author may not be used to endorse or promote products derived from
+ * this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Ethernet software status per interface.
+ */
+struct ep_softc {
+ struct arpcom arpcom; /* Ethernet common part */
+ int ep_io_addr; /* i/o bus address */
+ struct mbuf * top;
+ struct mbuf * mcur;
+ short cur_len;
+ u_short ep_connectors; /* Connectors on this card. */
+ u_char ep_connector; /* Configured connector. */
+ int stat; /* some flags */
+ int gone; /* adapter is not present (for PCCARD) */
+#define F_RX_FIRST 0x1
+#define F_PROMISC 0x8
+
+#define F_ACCESS_32_BITS 0x100
+
+ struct ep_board *epb;
+
+ int unit;
+
+#ifdef EP_LOCAL_STATS
+ short tx_underrun;
+ short rx_no_first;
+ short rx_no_mbuf;
+ short rx_bpf_disc;
+ short rx_overrunf;
+ short rx_overrunl;
+#endif
+};
+
+struct ep_board {
+ int epb_addr; /* address of this board */
+ char epb_used; /* was this entry already used for configuring ? */
+ /* data from EEPROM for later use */
+ u_short eth_addr[3]; /* Ethernet address */
+ u_short prod_id; /* product ID */
+ int cmd_off; /* command offset (bit shift) */
+ int mii_trans; /* activate MII transiever */
+ u_short res_cfg; /* resource configuration */
+};
+
+extern struct ep_softc* ep_softc[];
+extern struct ep_board ep_board[];
+extern int ep_boards;
+extern u_long ep_unit;
+
+extern struct ep_softc* ep_alloc (int, struct ep_board *);
+extern int ep_attach (struct ep_softc *);
+extern void ep_free (struct ep_softc *);
+extern void ep_intr (void *);
+
+extern u_int16_t get_e (struct ep_softc *, int);
OpenPOWER on IntegriCloud