summaryrefslogtreecommitdiffstats
path: root/sys/i386/isa/if_ep.c
diff options
context:
space:
mode:
authornate <nate@FreeBSD.org>1996-06-14 22:11:38 +0000
committernate <nate@FreeBSD.org>1996-06-14 22:11:38 +0000
commit83ef1da790d0a31a20a1094283c2839874e753a2 (patch)
tree088b94904abe8916a38602a29b6b19c53f787dc7 /sys/i386/isa/if_ep.c
parent0034509211a761bbdd3b327d88eb8f577a04d293 (diff)
downloadFreeBSD-src-83ef1da790d0a31a20a1094283c2839874e753a2.zip
FreeBSD-src-83ef1da790d0a31a20a1094283c2839874e753a2.tar.gz
At long last, we know have support for the 3C589 in a FreeBSD release
using the existing files using the existing PCCARD support. Now that this is in place I would like to fixup the PCCARD hooks and remove the if_zp driver. At this point, we support everything we used to support *AND MORE* with the PCCARD code. Submitted by: Naoki Hamada <nao@sbl.cl.nec.co.jp> (via the Nomad release) [ This works on both my 3C589B and 3C589C ]
Diffstat (limited to 'sys/i386/isa/if_ep.c')
-rw-r--r--sys/i386/isa/if_ep.c213
1 files changed, 211 insertions, 2 deletions
diff --git a/sys/i386/isa/if_ep.c b/sys/i386/isa/if_ep.c
index 772e043..ad3aa94 100644
--- a/sys/i386/isa/if_ep.c
+++ b/sys/i386/isa/if_ep.c
@@ -38,7 +38,7 @@
*/
/*
- * $Id: if_ep.c,v 1.45 1996/06/12 05:03:38 gpalmer Exp $
+ * $Id: if_ep.c,v 1.46 1996/06/14 21:28:35 nate Exp $
*
* Promiscuous mode added and interrupt logic slightly changed
* to reduce the number of adapter failures. Transceiver select
@@ -50,6 +50,12 @@
* babkin@hq.icb.chel.su
*/
+/*
+ * Pccard support for 3C589 by:
+ * HAMADA Naoki
+ * nao@tom-yam.or.jp
+ */
+
#include "ep.h"
#if NEP > 0
@@ -131,7 +137,9 @@ 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];
@@ -160,6 +168,171 @@ static struct kern_devconf kdc_isa_ep = {
DC_CLS_NETIF /* class */
};
+#include "crd.h"
+
+#if NCRD > 0
+#include "apm.h"
+#include <sys/select.h>
+#include <pccard/card.h>
+#include <pccard/driver.h>
+#include <pccard/slot.h>
+
+/*
+ * PC-Card (PCMCIA) specific code.
+ */
+static int card_intr __P((struct pccard_dev *));
+static void ep_unload __P((struct pccard_dev *));
+static void ep_suspend __P((struct pccard_dev *));
+static int ep_pccard_init __P((struct pccard_dev *, int));
+static int ep_pccard_attach __P((struct pccard_dev *));
+
+static struct pccard_drv ep_info = {
+ "ep",
+ card_intr,
+ ep_unload,
+ ep_suspend,
+ ep_pccard_init,
+ 0, /* Attributes - presently unused */
+ &net_imask
+};
+
+/* Resume is done by executing ep_pccard_init(dp, 0). */
+static void
+ep_suspend(dp)
+ struct pccard_dev *dp;
+{
+ struct ep_softc *sc = ep_softc[dp->isahd.id_unit];
+
+ printf("ep%d: suspending\n", dp->isahd.id_unit);
+ sc->gone = 1;
+}
+
+/*
+ *
+ */
+static int
+ep_pccard_init(dp, first)
+ struct pccard_dev *dp;
+ int first;
+{
+ struct isa_device *is = &dp->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++;
+ ep_isa_registerdev(sc, is);
+ }
+
+ /* 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;
+ epb->prod_id = get_e(sc, EEPROM_PROD_ID);
+
+ if (epb->prod_id != 0x9058) { /* 3C589's product id */
+ if (first) {
+ printf("ep%d: failed to come ready.\n", is->id_unit);
+ } else {
+ printf("ep%d: failed to resume.\n", is->id_unit);
+ }
+ 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 (first) {
+ if (ep_pccard_attach(dp) == 0) {
+ return (ENXIO);
+ }
+ sc->arpcom.ac_if.if_snd.ifq_maxlen = ifqmaxlen;
+ }
+
+ if (!first) {
+ sc->kdc->kdc_state = DC_IDLE;
+ sc->gone = 0;
+ printf("ep%d: resumed.\n", is->id_unit);
+ epinit(sc);
+ }
+
+ return (0);
+}
+
+static int
+ep_pccard_attach(dp)
+ struct pccard_dev *dp;
+{
+ struct isa_device *is = &dp->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))
+ printf("no connectors!");
+ 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);
+
+ ep_attach(sc);
+
+ return 1;
+}
+
+static void
+ep_unload(dp)
+ struct pccard_dev *dp;
+{
+ struct ep_softc *sc = ep_softc[dp->isahd.id_unit];
+
+ if (sc->kdc->kdc_state == DC_UNCONFIGURED) {
+ printf("ep%d: already unloaded\n", dp->isahd.id_unit);
+ return;
+ }
+ sc->kdc->kdc_state = DC_UNCONFIGURED;
+ sc->arpcom.ac_if.if_flags &= ~IFF_RUNNING;
+ sc->gone = 1;
+ printf("ep%d: unload\n", dp->isahd.id_unit);
+}
+
+/*
+ * card_intr - Shared interrupt called from
+ * front end of PC-Card handler.
+ */
+static int
+card_intr(dp)
+ struct pccard_dev *dp;
+{
+ epintr(dp->isahd.id_unit);
+ return(1);
+}
+
+#endif /* NCRD > 0 */
+
static void
ep_isa_registerdev(sc, id)
struct ep_softc *sc;
@@ -365,6 +538,10 @@ ep_isa_probe(is)
struct ep_board *epb;
u_short k;
+#if NCRD > 0
+ pccard_add_driver(&ep_info);
+#endif /* NCRD > 0 */
+
if(( epb=ep_look_for_board_at(is) )==0)
return (0);
@@ -466,6 +643,10 @@ ep_attach(sc)
struct sockaddr_dl *sdl;
u_short *p;
int i;
+ int attached;
+
+ sc->gone = 0;
+ attached = (ifp->if_softc != 0);
printf("ep%d: ", sc->unit);
/*
@@ -508,8 +689,10 @@ ep_attach(sc)
ifp->if_ioctl = epioctl;
ifp->if_watchdog = epwatchdog;
+ if (!attached) {
if_attach(ifp);
ether_ifattach(ifp);
+ }
/* device attach does transition from UNCONFIGURED to IDLE state */
sc->kdc->kdc_state=DC_IDLE;
@@ -557,7 +740,9 @@ ep_attach(sc)
sc->top = sc->mcur = 0;
#if NBPFILTER > 0
+ if (!attached) {
bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
+ }
#endif
return 0;
}
@@ -572,7 +757,10 @@ epinit(sc)
struct ep_softc *sc;
{
register struct ifnet *ifp = &sc->arpcom.ac_if;
- int s, i;
+ int s, i, j;
+
+ if (sc->gone)
+ return;
/*
if (ifp->if_addrlist == (struct ifaddr *) 0)
@@ -736,6 +924,10 @@ epstart(ifp)
struct mbuf *top;
int s, pad;
+ if (sc->gone) {
+ return;
+ }
+
s = splimp();
if (ifp->if_flags & IFF_OACTIVE) {
splx(s);
@@ -850,6 +1042,11 @@ epintr(unit)
int unit;
{
register struct ep_softc *sc = ep_softc[unit];
+
+ if (sc->gone) {
+ return;
+ }
+
ep_intr(sc);
}
@@ -1349,6 +1546,8 @@ static void
epwatchdog(ifp)
struct ifnet *ifp;
{
+ struct ep_softc *sc = ifp->if_softc;
+
/*
printf("ep: watchdog\n");
@@ -1356,6 +1555,10 @@ epwatchdog(ifp)
ifp->if_oerrors++;
*/
+ if (sc->gone) {
+ return;
+ }
+
ifp->if_flags &= ~IFF_OACTIVE;
epstart(ifp);
ep_intr(ifp->if_softc);
@@ -1365,6 +1568,10 @@ static void
epstop(sc)
struct ep_softc *sc;
{
+ if (sc->gone) {
+ return;
+ }
+
outw(BASE + EP_COMMAND, RX_DISABLE);
outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
@@ -1379,6 +1586,7 @@ epstop(sc)
}
+#if 0
static int
send_ID_sequence(port)
int port;
@@ -1393,6 +1601,7 @@ send_ID_sequence(port)
}
return (1);
}
+#endif
/*
OpenPOWER on IntegriCloud