- 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.
This commit is contained in:
mdodd 1999-09-26 06:42:36 +00:00
parent 07d248f02c
commit 8810bb96c7
6 changed files with 918 additions and 605 deletions

View File

@ -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];
u_long ep_unit;
static int eeprom_rdy __P((struct ep_softc *sc));
static char * ep_conn_type[] = {"UTP", "AUI", "???", "BNC"};
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 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 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);
}
ep_attach(sc);
return 1;
}
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;
@ -514,108 +175,6 @@ ep_free(sc)
return;
}
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 @@ epstart(ifp)
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 @@ epstart(ifp)
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 @@ epread(sc)
* 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 @@ epread(sc)
}
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 @@ epread(sc)
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 @@ epread(sc)
#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 @@ epread(sc)
}
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 @@ epread(sc)
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 @@ epread(sc)
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 */

344
sys/dev/ep/if_ep_isa.c Normal file
View File

@ -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

219
sys/dev/ep/if_ep_mca.c Normal file
View File

@ -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);

245
sys/dev/ep/if_ep_pccard.c Normal file
View File

@ -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);
}

View File

@ -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
* DELAY_MULTIPLE: How much to boost "base" delays, except
* for the inter-bit delays in get_eeprom_data. A cyrix Media GX needed this.
*/
/*
* 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, *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
*/

78
sys/dev/ep/if_epvar.h Normal file
View File

@ -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);