- Move driver to newbus.
- Provide identify methods for EtherExpress and 3c507 cards; this means these cards no longer need wired configs. - Provide a detach method.
This commit is contained in:
parent
3330d5fb09
commit
50e960d918
@ -206,6 +206,7 @@ device ed # NE[12]000, SMC Ultra, 3c503, DS8390 cards
|
||||
device ex # Intel EtherExpress Pro/10 and Pro/10+
|
||||
device ep # Etherlink III based cards
|
||||
device fe # Fujitsu MB8696x based cards
|
||||
device ie # EtherExpress 8/16, 3C507, StarLAN 10 etc.
|
||||
device lnc # NE2100, NE32-VL Lance Ethernet cards
|
||||
device sn # SMC's 9000 series of ethernet chips
|
||||
device xe # Xircom pccard ethernet
|
||||
|
@ -441,7 +441,8 @@ dev/ida/ida.c optional ida
|
||||
dev/ida/ida_disk.c optional ida
|
||||
dev/ida/ida_eisa.c optional ida eisa
|
||||
dev/ida/ida_pci.c optional ida pci
|
||||
dev/ie/if_ie.c count ie isa nowerror
|
||||
dev/ie/if_ie.c optional ie isa nowerror
|
||||
dev/ie/if_ie_isa.c optional ie isa
|
||||
dev/iicbus/iicbb_if.m optional iicbb
|
||||
dev/iicbus/iicbus_if.m optional iicbus
|
||||
dev/iicbus/if_ic.c optional ic
|
||||
|
@ -110,10 +110,6 @@
|
||||
* 16-pointers, we subtract iomem and and with 0xffff.
|
||||
*/
|
||||
|
||||
#include "ie.h"
|
||||
#include "opt_inet.h"
|
||||
#include "opt_ipx.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/eventhandler.h>
|
||||
@ -124,6 +120,14 @@
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/syslog.h>
|
||||
|
||||
#include <sys/module.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <machine/bus_pio.h>
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_types.h>
|
||||
@ -132,11 +136,8 @@
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/if_ether.h>
|
||||
|
||||
#include <machine/md_var.h>
|
||||
|
||||
#include <i386/isa/isa_device.h>
|
||||
#include <i386/isa/icu.h>
|
||||
#include <dev/ic/i82586.h>
|
||||
#include <dev/ie/if_ievar.h>
|
||||
#include <dev/ie/if_iereg.h>
|
||||
#include <dev/ie/if_ie507.h>
|
||||
#include <dev/ie/if_iee16.h>
|
||||
@ -144,10 +145,6 @@
|
||||
|
||||
#include <net/bpf.h>
|
||||
|
||||
#ifndef COMPAT_OLDISA
|
||||
#error "The ie device requires the old isa compatibility shims"
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#define IED_RINT 0x01
|
||||
#define IED_TINT 0x02
|
||||
@ -163,27 +160,11 @@ static int ie_debug = IED_RNR;
|
||||
/* Forward declaration */
|
||||
struct ie_softc;
|
||||
|
||||
static int ieprobe (struct isa_device * dvp);
|
||||
static int ieattach (struct isa_device * dvp);
|
||||
static ointhand2_t ieintr;
|
||||
static int sl_probe (struct isa_device * dvp);
|
||||
static int el_probe (struct isa_device * dvp);
|
||||
static int ee16_probe (struct isa_device * dvp);
|
||||
|
||||
static int check_ie_present (struct ie_softc *, caddr_t, unsigned);
|
||||
static void ieinit (void *);
|
||||
static void ie_stop (struct ie_softc *);
|
||||
static int ieioctl (struct ifnet *, u_long, caddr_t);
|
||||
static void iestart (struct ifnet *);
|
||||
|
||||
static void el_reset_586 (struct ie_softc *);
|
||||
static void el_chan_attn (struct ie_softc *);
|
||||
|
||||
static void sl_reset_586 (struct ie_softc *);
|
||||
static void sl_chan_attn (struct ie_softc *);
|
||||
|
||||
static void ee16_reset_586 (struct ie_softc *);
|
||||
static void ee16_chan_attn (struct ie_softc *);
|
||||
static __inline void
|
||||
ee16_interrupt_enable (struct ie_softc *);
|
||||
static void ee16_eeprom_outbits (struct ie_softc *, int, int);
|
||||
@ -197,7 +178,6 @@ static __inline void
|
||||
static void iereset (struct ie_softc *);
|
||||
static void ie_readframe (struct ie_softc *, int);
|
||||
static void ie_drop_packet_buffer (struct ie_softc *);
|
||||
static void sl_read_ether (struct ie_softc *, unsigned char *);
|
||||
static void find_ie_mem_size (struct ie_softc *);
|
||||
static void chan_attn_timeout (void *);
|
||||
static int command_and_wait (struct ie_softc *,
|
||||
@ -216,32 +196,12 @@ static void ie_mc_reset (struct ie_softc *);
|
||||
|
||||
#ifdef DEBUG
|
||||
static void print_rbd (volatile struct ie_recv_buf_desc * rbd);
|
||||
|
||||
static int in_ierint = 0;
|
||||
static int in_ietint = 0;
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This tells the autoconf code how to set us up.
|
||||
*/
|
||||
struct isa_driver iedriver = {
|
||||
INTR_TYPE_NET,
|
||||
ieprobe, ieattach, "ie"
|
||||
};
|
||||
COMPAT_ISA_DRIVER(ie, iedriver);
|
||||
|
||||
enum ie_hardware {
|
||||
IE_STARLAN10,
|
||||
IE_EN100,
|
||||
IE_SLFIBER,
|
||||
IE_3C507,
|
||||
IE_NI5210,
|
||||
IE_EE16,
|
||||
IE_UNKNOWN
|
||||
};
|
||||
|
||||
static const char *ie_hardware_names[] = {
|
||||
"None",
|
||||
"StarLAN 10",
|
||||
"EN100",
|
||||
"StarLAN Fiber",
|
||||
@ -281,238 +241,9 @@ static const char *ie_hardware_names[] = {
|
||||
#define NTXBUFS 1 /* number of transmit commands */
|
||||
#define IE_TBUF_SIZE ETHER_MAX_LEN /* size of transmit buffer */
|
||||
|
||||
/*
|
||||
* Ethernet status, per interface.
|
||||
*/
|
||||
static struct ie_softc {
|
||||
struct arpcom arpcom;
|
||||
void (*ie_reset_586) (struct ie_softc *);
|
||||
void (*ie_chan_attn) (struct ie_softc *);
|
||||
enum ie_hardware hard_type;
|
||||
int hard_vers;
|
||||
int unit;
|
||||
|
||||
u_short port; /* i/o base address for this interface */
|
||||
caddr_t iomem; /* memory size */
|
||||
caddr_t iomembot; /* memory base address */
|
||||
unsigned iosize;
|
||||
int bus_use; /* 0 means 16bit, 1 means 8 bit adapter */
|
||||
|
||||
int want_mcsetup;
|
||||
int promisc;
|
||||
int nframes;
|
||||
int nrxbufs;
|
||||
int ntxbufs;
|
||||
volatile struct ie_int_sys_conf_ptr *iscp;
|
||||
volatile struct ie_sys_ctl_block *scb;
|
||||
volatile struct ie_recv_frame_desc **rframes; /* nframes worth */
|
||||
volatile struct ie_recv_buf_desc **rbuffs; /* nrxbufs worth */
|
||||
volatile u_char **cbuffs; /* nrxbufs worth */
|
||||
int rfhead, rftail, rbhead, rbtail;
|
||||
|
||||
volatile struct ie_xmit_cmd **xmit_cmds; /* ntxbufs worth */
|
||||
volatile struct ie_xmit_buf **xmit_buffs; /* ntxbufs worth */
|
||||
volatile u_char **xmit_cbuffs; /* ntxbufs worth */
|
||||
int xmit_count;
|
||||
|
||||
struct ie_en_addr mcast_addrs[MAXMCAST + 1];
|
||||
int mcast_count;
|
||||
|
||||
u_short irq_encoded; /* encoded interrupt on IEE16 */
|
||||
} ie_softc[NIE];
|
||||
|
||||
#define MK_24(base, ptr) ((caddr_t)((uintptr_t)ptr - (uintptr_t)base))
|
||||
#define MK_16(base, ptr) ((u_short)(uintptr_t)MK_24(base, ptr))
|
||||
|
||||
#define PORT(sc) (sc->port)
|
||||
#define MEM(sc) (sc->iomem)
|
||||
|
||||
static int
|
||||
ieprobe(struct isa_device *dvp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = sl_probe(dvp);
|
||||
if (!ret)
|
||||
ret = el_probe(dvp);
|
||||
if (!ret)
|
||||
ret = ee16_probe(dvp);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
sl_probe(struct isa_device *dvp)
|
||||
{
|
||||
struct ie_softc * sc = &ie_softc[dvp->id_unit];
|
||||
u_char c;
|
||||
|
||||
sc->port = dvp->id_iobase;
|
||||
sc->iomembot = dvp->id_maddr;
|
||||
sc->iomem = 0;
|
||||
sc->bus_use = 0;
|
||||
|
||||
c = inb(PORT(sc) + IEATT_REVISION);
|
||||
switch (SL_BOARD(c)) {
|
||||
case SL10_BOARD:
|
||||
sc->hard_type = IE_STARLAN10;
|
||||
break;
|
||||
case EN100_BOARD:
|
||||
sc->hard_type = IE_EN100;
|
||||
break;
|
||||
case SLFIBER_BOARD:
|
||||
sc->hard_type = IE_SLFIBER;
|
||||
break;
|
||||
case 0x00:
|
||||
if (inb(PORT(sc) + IEATT_ATTRIB) != 0x55)
|
||||
return (0);
|
||||
|
||||
sc->hard_type = IE_NI5210;
|
||||
sc->bus_use = 1;
|
||||
|
||||
break;
|
||||
|
||||
/*
|
||||
* Anything else is not recognized or cannot be used.
|
||||
*/
|
||||
default:
|
||||
return (0);
|
||||
}
|
||||
|
||||
sc->ie_reset_586 = sl_reset_586;
|
||||
sc->ie_chan_attn = sl_chan_attn;
|
||||
|
||||
sc->hard_vers = SL_REV(c);
|
||||
|
||||
/*
|
||||
* Divine memory size on-board the card. Ususally 16k.
|
||||
*/
|
||||
find_ie_mem_size(sc);
|
||||
|
||||
if (!sc->iosize) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (!dvp->id_msize) {
|
||||
dvp->id_msize = sc->iosize;
|
||||
} else if (dvp->id_msize != sc->iosize) {
|
||||
printf("ie%d: kernel configured msize %d "
|
||||
"doesn't match board configured msize %d\n",
|
||||
sc->unit,
|
||||
dvp->id_msize,
|
||||
sc->iosize);
|
||||
return (0);
|
||||
}
|
||||
|
||||
switch (sc->hard_type) {
|
||||
case IE_EN100:
|
||||
case IE_STARLAN10:
|
||||
case IE_SLFIBER:
|
||||
case IE_NI5210:
|
||||
sl_read_ether(sc, sc->arpcom.ac_enaddr);
|
||||
break;
|
||||
default:
|
||||
if (bootverbose)
|
||||
printf("ie%d: unknown AT&T board type code %d\n",
|
||||
sc->unit,
|
||||
sc->hard_type);
|
||||
return (0);
|
||||
}
|
||||
|
||||
return (16);
|
||||
}
|
||||
|
||||
static int
|
||||
el_probe(struct isa_device *dvp)
|
||||
{
|
||||
struct ie_softc *sc = &ie_softc[dvp->id_unit];
|
||||
u_char c;
|
||||
int i;
|
||||
u_char signature[] = "*3COM*";
|
||||
|
||||
sc->unit = dvp->id_unit;
|
||||
sc->port = dvp->id_iobase;
|
||||
sc->iomembot = dvp->id_maddr;
|
||||
sc->bus_use = 0;
|
||||
|
||||
/* Need this for part of the probe. */
|
||||
sc->ie_reset_586 = el_reset_586;
|
||||
sc->ie_chan_attn = el_chan_attn;
|
||||
|
||||
/* Reset and put card in CONFIG state without changing address. */
|
||||
elink_reset();
|
||||
outb(ELINK_ID_PORT, 0x00);
|
||||
elink_idseq(ELINK_507_POLY);
|
||||
elink_idseq(ELINK_507_POLY);
|
||||
outb(ELINK_ID_PORT, 0xff);
|
||||
|
||||
c = inb(PORT(sc) + IE507_MADDR);
|
||||
if (c & 0x20) {
|
||||
#ifdef DEBUG
|
||||
printf("ie%d: can't map 3C507 RAM in high memory\n", sc->unit);
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
/* go to RUN state */
|
||||
outb(ELINK_ID_PORT, 0x00);
|
||||
elink_idseq(ELINK_507_POLY);
|
||||
outb(ELINK_ID_PORT, 0x00);
|
||||
|
||||
outb(PORT(sc) + IE507_CTRL, EL_CTRL_NRST);
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
if (inb(PORT(sc) + i) != signature[i])
|
||||
return (0);
|
||||
|
||||
c = inb(PORT(sc) + IE507_IRQ) & 0x0f;
|
||||
|
||||
if (dvp->id_irq != (1 << c)) {
|
||||
printf("ie%d: kernel configured irq %d "
|
||||
"doesn't match board configured irq %d\n",
|
||||
sc->unit, ffs(dvp->id_irq) - 1, c);
|
||||
return (0);
|
||||
}
|
||||
c = (inb(PORT(sc) + IE507_MADDR) & 0x1c) + 0xc0;
|
||||
|
||||
if (kvtop(dvp->id_maddr) != ((int) c << 12)) {
|
||||
printf("ie%d: kernel configured maddr %lx "
|
||||
"doesn't match board configured maddr %x\n",
|
||||
sc->unit, (u_long)kvtop(dvp->id_maddr), (int) c << 12);
|
||||
return (0);
|
||||
}
|
||||
outb(PORT(sc) + IE507_CTRL, EL_CTRL_NORMAL);
|
||||
|
||||
sc->hard_type = IE_3C507;
|
||||
sc->hard_vers = 0; /* 3C507 has no version number. */
|
||||
|
||||
/*
|
||||
* Divine memory size on-board the card.
|
||||
*/
|
||||
find_ie_mem_size(sc);
|
||||
|
||||
if (!sc->iosize) {
|
||||
printf("ie%d: can't find shared memory\n", sc->unit);
|
||||
outb(PORT(sc) + IE507_CTRL, EL_CTRL_NRST);
|
||||
return (0);
|
||||
}
|
||||
if (!dvp->id_msize)
|
||||
dvp->id_msize = sc->iosize;
|
||||
else if (dvp->id_msize != sc->iosize) {
|
||||
printf("ie%d: kernel configured msize %d "
|
||||
"doesn't match board configured msize %d\n",
|
||||
sc->unit, dvp->id_msize, sc->iosize);
|
||||
outb(PORT(sc) + IE507_CTRL, EL_CTRL_NRST);
|
||||
return (0);
|
||||
}
|
||||
sl_read_ether(sc, sc->arpcom.ac_enaddr);
|
||||
|
||||
/* Clear the interrupt latch just in case. */
|
||||
outb(PORT(sc) + IE507_ICTRL, 1);
|
||||
|
||||
return (16);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ee16_shutdown(void *xsc, int howto)
|
||||
{
|
||||
@ -523,236 +254,28 @@ ee16_shutdown(void *xsc, int howto)
|
||||
outb(PORT(sc) + IEE16_ECTRL, 0);
|
||||
}
|
||||
|
||||
|
||||
/* Taken almost exactly from Rod's if_ix.c. */
|
||||
|
||||
static int
|
||||
ee16_probe(struct isa_device *dvp)
|
||||
{
|
||||
struct ie_softc *sc = &ie_softc[dvp->id_unit];
|
||||
|
||||
int i;
|
||||
u_short board_id, id_var1, id_var2, checksum = 0;
|
||||
u_short eaddrtemp, irq;
|
||||
u_short pg, adjust, decode, edecode;
|
||||
u_char bart_config;
|
||||
u_long bd_maddr;
|
||||
|
||||
short irq_translate[] = {0, IRQ9, IRQ3, IRQ4, IRQ5, IRQ10, IRQ11, 0};
|
||||
char irq_encode[] = {0, 0, 0, 2, 3, 4, 0, 0, 0, 1, 5, 6, 0, 0, 0, 0};
|
||||
|
||||
/* Need this for part of the probe. */
|
||||
sc->ie_reset_586 = ee16_reset_586;
|
||||
sc->ie_chan_attn = ee16_chan_attn;
|
||||
|
||||
/* unsure if this is necessary */
|
||||
sc->bus_use = 0;
|
||||
|
||||
/* reset any ee16 at the current iobase */
|
||||
outb(dvp->id_iobase + IEE16_ECTRL, IEE16_RESET_ASIC);
|
||||
outb(dvp->id_iobase + IEE16_ECTRL, 0);
|
||||
DELAY(240);
|
||||
|
||||
/* now look for ee16. */
|
||||
board_id = id_var1 = id_var2 = 0;
|
||||
for (i = 0; i < 4; i++) {
|
||||
id_var1 = inb(dvp->id_iobase + IEE16_ID_PORT);
|
||||
id_var2 = ((id_var1 & 0x03) << 2);
|
||||
board_id |= ((id_var1 >> 4) << id_var2);
|
||||
}
|
||||
|
||||
if (board_id != IEE16_ID) {
|
||||
if (bootverbose)
|
||||
printf("ie%d: unknown board_id: %x\n", sc->unit, board_id);
|
||||
return (0);
|
||||
}
|
||||
/* need sc->port for ee16_read_eeprom */
|
||||
sc->port = dvp->id_iobase;
|
||||
sc->hard_type = IE_EE16;
|
||||
|
||||
/*
|
||||
* The shared RAM location on the EE16 is encoded into bits 3-7 of
|
||||
* EEPROM location 6. We zero the upper byte, and shift the 5 bits
|
||||
* right 3. The resulting number tells us the RAM location.
|
||||
* Because the EE16 supports either 16k or 32k of shared RAM, we
|
||||
* only worry about the 32k locations.
|
||||
*
|
||||
* NOTE: if a 64k EE16 exists, it should be added to this switch. then
|
||||
* the ia->ia_msize would need to be set per case statement.
|
||||
*
|
||||
* value msize location
|
||||
* ===== ===== ========
|
||||
* 0x03 0x8000 0xCC000
|
||||
* 0x06 0x8000 0xD0000
|
||||
* 0x0C 0x8000 0xD4000
|
||||
* 0x18 0x8000 0xD8000
|
||||
*
|
||||
*/
|
||||
|
||||
bd_maddr = 0;
|
||||
i = (ee16_read_eeprom(sc, 6) & 0x00ff) >> 3;
|
||||
switch (i) {
|
||||
case 0x03:
|
||||
bd_maddr = 0xCC000;
|
||||
break;
|
||||
case 0x06:
|
||||
bd_maddr = 0xD0000;
|
||||
break;
|
||||
case 0x0c:
|
||||
bd_maddr = 0xD4000;
|
||||
break;
|
||||
case 0x18:
|
||||
bd_maddr = 0xD8000;
|
||||
break;
|
||||
default:
|
||||
bd_maddr = 0;
|
||||
break;
|
||||
}
|
||||
dvp->id_msize = 0x8000;
|
||||
if (kvtop(dvp->id_maddr) != bd_maddr) {
|
||||
printf("ie%d: kernel configured maddr %lx "
|
||||
"doesn't match board configured maddr %lx\n",
|
||||
sc->unit, (u_long)kvtop(dvp->id_maddr), bd_maddr);
|
||||
}
|
||||
sc->iomembot = dvp->id_maddr;
|
||||
sc->iomem = 0; /* XXX some probes set this and some don't */
|
||||
sc->iosize = dvp->id_msize;
|
||||
|
||||
/* need to put the 586 in RESET while we access the eeprom. */
|
||||
outb(PORT(sc) + IEE16_ECTRL, IEE16_RESET_586);
|
||||
|
||||
/* read the eeprom and checksum it, should == IEE16_ID */
|
||||
for (i = 0; i < 0x40; i++)
|
||||
checksum += ee16_read_eeprom(sc, i);
|
||||
|
||||
if (checksum != IEE16_ID) {
|
||||
printf("ie%d: invalid eeprom checksum: %x\n", sc->unit, checksum);
|
||||
return (0);
|
||||
}
|
||||
/*
|
||||
* Size and test the memory on the board. The size of the memory
|
||||
* can be one of 16k, 32k, 48k or 64k. It can be located in the
|
||||
* address range 0xC0000 to 0xEFFFF on 16k boundaries.
|
||||
*
|
||||
* If the size does not match the passed in memory allocation size
|
||||
* issue a warning, but continue with the minimum of the two sizes.
|
||||
*/
|
||||
|
||||
switch (dvp->id_msize) {
|
||||
case 65536:
|
||||
case 32768: /* XXX Only support 32k and 64k right now */
|
||||
break;
|
||||
case 16384:
|
||||
case 49512:
|
||||
default:
|
||||
printf("ie%d: mapped memory size %d not supported\n",
|
||||
sc->unit, dvp->id_msize);
|
||||
return (0);
|
||||
break; /* NOTREACHED */
|
||||
}
|
||||
|
||||
if ((kvtop(dvp->id_maddr) < 0xC0000) ||
|
||||
(kvtop(dvp->id_maddr) + sc->iosize > 0xF0000)) {
|
||||
printf("ie%d: mapped memory location %p out of range\n",
|
||||
sc->unit, (void *)dvp->id_maddr);
|
||||
return (0);
|
||||
}
|
||||
pg = (kvtop(dvp->id_maddr) & 0x3C000) >> 14;
|
||||
adjust = IEE16_MCTRL_FMCS16 | (pg & 0x3) << 2;
|
||||
decode = ((1 << (sc->iosize / 16384)) - 1) << pg;
|
||||
edecode = ((~decode >> 4) & 0xF0) | (decode >> 8);
|
||||
|
||||
/* ZZZ This should be checked against eeprom location 6, low byte */
|
||||
outb(PORT(sc) + IEE16_MEMDEC, decode & 0xFF);
|
||||
/* ZZZ This should be checked against eeprom location 1, low byte */
|
||||
outb(PORT(sc) + IEE16_MCTRL, adjust);
|
||||
/* ZZZ Now if I could find this one I would have it made */
|
||||
outb(PORT(sc) + IEE16_MPCTRL, (~decode & 0xFF));
|
||||
/* ZZZ I think this is location 6, high byte */
|
||||
outb(PORT(sc) + IEE16_MECTRL, edecode); /* XXX disable Exxx */
|
||||
|
||||
(void) kvtop(dvp->id_maddr);
|
||||
|
||||
/*
|
||||
* first prime the stupid bart DRAM controller so that it works,
|
||||
* then zero out all of memory.
|
||||
*/
|
||||
bzero(sc->iomembot, 32);
|
||||
bzero(sc->iomembot, sc->iosize);
|
||||
|
||||
/*
|
||||
* Get the encoded interrupt number from the EEPROM, check it
|
||||
* against the passed in IRQ. Issue a warning if they do not match.
|
||||
* Always use the passed in IRQ, not the one in the EEPROM.
|
||||
*/
|
||||
irq = ee16_read_eeprom(sc, IEE16_EEPROM_CONFIG1);
|
||||
irq = (irq & IEE16_EEPROM_IRQ) >> IEE16_EEPROM_IRQ_SHIFT;
|
||||
irq = irq_translate[irq];
|
||||
if (dvp->id_irq > 0) {
|
||||
if (irq != dvp->id_irq) {
|
||||
printf("ie%d: WARNING: board configured "
|
||||
"at irq %u, using %u\n",
|
||||
dvp->id_unit, dvp->id_irq, irq);
|
||||
irq = dvp->id_unit;
|
||||
}
|
||||
} else {
|
||||
dvp->id_irq = irq;
|
||||
}
|
||||
sc->irq_encoded = irq_encode[ffs(irq) - 1];
|
||||
|
||||
/*
|
||||
* Get the hardware ethernet address from the EEPROM and save it in
|
||||
* the softc for use by the 586 setup code.
|
||||
*/
|
||||
eaddrtemp = ee16_read_eeprom(sc, IEE16_EEPROM_ENET_HIGH);
|
||||
sc->arpcom.ac_enaddr[1] = eaddrtemp & 0xFF;
|
||||
sc->arpcom.ac_enaddr[0] = eaddrtemp >> 8;
|
||||
eaddrtemp = ee16_read_eeprom(sc, IEE16_EEPROM_ENET_MID);
|
||||
sc->arpcom.ac_enaddr[3] = eaddrtemp & 0xFF;
|
||||
sc->arpcom.ac_enaddr[2] = eaddrtemp >> 8;
|
||||
eaddrtemp = ee16_read_eeprom(sc, IEE16_EEPROM_ENET_LOW);
|
||||
sc->arpcom.ac_enaddr[5] = eaddrtemp & 0xFF;
|
||||
sc->arpcom.ac_enaddr[4] = eaddrtemp >> 8;
|
||||
|
||||
/* disable the board interrupts */
|
||||
outb(PORT(sc) + IEE16_IRQ, sc->irq_encoded);
|
||||
|
||||
/* enable loopback to keep bad packets off the wire */
|
||||
if (sc->hard_type == IE_EE16) {
|
||||
bart_config = inb(PORT(sc) + IEE16_CONFIG);
|
||||
bart_config |= IEE16_BART_LOOPBACK;
|
||||
bart_config |= IEE16_BART_MCS16_TEST;/* inb doesn't get bit! */
|
||||
outb(PORT(sc) + IEE16_CONFIG, bart_config);
|
||||
bart_config = inb(PORT(sc) + IEE16_CONFIG);
|
||||
}
|
||||
/* take the board out of reset state */
|
||||
outb(PORT(sc) + IEE16_ECTRL, 0);
|
||||
DELAY(100);
|
||||
|
||||
if (!check_ie_present(sc, dvp->id_maddr, sc->iosize))
|
||||
return (0);
|
||||
|
||||
return (16); /* return the number of I/O ports */
|
||||
}
|
||||
|
||||
/*
|
||||
* Taken almost exactly from Bill's if_is.c, then modified beyond recognition.
|
||||
*/
|
||||
static int
|
||||
ieattach(struct isa_device *dvp)
|
||||
int
|
||||
ie_attach(device_t dev)
|
||||
{
|
||||
int factor;
|
||||
struct ie_softc *sc = &ie_softc[dvp->id_unit];
|
||||
struct ifnet *ifp = &sc->arpcom.ac_if;
|
||||
size_t allocsize;
|
||||
struct ie_softc * sc;
|
||||
struct ifnet * ifp;
|
||||
size_t allocsize;
|
||||
int factor;
|
||||
|
||||
dvp->id_ointr = ieintr;
|
||||
sc = device_get_softc(dev);
|
||||
ifp = &sc->arpcom.ac_if;
|
||||
|
||||
sc->dev = dev;
|
||||
sc->unit = device_get_unit(dev);
|
||||
|
||||
/*
|
||||
* based on the amount of memory we have, allocate our tx and rx
|
||||
* resources.
|
||||
*/
|
||||
factor = dvp->id_msize / 8192;
|
||||
factor = rman_get_size(sc->mem_res) / 8192;
|
||||
sc->nframes = factor * NFRAMES;
|
||||
sc->nrxbufs = factor * NRXBUFS;
|
||||
sc->ntxbufs = factor * NTXBUFS;
|
||||
@ -768,7 +291,7 @@ ieattach(struct isa_device *dvp)
|
||||
M_DEVBUF,
|
||||
M_NOWAIT);
|
||||
if (sc->rframes == NULL)
|
||||
return (0);
|
||||
return (ENXIO);
|
||||
sc->rbuffs =
|
||||
(volatile struct ie_recv_buf_desc **)&sc->rframes[sc->nframes];
|
||||
sc->cbuffs = (volatile u_char **)&sc->rbuffs[sc->nrxbufs];
|
||||
@ -778,15 +301,14 @@ ieattach(struct isa_device *dvp)
|
||||
(volatile struct ie_xmit_buf **)&sc->xmit_cmds[sc->ntxbufs];
|
||||
sc->xmit_cbuffs = (volatile u_char **)&sc->xmit_buffs[sc->ntxbufs];
|
||||
|
||||
if (bootverbose)
|
||||
device_printf(sc->dev, "hardware type %s, revision %d\n",
|
||||
ie_hardware_names[sc->hard_type], sc->hard_vers + 1);
|
||||
|
||||
ifp->if_softc = sc;
|
||||
ifp->if_unit = dvp->id_unit;
|
||||
ifp->if_unit = sc->unit;
|
||||
ifp->if_name = "ie";
|
||||
ifp->if_mtu = ETHERMTU;
|
||||
printf("ie%d: <%s R%d> address %6D\n", sc->unit,
|
||||
ie_hardware_names[sc->hard_type],
|
||||
sc->hard_vers + 1,
|
||||
sc->arpcom.ac_enaddr, ":");
|
||||
|
||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
|
||||
ifp->if_start = iestart;
|
||||
ifp->if_ioctl = ieioctl;
|
||||
@ -797,17 +319,20 @@ ieattach(struct isa_device *dvp)
|
||||
EVENTHANDLER_REGISTER(shutdown_post_sync, ee16_shutdown,
|
||||
sc, SHUTDOWN_PRI_DEFAULT);
|
||||
|
||||
device_printf(sc->dev, "Ethernet address %6D\n",
|
||||
sc->arpcom.ac_enaddr, ":");
|
||||
|
||||
ether_ifattach(ifp, sc->arpcom.ac_enaddr);
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* What to do upon receipt of an interrupt.
|
||||
*/
|
||||
static void
|
||||
ieintr(int unit)
|
||||
void
|
||||
ie_intr(void *xsc)
|
||||
{
|
||||
struct ie_softc *sc = &ie_softc[unit];
|
||||
struct ie_softc *sc = (struct ie_softc *)xsc;
|
||||
u_short status;
|
||||
|
||||
/* Clear the interrupt latch on the 3C507. */
|
||||
@ -1457,8 +982,8 @@ iestart(struct ifnet *ifp)
|
||||
/*
|
||||
* Check to see if there's an 82586 out there.
|
||||
*/
|
||||
static int
|
||||
check_ie_present(struct ie_softc *sc, caddr_t where, unsigned size)
|
||||
int
|
||||
check_ie_present(struct ie_softc *sc)
|
||||
{
|
||||
volatile struct ie_sys_conf_ptr *scp;
|
||||
volatile struct ie_int_sys_conf_ptr *iscp;
|
||||
@ -1468,7 +993,7 @@ check_ie_present(struct ie_softc *sc, caddr_t where, unsigned size)
|
||||
|
||||
s = splimp();
|
||||
|
||||
realbase = (uintptr_t) where + size - (1 << 24);
|
||||
realbase = (uintptr_t) sc->iomembot + sc->iosize - (1 << 24);
|
||||
|
||||
scp = (volatile struct ie_sys_conf_ptr *) (uintptr_t)
|
||||
(realbase + IE_SCP_ADDR);
|
||||
@ -1480,10 +1005,10 @@ check_ie_present(struct ie_softc *sc, caddr_t where, unsigned size)
|
||||
* controller's. This is NOT where the ISCP will be in normal
|
||||
* operation.
|
||||
*/
|
||||
iscp = (volatile struct ie_int_sys_conf_ptr *) where;
|
||||
iscp = (volatile struct ie_int_sys_conf_ptr *) sc->iomembot;
|
||||
bzero((volatile char *)iscp, sizeof *iscp);
|
||||
|
||||
scb = (volatile struct ie_sys_ctl_block *) where;
|
||||
scb = (volatile struct ie_sys_ctl_block *) sc->iomembot;
|
||||
bzero((volatile char *)scb, sizeof *scb);
|
||||
|
||||
scp->ie_bus_use = sc->bus_use; /* 8-bit or 16-bit */
|
||||
@ -1526,7 +1051,6 @@ check_ie_present(struct ie_softc *sc, caddr_t where, unsigned size)
|
||||
splx(s);
|
||||
return (0);
|
||||
}
|
||||
sc->iosize = size;
|
||||
sc->iomem = (caddr_t) (uintptr_t) realbase;
|
||||
|
||||
sc->iscp = iscp;
|
||||
@ -1553,7 +1077,7 @@ find_ie_mem_size(struct ie_softc *sc)
|
||||
sc->iosize = 0;
|
||||
|
||||
for (size = 65536; size >= 8192; size -= 8192) {
|
||||
if (check_ie_present(sc, sc->iomembot, size)) {
|
||||
if (check_ie_present(sc)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1561,7 +1085,7 @@ find_ie_mem_size(struct ie_softc *sc)
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
el_reset_586(struct ie_softc *sc)
|
||||
{
|
||||
outb(PORT(sc) + IE507_CTRL, EL_CTRL_RESET);
|
||||
@ -1570,13 +1094,13 @@ el_reset_586(struct ie_softc *sc)
|
||||
DELAY(100);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
sl_reset_586(struct ie_softc *sc)
|
||||
{
|
||||
outb(PORT(sc) + IEATT_RESET, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
ee16_reset_586(struct ie_softc *sc)
|
||||
{
|
||||
outb(PORT(sc) + IEE16_ECTRL, IEE16_RESET_586);
|
||||
@ -1585,25 +1109,25 @@ ee16_reset_586(struct ie_softc *sc)
|
||||
DELAY(100);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
el_chan_attn(struct ie_softc *sc)
|
||||
{
|
||||
outb(PORT(sc) + IE507_ATTN, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
sl_chan_attn(struct ie_softc *sc)
|
||||
{
|
||||
outb(PORT(sc) + IEATT_ATTN, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
ee16_chan_attn(struct ie_softc *sc)
|
||||
{
|
||||
outb(PORT(sc) + IEE16_ATTN, 0);
|
||||
}
|
||||
|
||||
static u_short
|
||||
u_short
|
||||
ee16_read_eeprom(struct ie_softc *sc, int location)
|
||||
{
|
||||
int ectrl, edata;
|
||||
@ -1687,7 +1211,7 @@ ee16_interrupt_enable(struct ie_softc *sc)
|
||||
DELAY(100);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
sl_read_ether(struct ie_softc *sc, unsigned char *addr)
|
||||
{
|
||||
int i;
|
||||
@ -1709,10 +1233,6 @@ iereset(struct ie_softc *sc)
|
||||
{
|
||||
int s = splimp();
|
||||
|
||||
if (sc->unit >= NIE) {
|
||||
splx(s);
|
||||
return;
|
||||
}
|
||||
printf("ie%d: reset\n", sc->unit);
|
||||
sc->arpcom.ac_if.if_flags &= ~IFF_UP;
|
||||
ieioctl(&sc->arpcom.ac_if, SIOCSIFFLAGS, 0);
|
||||
@ -1727,7 +1247,7 @@ iereset(struct ie_softc *sc)
|
||||
printf("ie%d: disable commands timed out\n", sc->unit);
|
||||
|
||||
#ifdef notdef
|
||||
if (!check_ie_present(sc, sc->iomembot, sc->iosize))
|
||||
if (!check_ie_present(sc))
|
||||
panic("ie disappeared!");
|
||||
#endif
|
||||
|
||||
@ -2187,3 +1707,91 @@ print_rbd(volatile struct ie_recv_buf_desc * rbd)
|
||||
}
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
int
|
||||
ie_alloc_resources (device_t dev)
|
||||
{
|
||||
struct ie_softc * sc;
|
||||
int error;
|
||||
|
||||
error = 0;
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
sc->io_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->io_rid,
|
||||
0, ~0, 1, RF_ACTIVE);
|
||||
if (!sc->io_res) {
|
||||
device_printf(dev, "No I/O space?!\n");
|
||||
error = ENOMEM;
|
||||
goto bad;
|
||||
}
|
||||
sc->io_bt = rman_get_bustag(sc->io_res);
|
||||
sc->io_bh = rman_get_bushandle(sc->io_res);
|
||||
|
||||
sc->mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->mem_rid,
|
||||
0, ~0, 1, RF_ACTIVE);
|
||||
if (!sc->mem_res) {
|
||||
device_printf(dev, "No Memory!\n");
|
||||
error = ENOMEM;
|
||||
goto bad;
|
||||
}
|
||||
sc->mem_bt = rman_get_bustag(sc->mem_res);
|
||||
sc->mem_bh = rman_get_bushandle(sc->mem_res);
|
||||
|
||||
sc->irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid,
|
||||
0, ~0, 1, RF_ACTIVE);
|
||||
if (!sc->irq_res) {
|
||||
device_printf(dev, "No IRQ!\n");
|
||||
error = ENOMEM;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
sc->port = rman_get_start(sc->io_res); /* XXX hack */
|
||||
sc->iomembot = rman_get_virtual(sc->mem_res);
|
||||
sc->iosize = rman_get_size(sc->mem_res);
|
||||
|
||||
return (0);
|
||||
bad:
|
||||
return (error);
|
||||
}
|
||||
|
||||
void
|
||||
ie_release_resources (device_t dev)
|
||||
{
|
||||
struct ie_softc * sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
if (sc->irq_ih)
|
||||
bus_teardown_intr(dev, sc->irq_res, sc->irq_ih);
|
||||
if (sc->io_res)
|
||||
bus_release_resource(dev, SYS_RES_IOPORT,
|
||||
sc->io_rid, sc->io_res);
|
||||
if (sc->irq_res)
|
||||
bus_release_resource(dev, SYS_RES_IRQ,
|
||||
sc->irq_rid, sc->irq_res);
|
||||
if (sc->mem_res)
|
||||
bus_release_resource(dev, SYS_RES_MEMORY,
|
||||
sc->mem_rid, sc->mem_res);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
ie_detach (device_t dev)
|
||||
{
|
||||
struct ie_softc * sc;
|
||||
struct ifnet * ifp;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
ifp = &sc->arpcom.ac_if;
|
||||
|
||||
if (sc->hard_type == IE_EE16)
|
||||
ee16_shutdown(sc, 0);
|
||||
|
||||
ie_stop(sc);
|
||||
ifp->if_flags &= ~IFF_RUNNING;
|
||||
ether_ifdetach(ifp);
|
||||
ie_release_resources(dev);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
885
sys/dev/ie/if_ie_isa.c
Normal file
885
sys/dev/ie/if_ie_isa.c
Normal file
@ -0,0 +1,885 @@
|
||||
/*-
|
||||
* Copyright (c) 2003 Matthew N. Dodd
|
||||
* 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.
|
||||
*
|
||||
* Portions:
|
||||
* Copyright (c) 1992, 1993, University of Vermont and State
|
||||
* Agricultural College.
|
||||
* Copyright (c) 1992, 1993, Garrett A. Wollman.
|
||||
* Copyright (c) 1990, 1991, William F. Jolitz
|
||||
* Copyright (c) 1990, The Regents of the University of California
|
||||
* Copyright (c) 1993, 1994, Charles M. Hannum
|
||||
* Copyright (c) 1993, 1994, 1995, Rodney W. Grimes
|
||||
* Copyright (c) 1997, Aaron C. Smith
|
||||
*
|
||||
* See if_ie.c for applicable license.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <sys/module.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <machine/bus_pio.h>
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <machine/clock.h>
|
||||
#include <machine/md_var.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <net/if_media.h>
|
||||
|
||||
#include <isa/isavar.h>
|
||||
#include <isa/pnpvar.h>
|
||||
|
||||
#include <i386/isa/elink.h>
|
||||
|
||||
#include <dev/ic/i82586.h>
|
||||
#include <dev/ie/if_ie507.h>
|
||||
#include <dev/ie/if_iee16.h>
|
||||
#include <dev/ie/if_iereg.h>
|
||||
#include <dev/ie/if_ievar.h>
|
||||
|
||||
static int ie_modevent (module_t, int, void *);
|
||||
|
||||
static void ie_isa_3C507_identify (driver_t *, device_t);
|
||||
static int ie_isa_3C507_probe (device_t);
|
||||
static int ie_isa_3C507_attach (device_t);
|
||||
static int ie_3C507_port_check (u_int32_t);
|
||||
|
||||
static void ie_isa_ee16_identify (driver_t *, device_t);
|
||||
static int ie_isa_ee16_probe (device_t);
|
||||
static int ie_isa_ee16_attach (device_t);
|
||||
static int ie_ee16_port_check (u_int32_t port);
|
||||
static u_int16_t ie_ee16_hw_read_eeprom (u_int32_t port, int loc);
|
||||
|
||||
static int ie_isa_sl_probe (device_t);
|
||||
static int ie_isa_sl_attach (device_t);
|
||||
static enum ie_hardware ie_isa_sl_get_hard_type (u_int32_t);
|
||||
|
||||
/*
|
||||
* 3Com 3C507 Etherlink 16
|
||||
*/
|
||||
#define IE_3C507_IOBASE_LOW 0x200
|
||||
#define IE_3C507_IOBASE_HIGH 0x3e0
|
||||
#define IE_3C507_IOSIZE 16
|
||||
|
||||
#define IE_3C507_IRQ_MASK 0x0f
|
||||
|
||||
#define IE_3C507_MADDR_HIGH 0x20
|
||||
#define IE_3C507_MADDR_MASK 0x1c
|
||||
#define IE_3C507_MADDR_BASE 0xc0000
|
||||
#define IE_3C507_MADDR_SHIFT 12
|
||||
|
||||
#define IE_3C507_MSIZE_MASK 3
|
||||
#define IE_3C507_MSIZE_SHIFT 14
|
||||
|
||||
static void
|
||||
ie_isa_3C507_identify (driver_t *driver, device_t parent)
|
||||
{
|
||||
char * desc = "3Com 3C507 Etherlink 16";
|
||||
device_t child;
|
||||
u_int32_t port, maddr, msize;
|
||||
u_int8_t irq, data;
|
||||
int error;
|
||||
|
||||
/* Reset and put card in CONFIG state without changing address. */
|
||||
elink_reset();
|
||||
elink_idseq(ELINK_507_POLY);
|
||||
elink_idseq(ELINK_507_POLY);
|
||||
outb(ELINK_ID_PORT, 0xff);
|
||||
|
||||
for (port = IE_3C507_IOBASE_LOW;
|
||||
port <= IE_3C507_IOBASE_HIGH;
|
||||
port += IE_3C507_IOSIZE) {
|
||||
|
||||
if (ie_3C507_port_check(port)) {
|
||||
#if DEBUG
|
||||
if (bootverbose) {
|
||||
device_printf(parent,
|
||||
"(if_ie) (3C507) not found at port %#x\n",
|
||||
port);
|
||||
}
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
outb(port + IE507_CTRL, EL_CTRL_NRST);
|
||||
|
||||
data = inb(port + IE507_IRQ);
|
||||
irq = data & IE_3C507_IRQ_MASK;
|
||||
|
||||
data = inb(port + IE507_MADDR);
|
||||
|
||||
if (data & IE_3C507_MADDR_HIGH) {
|
||||
if (bootverbose) {
|
||||
device_printf(parent,
|
||||
"(if_ie) can't map 3C507 RAM in high memory\n");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
maddr = IE_3C507_MADDR_BASE +
|
||||
((data & IE_3C507_MADDR_MASK)
|
||||
<< IE_3C507_MADDR_SHIFT);
|
||||
msize = ((data & IE_3C507_MSIZE_MASK) + 1)
|
||||
<< IE_3C507_MSIZE_SHIFT;
|
||||
|
||||
child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "ie", -1);
|
||||
device_set_desc_copy(child, desc);
|
||||
device_set_driver(child, driver);
|
||||
|
||||
error = bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1);
|
||||
if (error) {
|
||||
device_printf(parent, "(if_ie) Unable to set IRQ resource %d.\n",
|
||||
irq);
|
||||
error = device_delete_child(parent, child);
|
||||
continue;
|
||||
}
|
||||
|
||||
error = bus_set_resource(child, SYS_RES_IOPORT, 0, port, IE_3C507_IOSIZE);
|
||||
if (error) {
|
||||
device_printf(parent, "(if_ie) Unable to set IOPORT resource %#x-%#x.\n",
|
||||
port, port+IE_3C507_IOSIZE);
|
||||
error = device_delete_child(parent, child);
|
||||
continue;
|
||||
}
|
||||
|
||||
error = bus_set_resource(child, SYS_RES_MEMORY, 0, maddr, msize);
|
||||
if (error) {
|
||||
device_printf(parent, "(if_ie) Unable to set MEMORY resource %#x-%#x.\n",
|
||||
maddr, maddr+msize);
|
||||
error = device_delete_child(parent, child);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bootverbose) {
|
||||
device_printf(parent,
|
||||
"(if_ie) <%s> at port %#x-%#x irq %d iomem %#lx-%#lx (%dKB)\n",
|
||||
desc,
|
||||
port, (port + IE_3C507_IOSIZE) - 1,
|
||||
irq,
|
||||
(u_long)maddr, (u_long)(maddr + msize) - 1,
|
||||
(msize / 1024));
|
||||
}
|
||||
}
|
||||
|
||||
/* go to RUN state */
|
||||
outb(ELINK_ID_PORT, 0x00);
|
||||
elink_idseq(ELINK_507_POLY);
|
||||
outb(ELINK_ID_PORT, 0x00);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
ie_isa_3C507_probe (device_t dev)
|
||||
{
|
||||
u_int32_t iobase;
|
||||
|
||||
/* No ISA-PnP support */
|
||||
if (isa_get_vendorid(dev)) {
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* No ISA-HINT support */
|
||||
if (!device_get_desc(dev)) {
|
||||
return (EBUSY);
|
||||
}
|
||||
|
||||
/* Have we at least an ioport? */
|
||||
if ((iobase = bus_get_resource_start(dev, SYS_RES_IOPORT, 0)) == 0) {
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Is this thing really a 3c507? */
|
||||
if (ie_3C507_port_check(iobase)) {
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
ie_isa_3C507_attach (device_t dev)
|
||||
{
|
||||
struct ie_softc * sc;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
sc->io_rid = 0;
|
||||
sc->irq_rid = 0;
|
||||
sc->mem_rid = 0;
|
||||
|
||||
error = ie_alloc_resources(dev);
|
||||
if (error) {
|
||||
goto bad;
|
||||
}
|
||||
|
||||
sc->bus_use = 0;
|
||||
sc->ie_reset_586 = el_reset_586;
|
||||
sc->ie_chan_attn = el_chan_attn;
|
||||
sc->hard_type = IE_3C507;
|
||||
sc->hard_vers = 0;
|
||||
|
||||
outb(PORT(sc) + IE507_CTRL, EL_CTRL_NORMAL);
|
||||
|
||||
if (!check_ie_present(sc)) {
|
||||
error = ENXIO;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
sl_read_ether(sc, sc->arpcom.ac_enaddr);
|
||||
|
||||
/* Clear the interrupt latch just in case. */
|
||||
outb(PORT(sc) + IE507_ICTRL, 1);
|
||||
|
||||
error = ie_attach(dev);
|
||||
if (error) {
|
||||
device_printf(dev, "ie_attach() failed.\n");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET,
|
||||
ie_intr, sc, &sc->irq_ih);
|
||||
if (error) {
|
||||
device_printf(dev, "Unable to register interrupt handler\n");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
return (0);
|
||||
bad:
|
||||
ie_release_resources(dev);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* If a 3c507 is present, return 0
|
||||
* else, return 1.
|
||||
*/
|
||||
static int
|
||||
ie_3C507_port_check (u_int32_t port)
|
||||
{
|
||||
u_char * signature = "*3COM*";
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
if (inb(port + i) != signature[i])
|
||||
return (ENXIO);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Intel EtherExpress 16
|
||||
*/
|
||||
#define IE_EE16_ID_PORT 0x0f
|
||||
#define IE_EE16_ID 0xbaba
|
||||
#define IE_EE16_EEPROM_CONFIG1 0x00
|
||||
#define IE_EE16_EEPROM_IRQ_MASK 0xe000
|
||||
#define IE_EE16_EEPROM_IRQ_SHIFT 13
|
||||
#define IE_EE16_EEPROM_MEMCFG 0x06
|
||||
#define IE_EE16_IOSIZE 16
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* Test for 8/16 bit mode.
|
||||
* Test for invalid mem sizes.
|
||||
*/
|
||||
static void
|
||||
ie_isa_ee16_identify (driver_t *driver, device_t parent)
|
||||
{
|
||||
char * desc = "Intel EtherExpress 16";
|
||||
device_t child;
|
||||
u_int16_t ports[] = {
|
||||
0x300, 0x310, 0x320, 0x330,
|
||||
0x340, 0x350, 0x360, 0x370,
|
||||
0x200, 0x210, 0x220, 0x230,
|
||||
0x240, 0x250, 0x260, 0x270,
|
||||
0
|
||||
};
|
||||
u_int16_t irqs[] = { 0, 0x09, 0x03, 0x04, 0x05, 0x0a, 0x0b, 0 };
|
||||
u_int32_t port, maddr, msize;
|
||||
u_int8_t irq;
|
||||
u_int16_t data;
|
||||
int i, error;
|
||||
|
||||
for (i = 0; ports[i]; i++) {
|
||||
port = ports[i];
|
||||
|
||||
if (ie_ee16_port_check(port)) {
|
||||
#if DEBUG
|
||||
if (bootverbose) {
|
||||
device_printf(parent,
|
||||
"if_ie: (EE16) not found at port %#x\n",
|
||||
port);
|
||||
}
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
/* reset any ee16 at the current iobase */
|
||||
outb(port + IEE16_ECTRL, IEE16_RESET_ASIC);
|
||||
outb(port + IEE16_ECTRL, 0);
|
||||
DELAY(240);
|
||||
|
||||
data = ie_ee16_hw_read_eeprom(port, IE_EE16_EEPROM_CONFIG1);
|
||||
irq = irqs[((data & IE_EE16_EEPROM_IRQ_MASK)
|
||||
>> IE_EE16_EEPROM_IRQ_SHIFT)];
|
||||
|
||||
data = ie_ee16_hw_read_eeprom(port, IE_EE16_EEPROM_MEMCFG);
|
||||
maddr = 0xc0000 + ((ffs(data & 0x00ff) - 1) * 0x4000);
|
||||
msize = (fls((data & 0x00ff) >> (ffs(data & 0x00ff) - 1)))
|
||||
* 0x4000;
|
||||
|
||||
child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "ie", -1);
|
||||
device_set_desc_copy(child, desc);
|
||||
device_set_driver(child, driver);
|
||||
|
||||
error = bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1);
|
||||
if (error) {
|
||||
device_printf(parent, "(if_ie) Unable to set IRQ resource %d.\n",
|
||||
irq);
|
||||
error = device_delete_child(parent, child);
|
||||
continue;
|
||||
}
|
||||
|
||||
error = bus_set_resource(child, SYS_RES_IOPORT, 0, port, IE_EE16_IOSIZE);
|
||||
if (error) {
|
||||
device_printf(parent, "(if_ie) Unable to set IOPORT resource %#x-%#x.\n",
|
||||
port, port+IE_EE16_IOSIZE);
|
||||
error = device_delete_child(parent, child);
|
||||
continue;
|
||||
}
|
||||
|
||||
error = bus_set_resource(child, SYS_RES_MEMORY, 0, maddr, msize);
|
||||
if (error) {
|
||||
device_printf(parent, "(if_ie) Unable to set MEMORY resource %#x-%#x.\n",
|
||||
maddr, maddr+msize);
|
||||
error = device_delete_child(parent, child);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bootverbose) {
|
||||
device_printf(parent,
|
||||
"if_ie: <%s> at port %#x-%#x irq %d iomem %#lx-%#lx (%dKB)\n",
|
||||
desc,
|
||||
port, (port + IE_EE16_IOSIZE) - 1,
|
||||
irq,
|
||||
(u_long)maddr, (u_long)(maddr + msize) - 1,
|
||||
(msize / 1024));
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
ie_isa_ee16_probe (device_t dev)
|
||||
{
|
||||
u_int32_t iobase;
|
||||
|
||||
/* No ISA-PnP support */
|
||||
if (isa_get_vendorid(dev))
|
||||
return (ENXIO);
|
||||
|
||||
/* No ISA-HINT support */
|
||||
if (!device_get_desc(dev))
|
||||
return (EBUSY);
|
||||
|
||||
/* Have we at least an ioport? */
|
||||
if ((iobase = bus_get_resource_start(dev, SYS_RES_IOPORT, 0)) == 0)
|
||||
return (ENXIO);
|
||||
|
||||
/* Is this really an EE16? */
|
||||
if (ie_ee16_port_check(iobase))
|
||||
return (ENXIO);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
ie_isa_ee16_attach (device_t dev)
|
||||
{
|
||||
struct ie_softc * sc;
|
||||
int i, error;
|
||||
u_int16_t checksum;
|
||||
u_short eaddrtemp, pg, adjust, decode, edecode;
|
||||
u_char bart_config;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
sc->io_rid = 0;
|
||||
sc->irq_rid = 0;
|
||||
sc->mem_rid = 0;
|
||||
|
||||
error = ie_alloc_resources(dev);
|
||||
if (error) {
|
||||
goto bad;
|
||||
}
|
||||
|
||||
sc->bus_use = 0;
|
||||
sc->ie_reset_586 = ee16_reset_586;
|
||||
sc->ie_chan_attn = ee16_chan_attn;
|
||||
sc->hard_type = IE_EE16;
|
||||
sc->hard_vers = 0;
|
||||
sc->iomem = 0;
|
||||
|
||||
/* reset any ee16 at the current iobase */
|
||||
outb(PORT(sc) + IEE16_ECTRL, IEE16_RESET_ASIC);
|
||||
outb(PORT(sc) + IEE16_ECTRL, 0);
|
||||
DELAY(240);
|
||||
|
||||
/* Is this really an EE16? */
|
||||
if (ie_ee16_port_check(PORT(sc))) {
|
||||
device_printf(dev, "ie_ee16_port_check() failed\n");
|
||||
error = ENXIO;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* need to put the 586 in RESET while we access the eeprom. */
|
||||
outb(PORT(sc) + IEE16_ECTRL, IEE16_RESET_586);
|
||||
|
||||
/* read the eeprom and checksum it, should == IE_E16_ID */
|
||||
checksum = 0;
|
||||
for (i = 0; i < 0x40; i++)
|
||||
checksum += ie_ee16_hw_read_eeprom(PORT(sc), i);
|
||||
|
||||
if (checksum != IE_EE16_ID) {
|
||||
device_printf(dev, "invalid eeprom checksum: %x\n", checksum);
|
||||
error = ENXIO;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if ((kvtop(sc->iomembot) < 0xC0000) ||
|
||||
(kvtop(sc->iomembot) + sc->iosize > 0xF0000)) {
|
||||
device_printf(sc->dev, "mapped memory location %p out of range\n",
|
||||
(void *)sc->iomembot);
|
||||
error = ENXIO;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
pg = ((kvtop(sc->iomembot)) & 0x3C000) >> 14;
|
||||
adjust = IEE16_MCTRL_FMCS16 | (pg & 0x3) << 2;
|
||||
decode = ((1 << (sc->iosize / 16384)) - 1) << pg;
|
||||
edecode = ((~decode >> 4) & 0xF0) | (decode >> 8);
|
||||
|
||||
/* ZZZ This should be checked against eeprom location 6, low byte */
|
||||
outb(PORT(sc) + IEE16_MEMDEC, decode & 0xFF);
|
||||
/* ZZZ This should be checked against eeprom location 1, low byte */
|
||||
outb(PORT(sc) + IEE16_MCTRL, adjust);
|
||||
/* ZZZ Now if I could find this one I would have it made */
|
||||
outb(PORT(sc) + IEE16_MPCTRL, (~decode & 0xFF));
|
||||
/* ZZZ I think this is location 6, high byte */
|
||||
outb(PORT(sc) + IEE16_MECTRL, edecode); /* XXX disable Exxx */
|
||||
|
||||
#if 0
|
||||
(void) kvtop(sc->iomembot);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* first prime the stupid bart DRAM controller so that it works,
|
||||
* then zero out all of memory.
|
||||
*/
|
||||
bzero(sc->iomembot, 32);
|
||||
bzero(sc->iomembot, sc->iosize);
|
||||
|
||||
/* Get the encoded interrupt number from the EEPROM */
|
||||
sc->irq_encoded = ie_ee16_hw_read_eeprom(PORT(sc),
|
||||
IE_EE16_EEPROM_CONFIG1);
|
||||
sc->irq_encoded = (sc->irq_encoded & IE_EE16_EEPROM_IRQ_MASK) >>
|
||||
IE_EE16_EEPROM_IRQ_SHIFT;
|
||||
|
||||
/*
|
||||
* Get the hardware ethernet address from the EEPROM and save it in
|
||||
* the softc for use by the 586 setup code.
|
||||
*/
|
||||
eaddrtemp = ie_ee16_hw_read_eeprom(PORT(sc), IEE16_EEPROM_ENET_HIGH);
|
||||
sc->arpcom.ac_enaddr[1] = eaddrtemp & 0xFF;
|
||||
sc->arpcom.ac_enaddr[0] = eaddrtemp >> 8;
|
||||
eaddrtemp = ie_ee16_hw_read_eeprom(PORT(sc), IEE16_EEPROM_ENET_MID);
|
||||
sc->arpcom.ac_enaddr[3] = eaddrtemp & 0xFF;
|
||||
sc->arpcom.ac_enaddr[2] = eaddrtemp >> 8;
|
||||
eaddrtemp = ie_ee16_hw_read_eeprom(PORT(sc), IEE16_EEPROM_ENET_LOW);
|
||||
sc->arpcom.ac_enaddr[5] = eaddrtemp & 0xFF;
|
||||
sc->arpcom.ac_enaddr[4] = eaddrtemp >> 8;
|
||||
|
||||
/* disable the board interrupts */
|
||||
outb(PORT(sc) + IEE16_IRQ, sc->irq_encoded);
|
||||
|
||||
/* enable loopback to keep bad packets off the wire */
|
||||
bart_config = inb(PORT(sc) + IEE16_CONFIG);
|
||||
bart_config |= IEE16_BART_LOOPBACK;
|
||||
bart_config |= IEE16_BART_MCS16_TEST;/* inb doesn't get bit! */
|
||||
outb(PORT(sc) + IEE16_CONFIG, bart_config);
|
||||
bart_config = inb(PORT(sc) + IEE16_CONFIG);
|
||||
|
||||
/* take the board out of reset state */
|
||||
outb(PORT(sc) + IEE16_ECTRL, 0);
|
||||
DELAY(100);
|
||||
|
||||
if (!check_ie_present(sc)) {
|
||||
device_printf(dev, "check_ie_present() returned false.\n");
|
||||
error = ENXIO;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
error = ie_attach(dev);
|
||||
if (error) {
|
||||
device_printf(dev, "ie_attach() failed.\n");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET,
|
||||
ie_intr, sc, &sc->irq_ih);
|
||||
if (error) {
|
||||
device_printf(dev, "Unable to register interrupt handler\n");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
return (0);
|
||||
bad:
|
||||
ie_release_resources(dev);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* If an EE16 is present, return 0
|
||||
* else, return 1.
|
||||
*/
|
||||
static int
|
||||
ie_ee16_port_check (u_int32_t port)
|
||||
{
|
||||
int i;
|
||||
u_int16_t board_id;
|
||||
u_int8_t data;
|
||||
|
||||
board_id = 0;
|
||||
for (i = 0; i < 4; i++) {
|
||||
data = inb(port + IE_EE16_ID_PORT);
|
||||
board_id |= ((data >> 4) << ((data & 0x03) << 2));
|
||||
}
|
||||
|
||||
if (board_id != IE_EE16_ID)
|
||||
return (1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
ie_ee16_hw_eeprom_clock (u_int32_t port, int state)
|
||||
{
|
||||
u_int8_t ectrl;
|
||||
|
||||
ectrl = inb(port + IEE16_ECTRL);
|
||||
ectrl &= ~(IEE16_RESET_ASIC | IEE16_ECTRL_EESK);
|
||||
|
||||
if (state) {
|
||||
ectrl |= IEE16_ECTRL_EESK;
|
||||
}
|
||||
outb(port + IEE16_ECTRL, ectrl);
|
||||
DELAY(9); /* EESK must be stable for 8.38 uSec */
|
||||
}
|
||||
|
||||
static void
|
||||
ie_ee16_hw_eeprom_out (u_int32_t port, u_int16_t edata, int count)
|
||||
{
|
||||
u_int8_t ectrl;
|
||||
int i;
|
||||
|
||||
ectrl = inb(port + IEE16_ECTRL);
|
||||
ectrl &= ~IEE16_RESET_ASIC;
|
||||
|
||||
for (i = count - 1; i >= 0; i--) {
|
||||
ectrl &= ~IEE16_ECTRL_EEDI;
|
||||
if (edata & (1 << i)) {
|
||||
ectrl |= IEE16_ECTRL_EEDI;
|
||||
}
|
||||
outb(port + IEE16_ECTRL, ectrl);
|
||||
DELAY(1); /* eeprom data must be setup for 0.4 uSec */
|
||||
ie_ee16_hw_eeprom_clock(port, 1);
|
||||
ie_ee16_hw_eeprom_clock(port, 0);
|
||||
}
|
||||
ectrl &= ~IEE16_ECTRL_EEDI;
|
||||
outb(port + IEE16_ECTRL, ectrl);
|
||||
DELAY(1); /* eeprom data must be held for 0.4 uSec */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static u_int16_t
|
||||
ie_ee16_hw_eeprom_in (u_int32_t port)
|
||||
{
|
||||
u_int8_t ectrl;
|
||||
u_int16_t edata;
|
||||
int i;
|
||||
|
||||
ectrl = inb(port + IEE16_ECTRL);
|
||||
ectrl &= ~IEE16_RESET_ASIC;
|
||||
|
||||
for (edata = 0, i = 0; i < 16; i++) {
|
||||
edata = edata << 1;
|
||||
ie_ee16_hw_eeprom_clock(port, 1);
|
||||
ectrl = inb(port + IEE16_ECTRL);
|
||||
if (ectrl & IEE16_ECTRL_EEDO) {
|
||||
edata |= 1;
|
||||
}
|
||||
ie_ee16_hw_eeprom_clock(port, 0);
|
||||
}
|
||||
return (edata);
|
||||
}
|
||||
|
||||
static u_int16_t
|
||||
ie_ee16_hw_read_eeprom (u_int32_t port, int loc)
|
||||
{
|
||||
u_int8_t ectrl;
|
||||
u_int16_t edata;
|
||||
|
||||
ectrl = inb(port + IEE16_ECTRL);
|
||||
ectrl &= IEE16_ECTRL_MASK;
|
||||
ectrl |= IEE16_ECTRL_EECS;
|
||||
outb(port + IEE16_ECTRL, ectrl);
|
||||
|
||||
ie_ee16_hw_eeprom_out(port, IEE16_EEPROM_READ, IEE16_EEPROM_OPSIZE1);
|
||||
ie_ee16_hw_eeprom_out(port, loc, IEE16_EEPROM_ADDR_SIZE);
|
||||
edata = ie_ee16_hw_eeprom_in(port);
|
||||
|
||||
ectrl = inb(port + IEE16_ECTRL);
|
||||
ectrl &= ~(IEE16_RESET_ASIC | IEE16_ECTRL_EEDI | IEE16_ECTRL_EECS);
|
||||
outb(port + IEE16_ECTRL, ectrl);
|
||||
|
||||
ie_ee16_hw_eeprom_clock(port, 1);
|
||||
ie_ee16_hw_eeprom_clock(port, 0);
|
||||
|
||||
return (edata);
|
||||
}
|
||||
|
||||
/*
|
||||
* AT&T StarLan/
|
||||
*/
|
||||
|
||||
static int
|
||||
ie_isa_sl_probe (device_t dev)
|
||||
{
|
||||
u_int32_t iobase;
|
||||
|
||||
/* No ISA-PnP support */
|
||||
if (isa_get_vendorid(dev))
|
||||
return (ENXIO);
|
||||
|
||||
/* ISA-HINT support only! */
|
||||
if (device_get_desc(dev))
|
||||
return (EBUSY);
|
||||
|
||||
/* Have we at least an ioport? */
|
||||
if ((iobase = bus_get_resource_start(dev, SYS_RES_IOPORT, 0)) == 0)
|
||||
return (ENXIO);
|
||||
|
||||
/* Is this really an SL board? */
|
||||
if (ie_isa_sl_get_hard_type(iobase) == IE_NONE)
|
||||
return (ENXIO);
|
||||
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
static int
|
||||
ie_isa_sl_attach (device_t dev)
|
||||
{
|
||||
struct ie_softc * sc;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
sc->io_rid = 0;
|
||||
sc->irq_rid = 0;
|
||||
sc->mem_rid = 0;
|
||||
|
||||
error = ie_alloc_resources(dev);
|
||||
if (error) {
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* Is this really an SL board? */
|
||||
if ((sc->hard_type = ie_isa_sl_get_hard_type(PORT(sc))) == IE_NONE) {
|
||||
error = ENXIO;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
sc->hard_vers = SL_REV(inb(PORT(sc) + IEATT_REVISION));
|
||||
if (sc->hard_type == IE_NI5210) {
|
||||
sc->bus_use = 1;
|
||||
} else {
|
||||
sc->bus_use = 0;
|
||||
}
|
||||
|
||||
sc->ie_reset_586 = sl_reset_586;
|
||||
sc->ie_chan_attn = sl_chan_attn;
|
||||
|
||||
if (!check_ie_present(sc)) {
|
||||
error = ENXIO;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
switch (sc->hard_type) {
|
||||
case IE_EN100:
|
||||
case IE_STARLAN10:
|
||||
case IE_SLFIBER:
|
||||
case IE_NI5210:
|
||||
sl_read_ether(sc, sc->arpcom.ac_enaddr);
|
||||
break;
|
||||
default:
|
||||
if (bootverbose)
|
||||
device_printf(sc->dev, "unknown AT&T board type code %d\n", sc->hard_type);
|
||||
error = ENXIO;
|
||||
goto bad;
|
||||
break;
|
||||
}
|
||||
|
||||
error = ie_attach(dev);
|
||||
if (error) {
|
||||
device_printf(dev, "ie_attach() failed.\n");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET,
|
||||
ie_intr, sc, &sc->irq_ih);
|
||||
if (error) {
|
||||
device_printf(dev, "Unable to register interrupt handler\n");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
return (0);
|
||||
bad:
|
||||
ie_release_resources(dev);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
static enum ie_hardware
|
||||
ie_isa_sl_get_hard_type (u_int32_t port)
|
||||
{
|
||||
u_char c;
|
||||
enum ie_hardware retval;
|
||||
|
||||
c = inb(port + IEATT_REVISION);
|
||||
switch (SL_BOARD(c)) {
|
||||
case SL1_BOARD:
|
||||
if (inb(port + IEATT_ATTRIB) != NI5210_BOARD)
|
||||
retval = IE_NONE;
|
||||
retval = IE_NI5210;
|
||||
break;
|
||||
case SL10_BOARD:
|
||||
retval = IE_STARLAN10;
|
||||
break;
|
||||
case EN100_BOARD:
|
||||
retval = IE_EN100;
|
||||
break;
|
||||
case SLFIBER_BOARD:
|
||||
retval = IE_SLFIBER;
|
||||
break;
|
||||
default:
|
||||
retval = IE_NONE;
|
||||
}
|
||||
return (retval);
|
||||
}
|
||||
|
||||
static devclass_t ie_devclass;
|
||||
|
||||
static device_method_t ie_isa_3C507_methods[] = {
|
||||
DEVMETHOD(device_identify, ie_isa_3C507_identify),
|
||||
DEVMETHOD(device_probe, ie_isa_3C507_probe),
|
||||
DEVMETHOD(device_attach, ie_isa_3C507_attach),
|
||||
DEVMETHOD(device_detach, ie_detach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
static driver_t ie_isa_3C507_driver = {
|
||||
"ie",
|
||||
ie_isa_3C507_methods,
|
||||
sizeof(struct ie_softc),
|
||||
};
|
||||
DRIVER_MODULE(ie_3C507, isa, ie_isa_3C507_driver, ie_devclass, ie_modevent, 0);
|
||||
MODULE_DEPEND(ie_3C507, elink, 1, 1, 1);
|
||||
|
||||
static device_method_t ie_isa_ee16_methods[] = {
|
||||
DEVMETHOD(device_identify, ie_isa_ee16_identify),
|
||||
DEVMETHOD(device_probe, ie_isa_ee16_probe),
|
||||
DEVMETHOD(device_attach, ie_isa_ee16_attach),
|
||||
DEVMETHOD(device_detach, ie_detach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
static driver_t ie_isa_ee16_driver = {
|
||||
"ie",
|
||||
ie_isa_ee16_methods,
|
||||
sizeof(struct ie_softc),
|
||||
};
|
||||
DRIVER_MODULE(ie_EE16, isa, ie_isa_ee16_driver, ie_devclass, ie_modevent, 0);
|
||||
|
||||
static device_method_t ie_isa_sl_methods[] = {
|
||||
DEVMETHOD(device_probe, ie_isa_sl_probe),
|
||||
DEVMETHOD(device_attach, ie_isa_sl_attach),
|
||||
DEVMETHOD(device_detach, ie_detach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
static driver_t ie_isa_sl_driver = {
|
||||
"ie",
|
||||
ie_isa_sl_methods,
|
||||
sizeof(struct ie_softc),
|
||||
};
|
||||
DRIVER_MODULE(ie_SL, isa, ie_isa_sl_driver, ie_devclass, ie_modevent, 0);
|
||||
|
||||
static int
|
||||
ie_modevent (mod, what, arg)
|
||||
module_t mod;
|
||||
int what;
|
||||
void * arg;
|
||||
{
|
||||
device_t * devs;
|
||||
int count;
|
||||
int i;
|
||||
|
||||
switch (what) {
|
||||
case MOD_LOAD:
|
||||
break;
|
||||
case MOD_UNLOAD:
|
||||
devclass_get_devices(ie_devclass, &devs, &count);
|
||||
for (i = 0; i < count; i++)
|
||||
device_delete_child(device_get_parent(devs[i]), devs[i]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
return (0);
|
||||
}
|
@ -15,7 +15,7 @@
|
||||
#define SL10_BOARD 0x01
|
||||
#define EN100_BOARD 0x02
|
||||
#define SLFIBER_BOARD 0x03
|
||||
#define NI5210_BOARD 0x0055
|
||||
#define NI5210_BOARD 0x55
|
||||
|
||||
#define SL_ATTR_WIDTH 0x04 /* bus width: clear -> 8-bit */
|
||||
#define SL_ATTR_SPEED 0x08 /* medium speed: clear -> 10 Mbps */
|
||||
|
91
sys/dev/ie/if_ievar.h
Normal file
91
sys/dev/ie/if_ievar.h
Normal file
@ -0,0 +1,91 @@
|
||||
/*-
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
enum ie_hardware {
|
||||
IE_NONE,
|
||||
IE_STARLAN10,
|
||||
IE_EN100,
|
||||
IE_SLFIBER,
|
||||
IE_3C507,
|
||||
IE_NI5210,
|
||||
IE_EE16,
|
||||
IE_UNKNOWN
|
||||
};
|
||||
|
||||
/*
|
||||
* Ethernet status, per interface.
|
||||
*/
|
||||
struct ie_softc {
|
||||
struct arpcom arpcom;
|
||||
void (*ie_reset_586) (struct ie_softc *);
|
||||
void (*ie_chan_attn) (struct ie_softc *);
|
||||
enum ie_hardware hard_type;
|
||||
int hard_vers;
|
||||
int unit;
|
||||
|
||||
device_t dev;
|
||||
|
||||
struct resource * io_res;
|
||||
int io_rid;
|
||||
bus_space_tag_t io_bt;
|
||||
bus_space_handle_t io_bh;
|
||||
|
||||
struct resource * irq_res;
|
||||
int irq_rid;
|
||||
void * irq_ih;
|
||||
|
||||
struct resource * mem_res;
|
||||
int mem_rid;
|
||||
bus_space_tag_t mem_bt;
|
||||
bus_space_handle_t mem_bh;
|
||||
|
||||
u_short port; /* i/o base address for this interface */
|
||||
caddr_t iomem; /* memory size */
|
||||
caddr_t iomembot; /* memory base address */
|
||||
unsigned iosize;
|
||||
int bus_use; /* 0 means 16bit, 1 means 8 bit adapter */
|
||||
|
||||
int want_mcsetup;
|
||||
int promisc;
|
||||
int nframes;
|
||||
int nrxbufs;
|
||||
int ntxbufs;
|
||||
volatile struct ie_int_sys_conf_ptr *iscp;
|
||||
volatile struct ie_sys_ctl_block *scb;
|
||||
volatile struct ie_recv_frame_desc **rframes; /* nframes worth */
|
||||
volatile struct ie_recv_buf_desc **rbuffs; /* nrxbufs worth */
|
||||
volatile u_char **cbuffs; /* nrxbufs worth */
|
||||
int rfhead, rftail, rbhead, rbtail;
|
||||
|
||||
volatile struct ie_xmit_cmd **xmit_cmds; /* ntxbufs worth */
|
||||
volatile struct ie_xmit_buf **xmit_buffs; /* ntxbufs worth */
|
||||
volatile u_char **xmit_cbuffs; /* ntxbufs worth */
|
||||
int xmit_count;
|
||||
|
||||
struct ie_en_addr mcast_addrs[MAXMCAST + 1];
|
||||
int mcast_count;
|
||||
|
||||
u_short irq_encoded; /* encoded interrupt on IEE16 */
|
||||
};
|
||||
#define PORT(sc) sc->port
|
||||
#define MEM(sc) sc->iomem
|
||||
|
||||
void ie_intr (void *);
|
||||
int ie_alloc_resources (device_t);
|
||||
void ie_release_resources (device_t);
|
||||
int ie_attach (device_t);
|
||||
int ie_detach (device_t);
|
||||
|
||||
void el_reset_586 (struct ie_softc *);
|
||||
void el_chan_attn (struct ie_softc *);
|
||||
|
||||
void sl_reset_586 (struct ie_softc *);
|
||||
void sl_chan_attn (struct ie_softc *);
|
||||
|
||||
void ee16_reset_586 (struct ie_softc *);
|
||||
void ee16_chan_attn (struct ie_softc *);
|
||||
|
||||
void sl_read_ether (struct ie_softc *, unsigned char *);
|
||||
int check_ie_present (struct ie_softc *);
|
||||
|
@ -206,6 +206,7 @@ device ed # NE[12]000, SMC Ultra, 3c503, DS8390 cards
|
||||
device ex # Intel EtherExpress Pro/10 and Pro/10+
|
||||
device ep # Etherlink III based cards
|
||||
device fe # Fujitsu MB8696x based cards
|
||||
device ie # EtherExpress 8/16, 3C507, StarLAN 10 etc.
|
||||
device lnc # NE2100, NE32-VL Lance Ethernet cards
|
||||
device sn # SMC's 9000 series of ethernet chips
|
||||
device xe # Xircom pccard ethernet
|
||||
|
@ -505,15 +505,11 @@ device el 1
|
||||
hint.el.0.at="isa"
|
||||
hint.el.0.port="0x300"
|
||||
hint.el.0.irq="9"
|
||||
device ie 2
|
||||
hint.ie.0.at="isa"
|
||||
hint.ie.0.port="0x300"
|
||||
hint.ie.0.irq="5"
|
||||
hint.ie.0.maddr="0xd0000"
|
||||
hint.ie.1.at="isa"
|
||||
hint.ie.1.port="0x360"
|
||||
hint.ie.1.irq="7"
|
||||
hint.ie.1.maddr="0xd0000"
|
||||
device ie # Hints only required for Starlan
|
||||
hint.ie.2.at="isa"
|
||||
hint.ie.2.port="0x300"
|
||||
hint.ie.2.irq="5"
|
||||
hint.ie.2.maddr="0xd0000"
|
||||
device le 1
|
||||
hint.le.0.at="isa"
|
||||
hint.le.0.port="0x300"
|
||||
|
Loading…
Reference in New Issue
Block a user