summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1996-04-21 22:33:19 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1996-04-21 22:33:19 +0000
commit67d88b0a9910a68bb666b448d2dac29cb4d3d8c2 (patch)
tree967b89f6e07398a22bd8c76d30179b648776542d /sys/dev
parentba95d3c1d69cdb251d15a12ebf70f50b0ea2019b (diff)
partial sync with netbsd 960418, more to come
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/audio.c31
-rw-r--r--sys/dev/ccd.c13
-rw-r--r--sys/dev/cons.c6
-rw-r--r--sys/dev/dev_conf.h46
-rw-r--r--sys/dev/eisa/aha1742.c24
-rw-r--r--sys/dev/eisa/devlist2h.awk6
-rw-r--r--sys/dev/eisa/eisa.c45
-rw-r--r--sys/dev/eisa/eisadevs31
-rw-r--r--sys/dev/eisa/eisadevs.h28
-rw-r--r--sys/dev/eisa/eisadevs_data.h20
-rw-r--r--sys/dev/eisa/eisareg.h9
-rw-r--r--sys/dev/eisa/eisavar.h69
-rw-r--r--sys/dev/eisa/files.eisa10
-rw-r--r--sys/dev/ic/aic7xxx.c24
-rw-r--r--sys/dev/ic/aic7xxxvar.h6
-rw-r--r--sys/dev/ic/am7990.c57
-rw-r--r--sys/dev/ic/com.c116
-rw-r--r--sys/dev/ic/comvar.h5
-rw-r--r--sys/dev/ic/ncr5380sbc.c23
-rw-r--r--sys/dev/ic/smc90cx6.c1231
-rw-r--r--sys/dev/ic/smc90cx6reg.h99
-rw-r--r--sys/dev/ic/z8530sc.c108
-rw-r--r--sys/dev/ic/z8530sc.h12
-rw-r--r--sys/dev/ic/z8530tty.c253
-rw-r--r--sys/dev/isa/aha.c1662
-rw-r--r--sys/dev/isa/aha1542.c1587
-rw-r--r--sys/dev/isa/aha284x.c19
-rw-r--r--sys/dev/isa/ahareg.h264
-rw-r--r--sys/dev/isa/aic6360.c939
-rw-r--r--sys/dev/isa/ast.c33
-rw-r--r--sys/dev/isa/boca.c33
-rw-r--r--sys/dev/isa/bt.c1194
-rw-r--r--sys/dev/isa/bt742a.c1528
-rw-r--r--sys/dev/isa/btreg.h304
-rw-r--r--sys/dev/isa/com.c116
-rw-r--r--sys/dev/isa/comvar.h5
-rw-r--r--sys/dev/isa/fd.c36
-rw-r--r--sys/dev/isa/files.isa134
-rw-r--r--sys/dev/isa/gus.c21
-rw-r--r--sys/dev/isa/if_ed.c777
-rw-r--r--sys/dev/isa/if_eg.c22
-rw-r--r--sys/dev/isa/if_el.c25
-rw-r--r--sys/dev/isa/if_ep.c50
-rw-r--r--sys/dev/isa/if_fe.c22
-rw-r--r--sys/dev/isa/if_ie.c24
-rw-r--r--sys/dev/isa/if_le.c50
-rw-r--r--sys/dev/isa/isa.c20
-rw-r--r--sys/dev/isa/isadma.c13
-rw-r--r--sys/dev/isa/isavar.h29
-rw-r--r--sys/dev/isa/lpt.c50
-rw-r--r--sys/dev/isa/mcd.c26
-rw-r--r--sys/dev/isa/pas.c20
-rw-r--r--sys/dev/isa/pss.c56
-rw-r--r--sys/dev/isa/rtfps.c33
-rw-r--r--sys/dev/isa/sb.c26
-rw-r--r--sys/dev/isa/seagate.c16
-rw-r--r--sys/dev/isa/ultra14f.c16
-rw-r--r--sys/dev/isa/wd.c44
-rw-r--r--sys/dev/isa/wd7000.c747
-rw-r--r--sys/dev/isa/wds.c1306
-rw-r--r--sys/dev/isa/wdsreg.h147
-rw-r--r--sys/dev/isa/wss.c20
-rw-r--r--sys/dev/isa/wt.c26
-rw-r--r--sys/dev/pci/aic7870.c14
-rw-r--r--sys/dev/pci/files.pci24
-rw-r--r--sys/dev/pci/if_de.c95
-rw-r--r--sys/dev/pci/if_fpa.c4
-rw-r--r--sys/dev/pci/ncr.c79
-rw-r--r--sys/dev/pci/ncrstat.c16
-rw-r--r--sys/dev/pci/pci.c170
-rw-r--r--sys/dev/pci/pcidevs8
-rw-r--r--sys/dev/pci/pcidevs.h3
-rw-r--r--sys/dev/pci/pcidevs_data.h18
-rw-r--r--sys/dev/pci/pcireg.h37
-rw-r--r--sys/dev/pci/pcivar.h75
-rw-r--r--sys/dev/pci/ppb.c39
-rw-r--r--sys/dev/pcmcia/files.pcmcia5
-rw-r--r--sys/dev/ramdisk.c132
-rw-r--r--sys/dev/ramdisk.h5
-rw-r--r--sys/dev/rcons/files.rcons6
-rw-r--r--sys/dev/sun/kbd.c279
-rw-r--r--sys/dev/sun/ms.c57
-rw-r--r--sys/dev/tc/asc.c153
-rw-r--r--sys/dev/tc/files.tc10
-rw-r--r--sys/dev/tc/if_le.c99
-rw-r--r--sys/dev/tc/ioasicvar.h4
-rw-r--r--sys/dev/tc/tc.c20
-rw-r--r--sys/dev/tc/tcvar.h6
-rw-r--r--sys/dev/vnd.c14
89 files changed, 7623 insertions, 7461 deletions
diff --git a/sys/dev/audio.c b/sys/dev/audio.c
index 6b50084721e..887b7ba0f21 100644
--- a/sys/dev/audio.c
+++ b/sys/dev/audio.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: audio.c,v 1.6 1996/04/18 23:46:55 niklas Exp $ */
-/* $NetBSD: audio.c,v 1.22 1996/03/14 19:08:32 christos Exp $ */
+/* $OpenBSD: audio.c,v 1.7 1996/04/21 22:19:38 deraadt Exp $ */
+/* $NetBSD: audio.c,v 1.24 1996/03/30 22:51:23 christos Exp $ */
/*
* Copyright (c) 1991-1993 Regents of the University of California.
@@ -78,6 +78,7 @@
#include <sys/syslog.h>
#include <sys/kernel.h>
#include <sys/signalvar.h>
+#include <sys/conf.h>
#include <sys/audioio.h>
#include <dev/audiovar.h>
@@ -85,10 +86,6 @@
#ifdef AUDIO_DEBUG
#include <machine/stdarg.h>
-#ifndef TOLOG
-#define TOLOG 0x04
-#endif
-void kprintf __P((const char *fmt, int flags, struct tty *tp, va_list ap));
void
#ifdef __STDC__
@@ -101,7 +98,7 @@ Dprintf(fmt, va_alist)
va_list ap;
va_start(ap, fmt);
- kprintf(fmt, TOLOG, NULL, ap);
+ log(LOG_DEBUG, "%:", fmt, ap);
va_end(ap);
}
@@ -152,12 +149,6 @@ void audio_alloc_auzero __P((struct audio_softc *, int));
void audio_printsc __P((struct audio_softc *));
void audioattach __P((int));
int audio_hardware_attach __P((struct audio_hw_if *, void *));
-int audioopen __P((dev_t, int, int, struct proc *));
-int audioclose __P((dev_t, int, int, struct proc *));
-int audioread __P((dev_t, struct uio *, int));
-int audiowrite __P((dev_t, struct uio *, int));
-int audioioctl __P((dev_t, int, caddr_t, int, struct proc *));
-int audioselect __P((dev_t, int, struct proc *));
void audio_init_ring __P((struct audio_buffer *, int));
void audio_initbufs __P((struct audio_softc *));
static __inline int audio_sleep_timo __P((int *, char *, int));
@@ -171,7 +162,7 @@ void
audio_printsc(sc)
struct audio_softc *sc;
{
- printf("hwhandle %x hw_if %x ", sc->hw_hdl, sc->hw_if);
+ printf("hwhandle %p hw_if %p ", sc->hw_hdl, sc->hw_if);
printf("open %x mode %x\n", sc->sc_open, sc->sc_mode);
printf("rchan %x wchan %x ", sc->sc_rchan, sc->sc_wchan);
printf("rring blk %x pring nblk %x\n", sc->rr.nblk, sc->pr.nblk);
@@ -396,7 +387,7 @@ audiowrite(dev, uio, ioflag)
int
audioioctl(dev, cmd, addr, flag, p)
dev_t dev;
- int cmd;
+ u_long cmd;
caddr_t addr;
int flag;
struct proc *p;
@@ -1002,7 +993,7 @@ audio_write(dev, uio, ioflag)
#ifdef AUDIO_DEBUG
if (audiodebug > 1) {
int left = cb->ep - tp;
- Dprintf("audio_write: cc=%d tp=0x%x bs=%d nblk=%d left=%d\n", cc, tp, blocksize, cb->nblk, left);
+ Dprintf("audio_write: cc=%d tp=%p bs=%d nblk=%d left=%d\n", cc, tp, blocksize, cb->nblk, left);
}
#endif
#ifdef DIAGNOSTIC
@@ -1011,7 +1002,7 @@ audio_write(dev, uio, ioflag)
/* check for an overwrite. Should never happen */
if ((tp + towrite) > cb->ep) {
- DPRINTF(("audio_write: overwrite tp=0x%x towrite=%d ep=0x%x bs=%d\n",
+ DPRINTF(("audio_write: overwrite tp=%p towrite=%d ep=0x%x bs=%d\n",
tp, towrite, cb->ep, blocksize));
printf("audio_write: overwrite tp=%p towrite=%d ep=%p\n",
tp, towrite, cb->ep);
@@ -1038,7 +1029,7 @@ audio_write(dev, uio, ioflag)
}
if (error) {
#ifdef AUDIO_DEBUG
- printf("audio_write:(1) uiomove failed %d; cc=%d tp=0x%x bs=%d\n", error, cc, tp, blocksize);
+ printf("audio_write:(1) uiomove failed %d; cc=%d tp=%p bs=%d\n", error, cc, tp, blocksize);
#endif
break;
}
@@ -1241,7 +1232,7 @@ audiostartr(sc)
{
int error;
- DPRINTF(("audiostartr: tp=0x%x\n", sc->rr.tp));
+ DPRINTF(("audiostartr: tp=%p\n", sc->rr.tp));
error = sc->hw_if->start_input(sc->hw_hdl, sc->rr.tp, sc->sc_blksize,
audio_rint, (void *)sc);
@@ -1417,7 +1408,7 @@ audio_rint(v)
if (++cb->nblk < cb->maxblk) {
#ifdef AUDIO_DEBUG
if (audiodebug > 1)
- Dprintf("audio_rint: tp=0x%x cc=%d\n", tp, cc);
+ Dprintf("audio_rint: tp=%p cc=%d\n", tp, cc);
#endif
error = hw->start_input(sc->hw_hdl, tp, cc,
audio_rint, (void *)sc);
diff --git a/sys/dev/ccd.c b/sys/dev/ccd.c
index 8894ba7bddc..5d15458568e 100644
--- a/sys/dev/ccd.c
+++ b/sys/dev/ccd.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: ccd.c,v 1.9 1996/04/19 07:43:47 mickey Exp $ */
-/* $NetBSD: ccd.c,v 1.29 1996/03/07 15:00:11 christos Exp $ */
+/* $OpenBSD: ccd.c,v 1.10 1996/04/21 22:19:44 deraadt Exp $ */
+/* $NetBSD: ccd.c,v 1.31 1996/03/30 23:05:54 christos Exp $ */
/*-
* Copyright (c) 1996 The NetBSD Foundation, Inc.
@@ -109,6 +109,7 @@
#include <sys/fcntl.h>
#include <sys/vnode.h>
#include <sys/cpu.h>
+#include <sys/conf.h>
#include <dev/ccdvar.h>
@@ -747,7 +748,7 @@ ccdbuffer(cs, bp, bn, addr, bcount, cbpp)
#ifdef DEBUG
if (ccddebug & CCDB_IO)
- printf("ccdbuffer(%p, %p, %d, %p, %d)\n",
+ printf("ccdbuffer(%p, %p, %d, %p, %ld)\n",
cs, bp, bn, addr, bcount);
#endif
/*
@@ -834,7 +835,7 @@ ccdbuffer(cs, bp, bn, addr, bcount, cbpp)
#ifdef DEBUG
if (ccddebug & CCDB_IO)
- printf(" dev %x(u%d): cbp %p bn %d addr %p bcnt %d\n",
+ printf(" dev %x(u%d): cbp %p bn %d addr %p bcnt %ld\n",
ci->ci_dev, ci-cs->sc_cinfo, cbp, cbp->cb_buf.b_blkno,
cbp->cb_buf.b_data, cbp->cb_buf.b_bcount);
#endif
@@ -898,9 +899,9 @@ ccdiodone(vbp)
if (cbp->cb_flags & CBF_MIRROR)
printf("ccdiodone: mirror component\n");
else
- printf("ccdiodone: bp %p bcount %d resid %d\n",
+ printf("ccdiodone: bp %p bcount %ld resid %ld\n",
bp, bp->b_bcount, bp->b_resid);
- printf(" dev %x(u%d), cbp %p bn %d addr %p bcnt %d\n",
+ printf(" dev %x(u%d), cbp %p bn %d addr %p bcnt %ld\n",
cbp->cb_buf.b_dev, cbp->cb_comp, cbp,
cbp->cb_buf.b_blkno, cbp->cb_buf.b_data,
cbp->cb_buf.b_bcount);
diff --git a/sys/dev/cons.c b/sys/dev/cons.c
index d3f6c9ff18f..4cd2c5b558d 100644
--- a/sys/dev/cons.c
+++ b/sys/dev/cons.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: cons.c,v 1.6 1996/04/18 04:05:39 mickey Exp $ */
-/* $NetBSD: cons.c,v 1.29 1996/02/04 02:04:08 christos Exp $ */
+/* $OpenBSD: cons.c,v 1.7 1996/04/21 22:19:48 deraadt Exp $ */
+/* $NetBSD: cons.c,v 1.30 1996/04/08 19:57:30 jonathan Exp $ */
/*
* Copyright (c) 1988 University of Utah.
@@ -158,7 +158,7 @@ cnstop(tp, flag)
struct tty *tp;
int flag;
{
-
+ return (0);
}
int
diff --git a/sys/dev/dev_conf.h b/sys/dev/dev_conf.h
deleted file mode 100644
index a6d94f0e0f3..00000000000
--- a/sys/dev/dev_conf.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* $OpenBSD: dev_conf.h,v 1.1 1996/04/18 23:47:02 niklas Exp $ */
-/* $NetBSD: dev_conf.h,v 1.1 1996/03/07 15:00:13 christos Exp $ */
-
-/*
- * Copyright (c) 1995 Christos Zoulas. 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 Christos Zoulas.
- * 4. 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.
- */
-
-#include <sys/conf.h>
-
-#include "audio.h"
-cdev_decl(audio);
-
-cdev_decl(cn);
-
-#include "vnd.h"
-bdev_decl(vnd);
-cdev_decl(vnd);
-
-#include "ccd.h"
-bdev_decl(ccd);
-cdev_decl(ccd);
diff --git a/sys/dev/eisa/aha1742.c b/sys/dev/eisa/aha1742.c
index 8d01311a804..19bda5ff3b7 100644
--- a/sys/dev/eisa/aha1742.c
+++ b/sys/dev/eisa/aha1742.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: aha1742.c,v 1.4 1996/04/18 23:47:09 niklas Exp $ */
-/* $NetBSD: aha1742.c,v 1.57 1996/03/08 22:03:26 cgd Exp $ */
+/* $OpenBSD: aha1742.c,v 1.5 1996/04/21 22:20:12 deraadt Exp $ */
+/* $NetBSD: aha1742.c,v 1.59 1996/04/09 22:47:00 cgd Exp $ */
/*
* Copyright (c) 1994 Charles Hannum. All rights reserved.
@@ -263,12 +263,12 @@ struct ahb_ecb {
struct ahb_softc {
struct device sc_dev;
- struct isadev sc_id;
- void *sc_ih;
bus_chipset_tag_t sc_bc;
- bus_io_handle_t sc_ioh;
+ eisa_chipset_tag_t sc_ec;
+ bus_io_handle_t sc_ioh;
int sc_irq;
+ void *sc_ih;
struct ahb_ecb *immed_ecb; /* an outstanding immediete command */
struct ahb_ecb *ecbhash[ECB_HASH_SIZE];
@@ -320,8 +320,12 @@ struct scsi_device ahb_dev = {
int ahbmatch __P((struct device *, void *, void *));
void ahbattach __P((struct device *, struct device *, void *));
-struct cfdriver ahbcd = {
- NULL, "ahb", ahbmatch, ahbattach, DV_DULL, sizeof(struct ahb_softc)
+struct cfattach ahb_ca = {
+ sizeof(struct ahb_softc), ahbmatch, ahbattach
+};
+
+struct cfdriver ahb_cd = {
+ NULL, "ahb", DV_DULL
};
/*
@@ -466,9 +470,13 @@ ahbattach(parent, self, aux)
struct ahb_softc *ahb = (void *)self;
bus_chipset_tag_t bc = ea->ea_bc;
bus_io_handle_t ioh;
- char *model;
+ eisa_chipset_tag_t ec = ea->ea_ec;
+ eisa_intr_handle_t ih;
+ const char *model, *intrstr;
ahb->sc_bc = bc;
+ ahb->sc_ec = ec;
+
if (bus_io_map(bc, EISA_SLOT_ADDR(ea->ea_slot), EISA_SLOT_SIZE, &ioh))
panic("ahbattach: could not map I/O addresses");
ahb->sc_ioh = ioh;
diff --git a/sys/dev/eisa/devlist2h.awk b/sys/dev/eisa/devlist2h.awk
index 475234b6435..159691c7923 100644
--- a/sys/dev/eisa/devlist2h.awk
+++ b/sys/dev/eisa/devlist2h.awk
@@ -1,6 +1,6 @@
#! /usr/bin/awk -f
-# $OpenBSD: devlist2h.awk,v 1.1 1996/04/18 23:47:10 niklas Exp $
-# $NetBSD: devlist2h.awk,v 1.1 1996/02/26 23:46:20 cgd Exp $
+# $OpenBSD: devlist2h.awk,v 1.2 1996/04/21 22:20:18 deraadt Exp $
+# $NetBSD: devlist2h.awk,v 1.2 1996/04/09 20:07:16 cgd Exp $
#
# Copyright (c) 1995, 1996 Christopher G. Demetriou
# All rights reserved.
@@ -91,7 +91,7 @@ $1 == "product" {
products[nproducts, 1] = $2; # vendor name
products[nproducts, 2] = $3; # product id
printf("#define\tEISA_PRODUCT_%s%s\t\"", products[nproducts, 1],
- products[nproducts, 2]) > hfile
+ products[nproducts, 2]) > hfile
i = vendorindex[products[nproducts, 1]]; j = 2;
needspace = 0;
diff --git a/sys/dev/eisa/eisa.c b/sys/dev/eisa/eisa.c
index 38a72a42d9b..770077bbf1d 100644
--- a/sys/dev/eisa/eisa.c
+++ b/sys/dev/eisa/eisa.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: eisa.c,v 1.1 1996/04/18 23:47:10 niklas Exp $ */
-/* $NetBSD: eisa.c,v 1.7 1996/03/14 04:02:58 cgd Exp $ */
+/* $OpenBSD: eisa.c,v 1.2 1996/04/21 22:20:23 deraadt Exp $ */
+/* $NetBSD: eisa.c,v 1.11 1996/04/09 22:46:11 cgd Exp $ */
/*
* Copyright (c) 1995, 1996 Christopher G. Demetriou
@@ -52,8 +52,12 @@
int eisamatch __P((struct device *, void *, void *));
void eisaattach __P((struct device *, struct device *, void *));
-struct cfdriver eisacd = {
- NULL, "eisa", eisamatch, eisaattach, DV_DULL, sizeof(struct device)
+struct cfattach eisa_ca = {
+ sizeof(struct device), eisamatch, eisaattach
+};
+
+struct cfdriver eisa_cd = {
+ NULL, "eisa", DV_DULL
};
int eisasubmatch __P((struct device *, void *, void *));
@@ -62,8 +66,8 @@ void eisa_devinfo __P((const char *, char *));
int
eisamatch(parent, match, aux)
- struct device *parent;
- void *match, *aux;
+ struct device *parent;
+ void *match, *aux;
{
struct cfdata *cf = match;
struct eisabus_attach_args *eba = aux;
@@ -73,7 +77,7 @@ eisamatch(parent, match, aux)
/* XXX check other indicators */
- return (1);
+ return (1);
}
int
@@ -103,21 +107,24 @@ eisasubmatch(parent, match, aux)
if (cf->eisacf_slot != EISA_UNKNOWN_SLOT &&
cf->eisacf_slot != ea->ea_slot)
return 0;
- return ((*cf->cf_driver->cd_match)(parent, match, aux));
+ return ((*cf->cf_attach->ca_match)(parent, match, aux));
}
void
eisaattach(parent, self, aux)
- struct device *parent, *self;
- void *aux;
+ struct device *parent, *self;
+ void *aux;
{
struct eisabus_attach_args *eba = aux;
bus_chipset_tag_t bc;
- int slot;
+ eisa_chipset_tag_t ec;
+ int slot, maxnslots;
+ eisa_attach_hook(parent, self, eba);
printf("\n");
bc = eba->eba_bc;
+ ec = eba->eba_ec;
/*
* Search for and attach subdevices.
@@ -125,14 +132,15 @@ eisaattach(parent, self, aux)
* Slot 0 is the "motherboard" slot, and the code attaching
* the EISA bus should have already attached an ISA bus there.
*/
- for (slot = 1; slot < EISA_MAX_SLOT; slot++) {
+ maxnslots = eisa_maxslots(ec);
+ for (slot = 1; slot < maxnslots; slot++) {
struct eisa_attach_args ea;
- struct cfdata *cf;
u_int slotaddr;
bus_io_handle_t slotioh;
int i;
ea.ea_bc = bc;
+ ea.ea_ec = ec;
ea.ea_slot = slot;
slotaddr = EISA_SLOT_ADDR(slot);
@@ -142,7 +150,8 @@ eisaattach(parent, self, aux)
* about it.
*/
if (bus_io_map(bc, slotaddr, EISA_SLOT_SIZE, &slotioh)) {
- printf("%s: can't map I/O space for slot %d\n", slot);
+ printf("%s: can't map I/O space for slot %d\n",
+ self->dv_xname, slot);
continue;
}
@@ -195,14 +204,14 @@ eisaattach(parent, self, aux)
}
#ifdef EISAVERBOSE
-/*
+/*
* Descriptions of of known vendors and devices ("products").
- */
+ */
struct eisa_knowndev {
int flags;
const char *id, *name;
-};
-#define EISA_KNOWNDEV_NOPROD 0x01 /* match on vendor only */
+};
+#define EISA_KNOWNDEV_NOPROD 0x01 /* match on vendor only */
#include <dev/eisa/eisadevs_data.h>
#endif /* EISAVERBOSE */
diff --git a/sys/dev/eisa/eisadevs b/sys/dev/eisa/eisadevs
index 8a1e3e9e035..dafdad6d457 100644
--- a/sys/dev/eisa/eisadevs
+++ b/sys/dev/eisa/eisadevs
@@ -1,4 +1,4 @@
-$OpenBSD: eisadevs,v 1.1 1996/04/18 23:47:11 niklas Exp $
+$OpenBSD: eisadevs,v 1.2 1996/04/21 22:20:29 deraadt Exp $
/* $NetBSD: eisadevs,v 1.1 1996/02/26 23:46:22 cgd Exp $ */
/*
@@ -37,6 +37,7 @@ $OpenBSD: eisadevs,v 1.1 1996/04/18 23:47:11 niklas Exp $
*/
vendor ADP Adaptec
+vendor AMI AMI
vendor BUS BusLogic
vendor DEC Digital Equipment
vendor TCM 3Com
@@ -46,22 +47,26 @@ vendor TCM 3Com
*/
/* Adaptec products */
-product ADP 0000 AHA-1740
-product ADP 0001 AHA-1740A
-product ADP 0002 AHA-1742A
-product ADP 0400 AHA-1744
-product ADP 7770 AIC-7770 (on motherboard)
-product ADP 7771 AHA-274x
-product ADP 7756 AHA-284x (BIOS enabled)
-product ADP 7757 AHA-284x (BIOS disabled)
+product ADP 0000 AHA-1740 SCSI
+product ADP 0001 AHA-1740A SCSI
+product ADP 0002 AHA-1742A SCSI
+product ADP 0400 AHA-1744 SCSI
+product ADP 7770 AIC-7770 SCSI (on motherboard)
+product ADP 7771 AHA-274x SCSI
+product ADP 7756 AHA-284x SCSI (BIOS enabled)
+product ADP 7757 AHA-284x SCSI (BIOS disabled)
+
+/* AMI products */
+product AMI 4801 Series 48 SCSI
/* BusLogic products */
-/* XXX */
+product BUS 4201 Bt74xB SCSI
+product BUS 4202 Bt74xC SCSI
/* Digital Equipment products */
-product DEC 4250 DE425
+product DEC 4250 DE425 Ethernet
/* ??? DEC DEFEA */
/* 3Com products */
-product TCM 5092 3C579-TP
-product TCM 5093 3C579
+product TCM 5092 3C579-TP Ethernet
+product TCM 5093 3C579 Ethernet
diff --git a/sys/dev/eisa/eisadevs.h b/sys/dev/eisa/eisadevs.h
index 0f8b7c3b9b9..b9042f4bb3e 100644
--- a/sys/dev/eisa/eisadevs.h
+++ b/sys/dev/eisa/eisadevs.h
@@ -42,22 +42,26 @@
*/
/* Adaptec products */
-#define EISA_PRODUCT_ADP0000 "Adaptec AHA-1740"
-#define EISA_PRODUCT_ADP0001 "Adaptec AHA-1740A"
-#define EISA_PRODUCT_ADP0002 "Adaptec AHA-1742A"
-#define EISA_PRODUCT_ADP0400 "Adaptec AHA-1744"
-#define EISA_PRODUCT_ADP7770 "Adaptec AIC-7770 (on motherboard)"
-#define EISA_PRODUCT_ADP7771 "Adaptec AHA-274x"
-#define EISA_PRODUCT_ADP7756 "Adaptec AHA-284x (BIOS enabled)"
-#define EISA_PRODUCT_ADP7757 "Adaptec AHA-284x (BIOS disabled)"
+#define EISA_PRODUCT_ADP0000 "Adaptec AHA-1740 SCSI"
+#define EISA_PRODUCT_ADP0001 "Adaptec AHA-1740A SCSI"
+#define EISA_PRODUCT_ADP0002 "Adaptec AHA-1742A SCSI"
+#define EISA_PRODUCT_ADP0400 "Adaptec AHA-1744 SCSI"
+#define EISA_PRODUCT_ADP7770 "Adaptec AIC-7770 SCSI (on motherboard)"
+#define EISA_PRODUCT_ADP7771 "Adaptec AHA-274x SCSI"
+#define EISA_PRODUCT_ADP7756 "Adaptec AHA-284x SCSI (BIOS enabled)"
+#define EISA_PRODUCT_ADP7757 "Adaptec AHA-284x SCSI (BIOS disabled)"
+
+/* AMI products */
+#define EISA_PRODUCT_AMI4801 "AMI Series 48 SCSI"
/* BusLogic products */
-/* XXX */
+#define EISA_PRODUCT_BUS4201 "BusLogic Bt74xB SCSI"
+#define EISA_PRODUCT_BUS4202 "BusLogic Bt74xC SCSI"
/* Digital Equipment products */
-#define EISA_PRODUCT_DEC4250 "Digital Equipment DE425"
+#define EISA_PRODUCT_DEC4250 "Digital Equipment DE425 Ethernet"
/* ??? DEC DEFEA */
/* 3Com products */
-#define EISA_PRODUCT_TCM5092 "3Com 3C579-TP"
-#define EISA_PRODUCT_TCM5093 "3Com 3C579"
+#define EISA_PRODUCT_TCM5092 "3Com 3C579-TP Ethernet"
+#define EISA_PRODUCT_TCM5093 "3Com 3C579 Ethernet"
diff --git a/sys/dev/eisa/eisadevs_data.h b/sys/dev/eisa/eisadevs_data.h
index 2ba485a4c45..e91b1f799b6 100644
--- a/sys/dev/eisa/eisadevs_data.h
+++ b/sys/dev/eisa/eisadevs_data.h
@@ -80,6 +80,21 @@ struct eisa_knowndev eisa_knowndevs[] = {
},
{
0,
+ "AMI4801",
+ EISA_PRODUCT_AMI4801,
+ },
+ {
+ 0,
+ "BUS4201",
+ EISA_PRODUCT_BUS4201,
+ },
+ {
+ 0,
+ "BUS4202",
+ EISA_PRODUCT_BUS4202,
+ },
+ {
+ 0,
"DEC4250",
EISA_PRODUCT_DEC4250,
},
@@ -100,6 +115,11 @@ struct eisa_knowndev eisa_knowndevs[] = {
},
{
EISA_KNOWNDEV_NOPROD,
+ "AMI",
+ "AMI",
+ },
+ {
+ EISA_KNOWNDEV_NOPROD,
"BUS",
"BusLogic",
},
diff --git a/sys/dev/eisa/eisareg.h b/sys/dev/eisa/eisareg.h
index b965dfeda3f..8d53ac05e87 100644
--- a/sys/dev/eisa/eisareg.h
+++ b/sys/dev/eisa/eisareg.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: eisareg.h,v 1.2 1996/04/18 23:47:12 niklas Exp $ */
-/* $NetBSD: eisareg.h,v 1.2 1996/02/27 00:21:02 cgd Exp $ */
+/* $OpenBSD: eisareg.h,v 1.3 1996/04/21 22:20:42 deraadt Exp $ */
+/* $NetBSD: eisareg.h,v 1.3 1996/04/09 22:46:13 cgd Exp $ */
/*
* Copyright (c) 1995, 1996 Christopher G. Demetriou
@@ -43,11 +43,6 @@
*/
/*
- * Max number of EISA slots in a machine. 64K I/O space total.
- */
-#define EISA_MAX_SLOT 16 /* number of slots. 0 -> 0xf */
-
-/*
* Slot I/O space size, and I/O address of a given slot.
*/
#define EISA_SLOT_SIZE 0x1000
diff --git a/sys/dev/eisa/eisavar.h b/sys/dev/eisa/eisavar.h
index d0ddeeb1fbc..6b7b54ffe26 100644
--- a/sys/dev/eisa/eisavar.h
+++ b/sys/dev/eisa/eisavar.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: eisavar.h,v 1.3 1996/04/18 23:47:13 niklas Exp $ */
-/* $NetBSD: eisavar.h,v 1.4 1996/03/08 20:25:22 cgd Exp $ */
+/* $OpenBSD: eisavar.h,v 1.4 1996/04/21 22:20:45 deraadt Exp $ */
+/* $NetBSD: eisavar.h,v 1.9 1996/04/12 06:34:36 cgd Exp $ */
/*
* Copyright (c) 1995, 1996 Christopher G. Demetriou
@@ -32,22 +32,39 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __DEV_EISA_EISAVAR_H__
-#define __DEV_EISA_EISAVAR_H__
+#ifndef _DEV_EISA_EISAVAR_H_
+#define _DEV_EISA_EISAVAR_H_
/*
* Definitions for EISA autoconfiguration.
*
- * This file describes types, constants, and functions which are used
- * for EISA autoconfiguration.
+ * This file describes types and functions which are used for EISA
+ * configuration. Some of this information is machine-specific, and is
+ * separated into eisa_machdep.h.
*/
#include <machine/bus.h>
#include <dev/eisa/eisareg.h> /* For ID register & string info. */
+/*
+ * Structures and definitions needed by the machine-dependent header.
+ */
+struct eisabus_attach_args;
-typedef int eisa_slot_t; /* really only needs to be 4 bits */
+/*
+ * Machine-dependent definitions.
+ */
+#if (alpha + i386 != 1)
+ERROR: COMPILING FOR UNSUPPORTED MACHINE, OR MORE THAN ONE.
+#endif
+#if alpha
+#include <alpha/eisa/eisa_machdep.h>
+#endif
+#if i386
+#include <i386/eisa/eisa_machdep.h>
+#endif
+typedef int eisa_slot_t; /* really only needs to be 4 bits */
/*
* EISA bus attach arguments.
@@ -55,14 +72,15 @@ typedef int eisa_slot_t; /* really only needs to be 4 bits */
struct eisabus_attach_args {
char *eba_busname; /* XXX should be common */
bus_chipset_tag_t eba_bc; /* XXX should be common */
+ eisa_chipset_tag_t eba_ec;
};
-
/*
* EISA device attach arguments.
*/
struct eisa_attach_args {
bus_chipset_tag_t ea_bc;
+ eisa_chipset_tag_t ea_ec;
eisa_slot_t ea_slot;
u_int8_t ea_vid[EISA_NVIDREGS];
@@ -70,37 +88,10 @@ struct eisa_attach_args {
char ea_idstring[EISA_IDSTRINGLEN];
};
-
-/*
- * Easy to remember names for EISA device locators.
- */
-
-#define eisacf_slot cf_loc[0] /* slot */
-
-
-/*
- * EISA device locator values that mean "unknown" or "unspecified."
- * Note that not all are supplied by 'config' and should be filled
- * in by the device if appropriate.
- */
-
-#define EISA_UNKNOWN_SLOT ((eisa_slot_t)-1)
-
/*
- * The EISA bus cfdriver, so that subdevices can more easily tell
- * what bus they're on.
+ * Locators for EISA devices, as specified to config.
*/
+#define eisacf_slot cf_loc[0]
+#define EISA_UNKNOWN_SLOT -1 /* wildcarded 'slot' */
-extern struct cfdriver eisacd;
-
-/*
- * XXX interrupt attachment, etc., is done by using the ISA interfaces.
- * XXX THIS SHOULD CHANGE.
- */
-
-#include <dev/isa/isavar.h>
-
-#define eisa_intr_establish isa_intr_establish /* XXX */
-#define eisa_intr_disestablish isa_intr_disestablish /* XXX */
-
-#endif /* !__DEV_EISA_EISAVAR_H__ */
+#endif /* _DEV_EISA_EISAVAR_H_ */
diff --git a/sys/dev/eisa/files.eisa b/sys/dev/eisa/files.eisa
index 7db823d1a57..cc0b5443475 100644
--- a/sys/dev/eisa/files.eisa
+++ b/sys/dev/eisa/files.eisa
@@ -1,13 +1,15 @@
-# $OpenBSD: files.eisa,v 1.2 1996/04/18 23:47:14 niklas Exp $
-# $NetBSD: files.eisa,v 1.6 1996/03/04 03:29:12 cgd Exp $
+# $OpenBSD: files.eisa,v 1.3 1996/04/21 22:20:50 deraadt Exp $
+# $NetBSD: files.eisa,v 1.7 1996/03/17 00:47:21 thorpej Exp $
#
# Config.new file and device description for machine-independent EISA code.
# Included by ports that need it. Requires that the SCSI files be
# defined first.
-device eisa at eisabus {[slot = -1]}
+device eisa {[slot = -1]}
+attach eisa at eisabus
file dev/eisa/eisa.c eisa needs-flag
# Adaptec AHA-174x EISA SCSI Host Adapter family
-device ahb at eisa: scsi
+device ahb: scsi
+attach ahb at eisa
file dev/eisa/aha1742.c ahb
diff --git a/sys/dev/ic/aic7xxx.c b/sys/dev/ic/aic7xxx.c
index a3bf8e44807..215e059b98d 100644
--- a/sys/dev/ic/aic7xxx.c
+++ b/sys/dev/ic/aic7xxx.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: aic7xxx.c,v 1.3 1996/04/18 23:47:15 niklas Exp $ */
-/* $NetBSD: aic7xxx.c,v 1.3 1996/02/25 22:56:30 cgd Exp $ */
+/* $OpenBSD: aic7xxx.c,v 1.4 1996/04/21 22:21:03 deraadt Exp $ */
+/* $NetBSD: aic7xxx.c,v 1.5 1996/03/29 00:24:58 mycroft Exp $ */
/*
* Generic driver for the aic7xxx based adaptec SCSI controllers
@@ -63,13 +63,12 @@ void ahcminphys __P((struct buf *));
int ahc_poll __P((struct ahc_softc *, struct scsi_xfer *, int));
/* Different debugging levels */
+#ifdef AHC_DEBUG
#define AHC_SHOWMISC 0x0001
#define AHC_SHOWCMDS 0x0002
#define AHC_SHOWSCBS 0x0004
-/*#define AHC_DEBUG /**/
int ahc_debug = AHC_SHOWMISC;
-
-/*#define AHC_MORE_DEBUG /**/
+#endif
#ifdef AHC_MORE_DEBUG
#define DEBUGLEVEL -1
@@ -629,7 +628,6 @@ ahc_scsirate(offset, period, ahc, target)
struct ahc_softc *ahc;
int target;
{
- u_char scsirate;
int i;
for (i = 0; i < ahc_num_syncrates; i++) {
@@ -652,9 +650,15 @@ ahc_scsirate(offset, period, ahc, target)
#endif /* AHC_DEBUG */
}
-ahcprint()
+int
+ahcprint(aux, name)
+ void *aux;
+ char *name;
{
+ if (name != NULL)
+ printf("%s: scsibus ", name);
+ return UNCONF;
}
/*
@@ -768,7 +772,7 @@ ahcintr(ahc)
break;
case NO_IDENT:
panic("%s: No IDENTIFY message from reconnecting "
- "target %d at seqaddr = 0x%lx "
+ "target %d at seqaddr = 0x%x "
"SAVED_TCL == 0x%x\n",
ahc->sc_dev.dv_xname,
(inb(SELID + iobase) >> 4) & 0xf,
@@ -847,7 +851,7 @@ ahcintr(ahc)
*/
#ifdef AHC_DEBUG
if (ahc_debug & AHC_SHOWMISC)
- printf("Sending SDTR!!\n");
+ printf("Sending SDTR!!\n");
#endif
outb(HA_RETURN_1 + iobase, SEND_SDTR);
}
@@ -1018,7 +1022,6 @@ ahcintr(ahc)
if (xs->error == XS_NOERROR &&
scb->flags != SCB_CHKSENSE) {
- u_char flags;
u_char head;
u_char tail;
struct ahc_dma_seg *sg = scb->ahc_dma;
@@ -1389,7 +1392,6 @@ ahc_init(ahc)
ahc->sc_dev.dv_xname, sizeof(struct ahc_scb), SCB_DOWN_SIZE,
sizeof(struct ahc_dma_seg));
#endif /* AHC_DEBUG */
- /*printf("%s: reading board settings\n", ahc->sc_dev.dv_xname);/**/
/* Save the IRQ type before we do a chip reset */
diff --git a/sys/dev/ic/aic7xxxvar.h b/sys/dev/ic/aic7xxxvar.h
index 48e902a398c..82022e8ab35 100644
--- a/sys/dev/ic/aic7xxxvar.h
+++ b/sys/dev/ic/aic7xxxvar.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: aic7xxxvar.h,v 1.2 1996/04/18 23:47:16 niklas Exp $ */
-/* $NetBSD: aic7xxxvar.h,v 1.2 1996/03/14 02:30:30 cgd Exp $ */
+/* $OpenBSD: aic7xxxvar.h,v 1.3 1996/04/21 22:21:12 deraadt Exp $ */
+/* $NetBSD: aic7xxxvar.h,v 1.3 1996/03/29 00:25:02 mycroft Exp $ */
/*
* Interface to the generic driver for the aic7xxx based adaptec
@@ -27,8 +27,6 @@
#ifndef _AIC7XXX_H_
#define _AIC7XXX_H_
-/*#include "ahc.h" /* for NAHC from config */
-
#define AHC_NSEG 256 /* number of dma segments supported */
#define AHC_SCB_MAX 16 /*
diff --git a/sys/dev/ic/am7990.c b/sys/dev/ic/am7990.c
index 87c5712eba2..b050dd728db 100644
--- a/sys/dev/ic/am7990.c
+++ b/sys/dev/ic/am7990.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: am7990.c,v 1.4 1996/04/18 23:47:17 niklas Exp $ */
-/* $NetBSD: am7990.c,v 1.11 1996/03/14 19:05:07 christos Exp $ */
+/* $OpenBSD: am7990.c,v 1.5 1996/04/21 22:21:15 deraadt Exp $ */
+/* $NetBSD: am7990.c,v 1.16 1996/04/09 15:21:59 pk Exp $ */
/*-
* Copyright (c) 1995 Charles M. Hannum. All rights reserved.
@@ -74,6 +74,10 @@ void xmit_print __P((struct le_softc *, int));
#define ifp (&sc->sc_arpcom.ac_if)
+#ifndef ETHER_CMP
+#define ETHER_CMP(a, b) bcmp((a), (b), ETHER_ADDR_LEN)
+#endif
+
void
leconfig(sc)
struct le_softc *sc;
@@ -123,8 +127,8 @@ leconfig(sc)
panic("leconfig: weird memory size");
}
- printf(": address %s\n%s: %d receive buffers, %d transmit buffers\n",
- ether_sprintf(sc->sc_arpcom.ac_enaddr),
+ printf(": address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
+ printf("%s: %d receive buffers, %d transmit buffers\n",
sc->sc_dev.dv_xname, sc->sc_nrbuf, sc->sc_ntbuf);
mem = 0;
@@ -420,8 +424,7 @@ leread(sc, boff, len)
*/
if ((ifp->if_flags & IFF_PROMISC) != 0 &&
(eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
- bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr,
- sizeof(eh->ether_dhost)) != 0) {
+ ETHER_CMP(eh->ether_dhost, sc->sc_arpcom.ac_enaddr)) {
m_freem(m);
return;
}
@@ -430,10 +433,15 @@ leread(sc, boff, len)
#endif
#ifdef LANCE_REVC_BUG
- if (bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr,
- sizeof(eh->ether_dhost)) != 0 &&
- bcmp(eh->ether_dhost, etherbroadcastaddr,
- sizeof(eh->ether_dhost)) != 0) {
+ /*
+ * The old LANCE (Rev. C) chips have a bug which causes
+ * garbage to be inserted in front of the received packet.
+ * The work-around is to ignore packets with an invalid
+ * destination address (garbage will usually not match).
+ * Of course, this precludes multicast support...
+ */
+ if (ETHER_CMP(eh->ether_dhost, sc->sc_arpcom.ac_enaddr) &&
+ ETHER_CMP(eh->ether_dhost, etherbroadcastaddr)) {
m_freem(m);
return;
}
@@ -483,7 +491,7 @@ lerint(sc)
printf("%s: receive buffer error\n",
sc->sc_dev.dv_xname);
ifp->if_ierrors++;
- } else if (rmd.rmd1_bits & (LE_R1_STP | LE_R1_ENP) !=
+ } else if ((rmd.rmd1_bits & (LE_R1_STP | LE_R1_ENP)) !=
(LE_R1_STP | LE_R1_ENP)) {
printf("%s: dropping chained buffer\n",
sc->sc_dev.dv_xname);
@@ -503,8 +511,12 @@ lerint(sc)
#ifdef LEDEBUG
if (sc->sc_debug)
- printf("sc->sc_last_rd = %x, rmd = %x\n",
- sc->sc_last_rd, rmd);
+ printf("sc->sc_last_rd = %x, rmd: "
+ "ladr %04x, hadr %02x, flags %02x, "
+ "bcnt %04x, mcnt %04x\n",
+ sc->sc_last_rd,
+ rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits,
+ rmd.rmd2, rmd.rmd3);
#endif
if (++bix == sc->sc_nrbuf)
@@ -529,7 +541,11 @@ letint(sc)
#ifdef LEDEBUG
if (sc->sc_debug)
- printf("trans tmd = %x\n", tmd);
+ printf("trans tmd: "
+ "ladr %04x, hadr %02x, flags %02x, "
+ "bcnt %04x, mcnt %04x\n",
+ tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits,
+ tmd.tmd2, tmd.tmd3);
#endif
(*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix),
@@ -877,9 +893,10 @@ recv_print(sc, no)
rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits, rmd.rmd2, rmd.rmd3);
if (len >= sizeof(eh)) {
(*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh));
- printf("%s: dst %s", ether_sprintf(eh.ether_dhost));
+ printf("%s: dst %s", sc->sc_dev.dv_xname,
+ ether_sprintf(eh.ether_dhost));
printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
- ntohs(eh.ether_type));
+ ntohs(eh.ether_type));
}
}
@@ -902,7 +919,8 @@ xmit_print(sc, no)
tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, tmd.tmd2, tmd.tmd3);
if (len >= sizeof(eh)) {
(*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh));
- printf("%s: dst %s", ether_sprintf(eh.ether_dhost));
+ printf("%s: dst %s", sc->sc_dev.dv_xname,
+ ether_sprintf(eh.ether_dhost));
printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
ntohs(eh.ether_type));
}
@@ -938,8 +956,7 @@ lesetladrf(ac, af)
af[0] = af[1] = af[2] = af[3] = 0x0000;
ETHER_FIRST_MULTI(step, ac, enm);
while (enm != NULL) {
- if (bcmp(enm->enm_addrlo, enm->enm_addrhi,
- sizeof(enm->enm_addrlo)) != 0) {
+ if (ETHER_CMP(enm->enm_addrlo, enm->enm_addrhi)) {
/*
* We must listen to a range of multicast addresses.
* For now, just accept all multicasts, rather than
@@ -1058,7 +1075,6 @@ copytobuf_gap2(sc, fromv, boff, len)
volatile caddr_t buf = sc->sc_mem;
register caddr_t from = fromv;
register volatile u_int16_t *bptr;
- register int xfer;
if (boff & 0x1) {
/* handle unaligned first byte */
@@ -1088,7 +1104,6 @@ copyfrombuf_gap2(sc, tov, boff, len)
register caddr_t to = tov;
register volatile u_int16_t *bptr;
register u_int16_t tmp;
- register int xfer;
if (boff & 0x1) {
/* handle unaligned first byte */
diff --git a/sys/dev/ic/com.c b/sys/dev/ic/com.c
index d34ba82a096..77dd24748f4 100644
--- a/sys/dev/ic/com.c
+++ b/sys/dev/ic/com.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: com.c,v 1.10 1996/04/18 23:47:32 niklas Exp $ */
-/* $NetBSD: com.c,v 1.75 1996/03/10 09:01:24 cgd Exp $ */
+/* $OpenBSD: com.c,v 1.11 1996/04/21 22:23:15 deraadt Exp $ */
+/* $NetBSD: com.c,v 1.79 1996/04/15 18:54:31 cgd Exp $ */
/*-
* Copyright (c) 1993, 1994, 1995, 1996
@@ -57,7 +57,11 @@
#include <sys/types.h>
#include <sys/device.h>
-#include <machine/cpu.h>
+#ifdef i386 /* XXX */
+#include <machine/cpu.h> /* XXX */
+#else /* XXX */
+#include <machine/intr.h>
+#endif /* XXX */
#include <machine/bus.h>
#include <dev/isa/isavar.h>
@@ -69,6 +73,8 @@
#endif
#define com_lcr com_cfcr
+#include "com.h"
+
#define COM_IBUFSIZE (2 * 512)
#define COM_IHIGHWATER ((3 * COM_IBUFSIZE) / 4)
@@ -109,11 +115,9 @@ struct com_softc {
u_char sc_ibufs[2][COM_IBUFSIZE];
};
-int comprobe __P((struct device *, void *, void *));
#ifdef COM_HAYESP
int comprobeHAYESP __P((bus_io_handle_t hayespioh, struct com_softc *sc));
#endif
-void comattach __P((struct device *, struct device *, void *));
int comopen __P((dev_t, int, int, struct proc *));
int comclose __P((dev_t, int, int, struct proc *));
void comdiag __P((void *));
@@ -122,11 +126,30 @@ void compoll __P((void *));
int comparam __P((struct tty *, struct termios *));
void comstart __P((struct tty *));
-int cominit __P((bus_chipset_tag_t, bus_io_handle_t, int));
+/*
+ * XXX the following two cfattach structs should be different, and possibly
+ * XXX elsewhere.
+ */
+int comprobe __P((struct device *, void *, void *));
+void comattach __P((struct device *, struct device *, void *));
+
+#if NCOM_ISA
+struct cfattach com_isa_ca = {
+ sizeof(struct com_softc), comprobe, comattach
+};
+#endif
-struct cfdriver comcd = {
- NULL, "com", comprobe, comattach, DV_TTY, sizeof(struct com_softc)
+#if NCOM_COMMULTI
+struct cfattach com_commulti_ca = {
+ sizeof(struct com_softc), comprobe, comattach
};
+#endif
+
+struct cfdriver com_cd = {
+ NULL, "com", DV_TTY
+};
+
+int cominit __P((bus_chipset_tag_t, bus_io_handle_t, int));
#ifdef COMCONSOLE
int comdefaultrate = CONSPEED; /* XXX why set default? */
@@ -138,6 +161,7 @@ int comconsinit;
int comconsattached;
bus_chipset_tag_t comconsbc;
bus_io_handle_t comconsioh;
+tcflag_t comconscflag = TTYDEF_CFLAG;
int commajor;
int comsopen = 0;
@@ -157,7 +181,7 @@ extern int kgdb_debug_init;
#define CLR(t, f) (t) &= ~(f)
#define ISSET(t, f) ((t) & (f))
-#include "pcmciabus.h"
+/*#include "pcmciabus.h"*/
#if NPCMCIABUS >0
/* additional setup needed for pcmcia devices */
#include <dev/pcmcia/pcmciabus.h>
@@ -327,13 +351,22 @@ comprobe(parent, match, aux)
int iobase, needioh;
int rv = 1;
+ /*
+ * XXX should be broken out into functions for isa probe and
+ * XXX for commulti probe, with a helper function that contains
+ * XXX most of the interesting stuff.
+ */
+#if NCOM_ISA
if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
struct isa_attach_args *ia = aux;
bc = ia->ia_bc;
iobase = ia->ia_iobase;
needioh = 1;
- } else {
+ } else
+#endif
+#if NCOM_COMMULTI
+ if (1) {
struct commulti_attach_args *ca = aux;
if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ca->ca_slave)
@@ -343,7 +376,9 @@ comprobe(parent, match, aux)
iobase = ca->ca_iobase;
ioh = ca->ca_ioh;
needioh = 0;
- }
+ } else
+#endif
+ return(0); /* This cannot happen */
/* if it's in use as console, it's there. */
if (iobase == comconsaddr && !comconsattached)
@@ -358,12 +393,14 @@ comprobe(parent, match, aux)
bus_io_unmap(bc, ioh, COM_NPORTS);
out:
+#if NCOM_ISA
if (rv && !strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
struct isa_attach_args *ia = aux;
ia->ia_iosize = COM_NPORTS;
ia->ia_msize = 0;
}
+#endif
return (rv);
}
@@ -383,8 +420,14 @@ comattach(parent, self, aux)
int *hayespp;
#endif
+ /*
+ * XXX should be broken out into functions for isa attach and
+ * XXX for commulti attach, with a helper function that contains
+ * XXX most of the interesting stuff.
+ */
sc->sc_hwflags = 0;
sc->sc_swflags = 0;
+#if NCOM_ISA
if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
struct isa_attach_args *ia = aux;
@@ -399,7 +442,10 @@ comattach(parent, self, aux)
} else
ioh = comconsioh;
irq = ia->ia_irq;
- } else {
+ } else
+#endif
+#if NCOM_COMMULTI
+ if (1) {
struct commulti_attach_args *ca = aux;
/*
@@ -412,7 +458,9 @@ comattach(parent, self, aux)
if (ca->ca_noien)
sc->sc_hwflags |= COM_HW_NOIEN;
- }
+ } else
+#endif
+ panic("comattach: impossible");
sc->sc_bc = bc;
sc->sc_ioh = ioh;
@@ -473,9 +521,18 @@ comattach(parent, self, aux)
bus_io_write_1(bc, ioh, com_ier, 0);
bus_io_write_1(bc, ioh, com_mcr, 0);
- if (irq != IRQUNK)
- sc->sc_ih = isa_intr_establish(irq, IST_EDGE, IPL_TTY,
- comintr, sc, sc->sc_dev.dv_xname);
+ if (irq != IRQUNK) {
+#if NCOM_ISA
+ if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
+ struct isa_attach_args *ia = aux;
+
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, irq,
+ IST_EDGE, IPL_TTY, comintr, sc,
+ sc->sc_dev.dv_xname);
+ } else
+#endif
+ panic("comattach: IRQ but can't have one");
+ }
#ifdef KGDB
if (kgdb_dev == makedev(commajor, unit)) {
@@ -516,9 +573,9 @@ comopen(dev, flag, mode, p)
int s;
int error = 0;
- if (unit >= comcd.cd_ndevs)
+ if (unit >= com_cd.cd_ndevs)
return ENXIO;
- sc = comcd.cd_devs[unit];
+ sc = com_cd.cd_devs[unit];
if (!sc)
return ENXIO;
@@ -535,7 +592,10 @@ comopen(dev, flag, mode, p)
ttychars(tp);
tp->t_iflag = TTYDEF_IFLAG;
tp->t_oflag = TTYDEF_OFLAG;
- tp->t_cflag = TTYDEF_CFLAG;
+ if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
+ tp->t_cflag = comconscflag;
+ else
+ tp->t_cflag = TTYDEF_CFLAG;
if (ISSET(sc->sc_swflags, COM_SW_CLOCAL))
SET(tp->t_cflag, CLOCAL);
if (ISSET(sc->sc_swflags, COM_SW_CRTSCTS))
@@ -644,7 +704,7 @@ comclose(dev, flag, mode, p)
struct proc *p;
{
int unit = COMUNIT(dev);
- struct com_softc *sc = comcd.cd_devs[unit];
+ struct com_softc *sc = com_cd.cd_devs[unit];
struct tty *tp = sc->sc_tty;
bus_chipset_tag_t bc = sc->sc_bc;
bus_io_handle_t ioh = sc->sc_ioh;
@@ -684,7 +744,7 @@ comread(dev, uio, flag)
struct uio *uio;
int flag;
{
- struct com_softc *sc = comcd.cd_devs[COMUNIT(dev)];
+ struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
struct tty *tp = sc->sc_tty;
return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
@@ -696,7 +756,7 @@ comwrite(dev, uio, flag)
struct uio *uio;
int flag;
{
- struct com_softc *sc = comcd.cd_devs[COMUNIT(dev)];
+ struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
struct tty *tp = sc->sc_tty;
return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
@@ -706,7 +766,7 @@ struct tty *
comtty(dev)
dev_t dev;
{
- struct com_softc *sc = comcd.cd_devs[COMUNIT(dev)];
+ struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
struct tty *tp = sc->sc_tty;
return (tp);
@@ -734,7 +794,7 @@ comioctl(dev, cmd, data, flag, p)
struct proc *p;
{
int unit = COMUNIT(dev);
- struct com_softc *sc = comcd.cd_devs[unit];
+ struct com_softc *sc = com_cd.cd_devs[unit];
struct tty *tp = sc->sc_tty;
bus_chipset_tag_t bc = sc->sc_bc;
bus_io_handle_t ioh = sc->sc_ioh;
@@ -846,7 +906,7 @@ comparam(tp, t)
struct tty *tp;
struct termios *t;
{
- struct com_softc *sc = comcd.cd_devs[COMUNIT(tp->t_dev)];
+ struct com_softc *sc = com_cd.cd_devs[COMUNIT(tp->t_dev)];
bus_chipset_tag_t bc = sc->sc_bc;
bus_io_handle_t ioh = sc->sc_ioh;
int ospeed = comspeed(t->c_ospeed);
@@ -985,7 +1045,7 @@ void
comstart(tp)
struct tty *tp;
{
- struct com_softc *sc = comcd.cd_devs[COMUNIT(tp->t_dev)];
+ struct com_softc *sc = com_cd.cd_devs[COMUNIT(tp->t_dev)];
bus_chipset_tag_t bc = sc->sc_bc;
bus_io_handle_t ioh = sc->sc_ioh;
int s;
@@ -1106,8 +1166,8 @@ compoll(arg)
comevents = 0;
splx(s);
- for (unit = 0; unit < comcd.cd_ndevs; unit++) {
- sc = comcd.cd_devs[unit];
+ for (unit = 0; unit < com_cd.cd_ndevs; unit++) {
+ sc = com_cd.cd_devs[unit];
if (sc == 0 || sc->sc_ibufp == sc->sc_ibuf)
continue;
diff --git a/sys/dev/ic/comvar.h b/sys/dev/ic/comvar.h
index 9b412b06936..c3f8068caec 100644
--- a/sys/dev/ic/comvar.h
+++ b/sys/dev/ic/comvar.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: comvar.h,v 1.1 1996/04/19 16:08:34 niklas Exp $ */
-/* $NetBSD: comvar.h,v 1.3 1996/03/10 09:01:26 cgd Exp $ */
+/* $OpenBSD: comvar.h,v 1.2 1996/04/21 22:23:20 deraadt Exp $ */
+/* $NetBSD: comvar.h,v 1.4 1996/04/15 18:54:35 cgd Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@@ -46,3 +46,4 @@ extern int comconsaddr;
extern int comconsattached;
extern bus_chipset_tag_t comconsbc;
extern bus_io_handle_t comconsioh;
+extern tcflag_t comconscflag;
diff --git a/sys/dev/ic/ncr5380sbc.c b/sys/dev/ic/ncr5380sbc.c
index 2fe5e7db748..a7e356d4bac 100644
--- a/sys/dev/ic/ncr5380sbc.c
+++ b/sys/dev/ic/ncr5380sbc.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: ncr5380sbc.c,v 1.4 1996/04/18 23:47:19 niklas Exp $ */
-/* $NetBSD: ncr5380sbc.c,v 1.8 1996/03/07 15:00:17 christos Exp $ */
+/* $OpenBSD: ncr5380sbc.c,v 1.5 1996/04/21 22:21:21 deraadt Exp $ */
+/* $NetBSD: ncr5380sbc.c,v 1.9 1996/03/18 23:09:02 gwr Exp $ */
/*
* Copyright (c) 1995 David Jones, Gordon W. Ross
@@ -2330,8 +2330,25 @@ do_actions:
if (act_flags & ACT_DISCONNECT) {
/*
* The device has dropped BSY (or will soon).
- * Return and let ncr5380_sched() do its thing.
+ * We have to wait here for BSY to drop, otherwise
+ * the next command may decide we need a bus reset.
*/
+ timo = ncr5380_wait_nrq_timo; /* XXX */
+ for (;;) {
+ if (!SCI_BUSY(sc))
+ goto busfree;
+ if (--timo <= 0)
+ break;
+ delay(2);
+ }
+ /* Device is sitting on the bus! */
+ printf("%s: SCSI job did not finish, resetting...\n",
+ sc->sc_dev.dv_xname);
+ ncr5380_reset_scsibus(sc);
+ busfree:
+ NCR_TRACE("machine: discon, waited %d\n",
+ ncr5380_wait_nrq_timo - timo);
+
*sc->sci_icmd = 0;
*sc->sci_mode = 0;
*sc->sci_tcmd = PHASE_INVALID;
diff --git a/sys/dev/ic/smc90cx6.c b/sys/dev/ic/smc90cx6.c
new file mode 100644
index 00000000000..afa12df2b80
--- /dev/null
+++ b/sys/dev/ic/smc90cx6.c
@@ -0,0 +1,1231 @@
+/* $NetBSD: smc90cx6.c,v 1.16 1996/03/20 13:28:50 is Exp $ */
+
+/*
+ * Copyright (c) 1994, 1995 Ignatios Souvatzis
+ * 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 Ignatios Souvatzis
+ * for the NetBSD Project.
+ * 4. 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.
+ */
+
+/*
+ * Driver for the Commodore Busines Machines ARCnet card.
+ */
+
+#define BAHASMCOPY /**/
+#define BAHSOFTCOPY /**/
+#define BAHRETRANSMIT /**/
+/* #define BAHTIMINGS */
+/* #define BAH_DEBUG 3 */
+
+/* zeroth version of M68060 support */
+
+#if defined(M68060) && defined(BAHASMCOPY)
+#undef BAHASMCOPY
+#endif
+
+#include "bpfilter.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/buf.h>
+#include <sys/device.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/syslog.h>
+#include <sys/ioctl.h>
+#include <sys/errno.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/netisr.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#include <netinet/if_arc.h>
+#endif
+
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#include <net/bpfdesc.h>
+#endif
+
+#include <sys/kernel.h>
+#include <machine/cpu.h>
+#include <machine/mtpr.h>
+
+#include <amiga/amiga/device.h>
+#include <amiga/amiga/isr.h>
+#include <amiga/dev/zbusvar.h>
+#include <amiga/dev/if_bahreg.h>
+
+/* these should be elsewhere */
+
+#define ARC_MIN_LEN 1
+#define ARC_MIN_FORBID_LEN 254
+#define ARC_MAX_FORBID_LEN 256
+#define ARC_MAX_LEN 508
+#define ARC_ADDR_LEN 1
+
+/* for watchdog timer. This should be more than enough. */
+#define ARCTIMEOUT (5*IFNET_SLOWHZ)
+
+/*
+ * This currently uses 2 bufs for tx, 2 for rx
+ *
+ * New rx protocol:
+ *
+ * rx has a fillcount variable. If fillcount > (NRXBUF-1),
+ * rx can be switched off from rx hard int.
+ * Else rx is restarted on the other receiver.
+ * rx soft int counts down. if it is == (NRXBUF-1), it restarts
+ * the receiver.
+ * To ensure packet ordering (we need that for 1201 later), we have a counter
+ * which is incremented modulo 256 on each receive and a per buffer
+ * variable, which is set to the counter on filling. The soft int can
+ * compare both values to determine the older packet.
+ *
+ * Transmit direction:
+ *
+ * bah_start checks tx_fillcount
+ * case 2: return
+ *
+ * else fill tx_act ^ 1 && inc tx_fillcount
+ *
+ * check tx_fillcount again.
+ * case 2: set IFF_OACTIVE to stop arc_output from filling us.
+ * case 1: start tx
+ *
+ * tint clears IFF_OCATIVE, decrements and checks tx_fillcount
+ * case 1: start tx on tx_act ^ 1, softcall bah_start
+ * case 0: softcall bah_start
+ *
+ * #define fill(i) get mbuf && copy mbuf to chip(i)
+ */
+
+#ifdef BAHTIMINGS
+/*
+ * ARCnet stats; per interface.
+ */
+struct bah_stats {
+ u_long mincopyin;
+ u_long maxcopyin; /* divided by byte count */
+ u_long mincopyout;
+ u_long maxcopyout;
+ u_long minsend;
+ u_long maxsend;
+ u_long lasttxstart_mics;
+ struct timeval lasttxstart_tv;
+};
+
+#error BAHTIMINGS CODE IS BROKEN; use of clkread() is bogus
+#endif
+
+/*
+ * Arcnet software status per interface
+ */
+struct bah_softc {
+ struct device sc_dev;
+ struct arccom sc_arccom; /* Common arcnet structures */
+ struct isr sc_isr;
+ struct a2060 *sc_base;
+ u_long sc_recontime; /* seconds only, I'm lazy */
+ u_long sc_reconcount; /* for the above */
+ u_long sc_reconcount_excessive; /* for the above */
+#define ARC_EXCESSIVE_RECONS 20
+#define ARC_EXCESSIVE_RECONS_REWARN 400
+ u_char sc_intmask;
+ u_char sc_rx_act; /* 2..3 */
+ u_char sc_tx_act; /* 0..1 */
+ u_char sc_rx_fillcount;
+ u_char sc_tx_fillcount;
+ u_char sc_broadcast[2]; /* is it a broadcast packet? */
+ u_char sc_retransmits[2]; /* unused at the moment */
+#ifdef BAHTIMINGS
+ struct bah_stats sc_stats;
+#endif
+};
+
+int bah_zbus_match __P((struct device *, void *, void *));
+void bah_zbus_attach __P((struct device *, struct device *, void *));
+void bah_init __P((struct bah_softc *));
+void bah_reset __P((struct bah_softc *));
+void bah_stop __P((struct bah_softc *));
+void bah_start __P((struct ifnet *));
+int bahintr __P((struct bah_softc *sc));
+int bah_ioctl __P((struct ifnet *, unsigned long, caddr_t));
+void bah_watchdog __P((int));
+void movepout __P((u_char *from, u_char __volatile *to, int len));
+void movepin __P((u_char __volatile *from, u_char *to, int len));
+void bah_srint __P((void *vsc, void *dummy));
+void callstart __P((void *vsc, void *dummy));
+
+#ifdef BAHTIMINGS
+int clkread();
+#endif
+
+struct cfattach bah_zbus_ca = {
+ sizeof(struct bah_softc), bah_zbus_match, bah_zbus_attach
+};
+
+struct cfdriver bah_cd = {
+ NULL, "bah", DV_IFNET
+};
+
+int
+bah_zbus_match(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct zbus_args *zap = aux;
+
+ if ((zap->manid == 514 || zap->manid == 1053) && zap->prodid == 9)
+ return (1);
+
+ return (0);
+}
+
+void
+bah_zbus_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct bah_softc *sc = (void *)self;
+ struct zbus_args *zap = aux;
+ struct ifnet *ifp = &sc->sc_arccom.ac_if;
+ int s, linkaddress;
+
+#if (defined(BAH_DEBUG) && (BAH_DEBUG > 2))
+ printf("\n%s: attach(0x%x, 0x%x, 0x%x)\n",
+ sc->sc_dev.dv_xname, parent, self, aux);
+#endif
+ s = splhigh();
+ sc->sc_base = zap->va;
+
+ /*
+ * read the arcnet address from the board
+ */
+
+ sc->sc_base->kick1 = 0x0;
+ sc->sc_base->kick2 = 0x0;
+ DELAY(200);
+
+ sc->sc_base->kick1 = 0xFF;
+ sc->sc_base->kick2 = 0xFF;
+ do {
+ DELAY(200);
+ } while (!(sc->sc_base->status & ARC_POR));
+
+ linkaddress = sc->sc_base->dipswitches;
+
+#ifdef BAHTIMINGS
+ printf(": link addr 0x%02x(%ld), with timer\n",
+ linkaddress, linkaddress);
+#else
+ printf(": link addr 0x%02x(%ld)\n", linkaddress, linkaddress);
+#endif
+
+ sc->sc_arccom.ac_anaddr = linkaddress;
+
+ /* clear the int mask... */
+
+ sc->sc_base->status = sc->sc_intmask = 0;
+
+ sc->sc_base->command = ARC_CONF(CONF_LONG);
+ sc->sc_base->command = ARC_CLR(CLR_POR|CLR_RECONFIG);
+ sc->sc_recontime = sc->sc_reconcount = 0;
+
+ /* and reenable kernel int level */
+ splx(s);
+
+ /*
+ * set interface to stopped condition (reset)
+ */
+ bah_stop(sc);
+
+ ifp->if_unit = sc->sc_dev.dv_unit;
+ ifp->if_name = bah_cd.cd_name;
+ ifp->if_output = arc_output;
+ ifp->if_start = bah_start;
+ ifp->if_ioctl = bah_ioctl;
+ ifp->if_timer = 0;
+ ifp->if_watchdog = bah_watchdog;
+
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX |
+ IFF_NOTRAILERS | IFF_NOARP;
+
+ ifp->if_mtu = ARCMTU;
+
+ if_attach(ifp);
+ arc_ifattach(ifp);
+
+#if NBPFILTER > 0
+ bpfattach(&ifp->if_bpf, ifp, DLT_ARCNET, ARC_HDRLEN);
+#endif
+ /* under heavy load we need four of them: */
+ alloc_sicallback();
+ alloc_sicallback();
+ alloc_sicallback();
+ alloc_sicallback();
+
+ sc->sc_isr.isr_intr = bahintr;
+ sc->sc_isr.isr_arg = sc;
+ sc->sc_isr.isr_ipl = 2;
+ add_isr(&sc->sc_isr);
+}
+
+/*
+ * Initialize device
+ *
+ */
+void
+bah_init(sc)
+ struct bah_softc *sc;
+{
+ struct ifnet *ifp;
+ int s;
+
+ ifp = &sc->sc_arccom.ac_if;
+
+ if ((ifp->if_flags & IFF_RUNNING) == 0) {
+ s = splnet();
+ ifp->if_flags |= IFF_RUNNING;
+ bah_reset(sc);
+ bah_start(ifp);
+ splx(s);
+ }
+}
+
+/*
+ * Reset the interface...
+ *
+ * this assumes that it is called inside a critical section...
+ *
+ */
+void
+bah_reset(sc)
+ struct bah_softc *sc;
+{
+ struct ifnet *ifp;
+ int linkaddress;
+
+ ifp = &sc->sc_arccom.ac_if;
+
+#ifdef BAH_DEBUG
+ printf("%s: reset\n", sc->sc_dev.dv_xname);
+#endif
+ /* stop hardware in case it still runs */
+
+ sc->sc_base->kick1 = 0;
+ sc->sc_base->kick2 = 0;
+ DELAY(200);
+
+ /* and restart it */
+ sc->sc_base->kick1 = 0xFF;
+ sc->sc_base->kick2 = 0xFF;
+
+ do {
+ DELAY(200);
+ } while (!(sc->sc_base->status & ARC_POR));
+
+ linkaddress = sc->sc_base->dipswitches;
+
+#if defined(BAH_DEBUG) && (BAH_DEBUG > 2)
+ printf("bah%ld: reset: card reset, link addr = 0x%02x (%ld)\n",
+ ifp->if_unit, linkaddress, linkaddress);
+#endif
+ sc->sc_arccom.ac_anaddr = linkaddress;
+
+ /* tell the routing level about the (possibly changed) link address */
+ arc_ifattach(ifp);
+
+ /* POR is NMI, but we need it below: */
+ sc->sc_intmask = ARC_RECON|ARC_POR;
+ sc->sc_base->status = sc->sc_intmask;
+ sc->sc_base->command = ARC_CONF(CONF_LONG);
+
+#ifdef BAH_DEBUG
+ printf("%s: reset: chip configured, status=0x%02x\n",
+ sc->sc_dev.dv_xname, sc->sc_base->status);
+#endif
+
+ sc->sc_base->command = ARC_CLR(CLR_POR|CLR_RECONFIG);
+
+#ifdef BAH_DEBUG
+ printf("%s: reset: bits cleared, status=0x%02x\n",
+ sc->sc_dev.dv_xname, sc->sc_base->status);
+#endif
+
+ sc->sc_reconcount_excessive = ARC_EXCESSIVE_RECONS;
+
+ /* start receiver */
+
+ sc->sc_intmask |= ARC_RI;
+ sc->sc_rx_fillcount = 0;
+ sc->sc_rx_act = 2;
+
+ sc->sc_base->command = ARC_RXBC(2);
+ sc->sc_base->status = sc->sc_intmask;
+
+#ifdef BAH_DEBUG
+ printf("%s: reset: started receiver, status=0x%02x\n",
+ sc->sc_dev.dv_xname, sc->sc_base->status);
+#endif
+
+ /* and init transmitter status */
+ sc->sc_tx_act = 0;
+ sc->sc_tx_fillcount = 0;
+
+ ifp->if_flags |= IFF_RUNNING;
+ ifp->if_flags &= ~IFF_OACTIVE;
+
+#ifdef BAHTIMINGS
+ bzero((caddr_t)&(sc->sc_stats), sizeof(sc->sc_stats));
+ sc->sc_stats.mincopyin =
+ sc->sc_stats.mincopyout =
+ sc->sc_stats.minsend = ULONG_MAX;
+#endif
+
+ bah_start(ifp);
+}
+
+/*
+ * Take interface offline
+ */
+void
+bah_stop(sc)
+ struct bah_softc *sc;
+{
+ /* Stop the interrupts */
+ sc->sc_base->status = 0;
+
+ /* Stop the interface */
+ sc->sc_base->kick1 = 0;
+ sc->sc_base->kick2 = 0;
+
+ /* Stop watchdog timer */
+ sc->sc_arccom.ac_if.if_timer = 0;
+
+#ifdef BAHTIMINGS
+ log(LOG_DEBUG,"%s: to board: %6lu .. %6lu ns/byte\n",
+ sc->sc_dev.dv_xname,
+ sc->sc_stats.mincopyout, sc->sc_stats.maxcopyout);
+
+ log(LOG_DEBUG,"%s: from board: %6lu .. %6lu ns/byte\n",
+ sc->sc_dev.dv_xname,
+ sc->sc_stats.mincopyin, sc->sc_stats.maxcopyin);
+
+ log(LOG_DEBUG,"%s: send time: %6lu .. %6lu mics/byte\n",
+ sc->sc_dev.dv_xname,
+ sc->sc_stats.minsend, sc->sc_stats.maxsend);
+
+ sc->sc_stats.minsend =
+ sc->sc_stats.mincopyout =
+ sc->sc_stats.mincopyin = ULONG_MAX;
+ sc->sc_stats.maxsend =
+ sc->sc_stats.maxcopyout =
+ sc->sc_stats.maxcopyin = 0;
+#endif
+}
+
+__inline void
+movepout(from, to, len)
+ u_char *from;
+ __volatile u_char *to;
+ int len;
+{
+#ifdef BAHASMCOPY
+ u_short shortd;
+ u_long longd, longd1, longd2, longd3, longd4;
+
+ if ((len > 3) && ((long)from) & 3) {
+ switch (((long)from) & 3) {
+ case 3:
+ *to = *from++;
+ to += 2; --len;
+ break;
+ case 1:
+ *to = *from++;
+ to += 2; --len;
+ case 2:
+ shortd = *((u_short *)from)++;
+ asm("movepw %0,%1@(0)" : : "d"(shortd), "a"(to));
+ to += 4; len -= 2;
+ break;
+ default:
+ }
+
+ while (len >= 32) {
+ longd1 = *((u_long *)from)++;
+ longd2 = *((u_long *)from)++;
+ longd3 = *((u_long *)from)++;
+ longd4 = *((u_long *)from)++;
+ asm("movepl %0,%1@(0)" : : "d"(longd1), "a"(to));
+ asm("movepl %0,%1@(8)" : : "d"(longd2), "a"(to));
+ asm("movepl %0,%1@(16)" : : "d"(longd3), "a"(to));
+ asm("movepl %0,%1@(24)" : : "d"(longd4), "a"(to));
+
+ longd1 = *((u_long *)from)++;
+ longd2 = *((u_long *)from)++;
+ longd3 = *((u_long *)from)++;
+ longd4 = *((u_long *)from)++;
+ asm("movepl %0,%1@(32)" : : "d"(longd1), "a"(to));
+ asm("movepl %0,%1@(40)" : : "d"(longd2), "a"(to));
+ asm("movepl %0,%1@(48)" : : "d"(longd3), "a"(to));
+ asm("movepl %0,%1@(56)" : : "d"(longd4), "a"(to));
+
+ to += 64; len -= 32;
+ }
+ while (len > 0) {
+ longd = *((u_long *)from)++;
+ asm("movepl %0,%1@(0)" : : "d"(longd), "a"(to));
+ to += 8; len -= 4;
+ }
+ }
+#endif
+ while (len > 0) {
+ *to = *from++;
+ to += 2;
+ --len;
+ }
+}
+
+/*
+ * Start output on interface. Get another datagram to send
+ * off the interface queue, and copy it to the
+ * interface becore starting the output
+ *
+ * this assumes that it is called inside a critical section...
+ * XXX hm... does it still?
+ *
+ */
+void
+bah_start(ifp)
+ struct ifnet *ifp;
+{
+ struct bah_softc *sc;
+ struct mbuf *m,*mp;
+ __volatile u_char *bah_ram_ptr;
+ int len, tlen, offset, s, buffer;
+#ifdef BAHTIMINGS
+ u_long copystart, lencopy, perbyte;
+#endif
+
+ sc = bah_cd.cd_devs[ifp->if_unit];
+
+#if defined(BAH_DEBUG) && (BAH_DEBUG > 3)
+ printf("%s: start(0x%x)\n", sc->sc_dev.dv_xname, ifp);
+#endif
+
+ if ((ifp->if_flags & IFF_RUNNING) == 0)
+ return;
+
+ s = splnet();
+
+ if (sc->sc_tx_fillcount >= 2) {
+ splx(s);
+ return;
+ }
+
+ IF_DEQUEUE(&ifp->if_snd, m);
+ buffer = sc->sc_tx_act ^ 1;
+
+ splx(s);
+
+ if (m == 0)
+ return;
+
+#if NBPFILTER > 0
+ /*
+ * If bpf is listening on this interface, let it
+ * see the packet before we commit it to the wire
+ *
+ * (can't give the copy in A2060 card RAM to bpf, because
+ * that RAM is just accessed as on every other byte)
+ */
+ if (ifp->if_bpf)
+ bpf_mtap(ifp->if_bpf, m);
+#endif
+
+#ifdef BAH_DEBUG
+ m = m_pullup(m,3); /* gcc does structure padding */
+ printf("%s: start: filling %ld from %ld to %ld type %ld\n",
+ sc->sc_dev.dv_xname, buffer, mtod(m, u_char *)[0],
+ mtod(m, u_char *)[1], mtod(m, u_char *)[2]);
+#else
+ m = m_pullup(m, 2);
+#endif
+ bah_ram_ptr = sc->sc_base->buffers + buffer*512*2;
+
+ /* write the addresses to RAM and throw them away */
+
+ /*
+ * Hardware does this: Yet Another Microsecond Saved.
+ * (btw, timing code says usually 2 microseconds)
+ * bah_ram_ptr[0*2] = mtod(m, u_char *)[0];
+ */
+ bah_ram_ptr[1 * 2] = mtod(m, u_char *)[1];
+ m_adj(m, 2);
+
+ /* get total length left at this point */
+ tlen = m->m_pkthdr.len;
+ if (tlen < ARC_MIN_FORBID_LEN) {
+ offset = 256 - tlen;
+ bah_ram_ptr[2 * 2] = offset;
+ } else {
+ bah_ram_ptr[2 * 2] = 0;
+ if (tlen <= ARC_MAX_FORBID_LEN)
+ offset = 255; /* !!! */
+ else {
+ if (tlen > ARC_MAX_LEN)
+ tlen = ARC_MAX_LEN;
+ offset = 512 - tlen;
+ }
+ bah_ram_ptr[3 * 2] = offset;
+
+ }
+ bah_ram_ptr += offset * 2;
+
+ /* lets loop through the mbuf chain */
+
+ for (mp = m; mp; mp = mp->m_next) {
+ if ((len = mp->m_len)) { /* YAMS */
+#ifdef BAHTIMINGS
+ lencopy = len;
+ copystart = clkread();
+#endif
+ movepout(mtod(mp, caddr_t), bah_ram_ptr, len);
+
+#ifdef BAHTIMINGS
+ perbyte = 1000 * (clkread() - copystart) / lencopy;
+ sc->sc_stats.mincopyout =
+ ulmin(sc->sc_stats.mincopyout, perbyte);
+ sc->sc_stats.maxcopyout =
+ ulmax(sc->sc_stats.maxcopyout, perbyte);
+#endif
+ bah_ram_ptr += len*2;
+ }
+ }
+
+ sc->sc_broadcast[buffer] = (m->m_flags & M_BCAST) != 0;
+ sc->sc_retransmits[buffer] = (m->m_flags & M_BCAST) ? 1 : 5;
+
+ /* actually transmit the packet */
+ s = splnet();
+
+ if (++sc->sc_tx_fillcount > 1) {
+ /*
+ * We are filled up to the rim. No more bufs for the moment,
+ * please.
+ */
+ ifp->if_flags |= IFF_OACTIVE;
+ } else {
+#ifdef BAH_DEBUG
+ printf("%s: start: starting transmitter on buffer %d\n",
+ sc->sc_dev.dv_xname, buffer);
+#endif
+ /* Transmitter was off, start it */
+ sc->sc_tx_act = buffer;
+
+ /*
+ * We still can accept another buf, so don't:
+ * ifp->if_flags |= IFF_OACTIVE;
+ */
+ sc->sc_intmask |= ARC_TA;
+ sc->sc_base->command = ARC_TX(buffer);
+ sc->sc_base->status = sc->sc_intmask;
+
+ sc->sc_arccom.ac_if.if_timer = ARCTIMEOUT;
+#ifdef BAHTIMINGS
+ bcopy((caddr_t)&time,
+ (caddr_t)&(sc->sc_stats.lasttxstart_tv),
+ sizeof(struct timeval));
+
+ sc->sc_stats.lasttxstart_mics = clkread();
+#endif
+ }
+ splx(s);
+ m_freem(m);
+
+ /*
+ * After 10 times reading the docs, I realized
+ * that in the case the receiver NAKs the buffer request,
+ * the hardware retries till shutdown.
+ * This is integrated now in the code above.
+ */
+
+ return;
+}
+
+void
+callstart(vsc, dummy)
+ void *vsc, *dummy;
+{
+ struct bah_softc *sc;
+
+ sc = (struct bah_softc *)vsc;
+ bah_start(&sc->sc_arccom.ac_if);
+}
+
+__inline void
+movepin(from, to, len)
+ __volatile u_char *from;
+ u_char *to;
+ int len;
+{
+#ifdef BAHASMCOPY
+ unsigned long longd, longd1, longd2, longd3, longd4;
+ ushort shortd;
+
+ if ((len > 3) && (((long)to) & 3)) {
+ switch (((long)to) & 3) {
+ case 3: *to++ = *from;
+ from += 2; --len;
+ break;
+ case 1: *to++ = *from;
+ from += 2; --len;
+ case 2: asm ("movepw %1@(0),%0": "=d" (shortd) : "a" (from));
+ *((ushort *)to)++ = shortd;
+ from += 4; len -= 2;
+ break;
+ default:
+ }
+
+ while (len >= 32) {
+ asm("movepl %1@(0),%0" : "=d"(longd1) : "a" (from));
+ asm("movepl %1@(8),%0" : "=d"(longd2) : "a" (from));
+ asm("movepl %1@(16),%0" : "=d"(longd3) : "a" (from));
+ asm("movepl %1@(24),%0" : "=d"(longd4) : "a" (from));
+ *((unsigned long *)to)++ = longd1;
+ *((unsigned long *)to)++ = longd2;
+ *((unsigned long *)to)++ = longd3;
+ *((unsigned long *)to)++ = longd4;
+
+ asm("movepl %1@(32),%0" : "=d"(longd1) : "a" (from));
+ asm("movepl %1@(40),%0" : "=d"(longd2) : "a" (from));
+ asm("movepl %1@(48),%0" : "=d"(longd3) : "a" (from));
+ asm("movepl %1@(56),%0" : "=d"(longd4) : "a" (from));
+ *((unsigned long *)to)++ = longd1;
+ *((unsigned long *)to)++ = longd2;
+ *((unsigned long *)to)++ = longd3;
+ *((unsigned long *)to)++ = longd4;
+
+ from += 64; len -= 32;
+ }
+ while (len > 0) {
+ asm("movepl %1@(0),%0" : "=d"(longd) : "a" (from));
+ *((unsigned long *)to)++ = longd;
+ from += 8; len -= 4;
+ }
+
+ }
+#endif /* BAHASMCOPY */
+ while (len > 0) {
+ *to++ = *from;
+ from += 2;
+ --len;
+ }
+
+}
+
+/*
+ * Arcnet interface receiver soft interrupt:
+ * get the stuff out of any filled buffer we find.
+ */
+void
+bah_srint(vsc, dummy)
+ void *vsc, *dummy;
+{
+ struct bah_softc *sc;
+ int buffer, len, len1, amount, offset, s, i, type;
+ u_char __volatile *bah_ram_ptr;
+ struct mbuf *m, *dst, *head;
+ struct arc_header *ah;
+ struct ifnet *ifp;
+#ifdef BAHTIMINGS
+ u_long copystart, lencopy, perbyte;
+#endif
+ sc = (struct bah_softc *)vsc;
+ ifp = &sc->sc_arccom.ac_if;
+ head = 0;
+
+ s = splnet();
+ buffer = sc->sc_rx_act ^ 1;
+ splx(s);
+
+ /* Allocate header mbuf */
+ MGETHDR(m, M_DONTWAIT, MT_DATA);
+
+ if (m == 0) {
+ /*
+ * in case s.th. goes wrong with mem, drop it
+ * to make sure the receiver can be started again
+ * count it as input error (we dont have any other
+ * detectable)
+ */
+ ifp->if_ierrors++;
+ goto cleanup;
+ }
+
+ m->m_pkthdr.rcvif = ifp;
+
+ /*
+ * Align so that IP packet will be longword aligned. Here we
+ * assume that m_data of new packet is longword aligned.
+ * When implementing PHDS, we might have to change it to 2,
+ * (2*sizeof(ulong) - ARC_HDRNEWLEN)), packet type dependent.
+ */
+
+ bah_ram_ptr = sc->sc_base->buffers + buffer*512*2;
+ offset = bah_ram_ptr[2*2];
+ if (offset)
+ len = 256 - offset;
+ else {
+ offset = bah_ram_ptr[3*2];
+ len = 512 - offset;
+ }
+ type = bah_ram_ptr[offset*2];
+ m->m_data += 1 + arc_isphds(type);
+
+ head = m;
+ ah = mtod(head, struct arc_header *);
+
+ ah->arc_shost = bah_ram_ptr[0*2];
+ ah->arc_dhost = bah_ram_ptr[1*2];
+
+ m->m_pkthdr.len = len+2; /* whole packet length */
+ m->m_len = 2; /* mbuf filled with ARCnet addresses */
+ bah_ram_ptr += offset*2; /* ram buffer continues there */
+
+ while (len > 0) {
+
+ len1 = len;
+ amount = M_TRAILINGSPACE(m);
+
+ if (amount == 0) {
+ dst = m;
+ MGET(m, M_DONTWAIT, MT_DATA);
+
+ if (m == 0) {
+ ifp->if_ierrors++;
+ goto cleanup;
+ }
+
+ if (len1 >= MINCLSIZE)
+ MCLGET(m, M_DONTWAIT);
+
+ m->m_len = 0;
+ dst->m_next = m;
+ amount = M_TRAILINGSPACE(m);
+ }
+
+ if (amount < len1)
+ len1 = amount;
+
+#ifdef BAHTIMINGS
+ lencopy = len;
+ copystart = clkread();
+#endif
+
+ movepin(bah_ram_ptr, mtod(m, u_char *) + m->m_len, len1);
+
+#ifdef BAHTIMINGS
+ perbyte = 1000 * (clkread() - copystart) / lencopy;
+ sc->sc_stats.mincopyin =
+ ulmin(sc->sc_stats.mincopyin, perbyte);
+ sc->sc_stats.maxcopyin =
+ ulmax(sc->sc_stats.maxcopyin, perbyte);
+#endif
+
+ m->m_len += len1;
+ bah_ram_ptr += len1*2;
+ len -= len1;
+ }
+
+#if NBPFILTER > 0
+ if (ifp->if_bpf)
+ bpf_mtap(ifp->if_bpf, head);
+#endif
+
+ arc_input(&sc->sc_arccom.ac_if, head);
+
+ /* arc_input has freed it, we dont need to... */
+
+ head = NULL;
+ ifp->if_ipackets++;
+
+cleanup:
+
+ if (head != NULL)
+ m_freem(head);
+
+ /* mark buffer as invalid by source id 0 */
+ sc->sc_base->buffers[buffer*512*2] = 0;
+ s = splnet();
+
+ if (--sc->sc_rx_fillcount == 2 - 1) {
+
+ /* was off, restart it on buffer just emptied */
+ sc->sc_rx_act = buffer;
+ sc->sc_intmask |= ARC_RI;
+
+ /* this also clears the RI flag interupt: */
+ sc->sc_base->command = ARC_RXBC(buffer);
+ sc->sc_base->status = sc->sc_intmask;
+
+#ifdef BAH_DEBUG
+ printf("%s: srint: restarted rx on buf %ld\n",
+ sc->sc_dev.dv_xname, buffer);
+#endif
+ }
+ splx(s);
+}
+
+__inline static void
+bah_tint(sc, isr)
+ struct bah_softc *sc;
+ int isr;
+{
+ struct ifnet *ifp;
+
+ int buffer;
+#ifdef BAHTIMINGS
+ int clknow;
+#endif
+
+ ifp = &(sc->sc_arccom.ac_if);
+ buffer = sc->sc_tx_act;
+
+ /*
+ * retransmit code:
+ * Normal situtations first for fast path:
+ * If acknowledgement received ok or broadcast, we're ok.
+ * else if
+ */
+
+ if (isr & ARC_TMA || sc->sc_broadcast[buffer])
+ sc->sc_arccom.ac_if.if_opackets++;
+#ifdef BAHRETRANSMIT
+ else if (ifp->if_flags & IFF_LINK2 && ifp->if_timer > 0
+ && --sc->sc_retransmits[buffer] > 0) {
+ /* retransmit same buffer */
+ sc->sc_base->command = ARC_TX(buffer);
+ return;
+ }
+#endif
+ else
+ ifp->if_oerrors++;
+
+
+#ifdef BAHTIMINGS
+ clknow = clkread();
+
+ sc->sc_stats.minsend = ulmin(sc->sc_stats.minsend,
+ clknow - sc->sc_stats.lasttxstart_mics);
+
+ sc->sc_stats.maxsend = ulmax(sc->sc_stats.maxsend,
+ clknow - sc->sc_stats.lasttxstart_mics);
+#endif
+
+ /* We know we can accept another buffer at this point. */
+ ifp->if_flags &= ~IFF_OACTIVE;
+
+ if (--sc->sc_tx_fillcount > 0) {
+
+ /*
+ * start tx on other buffer.
+ * This also clears the int flag
+ */
+ buffer ^= 1;
+ sc->sc_tx_act = buffer;
+
+ /*
+ * already given:
+ * sc->sc_intmask |= ARC_TA;
+ * sc->sc_base->status = sc->sc_intmask;
+ */
+ sc->sc_base->command = ARC_TX(buffer);
+ /* init watchdog timer */
+ ifp->if_timer = ARCTIMEOUT;
+
+#ifdef BAHTIMINGS
+ bcopy((caddr_t)&time,
+ (caddr_t)&(sc->sc_stats.lasttxstart_tv),
+ sizeof(struct timeval));
+
+ sc->sc_stats.lasttxstart_mics = clkread();
+#endif
+
+#if defined(BAH_DEBUG) && (BAH_DEBUG > 1)
+ printf("%s: tint: starting tx on buffer %d, status 0x%02x\n",
+ sc->sc_dev.dv_xname, buffer, sc->sc_base->status);
+#endif
+ } else {
+ /* have to disable TX interrupt */
+ sc->sc_intmask &= ~ARC_TA;
+ sc->sc_base->status = sc->sc_intmask;
+ /* ... and watchdog timer */
+ ifp->if_timer = 0;
+
+#ifdef BAH_DEBUG
+ printf("%s: tint: no more buffers to send, status 0x%02x\n",
+ sc->sc_dev.dv_xname, sc->sc_base->status);
+#endif
+ }
+
+#ifdef BAHSOFTCOPY
+ /* schedule soft int to fill a new buffer for us */
+ add_sicallback((sifunc_t)callstart, sc, NULL);
+#else
+ /* call it directly */
+ callstart(sc, NULL);
+#endif
+}
+
+/*
+ * Our interrupt routine
+ */
+int
+bahintr(sc)
+ struct bah_softc *sc;
+{
+ u_char isr, maskedisr;
+ int buffer;
+ u_long newsec;
+
+ isr = sc->sc_base->status;
+ maskedisr = isr & sc->sc_intmask;
+ if (!maskedisr)
+ return (0);
+
+#if defined(BAH_DEBUG) && (BAH_DEBUG>1)
+ printf("%s: intr: status 0x%02x, intmask 0x%02x\n",
+ sc->sc_dev.dv_xname, isr, sc->sc_intmask);
+#endif
+
+ if (maskedisr & ARC_POR) {
+ sc->sc_arccom.ac_anaddr = sc->sc_base->dipswitches;
+ sc->sc_base->command = ARC_CLR(CLR_POR);
+ log(LOG_WARNING, "%s: intr: got spurious power on reset int\n",
+ sc->sc_dev.dv_xname);
+ }
+
+ if (maskedisr & ARC_RECON) {
+ /*
+ * we dont need to:
+ * sc->sc_base->command = ARC_CONF(CONF_LONG);
+ */
+ sc->sc_base->command = ARC_CLR(CLR_RECONFIG);
+ sc->sc_arccom.ac_if.if_collisions++;
+
+ /*
+ * If more than 2 seconds per reconfig:
+ * Reset time and counter.
+ * else:
+ * If more than ARC_EXCESSIVE_RECONFIGS reconfigs
+ * since last burst, complain and set treshold for
+ * warnings to ARC_EXCESSIVE_RECONS_REWARN.
+ *
+ * This allows for, e.g., new stations on the cable, or
+ * cable switching as long as it is over after (normally)
+ * 16 seconds.
+ *
+ * XXX TODO: check timeout bits in status word and double
+ * time if necessary.
+ */
+
+ newsec = time.tv_sec;
+ if (newsec - sc->sc_recontime > 2 * sc->sc_reconcount) {
+ sc->sc_recontime = newsec;
+ sc->sc_reconcount = 0;
+ sc->sc_reconcount_excessive = ARC_EXCESSIVE_RECONS;
+ } else if (++sc->sc_reconcount > sc->sc_reconcount_excessive) {
+ sc->sc_reconcount_excessive =
+ ARC_EXCESSIVE_RECONS_REWARN;
+ log(LOG_WARNING,
+ "%s: excessive token losses, cable problem?\n",
+ sc->sc_dev.dv_xname);
+ sc->sc_recontime = newsec;
+ sc->sc_reconcount = 0;
+ }
+ }
+
+ if (maskedisr & ARC_RI) {
+
+#if defined(BAH_DEBUG) && (BAH_DEBUG > 1)
+ printf("%s: intr: hard rint, act %ld\n",
+ sc->sc_dev.dv_xname, sc->sc_rx_act);
+#endif
+
+ buffer = sc->sc_rx_act;
+ /* look if buffer is marked invalid: */
+ if (sc->sc_base->buffers[buffer*512*2] == 0) {
+ /* invalid marked buffer (or illegally configured sender) */
+ log(LOG_WARNING,
+ "%s: spurious RX interrupt or sender 0 (ignored)\n",
+ sc->sc_dev.dv_xname);
+ /*
+ * restart receiver on same buffer.
+ */
+ sc->sc_base->command = ARC_RXBC(buffer);
+
+ } else if (++sc->sc_rx_fillcount > 1) {
+ sc->sc_intmask &= ~ARC_RI;
+ sc->sc_base->status = sc->sc_intmask;
+ } else {
+
+ buffer ^= 1;
+ sc->sc_rx_act = buffer;
+
+ /*
+ * Start receiver on other receive buffer.
+ * This also clears the RI interupt flag.
+ */
+ sc->sc_base->command = ARC_RXBC(buffer);
+ /* we are in the RX intr, so mask is ok for RX */
+
+#ifdef BAH_DEBUG
+ printf("%s: started rx for buffer %ld, status 0x%02x\n",
+ sc->sc_dev.dv_xname, sc->sc_rx_act,
+ sc->sc_base->status);
+#endif
+ }
+
+#ifdef BAHSOFTCOPY
+ /* this one starts a soft int to copy out of the hw */
+ add_sicallback((sifunc_t)bah_srint, sc,NULL);
+#else
+ /* this one does the copy here */
+ bah_srint(sc,NULL);
+#endif
+ }
+
+ if (maskedisr & ARC_TA)
+ bah_tint(sc, isr);
+
+ return (1);
+}
+
+/*
+ * Process an ioctl request.
+ * This code needs some work - it looks pretty ugly.
+ */
+int
+bah_ioctl(ifp, command, data)
+ register struct ifnet *ifp;
+ u_long command;
+ caddr_t data;
+{
+ struct bah_softc *sc;
+ register struct ifaddr *ifa;
+ int s, error;
+
+ error = 0;
+ sc = bah_cd.cd_devs[ifp->if_unit];
+ ifa = (struct ifaddr *)data;
+ s = splnet();
+
+#if defined(BAH_DEBUG) && (BAH_DEBUG > 2)
+ printf("%s: ioctl() called, cmd = 0x%x\n",
+ sc->sc_dev.dv_xname, command);
+#endif
+
+ switch (command) {
+ case SIOCSIFADDR:
+ ifp->if_flags |= IFF_UP;
+ switch (ifa->ifa_addr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ bah_init(sc);
+ break;
+#endif
+ default:
+ bah_init(sc);
+ break;
+ }
+
+ case SIOCSIFFLAGS:
+ if ((ifp->if_flags & IFF_UP) == 0 &&
+ (ifp->if_flags & IFF_RUNNING) != 0) {
+ /*
+ * If interface is marked down and it is running,
+ * then stop it.
+ */
+ bah_stop(sc);
+ ifp->if_flags &= ~IFF_RUNNING;
+ } else if ((ifp->if_flags & IFF_UP) != 0 &&
+ (ifp->if_flags & IFF_RUNNING) == 0) {
+ /*
+ * If interface is marked up and it is stopped, then
+ * start it.
+ */
+ bah_init(sc);
+ }
+ break;
+
+ /* Multicast not supported */
+
+ default:
+ error = EINVAL;
+ }
+
+ splx(s);
+ return (error);
+}
+
+/*
+ * watchdog routine for transmitter.
+ *
+ * We need this, because else a receiver whose hardware is alive, but whose
+ * software has not enabled the Receiver, would make our hardware wait forever
+ * Discovered this after 20 times reading the docs.
+ *
+ * Only thing we do is disable transmitter. We'll get an transmit timeout,
+ * and the int handler will have to decide not to retransmit (in case
+ * retransmission is implemented).
+ *
+ * This one assumes being called inside splnet(), and that net >= ipl2
+ */
+
+void
+bah_watchdog(unit)
+int unit;
+{
+ struct bah_softc *sc;
+ struct ifnet *ifp;
+
+ sc = bah_cd.cd_devs[unit];
+ ifp = &(sc->sc_arccom.ac_if);
+
+ sc->sc_base->command = ARC_TXDIS;
+ return;
+}
diff --git a/sys/dev/ic/smc90cx6reg.h b/sys/dev/ic/smc90cx6reg.h
new file mode 100644
index 00000000000..f2ec2a06e5c
--- /dev/null
+++ b/sys/dev/ic/smc90cx6reg.h
@@ -0,0 +1,99 @@
+/* $NetBSD: smc90cx6reg.h,v 1.4 1995/06/07 00:16:59 cgd Exp $ */
+
+/*
+ * Copyright (c) 1994, 1995 Ignatios Souvatzis
+ * 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 Ignatios Souvatzis
+ * for the NetBSD project.
+ * 4. 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.
+ */
+
+/*
+ * The A2060/A560 card use the SMC COM90C26 Arcnet chipset.
+ * First or last 16k segment, resp., write a fifo which drives the reset line.
+ * 2nd 16k segment contains the registers.
+ * 3rd 16k segment contains the buffer RAM.
+ * All are only accessible at even addresses.
+ */
+
+/* CBM Arcnet board */
+#define MANUFACTURER_1 514
+#define PRODUCT_1 9
+
+/* Ameristar board */
+#define MANUFACTURER_2 1053
+#define PRODUCT_2 9
+
+struct a2060 {
+ volatile u_int8_t kick1;
+ u_int8_t pad1[16383];
+ volatile u_int8_t status; /* also intmask */
+ u_int8_t pad2;
+ volatile u_int8_t command;
+ u_int8_t pad3[16381];
+ volatile u_int8_t buffers[4096]; /* even bytes only */
+ u_int8_t pad4[12228];
+ volatile u_int8_t kick2;
+ u_int8_t pad5[16383];
+};
+
+#define checkbyte buffers[0]
+#define dipswitches buffers[2]
+
+/* calculate address for board b, buffer no n and offset o */
+#define BUFPTR(b,n,o) (&(b)->buffers[(n)*512+(o)*2])
+
+#define ARC_TXDIS 0x01
+#define ARC_RXDIS 0x02
+#define ARC_TX(x) (0x03 | ((x)<<3))
+#define ARC_RX(x) (0x04 | ((x)<<3))
+#define ARC_RXBC(x) (0x84 | ((x)<<3))
+
+#define ARC_CONF(x) (0x05 | (x))
+#define CLR_POR 0x08
+#define CLR_RECONFIG 0x10
+
+#define ARC_CLR(x) (0x06 | (x))
+#define CONF_LONG 0x08
+#define CONF_SHORT 0x00
+
+/*
+ * These are not in the COM90C65 docs. Derived from the arcnet.asm
+ * packet driver by Philippe Prindeville and Russel Nelson.
+ */
+
+#define ARC_LDTST(x) (0x07 | (x))
+#define TEST_ON 0x08
+#define TEST_OFF 0x00
+
+#define ARC_TA 1 /* int mask also */
+#define ARC_TMA 2
+#define ARC_RECON 4 /* int mask also */
+#define ARC_TEST 8 /* not in the COM90C65 docs (see above) */
+#define ARC_POR 0x10 /* non maskable interrupt */
+#define ARC_ET1 0x20 /* timeout value bits, normally 1 */
+#define ARC_ET2 0x40 /* timeout value bits, normally 1 */
+#define ARC_RI 0x80 /* int mask also */
diff --git a/sys/dev/ic/z8530sc.c b/sys/dev/ic/z8530sc.c
index 7b7ef11d4aa..387f2b8aaf7 100644
--- a/sys/dev/ic/z8530sc.c
+++ b/sys/dev/ic/z8530sc.c
@@ -1,4 +1,5 @@
-/* $NetBSD: z8530sc.c,v 1.1 1996/01/24 01:07:23 gwr Exp $ */
+/* $OpenBSD: z8530sc.c,v 1.2 1996/04/21 22:21:35 deraadt Exp $ */
+/* $NetBSD: z8530sc.c,v 1.3 1996/04/10 21:44:35 gwr Exp $ */
/*
* Copyright (c) 1994 Gordon W. Ross
@@ -82,7 +83,7 @@ zs_break(cs, set)
cs->cs_preg[5] &= ~ZSWR5_BREAK;
cs->cs_creg[5] &= ~ZSWR5_BREAK;
}
- ZS_WRITE(cs, 5, cs->cs_creg[5]);
+ zs_write_reg(cs, 5, cs->cs_creg[5]);
splx(s);
}
@@ -96,8 +97,8 @@ zs_getspeed(cs)
{
int tconst;
- tconst = ZS_READ(cs, 12);
- tconst |= ZS_READ(cs, 13) << 8;
+ tconst = zs_read_reg(cs, 12);
+ tconst |= zs_read_reg(cs, 13) << 8;
return (TCONST_TO_BPS(cs->cs_pclk_div16, tconst));
}
@@ -112,21 +113,20 @@ zs_iflush(cs)
for (;;) {
/* Is there input available? */
- rr0 = *(cs->cs_reg_csr);
- ZS_DELAY();
+ rr0 = zs_read_csr(cs);
if ((rr0 & ZSRR0_RX_READY) == 0)
break;
- /* Read the data. */
- c = *(cs->cs_reg_data);
- ZS_DELAY();
+ /*
+ * First read the status, because reading the data
+ * destroys the status of this char.
+ */
+ rr1 = zs_read_reg(cs, 1);
+ c = zs_read_data(cs);
- /* Need to read status register too? */
- rr1 = ZS_READ(cs, 1);
if (rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) {
/* Clear the receive error. */
- *(cs->cs_reg_csr) = ZSWR0_RESET_ERRORS;
- ZS_DELAY();
+ zs_write_csr(cs, ZSWR0_RESET_ERRORS);
}
}
}
@@ -149,8 +149,7 @@ zs_loadchannelregs(cs)
bcopy((caddr_t)cs->cs_preg, (caddr_t)cs->cs_creg, 16);
reg = cs->cs_creg; /* current regs */
- *(cs->cs_reg_csr) = ZSM_RESET_ERR; /* XXX: reset error condition */
- ZS_DELAY();
+ zs_write_csr(cs, ZSM_RESET_ERR); /* XXX: reset error condition */
#if 1
/*
@@ -161,17 +160,17 @@ zs_loadchannelregs(cs)
#endif
/* baud clock divisor, stop bits, parity */
- ZS_WRITE(cs, 4, reg[4]);
+ zs_write_reg(cs, 4, reg[4]);
/* misc. TX/RX control bits */
- ZS_WRITE(cs, 10, reg[10]);
+ zs_write_reg(cs, 10, reg[10]);
/* char size, enable (RX/TX) */
- ZS_WRITE(cs, 3, reg[3] & ~ZSWR3_RX_ENABLE);
- ZS_WRITE(cs, 5, reg[5] & ~ZSWR5_TX_ENABLE);
+ zs_write_reg(cs, 3, reg[3] & ~ZSWR3_RX_ENABLE);
+ zs_write_reg(cs, 5, reg[5] & ~ZSWR5_TX_ENABLE);
/* interrupt enables: TX, TX, STATUS */
- ZS_WRITE(cs, 1, reg[1]);
+ zs_write_reg(cs, 1, reg[1]);
#if 0
/*
@@ -182,27 +181,27 @@ zs_loadchannelregs(cs)
* and they should not be touched thereafter.
*/
/* interrupt vector */
- ZS_WRITE(cs, 2, reg[2]);
+ zs_write_reg(cs, 2, reg[2]);
/* master interrupt control */
- ZS_WRITE(cs, 9, reg[9]);
+ zs_write_reg(cs, 9, reg[9]);
#endif
/* clock mode control */
- ZS_WRITE(cs, 11, reg[11]);
+ zs_write_reg(cs, 11, reg[11]);
/* baud rate (lo/hi) */
- ZS_WRITE(cs, 12, reg[12]);
- ZS_WRITE(cs, 13, reg[13]);
+ zs_write_reg(cs, 12, reg[12]);
+ zs_write_reg(cs, 13, reg[13]);
/* Misc. control bits */
- ZS_WRITE(cs, 14, reg[14]);
+ zs_write_reg(cs, 14, reg[14]);
/* which lines cause status interrupts */
- ZS_WRITE(cs, 15, reg[15]);
+ zs_write_reg(cs, 15, reg[15]);
/* char size, enable (RX/TX)*/
- ZS_WRITE(cs, 3, reg[3]);
- ZS_WRITE(cs, 5, reg[5]);
+ zs_write_reg(cs, 3, reg[3]);
+ zs_write_reg(cs, 5, reg[5]);
}
@@ -224,16 +223,15 @@ zsc_intr_hard(arg)
register struct zsc_softc *zsc = arg;
register struct zs_chanstate *cs_a;
register struct zs_chanstate *cs_b;
- register int rval, soft;
+ register int rval;
register u_char rr3;
cs_a = &zsc->zsc_cs[0];
cs_b = &zsc->zsc_cs[1];
rval = 0;
- soft = 0;
/* Note: only channel A has an RR3 */
- rr3 = ZS_READ(cs_a, 3);
+ rr3 = zs_read_reg(cs_a, 3);
/* Handle receive interrupts first. */
if (rr3 & ZSRR3_IP_A_RX)
@@ -241,33 +239,30 @@ zsc_intr_hard(arg)
if (rr3 & ZSRR3_IP_B_RX)
(*cs_b->cs_ops->zsop_rxint)(cs_b);
+ /* Handle status interrupts (i.e. flow control). */
+ if (rr3 & ZSRR3_IP_A_STAT)
+ (*cs_a->cs_ops->zsop_stint)(cs_a);
+ if (rr3 & ZSRR3_IP_B_STAT)
+ (*cs_b->cs_ops->zsop_stint)(cs_b);
+
/* Handle transmit done interrupts. */
if (rr3 & ZSRR3_IP_A_TX)
(*cs_a->cs_ops->zsop_txint)(cs_a);
if (rr3 & ZSRR3_IP_B_TX)
(*cs_b->cs_ops->zsop_txint)(cs_b);
- /* Handle status interrupts. */
- if (rr3 & ZSRR3_IP_A_STAT)
- (*cs_a->cs_ops->zsop_stint)(cs_a);
- if (rr3 & ZSRR3_IP_B_STAT)
- (*cs_b->cs_ops->zsop_stint)(cs_b);
-
/* Clear interrupt. */
if (rr3 & (ZSRR3_IP_A_RX | ZSRR3_IP_A_TX | ZSRR3_IP_A_STAT)) {
- *(cs_a->cs_reg_csr) = ZSWR0_CLR_INTR;
- ZS_DELAY();
+ zs_write_csr(cs_a, ZSWR0_CLR_INTR);
rval |= 1;
}
if (rr3 & (ZSRR3_IP_B_RX | ZSRR3_IP_B_TX | ZSRR3_IP_B_STAT)) {
- *(cs_b->cs_reg_csr) = ZSWR0_CLR_INTR;
- ZS_DELAY();
+ zs_write_csr(cs_b, ZSWR0_CLR_INTR);
rval |= 2;
}
- if ((cs_a->cs_softreq) || (cs_b->cs_softreq))
- {
- /* This is a machine-dependent function. */
+ if ((cs_a->cs_softreq) || (cs_b->cs_softreq)) {
+ /* This is a machine-dependent function (or macro). */
zsc_req_softint(zsc);
}
@@ -284,18 +279,19 @@ zsc_intr_soft(arg)
{
register struct zsc_softc *zsc = arg;
register struct zs_chanstate *cs;
- register int req, rval, s, unit;
+ register int rval, unit;
rval = 0;
for (unit = 0; unit < 2; unit++) {
cs = &zsc->zsc_cs[unit];
- s = splzs();
- req = cs->cs_softreq;
- cs->cs_softreq = 0;
- splx(s);
-
- if (req) {
+ /*
+ * The softint flag can be safely cleared once
+ * we have decided to call the softint routine.
+ * (No need to do splzs() first.)
+ */
+ if (cs->cs_softreq) {
+ cs->cs_softreq = 0;
(*cs->cs_ops->zsop_softint)(cs);
rval = 1;
}
@@ -304,15 +300,15 @@ zsc_intr_soft(arg)
}
-static int
+static void
zsnull_intr(cs)
struct zs_chanstate *cs;
{
- ZS_WRITE(cs, 1, 0);
- ZS_WRITE(cs, 15, 0);
+ zs_write_reg(cs, 1, 0);
+ zs_write_reg(cs, 15, 0);
}
-static int
+static void
zsnull_softint(cs)
struct zs_chanstate *cs;
{
diff --git a/sys/dev/ic/z8530sc.h b/sys/dev/ic/z8530sc.h
index 57ec9c4dc91..f271fe46bde 100644
--- a/sys/dev/ic/z8530sc.h
+++ b/sys/dev/ic/z8530sc.h
@@ -1,4 +1,4 @@
-/* $NetBSD: z8530sc.h,v 1.1 1996/01/24 01:07:24 gwr Exp $ */
+/* $NetBSD: z8530sc.h,v 1.2 1996/04/10 21:44:44 gwr Exp $ */
/*
* Copyright (c) 1994 Gordon W. Ross
@@ -50,10 +50,10 @@
* Function vector - per channel
*/
struct zsops {
- int (*zsop_rxint)(); /* receive char available */
- int (*zsop_stint)(); /* external/status */
- int (*zsop_txint)(); /* xmit buffer empty */
- int (*zsop_softint)(); /* process software interrupt */
+ void (*zsop_rxint)(); /* receive char available */
+ void (*zsop_stint)(); /* external/status */
+ void (*zsop_txint)(); /* xmit buffer empty */
+ void (*zsop_softint)(); /* process software interrupt */
};
extern struct zsops zsops_null;
@@ -93,9 +93,9 @@ struct zs_chanstate {
u_char cs_heldchange; /* change pending (creg != preg) */
u_char cs_rr0; /* last rr0 processed */
+ u_char cs_rr0_new; /* rr0 saved in status interrupt. */
char cs_softreq; /* need soft interrupt call */
- char cs__spare;
};
struct zsc_softc {
diff --git a/sys/dev/ic/z8530tty.c b/sys/dev/ic/z8530tty.c
index 577a2845d51..db07810fdf9 100644
--- a/sys/dev/ic/z8530tty.c
+++ b/sys/dev/ic/z8530tty.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: z8530tty.c,v 1.2 1996/04/18 23:47:26 niklas Exp $ */
-/* $NetBSD: z8530tty.c,v 1.1 1996/01/24 01:07:25 gwr Exp $ */
+/* $OpenBSD: z8530tty.c,v 1.3 1996/04/21 22:21:46 deraadt Exp $ */
+/* $NetBSD: z8530tty.c,v 1.6 1996/04/10 21:44:47 gwr Exp $ */
/*
* Copyright (c) 1994 Gordon W. Ross
@@ -60,6 +60,7 @@
#include <sys/conf.h>
#include <sys/file.h>
#include <sys/ioctl.h>
+#include <sys/malloc.h>
#include <sys/tty.h>
#include <sys/time.h>
#include <sys/kernel.h>
@@ -86,9 +87,14 @@ extern int zs_check_kgdb();
* Note: must be a power of two!
*/
#ifndef ZSTTY_RING_SIZE
-#define ZSTTY_RING_SIZE 1024
+#define ZSTTY_RING_SIZE 2048
#endif
-#define ZSTTY_RING_MASK (ZSTTY_RING_SIZE-1)
+
+/*
+ * Make this an option variable one can patch.
+ * But be warned: this must be a power of 2!
+ */
+int zstty_rbuf_size = ZSTTY_RING_SIZE;
struct zstty_softc {
struct device zst_dev; /* required first: base device */
@@ -126,7 +132,8 @@ struct zstty_softc {
*/
u_int zst_rbget; /* ring buffer `get' index */
volatile u_int zst_rbput; /* ring buffer `put' index */
- u_short zst_rbuf[ZSTTY_RING_SIZE]; /* rr1, data pairs */
+ u_int zst_ringmask;
+ u_short *zst_rbuf; /* rr1, data pairs */
};
@@ -134,9 +141,12 @@ struct zstty_softc {
static int zstty_match(struct device *, void *, void *);
static void zstty_attach(struct device *, struct device *, void *);
-struct cfdriver zsttycd = {
- NULL, "zstty", zstty_match, zstty_attach,
- DV_TTY, sizeof(struct zstty_softc), NULL,
+struct cfattach zstty_ca = {
+ sizeof(struct zstty_softc), zstty_match, zstty_attach
+};
+
+struct cfdriver zstty_cd = {
+ NULL, "zstty", DV_TTY
};
struct zsops zsops_tty;
@@ -221,11 +231,16 @@ zstty_attach(parent, self, aux)
}
printf("\n");
- tp = zst->zst_tty = ttymalloc();
+ tp = ttymalloc();
tp->t_dev = dev;
tp->t_oproc = zsstart;
tp->t_param = zsparam;
+ zst->zst_tty = tp;
+ zst->zst_ringmask = zstty_rbuf_size - 1;
+ zst->zst_rbuf = malloc(zstty_rbuf_size * sizeof(zst->zst_rbuf[0]),
+ M_DEVBUF, M_WAITOK);
+
/*
* Hardware init
*/
@@ -244,7 +259,7 @@ zstty_attach(parent, self, aux)
reset = (channel == 0) ?
ZSWR9_A_RESET : ZSWR9_B_RESET;
s = splzs();
- ZS_WRITE(cs, 9, reset);
+ zs_write_reg(cs, 9, reset);
splx(s);
}
@@ -269,10 +284,10 @@ zstty(dev)
int unit = minor(dev);
#ifdef DIAGNOSTIC
- if (unit >= zsttycd.cd_ndevs)
+ if (unit >= zstty_cd.cd_ndevs)
panic("zstty");
#endif
- zst = zsttycd.cd_devs[unit];
+ zst = zstty_cd.cd_devs[unit];
return (zst->zst_tty);
}
@@ -293,9 +308,9 @@ zsopen(dev, flags, mode, p)
int error, s, unit;
unit = minor(dev);
- if (unit >= zsttycd.cd_ndevs)
+ if (unit >= zstty_cd.cd_ndevs)
return (ENXIO);
- zst = zsttycd.cd_devs[unit];
+ zst = zstty_cd.cd_devs[unit];
if (zst == NULL)
return (ENXIO);
tp = zst->zst_tty;
@@ -344,12 +359,10 @@ zsopen(dev, flags, mode, p)
/* Wait for carrier. */
for (;;) {
- register int rr0;
/* Might never get status intr if carrier already on. */
- rr0 = *(cs->cs_reg_csr);
- ZS_DELAY();
- if (rr0 & ZSRR0_DCD) {
+ cs->cs_rr0 = zs_read_csr(cs);
+ if (cs->cs_rr0 & ZSRR0_DCD) {
tp->t_state |= TS_CARR_ON;
break;
}
@@ -399,7 +412,7 @@ zsclose(dev, flags, mode, p)
struct zsinfo *zi;
int hup, s;
- zst = zsttycd.cd_devs[minor(dev)];
+ zst = zstty_cd.cd_devs[minor(dev)];
cs = zst->zst_cs;
tp = zst->zst_tty;
@@ -437,7 +450,7 @@ zsread(dev, uio, flags)
register struct zstty_softc *zst;
register struct tty *tp;
- zst = zsttycd.cd_devs[minor(dev)];
+ zst = zstty_cd.cd_devs[minor(dev)];
tp = zst->zst_tty;
return (linesw[tp->t_line].l_read(tp, uio, flags));
}
@@ -451,7 +464,7 @@ zswrite(dev, uio, flags)
register struct zstty_softc *zst;
register struct tty *tp;
- zst = zsttycd.cd_devs[minor(dev)];
+ zst = zstty_cd.cd_devs[minor(dev)];
tp = zst->zst_tty;
return (linesw[tp->t_line].l_write(tp, uio, flags));
}
@@ -472,7 +485,7 @@ zsioctl(dev, cmd, data, flag, p)
register struct tty *tp;
register int error, tmp;
- zst = zsttycd.cd_devs[minor(dev)];
+ zst = zstty_cd.cd_devs[minor(dev)];
cs = zst->zst_cs;
tp = zst->zst_tty;
@@ -541,7 +554,7 @@ zsstart(tp)
register struct zs_chanstate *cs;
register int s, nch;
- zst = zsttycd.cd_devs[minor(tp->t_dev)];
+ zst = zstty_cd.cd_devs[minor(tp->t_dev)];
cs = zst->zst_cs;
s = spltty();
@@ -574,9 +587,8 @@ zsstart(tp)
cs->cs_preg[1] |= ZSWR1_TIE;
cs->cs_creg[1] |= ZSWR1_TIE;
- ZS_WRITE(cs, 1, cs->cs_creg[1]);
- *(cs->cs_reg_data) = *p;
- ZS_DELAY();
+ zs_write_reg(cs, 1, cs->cs_creg[1]);
+ zs_write_data(cs, *p);
zst->zst_tba = p + 1;
zst->zst_tbc = nch - 1;
} else {
@@ -587,7 +599,7 @@ zsstart(tp)
(void) splzs();
cs->cs_preg[1] &= ~ZSWR1_TIE;
cs->cs_creg[1] &= ~ZSWR1_TIE;
- ZS_WRITE(cs, 1, cs->cs_creg[1]);
+ zs_write_reg(cs, 1, cs->cs_creg[1]);
}
out:
splx(s);
@@ -605,7 +617,7 @@ zsstop(tp, flag)
register struct zs_chanstate *cs;
register int s;
- zst = zsttycd.cd_devs[minor(tp->t_dev)];
+ zst = zstty_cd.cd_devs[minor(tp->t_dev)];
cs = zst->zst_cs;
s = splzs();
@@ -637,7 +649,7 @@ zsparam(tp, t)
register int s, bps, cflag, tconst;
u_char tmp3, tmp4, tmp5, reset;
- zst = zsttycd.cd_devs[minor(tp->t_dev)];
+ zst = zstty_cd.cd_devs[minor(tp->t_dev)];
cs = zst->zst_cs;
/*
@@ -709,9 +721,8 @@ zsparam(tp, t)
*/
tmp3 |= ZSWR3_RX_ENABLE;
if (cflag & CCTS_OFLOW) {
- if (*(cs->cs_reg_csr) & ZSRR0_DCD)
+ if (zs_read_csr(cs) & ZSRR0_DCD)
tmp3 |= ZSWR3_HFC;
- ZS_DELAY();
}
cs->cs_preg[3] = tmp3;
@@ -773,7 +784,7 @@ zs_modem(zst, onoff)
cs->cs_heldchange = 1;
} else {
cs->cs_creg[5] = (cs->cs_creg[5] | bis) & and;
- ZS_WRITE(cs, 5, cs->cs_creg[5]);
+ zs_write_reg(cs, 5, cs->cs_creg[5]);
}
}
splx(s);
@@ -788,33 +799,37 @@ zs_modem(zst, onoff)
* XXX: need to do input flow-control to avoid ring overrun.
*/
-static int
+/*
+ * receiver ready interrupt. (splzs)
+ */
+static void
zstty_rxint(cs)
register struct zs_chanstate *cs;
{
register struct zstty_softc *zst;
- register put, put_next;
+ register put, put_next, ringmask;
register u_char c, rr0, rr1;
zst = cs->cs_private;
put = zst->zst_rbput;
+ ringmask = zst->zst_ringmask;
nextchar:
- /* Read the input data ASAP. */
- c = *(cs->cs_reg_data);
- ZS_DELAY();
- /* Save the status register too. */
- rr1 = ZS_READ(cs, 1);
+ /*
+ * First read the status, because reading the received char
+ * destroys the status of this char.
+ */
+ rr1 = zs_read_reg(cs, 1);
+ c = zs_read_data(cs);
if (rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) {
/* Clear the receive error. */
- *(cs->cs_reg_csr) = ZSWR0_RESET_ERRORS;
- ZS_DELAY();
+ zs_write_csr(cs, ZSWR0_RESET_ERRORS);
}
zst->zst_rbuf[put] = (c << 8) | rr1;
- put_next = (put + 1) & ZSTTY_RING_MASK;
+ put_next = (put + 1) & ringmask;
/* Would overrun if increment makes (put==get). */
if (put_next == zst->zst_rbget) {
@@ -825,8 +840,7 @@ nextchar:
}
/* Keep reading until the FIFO is empty. */
- rr0 = *(cs->cs_reg_csr);
- ZS_DELAY();
+ rr0 = zs_read_csr(cs);
if (rr0 & ZSRR0_RX_READY)
goto nextchar;
@@ -835,63 +849,93 @@ nextchar:
/* Ask for softint() call. */
cs->cs_softreq = 1;
- return(1);
}
-static int
+/*
+ * transmitter ready interrupt. (splzs)
+ */
+static void
zstty_txint(cs)
register struct zs_chanstate *cs;
{
register struct zstty_softc *zst;
- register int count, rval;
+ register int count;
zst = cs->cs_private;
count = zst->zst_tbc;
+ /*
+ * If our transmit buffer still has data,
+ * just send the next character.
+ */
if (count > 0) {
/* Send the next char. */
- *(cs->cs_reg_data) = *zst->zst_tba++;
- ZS_DELAY();
zst->zst_tbc = --count;
- rval = 0;
- } else {
- /* Nothing more to send. */
- *(cs->cs_reg_csr) = ZSWR0_RESET_TXINT;
- ZS_DELAY();
- zst->zst_intr_flags |= INTR_TX_EMPTY;
- rval = 1; /* want softcall */
+ zs_write_data(cs, *zst->zst_tba);
+ zst->zst_tba++;
+ return;
}
- cs->cs_softreq = rval;
- return (rval);
+ zs_write_csr(cs, ZSWR0_RESET_TXINT);
+
+ /* Ask the softint routine for more output. */
+ zst->zst_intr_flags |= INTR_TX_EMPTY;
+ cs->cs_softreq = 1;
}
-static int
+/*
+ * status change interrupt. (splzs)
+ */
+static void
zstty_stint(cs)
register struct zs_chanstate *cs;
{
register struct zstty_softc *zst;
- register int rr0;
+ register struct tty *tp;
+ register u_char rr0;
zst = cs->cs_private;
+ tp = zst->zst_tty;
- rr0 = *(cs->cs_reg_csr);
- ZS_DELAY();
+ rr0 = zs_read_csr(cs);
+ zs_write_csr(cs, ZSWR0_RESET_STATUS);
- *(cs->cs_reg_csr) = ZSWR0_RESET_STATUS;
- ZS_DELAY();
+ /*
+ * The chip's hardware flow control is, as noted in zsreg.h,
+ * busted---if the DCD line goes low the chip shuts off the
+ * receiver (!). If we want hardware CTS flow control but do
+ * not have it, and carrier is now on, turn HFC on; if we have
+ * HFC now but carrier has gone low, turn it off.
+ */
+ if (rr0 & ZSRR0_DCD) {
+ if (tp->t_cflag & CCTS_OFLOW &&
+ (cs->cs_creg[3] & ZSWR3_HFC) == 0) {
+ cs->cs_creg[3] |= ZSWR3_HFC;
+ zs_write_reg(cs, 3, cs->cs_creg[3]);
+ }
+ } else {
+ if (cs->cs_creg[3] & ZSWR3_HFC) {
+ cs->cs_creg[3] &= ~ZSWR3_HFC;
+ zs_write_reg(cs, 3, cs->cs_creg[3]);
+ }
+ }
- if ((rr0 & ZSRR0_BREAK) &&
+ /*
+ * Check here for console break, so that we can abort
+ * even when interrupts are locking up the machine.
+ */
+ if ((rr0 & ZSRR0_BREAK) &&
(zst->zst_hwflags & ZS_HWFLAG_CONSOLE))
{
zs_abort();
- return (0);
+ return;
}
+ cs->cs_rr0_new = rr0;
zst->zst_intr_flags |= INTR_ST_CHECK;
+
/* Ask for softint() call. */
cs->cs_softreq = 1;
- return (1);
}
/*
@@ -911,7 +955,10 @@ zsoverrun(zst, ptime, what)
}
}
-static int
+/*
+ * Software interrupt. Called at zssoft
+ */
+static void
zstty_softint(cs)
struct zs_chanstate *cs;
{
@@ -919,24 +966,29 @@ zstty_softint(cs)
register struct linesw *line;
register struct tty *tp;
register int get, c, s;
- int intr_flags;
+ int intr_flags, ringmask;
register u_short ring_data;
register u_char rr0, rr1;
zst = cs->cs_private;
tp = zst->zst_tty;
line = &linesw[tp->t_line];
+ ringmask = zst->zst_ringmask;
/* Atomically get and clear flags. */
s = splzs();
intr_flags = zst->zst_intr_flags;
zst->zst_intr_flags = 0;
- splx(s);
+
+ /*
+ * Lower to tty priority while servicing the ring.
+ */
+ (void) spltty();
if (intr_flags & INTR_RX_OVERRUN) {
/* May turn this on again below. */
intr_flags &= ~INTR_RX_OVERRUN;
- zsoverrun(zst, "ring");
+ zsoverrun(zst, &zst->zst_rotime, "ring");
}
/*
@@ -945,7 +997,7 @@ zstty_softint(cs)
get = zst->zst_rbget;
while (get != zst->zst_rbput) {
ring_data = zst->zst_rbuf[get];
- get = (get + 1) & ZSTTY_RING_MASK;
+ get = (get + 1) & ringmask;
if (ring_data & ZSRR1_DO)
intr_flags |= INTR_RX_OVERRUN;
@@ -960,32 +1012,36 @@ zstty_softint(cs)
}
zst->zst_rbget = get;
- /* If set, it is from the loop above. */
+ /*
+ * If the overrun flag is set now, it was set while
+ * copying char/status pairs from the ring, which
+ * means this was a hardware (fifo) overrun.
+ */
if (intr_flags & INTR_RX_OVERRUN) {
- zsoverrun(zst, "fifo");
+ zsoverrun(zst, &zst->zst_fotime, "fifo");
}
if (intr_flags & INTR_TX_EMPTY) {
/*
- * Transmit done. Change registers and resume,
- * or just clear BUSY.
+ * The transmitter output buffer count is zero.
+ * If we suspended output for a "held" change,
+ * then handle that now and resume. Otherwise,
+ * try to start a new output chunk.
*/
if (cs->cs_heldchange) {
- s = splzs();
- rr0 = *(cs->cs_reg_csr);
- ZS_DELAY();
+ (void) splzs();
+ rr0 = zs_read_csr(cs);
if ((rr0 & ZSRR0_DCD) == 0)
cs->cs_preg[3] &= ~ZSWR3_HFC;
zs_loadchannelregs(cs);
- splx(s);
+ (void) spltty();
cs->cs_heldchange = 0;
-
if (zst->zst_heldtbc &&
(tp->t_state & TS_TTSTOP) == 0)
{
zst->zst_tbc = zst->zst_heldtbc - 1;
- *(cs->cs_reg_data) = *zst->zst_tba++;
- ZS_DELAY();
+ zs_write_data(cs, *zst->zst_tba);
+ zst->zst_tba++;
goto tx_resumed;
}
}
@@ -1001,31 +1057,11 @@ zstty_softint(cs)
if (intr_flags & INTR_ST_CHECK) {
/*
- * Status line change.
- *
- * The chip's hardware flow control is, as noted in zsreg.h,
- * busted---if the DCD line goes low the chip shuts off the
- * receiver (!). If we want hardware CTS flow control but do
- * not have it, and carrier is now on, turn HFC on; if we have
- * HFC now but carrier has gone low, turn it off.
+ * Status line change. HFC bit is run in
+ * hardware interrupt, to avoid locking
+ * at splzs here.
*/
- s = splzs();
- rr0 = *(cs->cs_reg_csr);
- if (rr0 & ZSRR0_DCD) {
- if (tp->t_cflag & CCTS_OFLOW &&
- (cs->cs_creg[3] & ZSWR3_HFC) == 0) {
- cs->cs_creg[3] |= ZSWR3_HFC;
- ZS_WRITE(cs, 3, cs->cs_creg[3]);
- }
- } else {
- if (cs->cs_creg[3] & ZSWR3_HFC) {
- cs->cs_creg[3] &= ~ZSWR3_HFC;
- ZS_WRITE(cs, 3, cs->cs_creg[3]);
- }
- }
- splx(s);
-
- /* Was there a change on DCD? */
+ rr0 = cs->cs_rr0_new;
if ((rr0 ^ cs->cs_rr0) & ZSRR0_DCD) {
c = ((rr0 & ZSRR0_DCD) != 0);
if (line->l_modem(tp, c) == 0)
@@ -1034,7 +1070,7 @@ zstty_softint(cs)
cs->cs_rr0 = rr0;
}
- return (1);
+ splx(s);
}
struct zsops zsops_tty = {
@@ -1043,3 +1079,4 @@ struct zsops zsops_tty = {
zstty_txint, /* xmit buffer empty */
zstty_softint, /* process software interrupt */
};
+
diff --git a/sys/dev/isa/aha.c b/sys/dev/isa/aha.c
index 4a0bb77f998..d8a95ec3f85 100644
--- a/sys/dev/isa/aha.c
+++ b/sys/dev/isa/aha.c
@@ -1,8 +1,10 @@
-/* $OpenBSD: aha.c,v 1.13 1996/03/20 01:00:35 mickey Exp $ */
-/* $NetBSD: aha1542.c,v 1.55 1995/12/24 02:31:06 mycroft Exp $ */
+/* $NetBSD: aha.c,v 1.7 1996/04/11 22:27:59 cgd Exp $ */
+
+#define AHADIAG
+#define integrate
/*
- * Copyright (c) 1994 Charles Hannum. All rights reserved.
+ * Copyright (c) 1994, 1996 Charles M. Hannum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -14,7 +16,7 @@
* 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 Charles Hannum.
+ * This product includes software developed by Charles M. Hannum.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
@@ -45,13 +47,8 @@
* functioning of this software in any circumstances.
*/
-/*
- * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
- */
-
#include <sys/types.h>
#include <sys/param.h>
-#include <sys/syslog.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/errno.h>
@@ -64,99 +61,25 @@
#include <machine/pio.h>
-#include <dev/isa/isavar.h>
-#include <dev/isa/isadmavar.h>
#include <scsi/scsi_all.h>
#include <scsi/scsiconf.h>
+#include <dev/isa/isavar.h>
+#include <dev/isa/isadmavar.h>
+#include <dev/isa/ahareg.h>
+
#ifndef DDB
#define Debugger() panic("should call debugger here (aha1542.c)")
#endif /* ! DDB */
-/* XXX fixme:
- * on i386 at least, xfers to/from user memory
- * cannot be serviced at interrupt time.
- */
-#ifdef i386
-#define VOLATILE_XS(xs) \
- ((xs)->datalen > 0 && (xs)->bp == NULL && \
- ((xs)->flags & SCSI_POLL) == 0)
-#else
-#define VOLATILE_XS(xs) 0
-#endif
-
-#undef TUNE_1542 /* if bus speed check breaks the machine, undefine it */
-
-/************************** board definitions *******************************/
-
-/*
- * I/O Port Interface
- */
-#define AHA_BASE aha->sc_iobase
-#define AHA_CTRL_STAT_PORT (AHA_BASE + 0x0) /* control & status */
-#define AHA_CMD_DATA_PORT (AHA_BASE + 0x1) /* cmds and datas */
-#define AHA_INTR_PORT (AHA_BASE + 0x2) /* Intr. stat */
-
-/*
- * AHA_CTRL_STAT bits (write)
- */
-#define AHA_HRST 0x80 /* Hardware reset */
-#define AHA_SRST 0x40 /* Software reset */
-#define AHA_IRST 0x20 /* Interrupt reset */
-#define AHA_SCRST 0x10 /* SCSI bus reset */
-
-/*
- * AHA_CTRL_STAT bits (read)
- */
-#define AHA_STST 0x80 /* Self test in Progress */
-#define AHA_DIAGF 0x40 /* Diagnostic Failure */
-#define AHA_INIT 0x20 /* Mbx Init required */
-#define AHA_IDLE 0x10 /* Host Adapter Idle */
-#define AHA_CDF 0x08 /* cmd/data out port full */
-#define AHA_DF 0x04 /* Data in port full */
-#define AHA_INVDCMD 0x01 /* Invalid command */
-
/*
- * AHA_CMD_DATA bits (write)
- */
-#define AHA_NOP 0x00 /* No operation */
-#define AHA_MBX_INIT 0x01 /* Mbx initialization */
-#define AHA_START_SCSI 0x02 /* start scsi command */
-#define AHA_START_BIOS 0x03 /* start bios command */
-#define AHA_INQUIRE 0x04 /* Adapter Inquiry */
-#define AHA_MBO_INTR_EN 0x05 /* Enable MBO available interrupt */
-#define AHA_SEL_TIMEOUT_SET 0x06 /* set selection time-out */
-#define AHA_BUS_ON_TIME_SET 0x07 /* set bus-on time */
-#define AHA_BUS_OFF_TIME_SET 0x08 /* set bus-off time */
-#define AHA_SPEED_SET 0x09 /* set transfer speed */
-#define AHA_DEV_GET 0x0a /* return installed devices */
-#define AHA_CONF_GET 0x0b /* return configuration data */
-#define AHA_TARGET_EN 0x0c /* enable target mode */
-#define AHA_SETUP_GET 0x0d /* return setup data */
-#define AHA_WRITE_CH2 0x1a /* write channel 2 buffer */
-#define AHA_READ_CH2 0x1b /* read channel 2 buffer */
-#define AHA_WRITE_FIFO 0x1c /* write fifo buffer */
-#define AHA_READ_FIFO 0x1d /* read fifo buffer */
-#define AHA_ECHO 0x1e /* Echo command data */
-#define AHA_EXT_BIOS 0x28 /* return extended bios info */
-#define AHA_MBX_ENABLE 0x29 /* enable mail box interface */
-
-/*
- * AHA_INTR_PORT bits (read)
- */
-#define AHA_ANY_INTR 0x80 /* Any interrupt */
-#define AHA_SCRD 0x08 /* SCSI reset detected */
-#define AHA_HACC 0x04 /* Command complete */
-#define AHA_MBOA 0x02 /* MBX out empty */
-#define AHA_MBIF 0x01 /* MBX in full */
-
-/*
- * Mail box defs
+ * Mail box defs etc.
+ * these could be bigger but we need the aha_softc to fit on a single page..
*/
#define AHA_MBX_SIZE 16 /* mail box size */
-#define AHA_CCB_MAX 32 /* store up to 32 CCBs at one time */
-#define CCB_HASH_SIZE 32 /* hash table size for phystokv */
+#define AHA_CCB_MAX 16 /* store up to 32 CCBs at one time */
+#define CCB_HASH_SIZE 16 /* hash table size for phystokv */
#define CCB_HASH_SHIFT 9
#define CCB_HASH(x) ((((long)(x))>>CCB_HASH_SHIFT) & (CCB_HASH_SIZE - 1))
@@ -166,165 +89,15 @@
else \
(wmb)++;
-struct aha_mbx_out {
- u_char cmd;
- u_char ccb_addr[3];
-};
-
-struct aha_mbx_in {
- u_char stat;
- u_char ccb_addr[3];
-};
-
struct aha_mbx {
struct aha_mbx_out mbo[AHA_MBX_SIZE];
struct aha_mbx_in mbi[AHA_MBX_SIZE];
+ struct aha_mbx_out *cmbo; /* Collection Mail Box out */
struct aha_mbx_out *tmbo; /* Target Mail Box out */
struct aha_mbx_in *tmbi; /* Target Mail Box in */
};
-/*
- * mbo.cmd values
- */
-#define AHA_MBO_FREE 0x0 /* MBO entry is free */
-#define AHA_MBO_START 0x1 /* MBO activate entry */
-#define AHA_MBO_ABORT 0x2 /* MBO abort entry */
-
-/*
- * mbi.stat values
- */
-#define AHA_MBI_FREE 0x0 /* MBI entry is free */
-#define AHA_MBI_OK 0x1 /* completed without error */
-#define AHA_MBI_ABORT 0x2 /* aborted ccb */
-#define AHA_MBI_UNKNOWN 0x3 /* Tried to abort invalid CCB */
-#define AHA_MBI_ERROR 0x4 /* Completed with error */
-
-/* FOR OLD VERSIONS OF THE !%$@ this may have to be 16 (yuk) */
-#define AHA_NSEG 17 /* Number of scatter gather segments <= 16 */
- /* allow 60 K i/o (min) */
-
-struct aha_ccb {
- u_char opcode;
- u_char lun:3;
- u_char data_in:1; /* must be 0 */
- u_char data_out:1; /* must be 0 */
- u_char target:3;
- u_char scsi_cmd_length;
- u_char req_sense_length;
- u_char data_length[3];
- u_char data_addr[3];
- u_char link_addr[3];
- u_char link_id;
- u_char host_stat;
- u_char target_stat;
- u_char reserved[2];
- struct scsi_generic scsi_cmd;
- struct scsi_sense_data scsi_sense;
- struct aha_scat_gath {
- u_char seg_len[3];
- u_char seg_addr[3];
- } scat_gath[AHA_NSEG];
- /*----------------------------------------------------------------*/
-#define CCB_PHYS_SIZE ((int)&((struct aha_ccb *)0)->chain)
- TAILQ_ENTRY(aha_ccb) chain;
- struct aha_ccb *nexthash;
- struct scsi_xfer *xs; /* the scsi_xfer for this cmd */
- int flags;
-#define CCB_FREE 0
-#define CCB_ACTIVE 1
-#define CCB_ABORTED 2
- struct aha_mbx_out *mbx; /* pointer to mail box */
- struct isadma_seg ccb_phys[1]; /* phys segment of this ccb */
- struct isadma_seg data_phys[AHA_NSEG]; /* phys segments of data */
- int data_nseg; /* number of phys segments of data */
-};
-
-/*
- * opcode fields
- */
-#define AHA_INITIATOR_CCB 0x00 /* SCSI Initiator CCB */
-#define AHA_TARGET_CCB 0x01 /* SCSI Target CCB */
-#define AHA_INIT_SCAT_GATH_CCB 0x02 /* SCSI Initiator with scatter gather */
-#define AHA_RESET_CCB 0x81 /* SCSI Bus reset */
-
-/*
- * aha_ccb.host_stat values
- */
-#define AHA_OK 0x00 /* cmd ok */
-#define AHA_LINK_OK 0x0a /* Link cmd ok */
-#define AHA_LINK_IT 0x0b /* Link cmd ok + int */
-#define AHA_SEL_TIMEOUT 0x11 /* Selection time out */
-#define AHA_OVER_UNDER 0x12 /* Data over/under run */
-#define AHA_BUS_FREE 0x13 /* Bus dropped at unexpected time */
-#define AHA_INV_BUS 0x14 /* Invalid bus phase/sequence */
-#define AHA_BAD_MBO 0x15 /* Incorrect MBO cmd */
-#define AHA_BAD_CCB 0x16 /* Incorrect ccb opcode */
-#define AHA_BAD_LINK 0x17 /* Not same values of LUN for links */
-#define AHA_INV_TARGET 0x18 /* Invalid target direction */
-#define AHA_CCB_DUP 0x19 /* Duplicate CCB received */
-#define AHA_INV_CCB 0x1a /* Invalid CCB or segment list */
-#define AHA_ABORTED 42
-
-struct aha_setup {
- u_char sync_neg:1;
- u_char parity:1;
- u_char:6;
- u_char speed;
- u_char bus_on;
- u_char bus_off;
- u_char num_mbx;
- u_char mbx[3];
- struct {
- u_char offset:4;
- u_char period:3;
- u_char valid:1;
- } sync[8];
- u_char disc_sts;
-};
-
-struct aha_config {
- u_char chan;
- u_char intr;
- u_char scsi_dev:3;
- u_char:5;
-};
-
-struct aha_inquire {
- u_char boardid; /* type of board */
- /* 0x31 = AHA-1540 */
- /* 0x41 = AHA-1540A/1542A/1542B */
- /* 0x42 = AHA-1640 */
- /* 0x43 = AHA-1542C */
- /* 0x44 = AHA-1542CF */
- /* 0x45 = AHA-1542CF, BIOS v2.01 */
- u_char spec_opts; /* special options ID */
- /* 0x41 = Board is standard model */
- u_char revision_1; /* firmware revision [0-9A-Z] */
- u_char revision_2; /* firmware revision [0-9A-Z] */
-};
-
-struct aha_extbios {
- u_char flags; /* Bit 3 == 1 extended bios enabled */
- u_char mailboxlock; /* mail box lock code to unlock it */
-};
-
-#define INT9 0x01
-#define INT10 0x02
-#define INT11 0x04
-#define INT12 0x08
-#define INT14 0x20
-#define INT15 0x40
-
-#define CHAN0 0x01
-#define CHAN5 0x20
-#define CHAN6 0x40
-#define CHAN7 0x80
-
-/*********************************** end of board definitions***************/
-
-#ifdef AHADEBUG
-int aha_debug = 1;
-#endif /*AHADEBUG */
+#define KVTOPHYS(x) vtophys(x)
struct aha_softc {
struct device sc_dev;
@@ -334,28 +107,40 @@ struct aha_softc {
int sc_iobase;
int sc_irq, sc_drq;
- struct aha_mbx aha_mbx; /* all the mailboxes */
- struct aha_ccb *ccbhash[CCB_HASH_SIZE];
- TAILQ_HEAD(, aha_ccb) free_ccb;
- int numccbs;
- int aha_scsi_dev; /* our scsi id */
+ char sc_model[18],
+ sc_firmware[4];
+
+ struct aha_mbx sc_mbx; /* all the mailboxes */
+#define wmbx (&sc->sc_mbx)
+ struct aha_ccb *sc_ccbhash[CCB_HASH_SIZE];
+ TAILQ_HEAD(, aha_ccb) sc_free_ccb, sc_waiting_ccb;
+ int sc_numccbs, sc_mbofull;
+ int sc_scsi_dev; /* our scsi id */
struct scsi_link sc_link;
};
-int aha_cmd(); /* XXX must be varargs to prototype */
+#ifdef AHADEBUG
+int aha_debug = 1;
+#endif /* AHADEBUG */
+
+int aha_cmd __P((int, struct aha_softc *, int, u_char *, int, u_char *));
+integrate void aha_finish_ccbs __P((struct aha_softc *));
int ahaintr __P((void *));
-void aha_free_ccb __P((struct aha_softc *, struct aha_ccb *, int));
+integrate void aha_reset_ccb __P((struct aha_softc *, struct aha_ccb *));
+void aha_free_ccb __P((struct aha_softc *, struct aha_ccb *));
+integrate void aha_init_ccb __P((struct aha_softc *, struct aha_ccb *));
struct aha_ccb *aha_get_ccb __P((struct aha_softc *, int));
struct aha_ccb *aha_ccb_phys_kv __P((struct aha_softc *, u_long));
-struct aha_mbx_out *aha_send_mbo __P((struct aha_softc *, int, struct aha_ccb *));
+void aha_queue_ccb __P((struct aha_softc *, struct aha_ccb *));
+void aha_collect_mbo __P((struct aha_softc *));
+void aha_start_ccbs __P((struct aha_softc *));
void aha_done __P((struct aha_softc *, struct aha_ccb *));
-int aha_find __P((struct aha_softc *));
+int aha_find __P((struct isa_attach_args *, struct aha_softc *));
void aha_init __P((struct aha_softc *));
+void aha_inquire_setup_information __P((struct aha_softc *));
void ahaminphys __P((struct buf *));
int aha_scsi_cmd __P((struct scsi_xfer *));
int aha_poll __P((struct aha_softc *, struct scsi_xfer *, int));
-int aha_set_bus_speed __P((struct aha_softc *));
-int aha_bus_speed_check __P((struct aha_softc *, int));
void aha_timeout __P((void *arg));
struct scsi_adapter aha_switch = {
@@ -377,64 +162,75 @@ int ahaprobe __P((struct device *, void *, void *));
void ahaattach __P((struct device *, struct device *, void *));
int ahaprint __P((void *, char *));
-struct cfdriver ahacd = {
- NULL, "aha", ahaprobe, ahaattach, DV_DULL, sizeof(struct aha_softc)
+struct cfattach aha_ca = {
+ sizeof(struct aha_softc), ahaprobe, ahaattach
+};
+
+struct cfdriver aha_cd = {
+ NULL, "aha", DV_DULL
};
#define AHA_RESET_TIMEOUT 2000 /* time to wait for reset (mSec) */
+#define AHA_ABORT_TIMEOUT 2000 /* time to wait for abort (mSec) */
/*
- * aha_cmd(aha,icnt, ocnt,wait, retval, opcode, args)
+ * aha_cmd(iobase, sc, icnt, ibuf, ocnt, obuf)
+ *
* Activate Adapter command
- * icnt: number of args (outbound bytes written after opcode)
+ * icnt: number of args (outbound bytes including opcode)
+ * ibuf: argument buffer
* ocnt: number of expected returned bytes
+ * obuf: result buffer
* wait: number of seconds to wait for response
- * retval: buffer where to place returned bytes
- * opcode: opcode AHA_NOP, AHA_MBX_INIT, AHA_START_SCSI ...
- * args: parameters
*
- * Performs an adapter command through the ports. Not to be confused
- * with a scsi command, which is read in via the dma. One of the adapter
- * commands tells it to read in a scsi command but that one is done
- * separately. This is only called during set-up.
+ * Performs an adapter command through the ports. Not to be confused with a
+ * scsi command, which is read in via the dma; one of the adapter commands
+ * tells it to read in a scsi command.
*/
int
-aha_cmd(aha, icnt, ocnt, wait, retval, opcode, args)
- struct aha_softc *aha;
- int icnt, ocnt, wait;
- u_char *retval;
- unsigned opcode;
- u_char args;
+aha_cmd(iobase, sc, icnt, ibuf, ocnt, obuf)
+ int iobase;
+ struct aha_softc *sc;
+ int icnt, ocnt;
+ u_char *ibuf, *obuf;
{
- unsigned *ic = &opcode;
- u_char oc;
- register i;
- int sts;
+ const char *name;
+ register int i;
+ int wait;
+ u_char sts;
+ u_char opcode = ibuf[0];
+
+ if (sc == NULL)
+ name = sc->sc_dev.dv_xname;
+ else
+ name = "(probe)";
/*
- * multiply the wait argument by a big constant
- * zero defaults to 1 sec..
- * all wait loops are in 50uSec cycles
+ * Calculate a reasonable timeout for the command.
*/
- if (wait)
- wait *= 20000;
- else
- wait = 20000;
+ switch (opcode) {
+ case AHA_INQUIRE_DEVICES:
+ wait = 15 * 20000;
+ break;
+ default:
+ wait = 1 * 20000;
+ break;
+ }
+
/*
* Wait for the adapter to go idle, unless it's one of
* the commands which don't need this
*/
- if (opcode != AHA_MBX_INIT && opcode != AHA_START_SCSI) {
- i = 20000; /*do this for upto about a second */
- while (--i) {
- sts = inb(AHA_CTRL_STAT_PORT);
- if (sts & AHA_IDLE)
+ if (opcode != AHA_MBO_INTR_EN) {
+ for (i = 20000; i; i--) { /* 1 sec? */
+ sts = inb(iobase + AHA_STAT_PORT);
+ if (sts & AHA_STAT_IDLE)
break;
delay(50);
}
if (!i) {
printf("%s: aha_cmd, host not idle(0x%x)\n",
- aha->sc_dev.dv_xname, sts);
+ name, sts);
return ENXIO;
}
}
@@ -443,71 +239,68 @@ aha_cmd(aha, icnt, ocnt, wait, retval, opcode, args)
* queue feeding to us.
*/
if (ocnt) {
- while ((inb(AHA_CTRL_STAT_PORT)) & AHA_DF)
- inb(AHA_CMD_DATA_PORT);
+ while ((inb(iobase + AHA_STAT_PORT)) & AHA_STAT_DF)
+ inb(iobase + AHA_DATA_PORT);
}
/*
* Output the command and the number of arguments given
* for each byte, first check the port is empty.
*/
- icnt++;
- /* include the command */
while (icnt--) {
- sts = inb(AHA_CTRL_STAT_PORT);
for (i = wait; i; i--) {
- sts = inb(AHA_CTRL_STAT_PORT);
- if (!(sts & AHA_CDF))
+ sts = inb(iobase + AHA_STAT_PORT);
+ if (!(sts & AHA_STAT_CDF))
break;
delay(50);
}
if (!i) {
- if (opcode != AHA_INQUIRE)
- printf("%s: aha_cmd, cmd/data port full\n",
- aha->sc_dev.dv_xname);
- outb(AHA_CTRL_STAT_PORT, AHA_SRST);
+ if (opcode != AHA_INQUIRE_REVISION)
+ printf("%s: aha_cmd, cmd/data port full\n", name);
+ outb(iobase + AHA_CTRL_PORT, AHA_CTRL_SRST);
return ENXIO;
}
- outb(AHA_CMD_DATA_PORT, (u_char) (*ic++));
+ outb(iobase + AHA_CMD_PORT, *ibuf++);
}
/*
* If we expect input, loop that many times, each time,
* looking for the data register to have valid data
*/
while (ocnt--) {
- sts = inb(AHA_CTRL_STAT_PORT);
for (i = wait; i; i--) {
- sts = inb(AHA_CTRL_STAT_PORT);
- if (sts & AHA_DF)
+ sts = inb(iobase + AHA_STAT_PORT);
+ if (sts & AHA_STAT_DF)
break;
delay(50);
}
if (!i) {
- if (opcode != AHA_INQUIRE)
+ if (opcode != AHA_INQUIRE_REVISION)
printf("%s: aha_cmd, cmd/data port empty %d\n",
- aha->sc_dev.dv_xname, ocnt);
- outb(AHA_CTRL_STAT_PORT, AHA_SRST);
+ name, ocnt);
+ outb(iobase + AHA_CTRL_PORT, AHA_CTRL_SRST);
return ENXIO;
}
- oc = inb(AHA_CMD_DATA_PORT);
- if (retval)
- *retval++ = oc;
+ *obuf++ = inb(iobase + AHA_DATA_PORT);
}
/*
- * Wait for the board to report a finised instruction
+ * Wait for the board to report a finished instruction.
+ * We may get an extra interrupt for the HACC signal, but this is
+ * unimportant.
*/
- i = 20000;
- while (--i) {
- sts = inb(AHA_INTR_PORT);
- if (sts & AHA_HACC)
- break;
- delay(50);
- }
- if (!i) {
- printf("%s: aha_cmd, host not finished(0x%x)\n",
- aha->sc_dev.dv_xname, sts);
- return ENXIO;
+ if (opcode != AHA_MBO_INTR_EN) {
+ for (i = 20000; i; i--) { /* 1 sec? */
+ sts = inb(iobase + AHA_INTR_PORT);
+ /* XXX Need to save this in the interrupt handler? */
+ if (sts & AHA_INTR_HACC)
+ break;
+ delay(50);
+ }
+ if (!i) {
+ printf("%s: aha_cmd, host not finished(0x%x)\n",
+ name, sts);
+ return ENXIO;
+ }
}
- outb(AHA_CTRL_STAT_PORT, AHA_IRST);
+ outb(iobase + AHA_CTRL_PORT, AHA_CTRL_IRST);
return 0;
}
@@ -522,43 +315,20 @@ ahaprobe(parent, match, aux)
struct device *parent;
void *match, *aux;
{
- struct aha_softc *aha = match;
- struct isa_attach_args *ia = aux;
+ register struct isa_attach_args *ia = aux;
#ifdef NEWCONFIG
if (ia->ia_iobase == IOBASEUNK)
return 0;
#endif
- aha->sc_iobase = ia->ia_iobase;
-
- /*
- * Try initialise a unit at this location
- * sets up dma and bus speed, loads aha->sc_irq
- */
- if (aha_find(aha) != 0)
+ /* See if there is a unit at this location. */
+ if (aha_find(ia, NULL) != 0)
return 0;
- if (ia->ia_irq != IRQUNK) {
- if (ia->ia_irq != aha->sc_irq) {
- printf("%s: irq mismatch; kernel configured %d != board configured %d\n",
- aha->sc_dev.dv_xname, ia->ia_irq, aha->sc_irq);
- return 0;
- }
- } else
- ia->ia_irq = aha->sc_irq;
-
- if (ia->ia_drq != DRQUNK) {
- if (ia->ia_drq != aha->sc_drq) {
- printf("%s: drq mismatch; kernel configured %d != board configured %d\n",
- aha->sc_dev.dv_xname, ia->ia_drq, aha->sc_drq);
- return 0;
- }
- } else
- ia->ia_drq = aha->sc_drq;
-
ia->ia_msize = 0;
ia->ia_iosize = 4;
+ /* IRQ and DRQ set by aha_find(). */
return 1;
}
@@ -567,6 +337,7 @@ ahaprint(aux, name)
void *aux;
char *name;
{
+
if (name != NULL)
printf("%s: scsibus ", name);
return UNCONF;
@@ -581,274 +352,272 @@ ahaattach(parent, self, aux)
void *aux;
{
struct isa_attach_args *ia = aux;
- struct aha_softc *aha = (void *)self;
+ struct aha_softc *sc = (void *)self;
- if (ia->ia_drq != DRQUNK)
- isadma_cascade(ia->ia_drq);
+ if (aha_find(ia, sc) != 0)
+ panic("ahaattach: aha_find of %s failed", self->dv_xname);
+ sc->sc_iobase = ia->ia_iobase;
- aha_init(aha);
- TAILQ_INIT(&aha->free_ccb);
+ if (sc->sc_drq != DRQUNK)
+ isa_dmacascade(sc->sc_drq);
+
+ aha_inquire_setup_information(sc);
+ aha_init(sc);
+ TAILQ_INIT(&sc->sc_free_ccb);
+ TAILQ_INIT(&sc->sc_waiting_ccb);
/*
* fill in the prototype scsi_link.
*/
- aha->sc_link.adapter_softc = aha;
- aha->sc_link.adapter_target = aha->aha_scsi_dev;
- aha->sc_link.adapter = &aha_switch;
- aha->sc_link.device = &aha_dev;
- aha->sc_link.openings = 2;
-
- printf("\n");
+ sc->sc_link.adapter_softc = sc;
+ sc->sc_link.adapter_target = sc->sc_scsi_dev;
+ sc->sc_link.adapter = &aha_switch;
+ sc->sc_link.device = &aha_dev;
+ sc->sc_link.openings = 2;
#ifdef NEWCONFIG
- isa_establish(&aha->sc_id, &aha->sc_dev);
+ isa_establish(&sc->sc_id, &sc->sc_dev);
#endif
- aha->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_BIO, ahaintr,
- aha, aha->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, sc->sc_irq, IST_EDGE,
+ IPL_BIO, ahaintr, sc);
/*
* ask the adapter what subunits are present
*/
- config_found(self, &aha->sc_link, ahaprint);
+ config_found(self, &sc->sc_link, ahaprint);
}
-/*
- * Catch an interrupt from the adaptor
- */
-int
-ahaintr(arg)
- void *arg;
+integrate void
+aha_finish_ccbs(sc)
+ struct aha_softc *sc;
{
- struct aha_softc *aha = arg;
struct aha_mbx_in *wmbi;
- struct aha_mbx *wmbx;
struct aha_ccb *ccb;
- u_char stat;
int i;
- int found = 0;
-#ifdef AHADEBUG
- printf("%s: ahaintr ", aha->sc_dev.dv_xname);
-#endif /*AHADEBUG */
-
- /*
- * First acknowlege the interrupt, Then if it's not telling about
- * a completed operation just return.
- */
- stat = inb(AHA_INTR_PORT);
- if ((stat & (AHA_MBOA | AHA_MBIF)) == 0) {
- outb(AHA_CTRL_STAT_PORT, AHA_IRST);
- return -1; /* XXX */
- }
+ wmbi = wmbx->tmbi;
- /* Mail box out empty? */
- if (stat & AHA_MBOA) {
- /* Disable MBO available interrupt. */
- outb(AHA_CMD_DATA_PORT, AHA_MBO_INTR_EN);
- for (i = 100000; i; i--) {
- if (!(inb(AHA_CTRL_STAT_PORT) & AHA_CDF))
- break;
- delay(10);
- }
- if (!i) {
- printf("%s: ahaintr, cmd/data port full\n",
- aha->sc_dev.dv_xname);
- outb(AHA_CTRL_STAT_PORT, AHA_SRST);
- return 1;
+ if (wmbi->stat == AHA_MBI_FREE) {
+ for (i = 0; i < AHA_MBX_SIZE; i++) {
+ if (wmbi->stat != AHA_MBI_FREE) {
+ printf("%s: mbi not in round-robin order\n",
+ sc->sc_dev.dv_xname);
+ goto AGAIN;
+ }
+ aha_nextmbx(wmbi, wmbx, mbi);
}
- outb(AHA_CMD_DATA_PORT, 0x00); /* Disable */
- wakeup(&aha->aha_mbx);
+#ifdef AHADIAGnot
+ printf("%s: mbi interrupt with no full mailboxes\n",
+ sc->sc_dev.dv_xname);
+#endif
+ return;
}
- /* Mail box in full? */
- if ((stat & AHA_MBIF) == 0)
- return 1;
- wmbx = &aha->aha_mbx;
- wmbi = wmbx->tmbi;
AGAIN:
- while (wmbi->stat != AHA_MBI_FREE) {
- ccb = aha_ccb_phys_kv(aha, _3btol(wmbi->ccb_addr));
+ do {
+ ccb = aha_ccb_phys_kv(sc, phystol(wmbi->ccb_addr));
if (!ccb) {
- wmbi->stat = AHA_MBI_FREE;
- printf("%s: BAD CCB ADDR!\n", aha->sc_dev.dv_xname);
- continue;
+ printf("%s: bad mbi ccb pointer; skipping\n",
+ sc->sc_dev.dv_xname);
+ goto next;
}
- found++;
+
+#ifdef AHADEBUG
+ if (aha_debug) {
+ u_char *cp = &ccb->scsi_cmd;
+ printf("op=%x %x %x %x %x %x\n",
+ cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
+ printf("stat %x for mbi addr = 0x%08x, ",
+ wmbi->stat, wmbi);
+ printf("ccb addr = 0x%x\n", ccb);
+ }
+#endif /* AHADEBUG */
+
switch (wmbi->stat) {
case AHA_MBI_OK:
case AHA_MBI_ERROR:
+ if ((ccb->flags & CCB_ABORT) != 0) {
+ /*
+ * If we already started an abort, wait for it
+ * to complete before clearing the CCB. We
+ * could instead just clear CCB_SENDING, but
+ * what if the mailbox was already received?
+ * The worst that happens here is that we clear
+ * the CCB a bit later than we need to. BFD.
+ */
+ goto next;
+ }
break;
case AHA_MBI_ABORT:
- ccb->host_stat = AHA_ABORTED;
- break;
-
case AHA_MBI_UNKNOWN:
- ccb = 0;
+ /*
+ * Even if the CCB wasn't found, we clear it anyway.
+ * See preceeding comment.
+ */
break;
default:
- panic("Impossible mbxi status");
- }
-#ifdef AHADEBUG
- if (aha_debug && ccb) {
- u_char *cp = &ccb->scsi_cmd;
- printf("op=%x %x %x %x %x %x\n",
- cp[0], cp[1], cp[2],
- cp[3], cp[4], cp[5]);
- printf("stat %x for mbi addr = 0x%08x, ",
- wmbi->stat, wmbi);
- printf("ccb addr = 0x%x\n", ccb);
+ printf("%s: bad mbi status %02x; skipping\n",
+ sc->sc_dev.dv_xname, wmbi->stat);
+ goto next;
}
-#endif /* AHADEBUG */
+
+ untimeout(aha_timeout, ccb);
+ aha_done(sc, ccb);
+
+ next:
wmbi->stat = AHA_MBI_FREE;
- if (ccb) {
- untimeout(aha_timeout, ccb);
- aha_done(aha, ccb);
- }
aha_nextmbx(wmbi, wmbx, mbi);
- }
- if (!found) {
- for (i = 0; i < AHA_MBX_SIZE; i++) {
- if (wmbi->stat != AHA_MBI_FREE) {
- found++;
- break;
- }
- aha_nextmbx(wmbi, wmbx, mbi);
- }
- if (!found) {
-#if 0
- printf("%s: mbi interrupt with no full mailboxes\n",
- aha->sc_dev.dv_xname);
+ } while (wmbi->stat != AHA_MBI_FREE);
+
+ wmbx->tmbi = wmbi;
+}
+
+/*
+ * Catch an interrupt from the adaptor
+ */
+int
+ahaintr(arg)
+ void *arg;
+{
+ struct aha_softc *sc = arg;
+ int iobase = sc->sc_iobase;
+ u_char sts;
+
+#ifdef AHADEBUG
+ printf("%s: ahaintr ", sc->sc_dev.dv_xname);
+#endif /*AHADEBUG */
+
+ /*
+ * First acknowlege the interrupt, Then if it's not telling about
+ * a completed operation just return.
+ */
+ sts = inb(iobase + AHA_INTR_PORT);
+ if ((sts & AHA_INTR_ANYINTR) == 0)
+ return 0;
+ outb(iobase + AHA_CTRL_PORT, AHA_CTRL_IRST);
+
+#ifdef AHADIAG
+ /* Make sure we clear CCB_SENDING before finishing a CCB. */
+ aha_collect_mbo(sc);
#endif
- } else {
- found = 0;
- goto AGAIN;
- }
+
+ /* Mail box out empty? */
+ if (sts & AHA_INTR_MBOA) {
+ struct aha_toggle toggle;
+
+ toggle.cmd.opcode = AHA_MBO_INTR_EN;
+ toggle.cmd.enable = 0;
+ aha_cmd(iobase, sc, sizeof(toggle.cmd), (u_char *)&toggle.cmd, 0,
+ (u_char *)0);
+ aha_start_ccbs(sc);
}
- wmbx->tmbi = wmbi;
- outb(AHA_CTRL_STAT_PORT, AHA_IRST);
+
+ /* Mail box in full? */
+ if (sts & AHA_INTR_MBIF)
+ aha_finish_ccbs(sc);
+
return 1;
}
+integrate void
+aha_reset_ccb(sc, ccb)
+ struct aha_softc *sc;
+ struct aha_ccb *ccb;
+{
+
+ ccb->flags = 0;
+}
+
/*
- * A ccb (and hence a mbx-out is put onto the
- * free list.
+ * A ccb is put onto the free list.
*/
void
-aha_free_ccb(aha, ccb, flags)
- struct aha_softc *aha;
+aha_free_ccb(sc, ccb)
+ struct aha_softc *sc;
struct aha_ccb *ccb;
- int flags;
{
- int s, hashnum;
- struct aha_ccb **hashccb;
+ int s;
s = splbio();
- if (ccb->ccb_phys[0].addr)
- isadma_unmap((caddr_t)ccb, CCB_PHYS_SIZE, 1, ccb->ccb_phys);
-
- /* remove from hash table */
-
- hashnum = CCB_HASH(ccb->ccb_phys[0].addr);
- hashccb = &aha->ccbhash[hashnum];
-
- while (*hashccb) {
- if ((*hashccb)->ccb_phys[0].addr == ccb->ccb_phys[0].addr) {
- *hashccb = (*hashccb)->nexthash;
- break;
- }
- hashccb = &(*hashccb)->nexthash;
- }
-
- ccb->flags = CCB_FREE;
- TAILQ_INSERT_HEAD(&aha->free_ccb, ccb, chain);
+ aha_reset_ccb(sc, ccb);
+ TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, chain);
/*
* If there were none, wake anybody waiting for one to come free,
* starting with queued entries.
*/
if (ccb->chain.tqe_next == 0)
- wakeup(&aha->free_ccb);
+ wakeup(&sc->sc_free_ccb);
splx(s);
}
-static inline void
-aha_init_ccb(aha, ccb)
- struct aha_softc *aha;
- struct aha_ccb *ccb;
-{
- bzero(ccb, sizeof(struct aha_ccb));
-}
-
-static inline void
-aha_reset_ccb(aha, ccb)
- struct aha_softc *aha;
+integrate void
+aha_init_ccb(sc, ccb)
+ struct aha_softc *sc;
struct aha_ccb *ccb;
{
+ int hashnum;
+ bzero(ccb, sizeof(struct aha_ccb));
+ /*
+ * put in the phystokv hash table
+ * Never gets taken out.
+ */
+ ccb->hashkey = KVTOPHYS(ccb);
+ hashnum = CCB_HASH(ccb->hashkey);
+ ccb->nexthash = sc->sc_ccbhash[hashnum];
+ sc->sc_ccbhash[hashnum] = ccb;
+ aha_reset_ccb(sc, ccb);
}
/*
* Get a free ccb
+ *
+ * If there are none, see if we can allocate a new one. If so, put it in
+ * the hash table too otherwise either return an error or sleep.
*/
struct aha_ccb *
-aha_get_ccb(aha, flags)
- struct aha_softc *aha;
+aha_get_ccb(sc, flags)
+ struct aha_softc *sc;
int flags;
{
struct aha_ccb *ccb;
- int hashnum, mflags, s;
+ int s;
s = splbio();
- if (flags & SCSI_NOSLEEP)
- mflags = ISADMA_MAP_BOUNCE;
- else
- mflags = ISADMA_MAP_BOUNCE | ISADMA_MAP_WAITOK;
-
/*
- * If we can and have to, sleep waiting for one
- * to come free
+ * If we can and have to, sleep waiting for one to come free
+ * but only if we can't allocate a new one.
*/
for (;;) {
- ccb = aha->free_ccb.tqh_first;
+ ccb = sc->sc_free_ccb.tqh_first;
if (ccb) {
- TAILQ_REMOVE(&aha->free_ccb, ccb, chain);
+ TAILQ_REMOVE(&sc->sc_free_ccb, ccb, chain);
break;
}
- if (aha->numccbs < AHA_CCB_MAX) {
- if (ccb = (struct aha_ccb *) malloc(sizeof(struct aha_ccb),
- M_TEMP, M_NOWAIT)) {
- aha_init_ccb(aha, ccb);
- aha->numccbs++;
- } else {
+ if (sc->sc_numccbs < AHA_CCB_MAX) {
+ ccb = (struct aha_ccb *) malloc(sizeof(struct aha_ccb),
+ M_TEMP, M_NOWAIT);
+ if (!ccb) {
printf("%s: can't malloc ccb\n",
- aha->sc_dev.dv_xname);
+ sc->sc_dev.dv_xname);
goto out;
}
+ aha_init_ccb(sc, ccb);
+ sc->sc_numccbs++;
break;
}
if ((flags & SCSI_NOSLEEP) != 0)
goto out;
- tsleep(&aha->free_ccb, PRIBIO, "ahaccb", 0);
+ tsleep(&sc->sc_free_ccb, PRIBIO, "ahaccb", 0);
}
- aha_reset_ccb(aha, ccb);
- ccb->flags = CCB_ACTIVE;
-
- if (isadma_map((caddr_t)ccb, CCB_PHYS_SIZE, ccb->ccb_phys,
- mflags | ISADMA_MAP_CONTIG) == 1) {
- hashnum = CCB_HASH(ccb->ccb_phys[0].addr);
- ccb->nexthash = aha->ccbhash[hashnum];
- aha->ccbhash[hashnum] = ccb;
- } else {
- ccb->ccb_phys[0].addr = 0;
- aha_free_ccb(aha, ccb, flags);
- ccb = 0;
- }
+ ccb->flags |= CCB_ALLOC;
out:
splx(s);
@@ -856,74 +625,116 @@ out:
}
/*
- * given a physical address, find the ccb that it corresponds to.
+ * Given a physical address, find the ccb that it corresponds to.
*/
struct aha_ccb *
-aha_ccb_phys_kv(aha, ccb_phys)
- struct aha_softc *aha;
+aha_ccb_phys_kv(sc, ccb_phys)
+ struct aha_softc *sc;
u_long ccb_phys;
{
int hashnum = CCB_HASH(ccb_phys);
- struct aha_ccb *res = aha->ccbhash[hashnum];
+ struct aha_ccb *ccb = sc->sc_ccbhash[hashnum];
- while (res) {
- if (res->ccb_phys[0].addr == ccb_phys)
+ while (ccb) {
+ if (ccb->hashkey == ccb_phys)
break;
- res = res->nexthash;
+ ccb = ccb->nexthash;
}
+ return ccb;
+}
- return res;
+/*
+ * Queue a CCB to be sent to the controller, and send it if possible.
+ */
+void
+aha_queue_ccb(sc, ccb)
+ struct aha_softc *sc;
+ struct aha_ccb *ccb;
+{
+
+ TAILQ_INSERT_TAIL(&sc->sc_waiting_ccb, ccb, chain);
+ aha_start_ccbs(sc);
}
/*
- * Get a mbo and send the ccb.
+ * Garbage collect mailboxes that are no longer in use.
*/
-struct aha_mbx_out *
-aha_send_mbo(aha, cmd, ccb)
- struct aha_softc *aha;
- int cmd;
+void
+aha_collect_mbo(sc)
+ struct aha_softc *sc;
+{
+ struct aha_mbx_out *wmbo; /* Mail Box Out pointer */
struct aha_ccb *ccb;
+
+ wmbo = wmbx->cmbo;
+
+ while (sc->sc_mbofull > 0) {
+ if (wmbo->cmd != AHA_MBO_FREE)
+ break;
+
+#ifdef AHADIAG
+ ccb = aha_ccb_phys_kv(sc, phystol(wmbo->ccb_addr));
+ ccb->flags &= ~CCB_SENDING;
+#endif
+
+ --sc->sc_mbofull;
+ aha_nextmbx(wmbo, wmbx, mbo);
+ }
+
+ wmbx->cmbo = wmbo;
+}
+
+/*
+ * Send as many CCBs as we have empty mailboxes for.
+ */
+void
+aha_start_ccbs(sc)
+ struct aha_softc *sc;
{
+ int iobase = sc->sc_iobase;
struct aha_mbx_out *wmbo; /* Mail Box Out pointer */
- struct aha_mbx *wmbx; /* Mail Box pointer specified unit */
+ struct aha_ccb *ccb;
int i;
- /* Get the target out mail box pointer and increment. */
- wmbx = &aha->aha_mbx;
wmbo = wmbx->tmbo;
- aha_nextmbx(wmbx->tmbo, wmbx, mbo);
- /*
- * Check the outmail box is free or not.
- * Note: Under the normal operation, it shuld NOT happen to wait.
- */
- while (wmbo->cmd != AHA_MBO_FREE) {
- /* Enable mbo available interrupt. */
- outb(AHA_CMD_DATA_PORT, AHA_MBO_INTR_EN);
- for (i = 100000; i; i--) {
- if (!(inb(AHA_CTRL_STAT_PORT) & AHA_CDF))
+ while (ccb = sc->sc_waiting_ccb.tqh_first) {
+ if (sc->sc_mbofull >= AHA_MBX_SIZE) {
+ aha_collect_mbo(sc);
+ if (sc->sc_mbofull >= AHA_MBX_SIZE) {
+ struct aha_toggle toggle;
+
+ toggle.cmd.opcode = AHA_MBO_INTR_EN;
+ toggle.cmd.enable = 1;
+ aha_cmd(iobase, sc, sizeof(toggle.cmd),
+ (u_char *)&toggle.cmd, 0, (u_char *)0);
break;
- delay(10);
- }
- if (!i) {
- printf("%s: aha_send_mbo, cmd/data port full\n",
- aha->sc_dev.dv_xname);
- outb(AHA_CTRL_STAT_PORT, AHA_SRST);
- return NULL;
+ }
}
- outb(AHA_CMD_DATA_PORT, 0x01); /* Enable */
- tsleep(wmbx, PRIBIO, "ahasnd", 0);/*XXX can't do this */
- }
- /* Link ccb to mbo. */
- lto3b(ccb->ccb_phys[0].addr, wmbo->ccb_addr);
- ccb->mbx = wmbo;
- wmbo->cmd = cmd;
+ TAILQ_REMOVE(&sc->sc_waiting_ccb, ccb, chain);
+#ifdef AHADIAG
+ ccb->flags |= CCB_SENDING;
+#endif
+
+ /* Link ccb to mbo. */
+ ltophys(KVTOPHYS(ccb), wmbo->ccb_addr);
+ if (ccb->flags & CCB_ABORT)
+ wmbo->cmd = AHA_MBO_ABORT;
+ else
+ wmbo->cmd = AHA_MBO_START;
- /* Sent it! */
- outb(AHA_CMD_DATA_PORT, AHA_START_SCSI);
+ /* Tell the card to poll immediately. */
+ outb(iobase + AHA_CMD_PORT, AHA_START_SCSI);
- return wmbo;
+ if ((ccb->xs->flags & SCSI_POLL) == 0)
+ timeout(aha_timeout, ccb, (ccb->timeout * hz) / 1000);
+
+ ++sc->sc_mbofull;
+ aha_nextmbx(wmbo, wmbx, mbo);
+ }
+
+ wmbx->tmbo = wmbo;
}
/*
@@ -932,8 +743,8 @@ aha_send_mbo(aha, cmd, ccb)
* went. Wake up the owner if waiting
*/
void
-aha_done(aha, ccb)
- struct aha_softc *aha;
+aha_done(sc, ccb)
+ struct aha_softc *sc;
struct aha_ccb *ccb;
{
struct scsi_sense_data *s1, *s2;
@@ -944,23 +755,29 @@ aha_done(aha, ccb)
* Otherwise, put the results of the operation
* into the xfer and call whoever started it
*/
- if ((xs->flags & INUSE) == 0) {
- printf("%s: exiting but not in use!\n", aha->sc_dev.dv_xname);
+#ifdef AHADIAG
+ if (ccb->flags & CCB_SENDING) {
+ printf("%s: exiting ccb still in transit!\n", sc->sc_dev.dv_xname);
+ Debugger();
+ return;
+ }
+#endif
+ if ((ccb->flags & CCB_ALLOC) == 0) {
+ printf("%s: exiting ccb not allocated!\n", sc->sc_dev.dv_xname);
Debugger();
+ return;
}
if (xs->error == XS_NOERROR) {
if (ccb->host_stat != AHA_OK) {
switch (ccb->host_stat) {
- case AHA_ABORTED:
- xs->error = XS_DRIVER_STUFFUP;
- break;
case AHA_SEL_TIMEOUT: /* No response */
xs->error = XS_SELTIMEOUT;
break;
default: /* Other scsi protocol messes */
printf("%s: host_stat %x\n",
- aha->sc_dev.dv_xname, ccb->host_stat);
+ sc->sc_dev.dv_xname, ccb->host_stat);
xs->error = XS_DRIVER_STUFFUP;
+ break;
}
} else if (ccb->target_stat != SCSI_OK) {
switch (ccb->target_stat) {
@@ -976,27 +793,15 @@ aha_done(aha, ccb)
break;
default:
printf("%s: target_stat %x\n",
- aha->sc_dev.dv_xname, ccb->target_stat);
+ sc->sc_dev.dv_xname, ccb->target_stat);
xs->error = XS_DRIVER_STUFFUP;
+ break;
}
} else
xs->resid = 0;
}
+ aha_free_ccb(sc, ccb);
xs->flags |= ITSDONE;
-
- if (VOLATILE_XS(xs)) {
- wakeup(ccb);
- return;
- }
-
- if (ccb->data_nseg) {
- if (xs->flags & SCSI_DATA_IN)
- isadma_copyfrombuf(xs->data, xs->datalen,
- ccb->data_nseg, ccb->data_phys);
- isadma_unmap(xs->data, xs->datalen,
- ccb->data_nseg, ccb->data_phys);
- }
- aha_free_ccb(aha, ccb, xs->flags);
scsi_done(xs);
}
@@ -1004,147 +809,108 @@ aha_done(aha, ccb)
* Find the board and find its irq/drq
*/
int
-aha_find(aha)
- struct aha_softc *aha;
+aha_find(ia, sc)
+ struct isa_attach_args *ia;
+ struct aha_softc *sc;
{
- volatile int i, sts;
- struct aha_config conf;
- struct aha_inquire inquire;
- struct aha_extbios extbios;
+ int iobase = ia->ia_iobase;
+ int i;
+ u_char sts;
+ struct aha_config config;
+ int irq, drq;
/*
* reset board, If it doesn't respond, assume
* that it's not there.. good for the probe
*/
- outb(AHA_CTRL_STAT_PORT, AHA_HRST | AHA_SRST);
+ outb(iobase + AHA_CTRL_PORT, AHA_CTRL_HRST | AHA_CTRL_SRST);
+ delay(100);
for (i = AHA_RESET_TIMEOUT; i; i--) {
- sts = inb(AHA_CTRL_STAT_PORT);
- if (sts == (AHA_IDLE | AHA_INIT))
+ sts = inb(iobase + AHA_STAT_PORT);
+ if (sts == (AHA_STAT_IDLE | AHA_STAT_INIT))
break;
delay(1000); /* calibrated in msec */
}
if (!i) {
-#ifdef AHADEBUG
+#ifdef AHADEBUG
if (aha_debug)
printf("aha_find: No answer from adaptec board\n");
-#endif /*AHADEBUG */
- return ENXIO;
- }
-
- /*
- * Assume we have a board at this stage, do an adapter inquire
- * to find out what type of controller it is. If the command
- * fails, we assume it's either a crusty board or an old 1542
- * clone, and skip the board-specific stuff.
- */
- if (aha_cmd(aha, 0, sizeof(inquire), 1, &inquire, AHA_INQUIRE)) {
- /*
- * aha_cmd() already started the reset. It's not clear we
- * even need to bother here.
- */
- for (i = AHA_RESET_TIMEOUT; i; i--) {
- sts = inb(AHA_CTRL_STAT_PORT);
- if (sts == (AHA_IDLE | AHA_INIT))
- break;
- delay(1000);
- }
- if (!i) {
-#ifdef AHADEBUG
- printf("aha_init: soft reset failed\n");
-#endif /* AHADEBUG */
- return ENXIO;
- }
-#ifdef AHADEBUG
- printf("aha_init: inquire command failed\n");
#endif /* AHADEBUG */
- goto noinquire;
- }
-#ifdef AHADEBUG
- printf("%s: inquire %x, %x, %x, %x\n",
- aha->sc_dev.dv_xname,
- inquire.boardid, inquire.spec_opts,
- inquire.revision_1, inquire.revision_2);
-#endif /* AHADEBUG */
- /*
- * If we are a 1542C or 1542CF disable the extended bios so that the
- * mailbox interface is unlocked.
- * No need to check the extended bios flags as some of the
- * extensions that cause us problems are not flagged in that byte.
- */
- if (inquire.boardid == 0x43 || inquire.boardid == 0x44 ||
- inquire.boardid == 0x45) {
- aha_cmd(aha, 0, sizeof(extbios), 0, &extbios, AHA_EXT_BIOS);
-#ifdef AHADEBUG
- printf("%s: extended bios flags %x\n", aha->sc_dev.dv_xname,
- extbios.flags);
-#endif /* AHADEBUG */
- printf("%s: 1542C/CF detected, unlocking mailbox\n",
- aha->sc_dev.dv_xname);
- aha_cmd(aha, 2, 0, 0, 0, AHA_MBX_ENABLE,
- 0, extbios.mailboxlock);
+ return 1;
}
-noinquire:
/*
* setup dma channel from jumpers and save int
* level
*/
delay(1000); /* for Bustek 545 */
- aha_cmd(aha, 0, sizeof(conf), 0, &conf, AHA_CONF_GET);
- switch (conf.chan) {
+ config.cmd.opcode = AHA_INQUIRE_CONFIG;
+ aha_cmd(iobase, sc, sizeof(config.cmd), (u_char *)&config.cmd,
+ sizeof(config.reply), (u_char *)&config.reply);
+ switch (config.reply.chan) {
+ case EISADMA:
+ drq = DRQUNK; /* for EISA/VLB/PCI clones */
+ break;
case CHAN0:
- aha->sc_drq = 0;
+ drq = 0;
break;
case CHAN5:
- aha->sc_drq = 5;
+ drq = 5;
break;
case CHAN6:
- aha->sc_drq = 6;
+ drq = 6;
break;
case CHAN7:
- aha->sc_drq = 7;
+ drq = 7;
break;
default:
- printf("%s: illegal drq setting %x\n", aha->sc_dev.dv_xname,
- conf.chan);
- return EIO;
+ printf("aha_find: illegal drq setting %x\n", config.reply.chan);
+ return 1;
}
- switch (conf.intr) {
+ switch (config.reply.intr) {
case INT9:
- aha->sc_irq = 9;
+ irq = 9;
break;
case INT10:
- aha->sc_irq = 10;
+ irq = 10;
break;
case INT11:
- aha->sc_irq = 11;
+ irq = 11;
break;
case INT12:
- aha->sc_irq = 12;
+ irq = 12;
break;
case INT14:
- aha->sc_irq = 14;
+ irq = 14;
break;
case INT15:
- aha->sc_irq = 15;
+ irq = 15;
break;
default:
- printf("%s: illegal irq setting %x\n", aha->sc_dev.dv_xname,
- conf.intr);
+ printf("aha_find: illegal irq setting %x\n", config.reply.intr);
return EIO;
}
- /* who are we on the scsi bus? */
- aha->aha_scsi_dev = conf.scsi_dev;
+ if (sc != NULL) {
+ /* who are we on the scsi bus? */
+ sc->sc_scsi_dev = config.reply.scsi_dev;
- /*
- * Change the bus on/off times to not clash with other dma users.
- */
- aha_cmd(aha, 1, 0, 0, 0, AHA_BUS_ON_TIME_SET, 7);
- aha_cmd(aha, 1, 0, 0, 0, AHA_BUS_OFF_TIME_SET, 4);
+ sc->sc_iobase = iobase;
+ sc->sc_irq = irq;
+ sc->sc_drq = drq;
+ } else {
+ if (ia->ia_irq == IRQUNK)
+ ia->ia_irq = irq;
+ else if (ia->ia_irq != irq)
+ return 1;
+ if (ia->ia_drq == DRQUNK)
+ ia->ia_drq = drq;
+ else if (ia->ia_drq != drq)
+ return 1;
+ }
return 0;
}
@@ -1153,43 +919,176 @@ noinquire:
* Start the board, ready for normal operation
*/
void
-aha_init(aha)
- struct aha_softc *aha;
+aha_init(sc)
+ struct aha_softc *sc;
{
- u_char ad[3];
- struct isadma_seg mbx_phys[1];
+ int iobase = sc->sc_iobase;
+ struct aha_devices devices;
+ struct aha_setup setup;
+ struct aha_mailbox mailbox;
int i;
-#ifdef TUNE_1542
/*
- * Initialize memory transfer speed
- * Not compiled in by default because it breaks some machines
+ * XXX
+ * If we are a 1542C or later, disable the extended BIOS so that the
+ * mailbox interface is unlocked.
+ * No need to check the extended BIOS flags as some of the
+ * extensions that cause us problems are not flagged in that byte.
*/
- if (!aha_set_bus_speed(aha))
- panic("aha_init: cannot set bus speed");
-#endif /* TUNE_1542 */
+ if (!strncmp(sc->sc_model, "1542C", 5)) {
+ struct aha_extbios extbios;
+ struct aha_unlock unlock;
+
+ printf("%s: unlocking mailbox interface\n", sc->sc_dev.dv_xname);
+ extbios.cmd.opcode = AHA_EXT_BIOS;
+ aha_cmd(iobase, sc, sizeof(extbios.cmd), (u_char *)&extbios.cmd,
+ sizeof(extbios.reply), (u_char *)&extbios.reply);
+
+#ifdef AHADEBUG
+ printf("%s: flags=%02x, mailboxlock=%02x\n",
+ sc->sc_dev.dv_xname,
+ extbios.reply.flags, extbios.reply.mailboxlock);
+#endif /* AHADEBUG */
+ unlock.cmd.opcode = AHA_MBX_ENABLE;
+ unlock.cmd.junk = 0;
+ unlock.cmd.magic = extbios.reply.mailboxlock;
+ aha_cmd(iobase, sc, sizeof(unlock.cmd), (u_char *)&unlock.cmd,
+ 0, (u_char *)0);
+ }
+
+#if 0
/*
- * Initialize mail box. This mapping will never be undone.
+ * Change the bus on/off times to not clash with other dma users.
*/
- if (isadma_map((caddr_t)(&aha->aha_mbx), sizeof(struct aha_mbx),
- mbx_phys, ISADMA_MAP_CONTIG) != 1)
- panic("aha_init: cannot map mail box");
- lto3b(mbx_phys[0].addr, ad);
+ aha_cmd(sc, 1, 0, 0, 0, AHA_BUS_ON_TIME_SET, 7);
+ aha_cmd(sc, 1, 0, 0, 0, AHA_BUS_OFF_TIME_SET, 4);
+#endif
- aha_cmd(aha, 4, 0, 0, 0, AHA_MBX_INIT, AHA_MBX_SIZE,
- ad[0], ad[1], ad[2]);
+ /* Inquire Installed Devices (to force synchronous negotiation). */
+ devices.cmd.opcode = AHA_INQUIRE_DEVICES;
+ aha_cmd(iobase, sc, sizeof(devices.cmd), (u_char *)&devices.cmd,
+ sizeof(devices.reply), (u_char *)&devices.reply);
+
+ /* Obtain setup information from. */
+ setup.cmd.opcode = AHA_INQUIRE_SETUP;
+ setup.cmd.len = sizeof(setup.reply);
+ aha_cmd(iobase, sc, sizeof(setup.cmd), (u_char *)&setup.cmd,
+ sizeof(setup.reply), (u_char *)&setup.reply);
+
+ printf("%s: %s, %s\n",
+ sc->sc_dev.dv_xname,
+ setup.reply.sync_neg ? "sync" : "async",
+ setup.reply.parity ? "parity" : "no parity");
+
+ for (i = 0; i < 8; i++) {
+ if (!setup.reply.sync[i].valid ||
+ (!setup.reply.sync[i].offset && !setup.reply.sync[i].period))
+ continue;
+ printf("%s targ %d: sync, offset %d, period %dnsec\n",
+ sc->sc_dev.dv_xname, i,
+ setup.reply.sync[i].offset, setup.reply.sync[i].period * 50 + 200);
+ }
+ /*
+ * Set up initial mail box for round-robin operation.
+ */
for (i = 0; i < AHA_MBX_SIZE; i++) {
- aha->aha_mbx.mbo[i].cmd = AHA_MBO_FREE;
- aha->aha_mbx.mbi[i].stat = AHA_MBO_FREE;
+ wmbx->mbo[i].cmd = AHA_MBO_FREE;
+ wmbx->mbi[i].stat = AHA_MBO_FREE;
}
+ wmbx->cmbo = wmbx->tmbo = &wmbx->mbo[0];
+ wmbx->tmbi = &wmbx->mbi[0];
+ sc->sc_mbofull = 0;
+
+ /* Initialize mail box. */
+ mailbox.cmd.opcode = AHA_MBX_INIT;
+ mailbox.cmd.nmbx = AHA_MBX_SIZE;
+ ltophys(KVTOPHYS(wmbx), mailbox.cmd.addr);
+ aha_cmd(iobase, sc, sizeof(mailbox.cmd), (u_char *)&mailbox.cmd,
+ 0, (u_char *)0);
+}
+
+void
+aha_inquire_setup_information(sc)
+ struct aha_softc *sc;
+{
+ int iobase = sc->sc_iobase;
+ struct aha_revision revision;
+ u_char sts;
+ int i;
+ char *p;
+
+ strcpy(sc->sc_model, "unknown");
/*
- * Set up initial mail box for round-robin operation.
+ * Assume we have a board at this stage, do an adapter inquire
+ * to find out what type of controller it is. If the command
+ * fails, we assume it's either a crusty board or an old 1542
+ * clone, and skip the board-specific stuff.
*/
- aha->aha_mbx.tmbo = &aha->aha_mbx.mbo[0];
- aha->aha_mbx.tmbi = &aha->aha_mbx.mbi[0];
+ revision.cmd.opcode = AHA_INQUIRE_REVISION;
+ if (aha_cmd(iobase, sc, sizeof(revision.cmd), (u_char *)&revision.cmd,
+ sizeof(revision.reply), (u_char *)&revision.reply)) {
+ /*
+ * aha_cmd() already started the reset. It's not clear we
+ * even need to bother here.
+ */
+ for (i = AHA_RESET_TIMEOUT; i; i--) {
+ sts = inb(iobase + AHA_STAT_PORT);
+ if (sts == (AHA_STAT_IDLE | AHA_STAT_INIT))
+ break;
+ delay(1000);
+ }
+ if (!i) {
+#ifdef AHADEBUG
+ printf("aha_init: soft reset failed\n");
+#endif /* AHADEBUG */
+ return;
+ }
+#ifdef AHADEBUG
+ printf("aha_init: inquire command failed\n");
+#endif /* AHADEBUG */
+ goto noinquire;
+ }
+
+#ifdef AHADEBUG
+ printf("%s: inquire %x, %x, %x, %x\n",
+ sc->sc_dev.dv_xname,
+ revision.reply.boardid, revision.reply.spec_opts,
+ revision.reply.revision_1, revision.reply.revision_2);
+#endif /* AHADEBUG */
+
+ switch (revision.reply.boardid) {
+ case 0x31:
+ strcpy(sc->sc_model, "1540");
+ break;
+ case 0x41:
+ strcpy(sc->sc_model, "1540A/1542A/1542B");
+ break;
+ case 0x42:
+ strcpy(sc->sc_model, "1640");
+ break;
+ case 0x43:
+ strcpy(sc->sc_model, "1542C");
+ break;
+ case 0x44:
+ case 0x45:
+ strcpy(sc->sc_model, "1542CF");
+ break;
+ case 0x46:
+ strcpy(sc->sc_model, "1542CP");
+ break;
+ }
+
+ p = sc->sc_firmware;
+ *p++ = revision.reply.revision_1;
+ *p++ = '.';
+ *p++ = revision.reply.revision_2;
+ *p = '\0';
+
+noinquire:
+ printf(": model AHA-%s, firmware %s\n", sc->sc_model, sc->sc_firmware);
}
void
@@ -1211,12 +1110,13 @@ aha_scsi_cmd(xs)
struct scsi_xfer *xs;
{
struct scsi_link *sc_link = xs->sc_link;
- struct aha_softc *aha = sc_link->adapter_softc;
+ struct aha_softc *sc = sc_link->adapter_softc;
struct aha_ccb *ccb;
struct aha_scat_gath *sg;
- int seg, datalen, flags, mflags;
+ int seg; /* scatter gather seg being worked on */
+ u_long thiskv, thisphys, nextphys;
+ int bytes_this_seg, bytes_this_page, datalen, flags;
struct iovec *iovp;
- struct aha_mbx_out *mbo;
int s;
SC_DEBUG(sc_link, SDEV_DB2, ("aha_scsi_cmd\n"));
@@ -1226,44 +1126,28 @@ aha_scsi_cmd(xs)
* then we can't allow it to sleep
*/
flags = xs->flags;
- if (flags & SCSI_NOSLEEP)
- mflags = ISADMA_MAP_BOUNCE;
- else
- mflags = ISADMA_MAP_BOUNCE | ISADMA_MAP_WAITOK;
- if ((flags & (ITSDONE|INUSE)) != INUSE) {
- printf("%s: done or not in use?\n", aha->sc_dev.dv_xname);
- xs->flags &= ~ITSDONE;
- xs->flags |= INUSE;
- }
- if ((ccb = aha_get_ccb(aha, flags)) == NULL) {
+ if ((ccb = aha_get_ccb(sc, flags)) == NULL) {
xs->error = XS_DRIVER_STUFFUP;
return TRY_AGAIN_LATER;
}
ccb->xs = xs;
+ ccb->timeout = xs->timeout;
/*
* Put all the arguments for the xfer in the ccb
*/
if (flags & SCSI_RESET) {
ccb->opcode = AHA_RESET_CCB;
+ ccb->scsi_cmd_length = 0;
} else {
/* can't use S/G if zero length */
ccb->opcode = (xs->datalen ? AHA_INIT_SCAT_GATH_CCB
: AHA_INITIATOR_CCB);
+ bcopy(xs->cmd, &ccb->scsi_cmd,
+ ccb->scsi_cmd_length = xs->cmdlen);
}
- ccb->data_out = 0;
- ccb->data_in = 0;
- ccb->target = sc_link->target;
- ccb->lun = sc_link->lun;
- ccb->scsi_cmd_length = xs->cmdlen;
- ccb->req_sense_length = sizeof(ccb->scsi_sense);
- ccb->host_stat = 0x00;
- ccb->target_stat = 0x00;
- ccb->data_nseg = 0;
- if (xs->datalen && (flags & SCSI_RESET) == 0) {
- sg = ((struct aha_ccb *)(ccb->ccb_phys[0].addr))->scat_gath;
- lto3b((vm_offset_t)sg, ccb->data_addr);
+ if (xs->datalen) {
sg = ccb->scat_gath;
seg = 0;
#ifdef TFS
@@ -1272,8 +1156,8 @@ aha_scsi_cmd(xs)
datalen = ((struct uio *)xs->data)->uio_iovcnt;
xs->datalen = 0;
while (datalen && seg < AHA_NSEG) {
- lto3b(iovp->iov_base, sg->seg_addr);
- lto3b(iovp->iov_len, sg->seg_len);
+ ltophys(iovp->iov_base, sg->seg_addr);
+ ltophys(iovp->iov_len, sg->seg_len);
xs->datalen += iovp->iov_len;
SC_DEBUGN(sc_link, SDEV_DB4, ("UIO(0x%x@0x%x)",
iovp->iov_len, iovp->iov_base));
@@ -1283,109 +1167,129 @@ aha_scsi_cmd(xs)
datalen--;
}
} else
-#endif /*TFS_ONLY */
+#endif /* TFS */
{
/*
- * Set up the scatter gather block
+ * Set up the scatter-gather block.
*/
+ SC_DEBUG(sc_link, SDEV_DB4,
+ ("%d @0x%x:- ", xs->datalen, xs->data));
+
+ datalen = xs->datalen;
+ thiskv = (int)xs->data;
+ thisphys = KVTOPHYS(thiskv);
- ccb->data_nseg = isadma_map(xs->data, xs->datalen,
- ccb->data_phys, mflags);
- for (seg = 0; seg < ccb->data_nseg; seg++) {
- lto3b(ccb->data_phys[seg].addr,
- sg[seg].seg_addr);
- lto3b(ccb->data_phys[seg].length,
- sg[seg].seg_len);
+ while (datalen && seg < AHA_NSEG) {
+ bytes_this_seg = 0;
+
+ /* put in the base address */
+ ltophys(thisphys, sg->seg_addr);
+
+ SC_DEBUGN(sc_link, SDEV_DB4, ("0x%x", thisphys));
+
+ /* do it at least once */
+ nextphys = thisphys;
+ while (datalen && thisphys == nextphys) {
+ /*
+ * This page is contiguous (physically)
+ * with the the last, just extend the
+ * length
+ */
+ /* check it fits on the ISA bus */
+ if (thisphys > 0xFFFFFF) {
+ printf("%s: DMA beyond"
+ " end of ISA\n",
+ sc->sc_dev.dv_xname);
+ goto bad;
+ }
+ /* how far to the end of the page */
+ nextphys = (thisphys & ~PGOFSET) + NBPG;
+ bytes_this_page = nextphys - thisphys;
+ /**** or the data ****/
+ bytes_this_page = min(bytes_this_page,
+ datalen);
+ bytes_this_seg += bytes_this_page;
+ datalen -= bytes_this_page;
+
+ /* get more ready for the next page */
+ thiskv = (thiskv & ~PGOFSET) + NBPG;
+ if (datalen)
+ thisphys = KVTOPHYS(thiskv);
+ }
+ /*
+ * next page isn't contiguous, finish the seg
+ */
+ SC_DEBUGN(sc_link, SDEV_DB4,
+ ("(0x%x)", bytes_this_seg));
+ ltophys(bytes_this_seg, sg->seg_len);
+ sg++;
+ seg++;
}
}
- lto3b(ccb->data_nseg * sizeof(struct aha_scat_gath), ccb->data_length);
- if (ccb->data_nseg == 0) {
- printf("%s: aha_scsi_cmd, cannot map\n",
- aha->sc_dev.dv_xname);
- xs->error = XS_DRIVER_STUFFUP;
- aha_free_ccb(aha, ccb, flags);
- return COMPLETE;
- } else if (flags & SCSI_DATA_OUT)
- isadma_copytobuf(xs->data, xs->datalen,
- ccb->data_nseg, ccb->data_phys);
+ /* end of iov/kv decision */
+ SC_DEBUGN(sc_link, SDEV_DB4, ("\n"));
+ if (datalen) {
+ /*
+ * there's still data, must have run out of segs!
+ */
+ printf("%s: aha_scsi_cmd, more than %d dma segs\n",
+ sc->sc_dev.dv_xname, AHA_NSEG);
+ goto bad;
+ }
+ ltophys(KVTOPHYS(ccb->scat_gath), ccb->data_addr);
+ ltophys(seg * sizeof(struct aha_scat_gath), ccb->data_length);
} else { /* No data xfer, use non S/G values */
- lto3b(0, ccb->data_addr);
- lto3b(0, ccb->data_length);
+ ltophys(0, ccb->data_addr);
+ ltophys(0, ccb->data_length);
}
- ccb->link_id = 0;
- lto3b(0, ccb->link_addr);
- /*
- * Put the scsi command in the ccb and start it
- */
- if ((flags & SCSI_RESET) == 0)
- bcopy(xs->cmd, &ccb->scsi_cmd, ccb->scsi_cmd_length);
+ ccb->data_out = 0;
+ ccb->data_in = 0;
+ ccb->target = sc_link->target;
+ ccb->lun = sc_link->lun;
+ ccb->req_sense_length = sizeof(ccb->scsi_sense);
+ ccb->host_stat = 0x00;
+ ccb->target_stat = 0x00;
+ ccb->link_id = 0;
+ ltophys(0, ccb->link_addr);
s = splbio();
-
- isadma_copytobuf((caddr_t)ccb, CCB_PHYS_SIZE, 1, ccb->ccb_phys);
-
- if (aha_send_mbo(aha, AHA_MBO_START, ccb) == NULL) {
- splx(s);
- xs->error = XS_DRIVER_STUFFUP;
- if (ccb->data_nseg)
- isadma_unmap(xs->data, xs->datalen,
- ccb->data_nseg, ccb->data_phys);
- aha_free_ccb(aha, ccb, flags);
- return TRY_AGAIN_LATER;
- }
+ aha_queue_ccb(sc, ccb);
+ splx(s);
/*
* Usually return SUCCESSFULLY QUEUED
*/
SC_DEBUG(sc_link, SDEV_DB3, ("cmd_sent\n"));
-
- if (VOLATILE_XS(xs)) {
- timeout(aha_timeout, ccb, (xs->timeout * hz) / 1000);
- while ((ccb->xs->flags & ITSDONE) == 0) {
- tsleep(ccb, PRIBIO, "ahawait", 0);
- }
- splx(s);
- if (ccb->data_nseg) {
- if (flags & SCSI_DATA_IN)
- isadma_copyfrombuf(xs->data, xs->datalen,
- ccb->data_nseg, ccb->data_phys);
- isadma_unmap(xs->data, xs->datalen,
- ccb->data_nseg, ccb->data_phys);
- }
- aha_free_ccb(aha, ccb, xs->flags);
- scsi_done(xs);
- return COMPLETE;
- }
-
- if ((flags & SCSI_POLL) == 0) {
- timeout(aha_timeout, ccb, (xs->timeout * hz) / 1000);
- splx(s);
+ if ((flags & SCSI_POLL) == 0)
return SUCCESSFULLY_QUEUED;
- }
-
- splx(s);
/*
* If we can't use interrupts, poll on completion
*/
- if (aha_poll(aha, xs, xs->timeout)) {
+ if (aha_poll(sc, xs, ccb->timeout)) {
aha_timeout(ccb);
- if (aha_poll(aha, xs, 2000))
+ if (aha_poll(sc, xs, ccb->timeout))
aha_timeout(ccb);
}
return COMPLETE;
+
+bad:
+ xs->error = XS_DRIVER_STUFFUP;
+ aha_free_ccb(sc, ccb);
+ return COMPLETE;
}
/*
* Poll a particular unit, looking for a particular xs
*/
int
-aha_poll(aha, xs, count)
- struct aha_softc *aha;
+aha_poll(sc, xs, count)
+ struct aha_softc *sc;
struct scsi_xfer *xs;
int count;
{
+ int iobase = sc->sc_iobase;
/* timeouts are in msec, so we loop in 1000 usec cycles */
while (count) {
@@ -1393,8 +1297,8 @@ aha_poll(aha, xs, count)
* If we had interrupts enabled, would we
* have got an interrupt?
*/
- if (inb(AHA_INTR_PORT) & AHA_ANY_INTR)
- ahaintr(aha);
+ if (inb(iobase + AHA_INTR_PORT) & AHA_INTR_ANYINTR)
+ ahaintr(sc);
if (xs->flags & ITSDONE)
return 0;
delay(1000); /* only happens in boot so ok */
@@ -1403,141 +1307,6 @@ aha_poll(aha, xs, count)
return 1;
}
-#ifdef TUNE_1542
-/*
- * Try all the speeds from slowest to fastest.. if it finds a
- * speed that fails, back off one notch from the last working
- * speed (unless there is no other notch).
- * Returns the nSEC value of the time used
- * or 0 if it could get a working speed (or the NEXT speed
- * failed)
- */
-static struct bus_speed {
- u_char arg;
- int nsecs;
-} aha_bus_speeds[] = {
- {0x88, 100},
- {0x99, 150},
- {0xaa, 200},
- {0xbb, 250},
- {0xcc, 300},
- {0xdd, 350},
- {0xee, 400},
- {0xff, 450}
-};
-
-int
-aha_set_bus_speed(aha)
- struct aha_softc *aha;
-{
- int speed;
- int lastworking;
-
- lastworking = -1;
- for (speed = 7; speed >= 0; speed--) {
- if (!aha_bus_speed_check(aha, speed))
- break;
- lastworking = speed;
- }
- if (lastworking == -1) {
- printf(" no working bus speed");
- return 0;
- }
- printf(", %d nsec ", aha_bus_speeds[lastworking].nsecs);
- if (lastworking == 7) /* is slowest already */
- printf("marginal");
- else {
- lastworking++;
- printf("ok, using %d nsec", aha_bus_speeds[lastworking].nsecs);
- }
- if (!aha_bus_speed_check(aha, lastworking)) {
- printf("test retry failed.. aborting.");
- return 0;
- }
- return 1;
-}
-
-/*
- * Set the DMA speed to the Nth speed and try an xfer. If it
- * fails return 0, if it succeeds return the nSec value selected
- * If there is no such speed return COMPLETE.
- */
-char aha_scratch_buf[256];
-char aha_test_string[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz!@";
-
-int
-aha_bus_speed_check(aha, speed)
- struct aha_softc *aha;
- int speed;
-{
- int numspeeds = sizeof(aha_bus_speeds) / sizeof(struct bus_speed);
- int result, loopcount;
- struct isadma_seg test_phys[1], scratch_phys[1];
- u_char ad[3];
-
- result = 1;
-
- if (isadma_map(aha_scratch_buf, sizeof(aha_scratch_buf),
- scratch_phys, ISADMA_MAP_CONTIG) != 1)
- return 0;
- if (isadma_map(aha_test_string, sizeof(aha_test_string),
- test_phys, ISADMA_MAP_CONTIG) != 1) {
- isadma_unmap(aha_scratch_buf, sizeof(aha_scratch_buf),
- 1, scratch_phys);
- return 0;
- }
- isadma_copytobuf(aha_test_string, sizeof(aha_test_string),
- 1, test_phys);
-
- /*
- * Set the dma-speed
- */
- aha_cmd(aha, 1, 0, 0, 0, AHA_SPEED_SET, aha_bus_speeds[speed].arg);
-
- /*
- * put the test data into the buffer and calculate
- * it's address. Read it onto the board
- */
- for (loopcount = 100; loopcount; loopcount--) {
- lto3b(test_phys[0].addr, ad);
- aha_cmd(aha, 3, 0, 0, 0, AHA_WRITE_FIFO, ad[0], ad[1], ad[2]);
-
- /*
- * Clear the buffer then copy the contents back from the
- * board.
- */
- bzero(aha_scratch_buf, 54);
- isadma_copytobuf(aha_scratch_buf, sizeof(aha_scratch_buf),
- 1, scratch_phys);
-
- lto3b(scratch_phys[0].addr, ad);
- aha_cmd(aha, 3, 0, 0, 0, AHA_READ_FIFO, ad[0], ad[1], ad[2]);
- isadma_copyfrombuf(aha_scratch_buf, sizeof(aha_scratch_buf),
- 1, scratch_phys);
-
- /*
- * Compare the original data and the final data and return the
- * correct value depending upon the result. We only check the
- * first 54 bytes, because that's all the board copies during
- * WRITE_FIFO and READ_FIFO.
- */
- if (bcmp(aha_test_string, aha_scratch_buf, 54)) {
- result = 0; /* failed test */
- break;
- }
- }
-
- isadma_unmap(aha_scratch_buf, sizeof(aha_scratch_buf),
- 1, scratch_phys);
- isadma_unmap(aha_test_string, sizeof(aha_test_string),
- 1, test_phys);
-
- /* copy succeeded; assume speed ok */
- return result;
-}
-#endif /* TUNE_1542 */
-
void
aha_timeout(arg)
void *arg;
@@ -1545,7 +1314,7 @@ aha_timeout(arg)
struct aha_ccb *ccb = arg;
struct scsi_xfer *xs = ccb->xs;
struct scsi_link *sc_link = xs->sc_link;
- struct aha_softc *aha = sc_link->adapter_softc;
+ struct aha_softc *sc = sc_link->adapter_softc;
int s;
sc_print_addr(sc_link);
@@ -1553,34 +1322,33 @@ aha_timeout(arg)
s = splbio();
+#ifdef AHADIAG
/*
* If The ccb's mbx is not free, then the board has gone south?
*/
- if (aha_ccb_phys_kv(aha, _3btol(ccb->mbx->ccb_addr)) == ccb &&
- ccb->mbx->cmd != AHA_MBO_FREE) {
- printf("%s: not taking commands!\n", aha->sc_dev.dv_xname);
+ aha_collect_mbo(sc);
+ if (ccb->flags & CCB_SENDING) {
+ printf("%s: not taking commands!\n", sc->sc_dev.dv_xname);
Debugger();
}
+#endif
/*
* If it has been through before, then
* a previous abort has failed, don't
* try abort again
*/
- if (ccb->flags == CCB_ABORTED) {
+ if (ccb->flags & CCB_ABORT) {
/* abort timed out */
printf(" AGAIN\n");
- ccb->xs->retries = 0;
- aha_done(aha, ccb);
+ /* XXX Must reset! */
} else {
/* abort the operation that has timed out */
printf("\n");
ccb->xs->error = XS_TIMEOUT;
- ccb->flags = CCB_ABORTED;
- aha_send_mbo(aha, AHA_MBO_ABORT, ccb);
- /* 2 secs for the abort */
- if ((xs->flags & SCSI_POLL) == 0)
- timeout(aha_timeout, ccb, 2 * hz);
+ ccb->timeout = AHA_ABORT_TIMEOUT;
+ ccb->flags |= CCB_ABORT;
+ aha_queue_ccb(sc, ccb);
}
splx(s);
diff --git a/sys/dev/isa/aha1542.c b/sys/dev/isa/aha1542.c
deleted file mode 100644
index a1c559ad646..00000000000
--- a/sys/dev/isa/aha1542.c
+++ /dev/null
@@ -1,1587 +0,0 @@
-/* $OpenBSD: aha1542.c,v 1.13 1996/03/20 01:00:35 mickey Exp $ */
-/* $NetBSD: aha1542.c,v 1.55 1995/12/24 02:31:06 mycroft Exp $ */
-
-/*
- * Copyright (c) 1994 Charles Hannum. 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 Charles Hannum.
- * 4. 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.
- */
-
-/*
- * Originally written by Julian Elischer (julian@tfs.com)
- * for TRW Financial Systems for use under the MACH(2.5) operating system.
- *
- * TRW Financial Systems, in accordance with their agreement with Carnegie
- * Mellon University, makes this software available to CMU to distribute
- * or use in any manner that they see fit as long as this message is kept with
- * the software. For this reason TFS also grants any other persons or
- * organisations permission to use or modify this software.
- *
- * TFS supplies this software to be publicly redistributed
- * on the understanding that TFS is not responsible for the correct
- * functioning of this software in any circumstances.
- */
-
-/*
- * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
- */
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/syslog.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/errno.h>
-#include <sys/ioctl.h>
-#include <sys/device.h>
-#include <sys/malloc.h>
-#include <sys/buf.h>
-#include <sys/proc.h>
-#include <sys/user.h>
-
-#include <machine/pio.h>
-
-#include <dev/isa/isavar.h>
-#include <dev/isa/isadmavar.h>
-#include <scsi/scsi_all.h>
-#include <scsi/scsiconf.h>
-
-#ifndef DDB
-#define Debugger() panic("should call debugger here (aha1542.c)")
-#endif /* ! DDB */
-
-/* XXX fixme:
- * on i386 at least, xfers to/from user memory
- * cannot be serviced at interrupt time.
- */
-#ifdef i386
-#define VOLATILE_XS(xs) \
- ((xs)->datalen > 0 && (xs)->bp == NULL && \
- ((xs)->flags & SCSI_POLL) == 0)
-#else
-#define VOLATILE_XS(xs) 0
-#endif
-
-#undef TUNE_1542 /* if bus speed check breaks the machine, undefine it */
-
-/************************** board definitions *******************************/
-
-/*
- * I/O Port Interface
- */
-#define AHA_BASE aha->sc_iobase
-#define AHA_CTRL_STAT_PORT (AHA_BASE + 0x0) /* control & status */
-#define AHA_CMD_DATA_PORT (AHA_BASE + 0x1) /* cmds and datas */
-#define AHA_INTR_PORT (AHA_BASE + 0x2) /* Intr. stat */
-
-/*
- * AHA_CTRL_STAT bits (write)
- */
-#define AHA_HRST 0x80 /* Hardware reset */
-#define AHA_SRST 0x40 /* Software reset */
-#define AHA_IRST 0x20 /* Interrupt reset */
-#define AHA_SCRST 0x10 /* SCSI bus reset */
-
-/*
- * AHA_CTRL_STAT bits (read)
- */
-#define AHA_STST 0x80 /* Self test in Progress */
-#define AHA_DIAGF 0x40 /* Diagnostic Failure */
-#define AHA_INIT 0x20 /* Mbx Init required */
-#define AHA_IDLE 0x10 /* Host Adapter Idle */
-#define AHA_CDF 0x08 /* cmd/data out port full */
-#define AHA_DF 0x04 /* Data in port full */
-#define AHA_INVDCMD 0x01 /* Invalid command */
-
-/*
- * AHA_CMD_DATA bits (write)
- */
-#define AHA_NOP 0x00 /* No operation */
-#define AHA_MBX_INIT 0x01 /* Mbx initialization */
-#define AHA_START_SCSI 0x02 /* start scsi command */
-#define AHA_START_BIOS 0x03 /* start bios command */
-#define AHA_INQUIRE 0x04 /* Adapter Inquiry */
-#define AHA_MBO_INTR_EN 0x05 /* Enable MBO available interrupt */
-#define AHA_SEL_TIMEOUT_SET 0x06 /* set selection time-out */
-#define AHA_BUS_ON_TIME_SET 0x07 /* set bus-on time */
-#define AHA_BUS_OFF_TIME_SET 0x08 /* set bus-off time */
-#define AHA_SPEED_SET 0x09 /* set transfer speed */
-#define AHA_DEV_GET 0x0a /* return installed devices */
-#define AHA_CONF_GET 0x0b /* return configuration data */
-#define AHA_TARGET_EN 0x0c /* enable target mode */
-#define AHA_SETUP_GET 0x0d /* return setup data */
-#define AHA_WRITE_CH2 0x1a /* write channel 2 buffer */
-#define AHA_READ_CH2 0x1b /* read channel 2 buffer */
-#define AHA_WRITE_FIFO 0x1c /* write fifo buffer */
-#define AHA_READ_FIFO 0x1d /* read fifo buffer */
-#define AHA_ECHO 0x1e /* Echo command data */
-#define AHA_EXT_BIOS 0x28 /* return extended bios info */
-#define AHA_MBX_ENABLE 0x29 /* enable mail box interface */
-
-/*
- * AHA_INTR_PORT bits (read)
- */
-#define AHA_ANY_INTR 0x80 /* Any interrupt */
-#define AHA_SCRD 0x08 /* SCSI reset detected */
-#define AHA_HACC 0x04 /* Command complete */
-#define AHA_MBOA 0x02 /* MBX out empty */
-#define AHA_MBIF 0x01 /* MBX in full */
-
-/*
- * Mail box defs
- */
-#define AHA_MBX_SIZE 16 /* mail box size */
-
-#define AHA_CCB_MAX 32 /* store up to 32 CCBs at one time */
-#define CCB_HASH_SIZE 32 /* hash table size for phystokv */
-#define CCB_HASH_SHIFT 9
-#define CCB_HASH(x) ((((long)(x))>>CCB_HASH_SHIFT) & (CCB_HASH_SIZE - 1))
-
-#define aha_nextmbx(wmb, mbx, mbio) \
- if ((wmb) == &(mbx)->mbio[AHA_MBX_SIZE - 1]) \
- (wmb) = &(mbx)->mbio[0]; \
- else \
- (wmb)++;
-
-struct aha_mbx_out {
- u_char cmd;
- u_char ccb_addr[3];
-};
-
-struct aha_mbx_in {
- u_char stat;
- u_char ccb_addr[3];
-};
-
-struct aha_mbx {
- struct aha_mbx_out mbo[AHA_MBX_SIZE];
- struct aha_mbx_in mbi[AHA_MBX_SIZE];
- struct aha_mbx_out *tmbo; /* Target Mail Box out */
- struct aha_mbx_in *tmbi; /* Target Mail Box in */
-};
-
-/*
- * mbo.cmd values
- */
-#define AHA_MBO_FREE 0x0 /* MBO entry is free */
-#define AHA_MBO_START 0x1 /* MBO activate entry */
-#define AHA_MBO_ABORT 0x2 /* MBO abort entry */
-
-/*
- * mbi.stat values
- */
-#define AHA_MBI_FREE 0x0 /* MBI entry is free */
-#define AHA_MBI_OK 0x1 /* completed without error */
-#define AHA_MBI_ABORT 0x2 /* aborted ccb */
-#define AHA_MBI_UNKNOWN 0x3 /* Tried to abort invalid CCB */
-#define AHA_MBI_ERROR 0x4 /* Completed with error */
-
-/* FOR OLD VERSIONS OF THE !%$@ this may have to be 16 (yuk) */
-#define AHA_NSEG 17 /* Number of scatter gather segments <= 16 */
- /* allow 60 K i/o (min) */
-
-struct aha_ccb {
- u_char opcode;
- u_char lun:3;
- u_char data_in:1; /* must be 0 */
- u_char data_out:1; /* must be 0 */
- u_char target:3;
- u_char scsi_cmd_length;
- u_char req_sense_length;
- u_char data_length[3];
- u_char data_addr[3];
- u_char link_addr[3];
- u_char link_id;
- u_char host_stat;
- u_char target_stat;
- u_char reserved[2];
- struct scsi_generic scsi_cmd;
- struct scsi_sense_data scsi_sense;
- struct aha_scat_gath {
- u_char seg_len[3];
- u_char seg_addr[3];
- } scat_gath[AHA_NSEG];
- /*----------------------------------------------------------------*/
-#define CCB_PHYS_SIZE ((int)&((struct aha_ccb *)0)->chain)
- TAILQ_ENTRY(aha_ccb) chain;
- struct aha_ccb *nexthash;
- struct scsi_xfer *xs; /* the scsi_xfer for this cmd */
- int flags;
-#define CCB_FREE 0
-#define CCB_ACTIVE 1
-#define CCB_ABORTED 2
- struct aha_mbx_out *mbx; /* pointer to mail box */
- struct isadma_seg ccb_phys[1]; /* phys segment of this ccb */
- struct isadma_seg data_phys[AHA_NSEG]; /* phys segments of data */
- int data_nseg; /* number of phys segments of data */
-};
-
-/*
- * opcode fields
- */
-#define AHA_INITIATOR_CCB 0x00 /* SCSI Initiator CCB */
-#define AHA_TARGET_CCB 0x01 /* SCSI Target CCB */
-#define AHA_INIT_SCAT_GATH_CCB 0x02 /* SCSI Initiator with scatter gather */
-#define AHA_RESET_CCB 0x81 /* SCSI Bus reset */
-
-/*
- * aha_ccb.host_stat values
- */
-#define AHA_OK 0x00 /* cmd ok */
-#define AHA_LINK_OK 0x0a /* Link cmd ok */
-#define AHA_LINK_IT 0x0b /* Link cmd ok + int */
-#define AHA_SEL_TIMEOUT 0x11 /* Selection time out */
-#define AHA_OVER_UNDER 0x12 /* Data over/under run */
-#define AHA_BUS_FREE 0x13 /* Bus dropped at unexpected time */
-#define AHA_INV_BUS 0x14 /* Invalid bus phase/sequence */
-#define AHA_BAD_MBO 0x15 /* Incorrect MBO cmd */
-#define AHA_BAD_CCB 0x16 /* Incorrect ccb opcode */
-#define AHA_BAD_LINK 0x17 /* Not same values of LUN for links */
-#define AHA_INV_TARGET 0x18 /* Invalid target direction */
-#define AHA_CCB_DUP 0x19 /* Duplicate CCB received */
-#define AHA_INV_CCB 0x1a /* Invalid CCB or segment list */
-#define AHA_ABORTED 42
-
-struct aha_setup {
- u_char sync_neg:1;
- u_char parity:1;
- u_char:6;
- u_char speed;
- u_char bus_on;
- u_char bus_off;
- u_char num_mbx;
- u_char mbx[3];
- struct {
- u_char offset:4;
- u_char period:3;
- u_char valid:1;
- } sync[8];
- u_char disc_sts;
-};
-
-struct aha_config {
- u_char chan;
- u_char intr;
- u_char scsi_dev:3;
- u_char:5;
-};
-
-struct aha_inquire {
- u_char boardid; /* type of board */
- /* 0x31 = AHA-1540 */
- /* 0x41 = AHA-1540A/1542A/1542B */
- /* 0x42 = AHA-1640 */
- /* 0x43 = AHA-1542C */
- /* 0x44 = AHA-1542CF */
- /* 0x45 = AHA-1542CF, BIOS v2.01 */
- u_char spec_opts; /* special options ID */
- /* 0x41 = Board is standard model */
- u_char revision_1; /* firmware revision [0-9A-Z] */
- u_char revision_2; /* firmware revision [0-9A-Z] */
-};
-
-struct aha_extbios {
- u_char flags; /* Bit 3 == 1 extended bios enabled */
- u_char mailboxlock; /* mail box lock code to unlock it */
-};
-
-#define INT9 0x01
-#define INT10 0x02
-#define INT11 0x04
-#define INT12 0x08
-#define INT14 0x20
-#define INT15 0x40
-
-#define CHAN0 0x01
-#define CHAN5 0x20
-#define CHAN6 0x40
-#define CHAN7 0x80
-
-/*********************************** end of board definitions***************/
-
-#ifdef AHADEBUG
-int aha_debug = 1;
-#endif /*AHADEBUG */
-
-struct aha_softc {
- struct device sc_dev;
- struct isadev sc_id;
- void *sc_ih;
-
- int sc_iobase;
- int sc_irq, sc_drq;
-
- struct aha_mbx aha_mbx; /* all the mailboxes */
- struct aha_ccb *ccbhash[CCB_HASH_SIZE];
- TAILQ_HEAD(, aha_ccb) free_ccb;
- int numccbs;
- int aha_scsi_dev; /* our scsi id */
- struct scsi_link sc_link;
-};
-
-int aha_cmd(); /* XXX must be varargs to prototype */
-int ahaintr __P((void *));
-void aha_free_ccb __P((struct aha_softc *, struct aha_ccb *, int));
-struct aha_ccb *aha_get_ccb __P((struct aha_softc *, int));
-struct aha_ccb *aha_ccb_phys_kv __P((struct aha_softc *, u_long));
-struct aha_mbx_out *aha_send_mbo __P((struct aha_softc *, int, struct aha_ccb *));
-void aha_done __P((struct aha_softc *, struct aha_ccb *));
-int aha_find __P((struct aha_softc *));
-void aha_init __P((struct aha_softc *));
-void ahaminphys __P((struct buf *));
-int aha_scsi_cmd __P((struct scsi_xfer *));
-int aha_poll __P((struct aha_softc *, struct scsi_xfer *, int));
-int aha_set_bus_speed __P((struct aha_softc *));
-int aha_bus_speed_check __P((struct aha_softc *, int));
-void aha_timeout __P((void *arg));
-
-struct scsi_adapter aha_switch = {
- aha_scsi_cmd,
- ahaminphys,
- 0,
- 0,
-};
-
-/* the below structure is so we have a default dev struct for out link struct */
-struct scsi_device aha_dev = {
- NULL, /* Use default error handler */
- NULL, /* have a queue, served by this */
- NULL, /* have no async handler */
- NULL, /* Use default 'done' routine */
-};
-
-int ahaprobe __P((struct device *, void *, void *));
-void ahaattach __P((struct device *, struct device *, void *));
-int ahaprint __P((void *, char *));
-
-struct cfdriver ahacd = {
- NULL, "aha", ahaprobe, ahaattach, DV_DULL, sizeof(struct aha_softc)
-};
-
-#define AHA_RESET_TIMEOUT 2000 /* time to wait for reset (mSec) */
-
-/*
- * aha_cmd(aha,icnt, ocnt,wait, retval, opcode, args)
- * Activate Adapter command
- * icnt: number of args (outbound bytes written after opcode)
- * ocnt: number of expected returned bytes
- * wait: number of seconds to wait for response
- * retval: buffer where to place returned bytes
- * opcode: opcode AHA_NOP, AHA_MBX_INIT, AHA_START_SCSI ...
- * args: parameters
- *
- * Performs an adapter command through the ports. Not to be confused
- * with a scsi command, which is read in via the dma. One of the adapter
- * commands tells it to read in a scsi command but that one is done
- * separately. This is only called during set-up.
- */
-int
-aha_cmd(aha, icnt, ocnt, wait, retval, opcode, args)
- struct aha_softc *aha;
- int icnt, ocnt, wait;
- u_char *retval;
- unsigned opcode;
- u_char args;
-{
- unsigned *ic = &opcode;
- u_char oc;
- register i;
- int sts;
-
- /*
- * multiply the wait argument by a big constant
- * zero defaults to 1 sec..
- * all wait loops are in 50uSec cycles
- */
- if (wait)
- wait *= 20000;
- else
- wait = 20000;
- /*
- * Wait for the adapter to go idle, unless it's one of
- * the commands which don't need this
- */
- if (opcode != AHA_MBX_INIT && opcode != AHA_START_SCSI) {
- i = 20000; /*do this for upto about a second */
- while (--i) {
- sts = inb(AHA_CTRL_STAT_PORT);
- if (sts & AHA_IDLE)
- break;
- delay(50);
- }
- if (!i) {
- printf("%s: aha_cmd, host not idle(0x%x)\n",
- aha->sc_dev.dv_xname, sts);
- return ENXIO;
- }
- }
- /*
- * Now that it is idle, if we expect output, preflush the
- * queue feeding to us.
- */
- if (ocnt) {
- while ((inb(AHA_CTRL_STAT_PORT)) & AHA_DF)
- inb(AHA_CMD_DATA_PORT);
- }
- /*
- * Output the command and the number of arguments given
- * for each byte, first check the port is empty.
- */
- icnt++;
- /* include the command */
- while (icnt--) {
- sts = inb(AHA_CTRL_STAT_PORT);
- for (i = wait; i; i--) {
- sts = inb(AHA_CTRL_STAT_PORT);
- if (!(sts & AHA_CDF))
- break;
- delay(50);
- }
- if (!i) {
- if (opcode != AHA_INQUIRE)
- printf("%s: aha_cmd, cmd/data port full\n",
- aha->sc_dev.dv_xname);
- outb(AHA_CTRL_STAT_PORT, AHA_SRST);
- return ENXIO;
- }
- outb(AHA_CMD_DATA_PORT, (u_char) (*ic++));
- }
- /*
- * If we expect input, loop that many times, each time,
- * looking for the data register to have valid data
- */
- while (ocnt--) {
- sts = inb(AHA_CTRL_STAT_PORT);
- for (i = wait; i; i--) {
- sts = inb(AHA_CTRL_STAT_PORT);
- if (sts & AHA_DF)
- break;
- delay(50);
- }
- if (!i) {
- if (opcode != AHA_INQUIRE)
- printf("%s: aha_cmd, cmd/data port empty %d\n",
- aha->sc_dev.dv_xname, ocnt);
- outb(AHA_CTRL_STAT_PORT, AHA_SRST);
- return ENXIO;
- }
- oc = inb(AHA_CMD_DATA_PORT);
- if (retval)
- *retval++ = oc;
- }
- /*
- * Wait for the board to report a finised instruction
- */
- i = 20000;
- while (--i) {
- sts = inb(AHA_INTR_PORT);
- if (sts & AHA_HACC)
- break;
- delay(50);
- }
- if (!i) {
- printf("%s: aha_cmd, host not finished(0x%x)\n",
- aha->sc_dev.dv_xname, sts);
- return ENXIO;
- }
- outb(AHA_CTRL_STAT_PORT, AHA_IRST);
- return 0;
-}
-
-/*
- * Check if the device can be found at the port given
- * and if so, set it up ready for further work
- * as an argument, takes the isa_device structure from
- * autoconf.c
- */
-int
-ahaprobe(parent, match, aux)
- struct device *parent;
- void *match, *aux;
-{
- struct aha_softc *aha = match;
- struct isa_attach_args *ia = aux;
-
-#ifdef NEWCONFIG
- if (ia->ia_iobase == IOBASEUNK)
- return 0;
-#endif
-
- aha->sc_iobase = ia->ia_iobase;
-
- /*
- * Try initialise a unit at this location
- * sets up dma and bus speed, loads aha->sc_irq
- */
- if (aha_find(aha) != 0)
- return 0;
-
- if (ia->ia_irq != IRQUNK) {
- if (ia->ia_irq != aha->sc_irq) {
- printf("%s: irq mismatch; kernel configured %d != board configured %d\n",
- aha->sc_dev.dv_xname, ia->ia_irq, aha->sc_irq);
- return 0;
- }
- } else
- ia->ia_irq = aha->sc_irq;
-
- if (ia->ia_drq != DRQUNK) {
- if (ia->ia_drq != aha->sc_drq) {
- printf("%s: drq mismatch; kernel configured %d != board configured %d\n",
- aha->sc_dev.dv_xname, ia->ia_drq, aha->sc_drq);
- return 0;
- }
- } else
- ia->ia_drq = aha->sc_drq;
-
- ia->ia_msize = 0;
- ia->ia_iosize = 4;
- return 1;
-}
-
-int
-ahaprint(aux, name)
- void *aux;
- char *name;
-{
- if (name != NULL)
- printf("%s: scsibus ", name);
- return UNCONF;
-}
-
-/*
- * Attach all the sub-devices we can find
- */
-void
-ahaattach(parent, self, aux)
- struct device *parent, *self;
- void *aux;
-{
- struct isa_attach_args *ia = aux;
- struct aha_softc *aha = (void *)self;
-
- if (ia->ia_drq != DRQUNK)
- isadma_cascade(ia->ia_drq);
-
- aha_init(aha);
- TAILQ_INIT(&aha->free_ccb);
-
- /*
- * fill in the prototype scsi_link.
- */
- aha->sc_link.adapter_softc = aha;
- aha->sc_link.adapter_target = aha->aha_scsi_dev;
- aha->sc_link.adapter = &aha_switch;
- aha->sc_link.device = &aha_dev;
- aha->sc_link.openings = 2;
-
- printf("\n");
-
-#ifdef NEWCONFIG
- isa_establish(&aha->sc_id, &aha->sc_dev);
-#endif
- aha->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_BIO, ahaintr,
- aha, aha->sc_dev.dv_xname);
-
- /*
- * ask the adapter what subunits are present
- */
- config_found(self, &aha->sc_link, ahaprint);
-}
-
-/*
- * Catch an interrupt from the adaptor
- */
-int
-ahaintr(arg)
- void *arg;
-{
- struct aha_softc *aha = arg;
- struct aha_mbx_in *wmbi;
- struct aha_mbx *wmbx;
- struct aha_ccb *ccb;
- u_char stat;
- int i;
- int found = 0;
-
-#ifdef AHADEBUG
- printf("%s: ahaintr ", aha->sc_dev.dv_xname);
-#endif /*AHADEBUG */
-
- /*
- * First acknowlege the interrupt, Then if it's not telling about
- * a completed operation just return.
- */
- stat = inb(AHA_INTR_PORT);
- if ((stat & (AHA_MBOA | AHA_MBIF)) == 0) {
- outb(AHA_CTRL_STAT_PORT, AHA_IRST);
- return -1; /* XXX */
- }
-
- /* Mail box out empty? */
- if (stat & AHA_MBOA) {
- /* Disable MBO available interrupt. */
- outb(AHA_CMD_DATA_PORT, AHA_MBO_INTR_EN);
- for (i = 100000; i; i--) {
- if (!(inb(AHA_CTRL_STAT_PORT) & AHA_CDF))
- break;
- delay(10);
- }
- if (!i) {
- printf("%s: ahaintr, cmd/data port full\n",
- aha->sc_dev.dv_xname);
- outb(AHA_CTRL_STAT_PORT, AHA_SRST);
- return 1;
- }
- outb(AHA_CMD_DATA_PORT, 0x00); /* Disable */
- wakeup(&aha->aha_mbx);
- }
-
- /* Mail box in full? */
- if ((stat & AHA_MBIF) == 0)
- return 1;
- wmbx = &aha->aha_mbx;
- wmbi = wmbx->tmbi;
-AGAIN:
- while (wmbi->stat != AHA_MBI_FREE) {
- ccb = aha_ccb_phys_kv(aha, _3btol(wmbi->ccb_addr));
- if (!ccb) {
- wmbi->stat = AHA_MBI_FREE;
- printf("%s: BAD CCB ADDR!\n", aha->sc_dev.dv_xname);
- continue;
- }
- found++;
- switch (wmbi->stat) {
- case AHA_MBI_OK:
- case AHA_MBI_ERROR:
- break;
-
- case AHA_MBI_ABORT:
- ccb->host_stat = AHA_ABORTED;
- break;
-
- case AHA_MBI_UNKNOWN:
- ccb = 0;
- break;
-
- default:
- panic("Impossible mbxi status");
- }
-#ifdef AHADEBUG
- if (aha_debug && ccb) {
- u_char *cp = &ccb->scsi_cmd;
- printf("op=%x %x %x %x %x %x\n",
- cp[0], cp[1], cp[2],
- cp[3], cp[4], cp[5]);
- printf("stat %x for mbi addr = 0x%08x, ",
- wmbi->stat, wmbi);
- printf("ccb addr = 0x%x\n", ccb);
- }
-#endif /* AHADEBUG */
- wmbi->stat = AHA_MBI_FREE;
- if (ccb) {
- untimeout(aha_timeout, ccb);
- aha_done(aha, ccb);
- }
- aha_nextmbx(wmbi, wmbx, mbi);
- }
- if (!found) {
- for (i = 0; i < AHA_MBX_SIZE; i++) {
- if (wmbi->stat != AHA_MBI_FREE) {
- found++;
- break;
- }
- aha_nextmbx(wmbi, wmbx, mbi);
- }
- if (!found) {
-#if 0
- printf("%s: mbi interrupt with no full mailboxes\n",
- aha->sc_dev.dv_xname);
-#endif
- } else {
- found = 0;
- goto AGAIN;
- }
- }
- wmbx->tmbi = wmbi;
- outb(AHA_CTRL_STAT_PORT, AHA_IRST);
- return 1;
-}
-
-/*
- * A ccb (and hence a mbx-out is put onto the
- * free list.
- */
-void
-aha_free_ccb(aha, ccb, flags)
- struct aha_softc *aha;
- struct aha_ccb *ccb;
- int flags;
-{
- int s, hashnum;
- struct aha_ccb **hashccb;
-
- s = splbio();
-
- if (ccb->ccb_phys[0].addr)
- isadma_unmap((caddr_t)ccb, CCB_PHYS_SIZE, 1, ccb->ccb_phys);
-
- /* remove from hash table */
-
- hashnum = CCB_HASH(ccb->ccb_phys[0].addr);
- hashccb = &aha->ccbhash[hashnum];
-
- while (*hashccb) {
- if ((*hashccb)->ccb_phys[0].addr == ccb->ccb_phys[0].addr) {
- *hashccb = (*hashccb)->nexthash;
- break;
- }
- hashccb = &(*hashccb)->nexthash;
- }
-
- ccb->flags = CCB_FREE;
- TAILQ_INSERT_HEAD(&aha->free_ccb, ccb, chain);
-
- /*
- * If there were none, wake anybody waiting for one to come free,
- * starting with queued entries.
- */
- if (ccb->chain.tqe_next == 0)
- wakeup(&aha->free_ccb);
-
- splx(s);
-}
-
-static inline void
-aha_init_ccb(aha, ccb)
- struct aha_softc *aha;
- struct aha_ccb *ccb;
-{
- bzero(ccb, sizeof(struct aha_ccb));
-}
-
-static inline void
-aha_reset_ccb(aha, ccb)
- struct aha_softc *aha;
- struct aha_ccb *ccb;
-{
-
-}
-
-/*
- * Get a free ccb
- */
-struct aha_ccb *
-aha_get_ccb(aha, flags)
- struct aha_softc *aha;
- int flags;
-{
- struct aha_ccb *ccb;
- int hashnum, mflags, s;
-
- s = splbio();
-
- if (flags & SCSI_NOSLEEP)
- mflags = ISADMA_MAP_BOUNCE;
- else
- mflags = ISADMA_MAP_BOUNCE | ISADMA_MAP_WAITOK;
-
- /*
- * If we can and have to, sleep waiting for one
- * to come free
- */
- for (;;) {
- ccb = aha->free_ccb.tqh_first;
- if (ccb) {
- TAILQ_REMOVE(&aha->free_ccb, ccb, chain);
- break;
- }
- if (aha->numccbs < AHA_CCB_MAX) {
- if (ccb = (struct aha_ccb *) malloc(sizeof(struct aha_ccb),
- M_TEMP, M_NOWAIT)) {
- aha_init_ccb(aha, ccb);
- aha->numccbs++;
- } else {
- printf("%s: can't malloc ccb\n",
- aha->sc_dev.dv_xname);
- goto out;
- }
- break;
- }
- if ((flags & SCSI_NOSLEEP) != 0)
- goto out;
- tsleep(&aha->free_ccb, PRIBIO, "ahaccb", 0);
- }
-
- aha_reset_ccb(aha, ccb);
- ccb->flags = CCB_ACTIVE;
-
- if (isadma_map((caddr_t)ccb, CCB_PHYS_SIZE, ccb->ccb_phys,
- mflags | ISADMA_MAP_CONTIG) == 1) {
- hashnum = CCB_HASH(ccb->ccb_phys[0].addr);
- ccb->nexthash = aha->ccbhash[hashnum];
- aha->ccbhash[hashnum] = ccb;
- } else {
- ccb->ccb_phys[0].addr = 0;
- aha_free_ccb(aha, ccb, flags);
- ccb = 0;
- }
-
-out:
- splx(s);
- return (ccb);
-}
-
-/*
- * given a physical address, find the ccb that it corresponds to.
- */
-struct aha_ccb *
-aha_ccb_phys_kv(aha, ccb_phys)
- struct aha_softc *aha;
- u_long ccb_phys;
-{
- int hashnum = CCB_HASH(ccb_phys);
- struct aha_ccb *res = aha->ccbhash[hashnum];
-
- while (res) {
- if (res->ccb_phys[0].addr == ccb_phys)
- break;
- res = res->nexthash;
- }
-
- return res;
-}
-
-/*
- * Get a mbo and send the ccb.
- */
-struct aha_mbx_out *
-aha_send_mbo(aha, cmd, ccb)
- struct aha_softc *aha;
- int cmd;
- struct aha_ccb *ccb;
-{
- struct aha_mbx_out *wmbo; /* Mail Box Out pointer */
- struct aha_mbx *wmbx; /* Mail Box pointer specified unit */
- int i;
-
- /* Get the target out mail box pointer and increment. */
- wmbx = &aha->aha_mbx;
- wmbo = wmbx->tmbo;
- aha_nextmbx(wmbx->tmbo, wmbx, mbo);
-
- /*
- * Check the outmail box is free or not.
- * Note: Under the normal operation, it shuld NOT happen to wait.
- */
- while (wmbo->cmd != AHA_MBO_FREE) {
- /* Enable mbo available interrupt. */
- outb(AHA_CMD_DATA_PORT, AHA_MBO_INTR_EN);
- for (i = 100000; i; i--) {
- if (!(inb(AHA_CTRL_STAT_PORT) & AHA_CDF))
- break;
- delay(10);
- }
- if (!i) {
- printf("%s: aha_send_mbo, cmd/data port full\n",
- aha->sc_dev.dv_xname);
- outb(AHA_CTRL_STAT_PORT, AHA_SRST);
- return NULL;
- }
- outb(AHA_CMD_DATA_PORT, 0x01); /* Enable */
- tsleep(wmbx, PRIBIO, "ahasnd", 0);/*XXX can't do this */
- }
-
- /* Link ccb to mbo. */
- lto3b(ccb->ccb_phys[0].addr, wmbo->ccb_addr);
- ccb->mbx = wmbo;
- wmbo->cmd = cmd;
-
- /* Sent it! */
- outb(AHA_CMD_DATA_PORT, AHA_START_SCSI);
-
- return wmbo;
-}
-
-/*
- * We have a ccb which has been processed by the
- * adaptor, now we look to see how the operation
- * went. Wake up the owner if waiting
- */
-void
-aha_done(aha, ccb)
- struct aha_softc *aha;
- struct aha_ccb *ccb;
-{
- struct scsi_sense_data *s1, *s2;
- struct scsi_xfer *xs = ccb->xs;
-
- SC_DEBUG(xs->sc_link, SDEV_DB2, ("aha_done\n"));
- /*
- * Otherwise, put the results of the operation
- * into the xfer and call whoever started it
- */
- if ((xs->flags & INUSE) == 0) {
- printf("%s: exiting but not in use!\n", aha->sc_dev.dv_xname);
- Debugger();
- }
- if (xs->error == XS_NOERROR) {
- if (ccb->host_stat != AHA_OK) {
- switch (ccb->host_stat) {
- case AHA_ABORTED:
- xs->error = XS_DRIVER_STUFFUP;
- break;
- case AHA_SEL_TIMEOUT: /* No response */
- xs->error = XS_SELTIMEOUT;
- break;
- default: /* Other scsi protocol messes */
- printf("%s: host_stat %x\n",
- aha->sc_dev.dv_xname, ccb->host_stat);
- xs->error = XS_DRIVER_STUFFUP;
- }
- } else if (ccb->target_stat != SCSI_OK) {
- switch (ccb->target_stat) {
- case SCSI_CHECK:
- s1 = (struct scsi_sense_data *) (((char *) (&ccb->scsi_cmd)) +
- ccb->scsi_cmd_length);
- s2 = &xs->sense;
- *s2 = *s1;
- xs->error = XS_SENSE;
- break;
- case SCSI_BUSY:
- xs->error = XS_BUSY;
- break;
- default:
- printf("%s: target_stat %x\n",
- aha->sc_dev.dv_xname, ccb->target_stat);
- xs->error = XS_DRIVER_STUFFUP;
- }
- } else
- xs->resid = 0;
- }
- xs->flags |= ITSDONE;
-
- if (VOLATILE_XS(xs)) {
- wakeup(ccb);
- return;
- }
-
- if (ccb->data_nseg) {
- if (xs->flags & SCSI_DATA_IN)
- isadma_copyfrombuf(xs->data, xs->datalen,
- ccb->data_nseg, ccb->data_phys);
- isadma_unmap(xs->data, xs->datalen,
- ccb->data_nseg, ccb->data_phys);
- }
- aha_free_ccb(aha, ccb, xs->flags);
- scsi_done(xs);
-}
-
-/*
- * Find the board and find its irq/drq
- */
-int
-aha_find(aha)
- struct aha_softc *aha;
-{
- volatile int i, sts;
- struct aha_config conf;
- struct aha_inquire inquire;
- struct aha_extbios extbios;
-
- /*
- * reset board, If it doesn't respond, assume
- * that it's not there.. good for the probe
- */
-
- outb(AHA_CTRL_STAT_PORT, AHA_HRST | AHA_SRST);
-
- for (i = AHA_RESET_TIMEOUT; i; i--) {
- sts = inb(AHA_CTRL_STAT_PORT);
- if (sts == (AHA_IDLE | AHA_INIT))
- break;
- delay(1000); /* calibrated in msec */
- }
- if (!i) {
-#ifdef AHADEBUG
- if (aha_debug)
- printf("aha_find: No answer from adaptec board\n");
-#endif /*AHADEBUG */
- return ENXIO;
- }
-
- /*
- * Assume we have a board at this stage, do an adapter inquire
- * to find out what type of controller it is. If the command
- * fails, we assume it's either a crusty board or an old 1542
- * clone, and skip the board-specific stuff.
- */
- if (aha_cmd(aha, 0, sizeof(inquire), 1, &inquire, AHA_INQUIRE)) {
- /*
- * aha_cmd() already started the reset. It's not clear we
- * even need to bother here.
- */
- for (i = AHA_RESET_TIMEOUT; i; i--) {
- sts = inb(AHA_CTRL_STAT_PORT);
- if (sts == (AHA_IDLE | AHA_INIT))
- break;
- delay(1000);
- }
- if (!i) {
-#ifdef AHADEBUG
- printf("aha_init: soft reset failed\n");
-#endif /* AHADEBUG */
- return ENXIO;
- }
-#ifdef AHADEBUG
- printf("aha_init: inquire command failed\n");
-#endif /* AHADEBUG */
- goto noinquire;
- }
-#ifdef AHADEBUG
- printf("%s: inquire %x, %x, %x, %x\n",
- aha->sc_dev.dv_xname,
- inquire.boardid, inquire.spec_opts,
- inquire.revision_1, inquire.revision_2);
-#endif /* AHADEBUG */
- /*
- * If we are a 1542C or 1542CF disable the extended bios so that the
- * mailbox interface is unlocked.
- * No need to check the extended bios flags as some of the
- * extensions that cause us problems are not flagged in that byte.
- */
- if (inquire.boardid == 0x43 || inquire.boardid == 0x44 ||
- inquire.boardid == 0x45) {
- aha_cmd(aha, 0, sizeof(extbios), 0, &extbios, AHA_EXT_BIOS);
-#ifdef AHADEBUG
- printf("%s: extended bios flags %x\n", aha->sc_dev.dv_xname,
- extbios.flags);
-#endif /* AHADEBUG */
- printf("%s: 1542C/CF detected, unlocking mailbox\n",
- aha->sc_dev.dv_xname);
- aha_cmd(aha, 2, 0, 0, 0, AHA_MBX_ENABLE,
- 0, extbios.mailboxlock);
- }
-noinquire:
-
- /*
- * setup dma channel from jumpers and save int
- * level
- */
- delay(1000); /* for Bustek 545 */
- aha_cmd(aha, 0, sizeof(conf), 0, &conf, AHA_CONF_GET);
- switch (conf.chan) {
- case CHAN0:
- aha->sc_drq = 0;
- break;
- case CHAN5:
- aha->sc_drq = 5;
- break;
- case CHAN6:
- aha->sc_drq = 6;
- break;
- case CHAN7:
- aha->sc_drq = 7;
- break;
- default:
- printf("%s: illegal drq setting %x\n", aha->sc_dev.dv_xname,
- conf.chan);
- return EIO;
- }
-
- switch (conf.intr) {
- case INT9:
- aha->sc_irq = 9;
- break;
- case INT10:
- aha->sc_irq = 10;
- break;
- case INT11:
- aha->sc_irq = 11;
- break;
- case INT12:
- aha->sc_irq = 12;
- break;
- case INT14:
- aha->sc_irq = 14;
- break;
- case INT15:
- aha->sc_irq = 15;
- break;
- default:
- printf("%s: illegal irq setting %x\n", aha->sc_dev.dv_xname,
- conf.intr);
- return EIO;
- }
-
- /* who are we on the scsi bus? */
- aha->aha_scsi_dev = conf.scsi_dev;
-
- /*
- * Change the bus on/off times to not clash with other dma users.
- */
- aha_cmd(aha, 1, 0, 0, 0, AHA_BUS_ON_TIME_SET, 7);
- aha_cmd(aha, 1, 0, 0, 0, AHA_BUS_OFF_TIME_SET, 4);
-
- return 0;
-}
-
-/*
- * Start the board, ready for normal operation
- */
-void
-aha_init(aha)
- struct aha_softc *aha;
-{
- u_char ad[3];
- struct isadma_seg mbx_phys[1];
- int i;
-
-#ifdef TUNE_1542
- /*
- * Initialize memory transfer speed
- * Not compiled in by default because it breaks some machines
- */
- if (!aha_set_bus_speed(aha))
- panic("aha_init: cannot set bus speed");
-#endif /* TUNE_1542 */
-
- /*
- * Initialize mail box. This mapping will never be undone.
- */
- if (isadma_map((caddr_t)(&aha->aha_mbx), sizeof(struct aha_mbx),
- mbx_phys, ISADMA_MAP_CONTIG) != 1)
- panic("aha_init: cannot map mail box");
- lto3b(mbx_phys[0].addr, ad);
-
- aha_cmd(aha, 4, 0, 0, 0, AHA_MBX_INIT, AHA_MBX_SIZE,
- ad[0], ad[1], ad[2]);
-
- for (i = 0; i < AHA_MBX_SIZE; i++) {
- aha->aha_mbx.mbo[i].cmd = AHA_MBO_FREE;
- aha->aha_mbx.mbi[i].stat = AHA_MBO_FREE;
- }
-
- /*
- * Set up initial mail box for round-robin operation.
- */
- aha->aha_mbx.tmbo = &aha->aha_mbx.mbo[0];
- aha->aha_mbx.tmbi = &aha->aha_mbx.mbi[0];
-}
-
-void
-ahaminphys(bp)
- struct buf *bp;
-{
-
- if (bp->b_bcount > ((AHA_NSEG - 1) << PGSHIFT))
- bp->b_bcount = ((AHA_NSEG - 1) << PGSHIFT);
- minphys(bp);
-}
-
-/*
- * start a scsi operation given the command and the data address. Also needs
- * the unit, target and lu.
- */
-int
-aha_scsi_cmd(xs)
- struct scsi_xfer *xs;
-{
- struct scsi_link *sc_link = xs->sc_link;
- struct aha_softc *aha = sc_link->adapter_softc;
- struct aha_ccb *ccb;
- struct aha_scat_gath *sg;
- int seg, datalen, flags, mflags;
- struct iovec *iovp;
- struct aha_mbx_out *mbo;
- int s;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("aha_scsi_cmd\n"));
- /*
- * get a ccb to use. If the transfer
- * is from a buf (possibly from interrupt time)
- * then we can't allow it to sleep
- */
- flags = xs->flags;
- if (flags & SCSI_NOSLEEP)
- mflags = ISADMA_MAP_BOUNCE;
- else
- mflags = ISADMA_MAP_BOUNCE | ISADMA_MAP_WAITOK;
- if ((flags & (ITSDONE|INUSE)) != INUSE) {
- printf("%s: done or not in use?\n", aha->sc_dev.dv_xname);
- xs->flags &= ~ITSDONE;
- xs->flags |= INUSE;
- }
- if ((ccb = aha_get_ccb(aha, flags)) == NULL) {
- xs->error = XS_DRIVER_STUFFUP;
- return TRY_AGAIN_LATER;
- }
- ccb->xs = xs;
-
- /*
- * Put all the arguments for the xfer in the ccb
- */
- if (flags & SCSI_RESET) {
- ccb->opcode = AHA_RESET_CCB;
- } else {
- /* can't use S/G if zero length */
- ccb->opcode = (xs->datalen ? AHA_INIT_SCAT_GATH_CCB
- : AHA_INITIATOR_CCB);
- }
- ccb->data_out = 0;
- ccb->data_in = 0;
- ccb->target = sc_link->target;
- ccb->lun = sc_link->lun;
- ccb->scsi_cmd_length = xs->cmdlen;
- ccb->req_sense_length = sizeof(ccb->scsi_sense);
- ccb->host_stat = 0x00;
- ccb->target_stat = 0x00;
- ccb->data_nseg = 0;
-
- if (xs->datalen && (flags & SCSI_RESET) == 0) {
- sg = ((struct aha_ccb *)(ccb->ccb_phys[0].addr))->scat_gath;
- lto3b((vm_offset_t)sg, ccb->data_addr);
- sg = ccb->scat_gath;
- seg = 0;
-#ifdef TFS
- if (flags & SCSI_DATA_UIO) {
- iovp = ((struct uio *)xs->data)->uio_iov;
- datalen = ((struct uio *)xs->data)->uio_iovcnt;
- xs->datalen = 0;
- while (datalen && seg < AHA_NSEG) {
- lto3b(iovp->iov_base, sg->seg_addr);
- lto3b(iovp->iov_len, sg->seg_len);
- xs->datalen += iovp->iov_len;
- SC_DEBUGN(sc_link, SDEV_DB4, ("UIO(0x%x@0x%x)",
- iovp->iov_len, iovp->iov_base));
- sg++;
- iovp++;
- seg++;
- datalen--;
- }
- } else
-#endif /*TFS_ONLY */
- {
- /*
- * Set up the scatter gather block
- */
-
- ccb->data_nseg = isadma_map(xs->data, xs->datalen,
- ccb->data_phys, mflags);
- for (seg = 0; seg < ccb->data_nseg; seg++) {
- lto3b(ccb->data_phys[seg].addr,
- sg[seg].seg_addr);
- lto3b(ccb->data_phys[seg].length,
- sg[seg].seg_len);
- }
- }
- lto3b(ccb->data_nseg * sizeof(struct aha_scat_gath), ccb->data_length);
- if (ccb->data_nseg == 0) {
- printf("%s: aha_scsi_cmd, cannot map\n",
- aha->sc_dev.dv_xname);
- xs->error = XS_DRIVER_STUFFUP;
- aha_free_ccb(aha, ccb, flags);
- return COMPLETE;
- } else if (flags & SCSI_DATA_OUT)
- isadma_copytobuf(xs->data, xs->datalen,
- ccb->data_nseg, ccb->data_phys);
- } else { /* No data xfer, use non S/G values */
- lto3b(0, ccb->data_addr);
- lto3b(0, ccb->data_length);
- }
- ccb->link_id = 0;
- lto3b(0, ccb->link_addr);
-
- /*
- * Put the scsi command in the ccb and start it
- */
- if ((flags & SCSI_RESET) == 0)
- bcopy(xs->cmd, &ccb->scsi_cmd, ccb->scsi_cmd_length);
-
- s = splbio();
-
- isadma_copytobuf((caddr_t)ccb, CCB_PHYS_SIZE, 1, ccb->ccb_phys);
-
- if (aha_send_mbo(aha, AHA_MBO_START, ccb) == NULL) {
- splx(s);
- xs->error = XS_DRIVER_STUFFUP;
- if (ccb->data_nseg)
- isadma_unmap(xs->data, xs->datalen,
- ccb->data_nseg, ccb->data_phys);
- aha_free_ccb(aha, ccb, flags);
- return TRY_AGAIN_LATER;
- }
-
- /*
- * Usually return SUCCESSFULLY QUEUED
- */
- SC_DEBUG(sc_link, SDEV_DB3, ("cmd_sent\n"));
-
- if (VOLATILE_XS(xs)) {
- timeout(aha_timeout, ccb, (xs->timeout * hz) / 1000);
- while ((ccb->xs->flags & ITSDONE) == 0) {
- tsleep(ccb, PRIBIO, "ahawait", 0);
- }
- splx(s);
- if (ccb->data_nseg) {
- if (flags & SCSI_DATA_IN)
- isadma_copyfrombuf(xs->data, xs->datalen,
- ccb->data_nseg, ccb->data_phys);
- isadma_unmap(xs->data, xs->datalen,
- ccb->data_nseg, ccb->data_phys);
- }
- aha_free_ccb(aha, ccb, xs->flags);
- scsi_done(xs);
- return COMPLETE;
- }
-
- if ((flags & SCSI_POLL) == 0) {
- timeout(aha_timeout, ccb, (xs->timeout * hz) / 1000);
- splx(s);
- return SUCCESSFULLY_QUEUED;
- }
-
- splx(s);
-
- /*
- * If we can't use interrupts, poll on completion
- */
- if (aha_poll(aha, xs, xs->timeout)) {
- aha_timeout(ccb);
- if (aha_poll(aha, xs, 2000))
- aha_timeout(ccb);
- }
- return COMPLETE;
-}
-
-/*
- * Poll a particular unit, looking for a particular xs
- */
-int
-aha_poll(aha, xs, count)
- struct aha_softc *aha;
- struct scsi_xfer *xs;
- int count;
-{
-
- /* timeouts are in msec, so we loop in 1000 usec cycles */
- while (count) {
- /*
- * If we had interrupts enabled, would we
- * have got an interrupt?
- */
- if (inb(AHA_INTR_PORT) & AHA_ANY_INTR)
- ahaintr(aha);
- if (xs->flags & ITSDONE)
- return 0;
- delay(1000); /* only happens in boot so ok */
- count--;
- }
- return 1;
-}
-
-#ifdef TUNE_1542
-/*
- * Try all the speeds from slowest to fastest.. if it finds a
- * speed that fails, back off one notch from the last working
- * speed (unless there is no other notch).
- * Returns the nSEC value of the time used
- * or 0 if it could get a working speed (or the NEXT speed
- * failed)
- */
-static struct bus_speed {
- u_char arg;
- int nsecs;
-} aha_bus_speeds[] = {
- {0x88, 100},
- {0x99, 150},
- {0xaa, 200},
- {0xbb, 250},
- {0xcc, 300},
- {0xdd, 350},
- {0xee, 400},
- {0xff, 450}
-};
-
-int
-aha_set_bus_speed(aha)
- struct aha_softc *aha;
-{
- int speed;
- int lastworking;
-
- lastworking = -1;
- for (speed = 7; speed >= 0; speed--) {
- if (!aha_bus_speed_check(aha, speed))
- break;
- lastworking = speed;
- }
- if (lastworking == -1) {
- printf(" no working bus speed");
- return 0;
- }
- printf(", %d nsec ", aha_bus_speeds[lastworking].nsecs);
- if (lastworking == 7) /* is slowest already */
- printf("marginal");
- else {
- lastworking++;
- printf("ok, using %d nsec", aha_bus_speeds[lastworking].nsecs);
- }
- if (!aha_bus_speed_check(aha, lastworking)) {
- printf("test retry failed.. aborting.");
- return 0;
- }
- return 1;
-}
-
-/*
- * Set the DMA speed to the Nth speed and try an xfer. If it
- * fails return 0, if it succeeds return the nSec value selected
- * If there is no such speed return COMPLETE.
- */
-char aha_scratch_buf[256];
-char aha_test_string[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz!@";
-
-int
-aha_bus_speed_check(aha, speed)
- struct aha_softc *aha;
- int speed;
-{
- int numspeeds = sizeof(aha_bus_speeds) / sizeof(struct bus_speed);
- int result, loopcount;
- struct isadma_seg test_phys[1], scratch_phys[1];
- u_char ad[3];
-
- result = 1;
-
- if (isadma_map(aha_scratch_buf, sizeof(aha_scratch_buf),
- scratch_phys, ISADMA_MAP_CONTIG) != 1)
- return 0;
- if (isadma_map(aha_test_string, sizeof(aha_test_string),
- test_phys, ISADMA_MAP_CONTIG) != 1) {
- isadma_unmap(aha_scratch_buf, sizeof(aha_scratch_buf),
- 1, scratch_phys);
- return 0;
- }
- isadma_copytobuf(aha_test_string, sizeof(aha_test_string),
- 1, test_phys);
-
- /*
- * Set the dma-speed
- */
- aha_cmd(aha, 1, 0, 0, 0, AHA_SPEED_SET, aha_bus_speeds[speed].arg);
-
- /*
- * put the test data into the buffer and calculate
- * it's address. Read it onto the board
- */
- for (loopcount = 100; loopcount; loopcount--) {
- lto3b(test_phys[0].addr, ad);
- aha_cmd(aha, 3, 0, 0, 0, AHA_WRITE_FIFO, ad[0], ad[1], ad[2]);
-
- /*
- * Clear the buffer then copy the contents back from the
- * board.
- */
- bzero(aha_scratch_buf, 54);
- isadma_copytobuf(aha_scratch_buf, sizeof(aha_scratch_buf),
- 1, scratch_phys);
-
- lto3b(scratch_phys[0].addr, ad);
- aha_cmd(aha, 3, 0, 0, 0, AHA_READ_FIFO, ad[0], ad[1], ad[2]);
- isadma_copyfrombuf(aha_scratch_buf, sizeof(aha_scratch_buf),
- 1, scratch_phys);
-
- /*
- * Compare the original data and the final data and return the
- * correct value depending upon the result. We only check the
- * first 54 bytes, because that's all the board copies during
- * WRITE_FIFO and READ_FIFO.
- */
- if (bcmp(aha_test_string, aha_scratch_buf, 54)) {
- result = 0; /* failed test */
- break;
- }
- }
-
- isadma_unmap(aha_scratch_buf, sizeof(aha_scratch_buf),
- 1, scratch_phys);
- isadma_unmap(aha_test_string, sizeof(aha_test_string),
- 1, test_phys);
-
- /* copy succeeded; assume speed ok */
- return result;
-}
-#endif /* TUNE_1542 */
-
-void
-aha_timeout(arg)
- void *arg;
-{
- struct aha_ccb *ccb = arg;
- struct scsi_xfer *xs = ccb->xs;
- struct scsi_link *sc_link = xs->sc_link;
- struct aha_softc *aha = sc_link->adapter_softc;
- int s;
-
- sc_print_addr(sc_link);
- printf("timed out");
-
- s = splbio();
-
- /*
- * If The ccb's mbx is not free, then the board has gone south?
- */
- if (aha_ccb_phys_kv(aha, _3btol(ccb->mbx->ccb_addr)) == ccb &&
- ccb->mbx->cmd != AHA_MBO_FREE) {
- printf("%s: not taking commands!\n", aha->sc_dev.dv_xname);
- Debugger();
- }
-
- /*
- * If it has been through before, then
- * a previous abort has failed, don't
- * try abort again
- */
- if (ccb->flags == CCB_ABORTED) {
- /* abort timed out */
- printf(" AGAIN\n");
- ccb->xs->retries = 0;
- aha_done(aha, ccb);
- } else {
- /* abort the operation that has timed out */
- printf("\n");
- ccb->xs->error = XS_TIMEOUT;
- ccb->flags = CCB_ABORTED;
- aha_send_mbo(aha, AHA_MBO_ABORT, ccb);
- /* 2 secs for the abort */
- if ((xs->flags & SCSI_POLL) == 0)
- timeout(aha_timeout, ccb, 2 * hz);
- }
-
- splx(s);
-}
diff --git a/sys/dev/isa/aha284x.c b/sys/dev/isa/aha284x.c
index 749f87840e0..bff15bed8e3 100644
--- a/sys/dev/isa/aha284x.c
+++ b/sys/dev/isa/aha284x.c
@@ -1,4 +1,4 @@
-/* $NetBSD: aha284x.c,v 1.2 1996/01/13 02:06:30 thorpej Exp $ */
+/* $NetBSD: aha284x.c,v 1.4 1996/04/11 22:28:04 cgd Exp $ */
/*
* Copyright (c) 1996 Michael Graff. All rights reserved.
@@ -47,13 +47,12 @@
static int ahe_probe __P((struct device *, void *, void *));
static void ahe_attach __P((struct device *, struct device *, void *));
-struct cfdriver ahecd = {
- NULL, /* devices found */
- "ahe", /* device name */
- ahe_probe, /* match routine */
- ahe_attach, /* attach routine */
- DV_DULL, /* device class */
- sizeof(struct ahc_softc), /* size of private dev data */
+struct cfattach ahe_ca = {
+ sizeof(struct ahc_softc), ahe_probe, ahe_attach
+};
+
+struct cfdriver ahe_cd = {
+ NULL, "ahe", DV_DULL
};
/*
@@ -179,8 +178,8 @@ ahe_attach(parent, self, aux)
#ifdef NEWCONFIG
isa_establish(&ahc->sc_id, &ahc->sc_dev);
#endif
- ahc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_BIO,
- ahcintr, ahc, ahc->sc_dev.dv_xname);
+ ahc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_BIO, ahcintr, ahc, ahc->sc_dev.dv_xname);
/*
* attach the devices on the bus
diff --git a/sys/dev/isa/ahareg.h b/sys/dev/isa/ahareg.h
new file mode 100644
index 00000000000..a55684bf044
--- /dev/null
+++ b/sys/dev/isa/ahareg.h
@@ -0,0 +1,264 @@
+typedef u_int8_t physaddr[3];
+typedef u_int8_t physlen[3];
+#define ltophys _lto3b
+#define phystol _3btol
+
+/*
+ * I/O port offsets
+ */
+#define AHA_CTRL_PORT 0 /* control (wo) */
+#define AHA_STAT_PORT 0 /* status (ro) */
+#define AHA_CMD_PORT 1 /* command (wo) */
+#define AHA_DATA_PORT 1 /* data (ro) */
+#define AHA_INTR_PORT 2 /* interrupt status (ro) */
+
+/*
+ * AHA_CTRL bits
+ */
+#define AHA_CTRL_HRST 0x80 /* Hardware reset */
+#define AHA_CTRL_SRST 0x40 /* Software reset */
+#define AHA_CTRL_IRST 0x20 /* Interrupt reset */
+#define AHA_CTRL_SCRST 0x10 /* SCSI bus reset */
+
+/*
+ * AHA_STAT bits
+ */
+#define AHA_STAT_STST 0x80 /* Self test in Progress */
+#define AHA_STAT_DIAGF 0x40 /* Diagnostic Failure */
+#define AHA_STAT_INIT 0x20 /* Mbx Init required */
+#define AHA_STAT_IDLE 0x10 /* Host Adapter Idle */
+#define AHA_STAT_CDF 0x08 /* cmd/data out port full */
+#define AHA_STAT_DF 0x04 /* Data in port full */
+#define AHA_STAT_INVDCMD 0x01 /* Invalid command */
+
+/*
+ * AHA_CMD opcodes
+ */
+#define AHA_NOP 0x00 /* No operation */
+#define AHA_MBX_INIT 0x01 /* Mbx initialization */
+#define AHA_START_SCSI 0x02 /* start scsi command */
+#define AHA_INQUIRE_REVISION 0x04 /* Adapter Inquiry */
+#define AHA_MBO_INTR_EN 0x05 /* Enable MBO available interrupt */
+/*#define AHA_SEL_TIMEOUT_SET 0x06 /* set selection time-out */
+/*#define AHA_BUS_ON_TIME_SET 0x07 /* set bus-on time */
+/*#define AHA_BUS_OFF_TIME_SET 0x08 /* set bus-off time */
+/*#define AHA_SPEED_SET 0x09 /* set transfer speed */
+#define AHA_INQUIRE_DEVICES 0x0a /* return installed devices 0-7 */
+#define AHA_INQUIRE_CONFIG 0x0b /* return configuration data */
+#define AHA_TARGET_EN 0x0c /* enable target mode */
+#define AHA_INQUIRE_SETUP 0x0d /* return setup data */
+#define AHA_ECHO 0x1e /* Echo command data */
+#define AHA_INQUIRE_DEVICES_2 0x23 /* return installed devices 8-15 */
+#define AHA_EXT_BIOS 0x28 /* return extended bios info */
+#define AHA_MBX_ENABLE 0x29 /* enable mail box interface */
+
+/*
+ * AHA_INTR bits
+ */
+#define AHA_INTR_ANYINTR 0x80 /* Any interrupt */
+#define AHA_INTR_SCRD 0x08 /* SCSI reset detected */
+#define AHA_INTR_HACC 0x04 /* Command complete */
+#define AHA_INTR_MBOA 0x02 /* MBX out empty */
+#define AHA_INTR_MBIF 0x01 /* MBX in full */
+
+struct aha_mbx_out {
+ u_char cmd;
+ physaddr ccb_addr;
+};
+
+struct aha_mbx_in {
+ u_char stat;
+ physaddr ccb_addr;
+};
+
+/*
+ * mbo.cmd values
+ */
+#define AHA_MBO_FREE 0x0 /* MBO entry is free */
+#define AHA_MBO_START 0x1 /* MBO activate entry */
+#define AHA_MBO_ABORT 0x2 /* MBO abort entry */
+
+/*
+ * mbi.stat values
+ */
+#define AHA_MBI_FREE 0x0 /* MBI entry is free */
+#define AHA_MBI_OK 0x1 /* completed without error */
+#define AHA_MBI_ABORT 0x2 /* aborted ccb */
+#define AHA_MBI_UNKNOWN 0x3 /* Tried to abort invalid CCB */
+#define AHA_MBI_ERROR 0x4 /* Completed with error */
+
+/* FOR OLD VERSIONS OF THE !%$@ this may have to be 16 (yuk) */
+#define AHA_NSEG 17 /* Number of scatter gather segments <= 16 */
+ /* allow 64 K i/o (min) */
+
+struct aha_scat_gath {
+ physlen seg_len;
+ physaddr seg_addr;
+};
+
+struct aha_ccb {
+ u_char opcode;
+ u_char lun:3;
+ u_char data_in:1; /* must be 0 */
+ u_char data_out:1; /* must be 0 */
+ u_char target:3;
+ u_char scsi_cmd_length;
+ u_char req_sense_length;
+ physlen data_length;
+ physaddr data_addr;
+ physaddr link_addr;
+ u_char link_id;
+ u_char host_stat;
+ u_char target_stat;
+ u_char reserved[2];
+ struct scsi_generic scsi_cmd;
+ struct scsi_sense_data scsi_sense;
+ struct aha_scat_gath scat_gath[AHA_NSEG];
+ /*----------------------------------------------------------------*/
+ TAILQ_ENTRY(aha_ccb) chain;
+ struct aha_ccb *nexthash;
+ long hashkey;
+ struct scsi_xfer *xs; /* the scsi_xfer for this cmd */
+ int flags;
+#define CCB_ALLOC 0x01
+#define CCB_ABORT 0x02
+#ifdef AHADIAG
+#define CCB_SENDING 0x04
+#endif
+ int timeout;
+};
+
+/*
+ * opcode fields
+ */
+#define AHA_INITIATOR_CCB 0x00 /* SCSI Initiator CCB */
+#define AHA_TARGET_CCB 0x01 /* SCSI Target CCB */
+#define AHA_INIT_SCAT_GATH_CCB 0x02 /* SCSI Initiator with scatter gather */
+#define AHA_RESET_CCB 0x81 /* SCSI Bus reset */
+
+/*
+ * aha_ccb.host_stat values
+ */
+#define AHA_OK 0x00 /* cmd ok */
+#define AHA_LINK_OK 0x0a /* Link cmd ok */
+#define AHA_LINK_IT 0x0b /* Link cmd ok + int */
+#define AHA_SEL_TIMEOUT 0x11 /* Selection time out */
+#define AHA_OVER_UNDER 0x12 /* Data over/under run */
+#define AHA_BUS_FREE 0x13 /* Bus dropped at unexpected time */
+#define AHA_INV_BUS 0x14 /* Invalid bus phase/sequence */
+#define AHA_BAD_MBO 0x15 /* Incorrect MBO cmd */
+#define AHA_BAD_CCB 0x16 /* Incorrect ccb opcode */
+#define AHA_BAD_LINK 0x17 /* Not same values of LUN for links */
+#define AHA_INV_TARGET 0x18 /* Invalid target direction */
+#define AHA_CCB_DUP 0x19 /* Duplicate CCB received */
+#define AHA_INV_CCB 0x1a /* Invalid CCB or segment list */
+
+struct aha_revision {
+ struct {
+ u_char opcode;
+ } cmd;
+ struct {
+ u_char boardid; /* type of board */
+ /* 0x31 = AHA-1540 */
+ /* 0x41 = AHA-1540A/1542A/1542B */
+ /* 0x42 = AHA-1640 */
+ /* 0x43 = AHA-1542C */
+ /* 0x44 = AHA-1542CF */
+ /* 0x45 = AHA-1542CF, BIOS v2.01 */
+ /* 0x46 = AHA-1542CP */
+ u_char spec_opts; /* special options ID */
+ /* 0x41 = Board is standard model */
+ u_char revision_1; /* firmware revision [0-9A-Z] */
+ u_char revision_2; /* firmware revision [0-9A-Z] */
+ } reply;
+};
+
+struct aha_extbios {
+ struct {
+ u_char opcode;
+ } cmd;
+ struct {
+ u_char flags; /* Bit 3 == 1 extended bios enabled */
+ u_char mailboxlock; /* mail box lock code to unlock it */
+ } reply;
+};
+
+struct aha_toggle {
+ struct {
+ u_char opcode;
+ u_char enable;
+ } cmd;
+};
+
+struct aha_config {
+ struct {
+ u_char opcode;
+ } cmd;
+ struct {
+ u_char chan;
+ u_char intr;
+ u_char scsi_dev:3;
+ u_char :5;
+ } reply;
+};
+
+struct aha_mailbox {
+ struct {
+ u_char opcode;
+ u_char nmbx;
+ physaddr addr;
+ } cmd;
+};
+
+struct aha_unlock {
+ struct {
+ u_char opcode;
+ u_char junk;
+ u_char magic;
+ } cmd;
+};
+
+struct aha_devices {
+ struct {
+ u_char opcode;
+ } cmd;
+ struct {
+ u_char junk[8];
+ } reply;
+};
+
+struct aha_setup {
+ struct {
+ u_char opcode;
+ u_char len;
+ } cmd;
+ struct {
+ u_char sync_neg:1;
+ u_char parity:1;
+ u_char :6;
+ u_char speed;
+ u_char bus_on;
+ u_char bus_off;
+ u_char num_mbx;
+ u_char mbx[3];
+ struct {
+ u_char offset:4;
+ u_char period:3;
+ u_char valid:1;
+ } sync[8];
+ u_char disc_sts;
+ } reply;
+};
+
+#define INT9 0x01
+#define INT10 0x02
+#define INT11 0x04
+#define INT12 0x08
+#define INT14 0x20
+#define INT15 0x40
+
+#define EISADMA 0x00
+#define CHAN0 0x01
+#define CHAN5 0x20
+#define CHAN6 0x40
+#define CHAN7 0x80
diff --git a/sys/dev/isa/aic6360.c b/sys/dev/isa/aic6360.c
index c159feff414..f88a484ea62 100644
--- a/sys/dev/isa/aic6360.c
+++ b/sys/dev/isa/aic6360.c
@@ -1,4 +1,7 @@
-/* $NetBSD: aic6360.c,v 1.36.2.1 1995/10/18 21:40:12 pk Exp $ */
+/* $OpenBSD: aic6360.c,v 1.7 1996/04/21 22:22:39 deraadt Exp $ */
+/* $NetBSD: aic6360.c,v 1.44 1996/04/11 22:28:08 cgd Exp $ */
+
+#define integrate static inline
/*
* Copyright (c) 1994, 1995 Charles Hannum. All rights reserved.
@@ -13,7 +16,7 @@
* 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 Charles Hannum.
+ * This product includes software developed by Charles M. Hannum.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
@@ -105,6 +108,8 @@
*/
#define AIC_DEBUG 1
+#define AIC_ABORT_TIMEOUT 2000 /* time to wait for abort */
+
/* End of customizable parameters */
#if AIC_USE_EISA_DMA || AIC_USE_ISA_DMA
@@ -136,45 +141,44 @@
*/
/* AIC6360 definitions */
-#define IOBASE sc->sc_iobase
-#define SCSISEQ (IOBASE + 0x00) /* SCSI sequence control */
-#define SXFRCTL0 (IOBASE + 0x01) /* SCSI transfer control 0 */
-#define SXFRCTL1 (IOBASE + 0x02) /* SCSI transfer control 1 */
-#define SCSISIG (IOBASE + 0x03) /* SCSI signal in/out */
-#define SCSIRATE (IOBASE + 0x04) /* SCSI rate control */
-#define SCSIID (IOBASE + 0x05) /* SCSI ID */
-#define SELID (IOBASE + 0x05) /* Selection/Reselection ID */
-#define SCSIDAT (IOBASE + 0x06) /* SCSI Latched Data */
-#define SCSIBUS (IOBASE + 0x07) /* SCSI Data Bus*/
-#define STCNT0 (IOBASE + 0x08) /* SCSI transfer count */
-#define STCNT1 (IOBASE + 0x09)
-#define STCNT2 (IOBASE + 0x0a)
-#define CLRSINT0 (IOBASE + 0x0b) /* Clear SCSI interrupts 0 */
-#define SSTAT0 (IOBASE + 0x0b) /* SCSI interrupt status 0 */
-#define CLRSINT1 (IOBASE + 0x0c) /* Clear SCSI interrupts 1 */
-#define SSTAT1 (IOBASE + 0x0c) /* SCSI status 1 */
-#define SSTAT2 (IOBASE + 0x0d) /* SCSI status 2 */
-#define SCSITEST (IOBASE + 0x0e) /* SCSI test control */
-#define SSTAT3 (IOBASE + 0x0e) /* SCSI status 3 */
-#define CLRSERR (IOBASE + 0x0f) /* Clear SCSI errors */
-#define SSTAT4 (IOBASE + 0x0f) /* SCSI status 4 */
-#define SIMODE0 (IOBASE + 0x10) /* SCSI interrupt mode 0 */
-#define SIMODE1 (IOBASE + 0x11) /* SCSI interrupt mode 1 */
-#define DMACNTRL0 (IOBASE + 0x12) /* DMA control 0 */
-#define DMACNTRL1 (IOBASE + 0x13) /* DMA control 1 */
-#define DMASTAT (IOBASE + 0x14) /* DMA status */
-#define FIFOSTAT (IOBASE + 0x15) /* FIFO status */
-#define DMADATA (IOBASE + 0x16) /* DMA data */
-#define DMADATAL (IOBASE + 0x16) /* DMA data low byte */
-#define DMADATAH (IOBASE + 0x17) /* DMA data high byte */
-#define BRSTCNTRL (IOBASE + 0x18) /* Burst Control */
-#define DMADATALONG (IOBASE + 0x18)
-#define PORTA (IOBASE + 0x1a) /* Port A */
-#define PORTB (IOBASE + 0x1b) /* Port B */
-#define REV (IOBASE + 0x1c) /* Revision (001 for 6360) */
-#define STACK (IOBASE + 0x1d) /* Stack */
-#define TEST (IOBASE + 0x1e) /* Test register */
-#define ID (IOBASE + 0x1f) /* ID register */
+#define SCSISEQ 0x00 /* SCSI sequence control */
+#define SXFRCTL0 0x01 /* SCSI transfer control 0 */
+#define SXFRCTL1 0x02 /* SCSI transfer control 1 */
+#define SCSISIG 0x03 /* SCSI signal in/out */
+#define SCSIRATE 0x04 /* SCSI rate control */
+#define SCSIID 0x05 /* SCSI ID */
+#define SELID 0x05 /* Selection/Reselection ID */
+#define SCSIDAT 0x06 /* SCSI Latched Data */
+#define SCSIBUS 0x07 /* SCSI Data Bus*/
+#define STCNT0 0x08 /* SCSI transfer count */
+#define STCNT1 0x09
+#define STCNT2 0x0a
+#define CLRSINT0 0x0b /* Clear SCSI interrupts 0 */
+#define SSTAT0 0x0b /* SCSI interrupt status 0 */
+#define CLRSINT1 0x0c /* Clear SCSI interrupts 1 */
+#define SSTAT1 0x0c /* SCSI status 1 */
+#define SSTAT2 0x0d /* SCSI status 2 */
+#define SCSITEST 0x0e /* SCSI test control */
+#define SSTAT3 0x0e /* SCSI status 3 */
+#define CLRSERR 0x0f /* Clear SCSI errors */
+#define SSTAT4 0x0f /* SCSI status 4 */
+#define SIMODE0 0x10 /* SCSI interrupt mode 0 */
+#define SIMODE1 0x11 /* SCSI interrupt mode 1 */
+#define DMACNTRL0 0x12 /* DMA control 0 */
+#define DMACNTRL1 0x13 /* DMA control 1 */
+#define DMASTAT 0x14 /* DMA status */
+#define FIFOSTAT 0x15 /* FIFO status */
+#define DMADATA 0x16 /* DMA data */
+#define DMADATAL 0x16 /* DMA data low byte */
+#define DMADATAH 0x17 /* DMA data high byte */
+#define BRSTCNTRL 0x18 /* Burst Control */
+#define DMADATALONG 0x18
+#define PORTA 0x1a /* Port A */
+#define PORTB 0x1b /* Port B */
+#define REV 0x1c /* Revision (001 for 6360) */
+#define STACK 0x1d /* Stack */
+#define TEST 0x1e /* Test register */
+#define ID 0x1f /* ID register */
#define IDSTRING "(C)1991ADAPTECAIC6360 "
@@ -455,10 +459,12 @@ struct aic_acb {
TAILQ_ENTRY(aic_acb) chain;
struct scsi_xfer *xs; /* SCSI xfer ctrl block from above */
int flags;
-#define ACB_FREE 0
-#define ACB_ACTIVE 1
-#define ACB_CHKSENSE 2
-#define ACB_ABORTED 3
+#define ACB_ALLOC 0x01
+#define ACB_NEXUS 0x02
+#define ACB_SENSE 0x04
+#define ACB_ABORT 0x40
+#define ACB_RESET 0x80
+ int timeout;
};
/*
@@ -506,13 +512,14 @@ struct aic_softc {
u_char sc_phase; /* Current bus phase */
u_char sc_prevphase; /* Previous bus phase */
u_char sc_state; /* State applicable to the adapter */
-#define AIC_IDLE 0x01
-#define AIC_SELECTING 0x02 /* SCSI command is arbiting */
-#define AIC_RESELECTED 0x04 /* Has been reselected */
-#define AIC_CONNECTED 0x08 /* Actively using the SCSI bus */
-#define AIC_DISCONNECT 0x10 /* MSG_DISCONNECT received */
-#define AIC_CMDCOMPLETE 0x20 /* MSG_CMDCOMPLETE received */
-#define AIC_CLEANING 0x40
+#define AIC_INIT 0
+#define AIC_IDLE 1
+#define AIC_SELECTING 2 /* SCSI command is arbiting */
+#define AIC_RESELECTED 3 /* Has been reselected */
+#define AIC_CONNECTED 4 /* Actively using the SCSI bus */
+#define AIC_DISCONNECT 5 /* MSG_DISCONNECT received */
+#define AIC_CMDCOMPLETE 6 /* MSG_CMDCOMPLETE received */
+#define AIC_CLEANING 7
u_char sc_flags;
#define AIC_DROP_MSGIN 0x01 /* Discard all msgs (parity err detected) */
#define AIC_ABORTING 0x02 /* Bailing out */
@@ -526,10 +533,10 @@ struct aic_softc {
u_char sc_currmsg; /* Message currently ready to transmit */
#define SEND_DEV_RESET 0x01
#define SEND_PARITY_ERROR 0x02
-#define SEND_ABORT 0x04
+#define SEND_INIT_DET_ERR 0x04
#define SEND_REJECT 0x08
-#define SEND_INIT_DET_ERR 0x10
-#define SEND_IDENTIFY 0x20
+#define SEND_IDENTIFY 0x10
+#define SEND_ABORT 0x20
#define SEND_SDTR 0x40
#define SEND_WDTR 0x80
#define AIC_MAX_MSG_LEN 8
@@ -580,6 +587,8 @@ void aic_done __P((struct aic_softc *, struct aic_acb *));
void aic_dequeue __P((struct aic_softc *, struct aic_acb *));
int aic_scsi_cmd __P((struct scsi_xfer *));
int aic_poll __P((struct aic_softc *, struct scsi_xfer *, int));
+integrate void aic_sched_msgout __P((struct aic_softc *, u_char));
+integrate void aic_setsync __P((struct aic_softc *, struct aic_tinfo *));
void aic_select __P((struct aic_softc *, struct aic_acb *));
void aic_timeout __P((void *));
int aic_find __P((struct aic_softc *));
@@ -592,8 +601,12 @@ void aic_dump_driver();
void aic_dump6360();
#endif
-struct cfdriver aiccd = {
- NULL, "aic", aicprobe, aicattach, DV_DULL, sizeof(struct aic_softc)
+struct cfattach aic_ca = {
+ sizeof(struct aic_softc), aicprobe, aicattach
+};
+
+struct cfdriver aic_cd = {
+ NULL, "aic", DV_DULL
};
struct scsi_adapter aic_switch = {
@@ -668,12 +681,13 @@ int
aic_find(sc)
struct aic_softc *sc;
{
+ int iobase = sc->sc_iobase;
char chip_id[sizeof(IDSTRING)]; /* For chips that support it */
char *start;
int i;
/* Remove aic6360 from possible powerdown mode */
- outb(DMACNTRL0, 0);
+ outb(iobase + DMACNTRL0, 0);
/* Thanks to mark@aggregate.com for the new method for detecting
* whether the chip is present or not. Bonus: may also work for
@@ -687,13 +701,13 @@ aic_find(sc)
*/
/* Push the sequence 0,1,..,15 on the stack */
#define STSIZE 16
- outb(DMACNTRL1, 0); /* Reset stack pointer */
+ outb(iobase + DMACNTRL1, 0); /* Reset stack pointer */
for (i = 0; i < STSIZE; i++)
- outb(STACK, i);
+ outb(iobase + STACK, i);
/* See if we can pull out the same sequence */
- outb(DMACNTRL1, 0);
- for (i = 0; i < STSIZE && inb(STACK) == i; i++)
+ outb(iobase + DMACNTRL1, 0);
+ for (i = 0; i < STSIZE && inb(iobase + STACK) == i; i++)
;
if (i != STSIZE) {
AIC_START(("STACK futzed at %d.\n", i));
@@ -704,10 +718,10 @@ aic_find(sc)
* now only used for informational purposes.
*/
bzero(chip_id, sizeof(chip_id));
- insb(ID, chip_id, sizeof(IDSTRING)-1);
+ insb(iobase + ID, chip_id, sizeof(IDSTRING)-1);
AIC_START(("AIC found at 0x%x ", sc->sc_iobase));
AIC_START(("ID: %s ",chip_id));
- AIC_START(("chip revision %d\n",(int)inb(REV)));
+ AIC_START(("chip revision %d\n",(int)inb(iobase + REV)));
sc->sc_initiator = 7;
sc->sc_freq = 20; /* XXXX Assume 20 MHz. */
@@ -749,7 +763,7 @@ aicattach(parent, self, aux)
struct aic_softc *sc = (void *)self;
AIC_TRACE(("aicattach "));
- sc->sc_state = 0;
+ sc->sc_state = AIC_INIT;
aic_init(sc); /* Init chip and driver */
/*
@@ -766,8 +780,8 @@ aicattach(parent, self, aux)
#ifdef NEWCONFIG
isa_establish(&sc->sc_id, &sc->sc_dev);
#endif
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_BIO, aicintr,
- sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_BIO, aicintr, sc, sc->sc_dev.dv_xname);
config_found(self, &sc->sc_link, aicprint);
}
@@ -782,32 +796,33 @@ void
aic_reset(sc)
struct aic_softc *sc;
{
+ int iobase = sc->sc_iobase;
- outb(SCSITEST, 0); /* Doc. recommends to clear these two */
- outb(TEST, 0); /* registers before operations commence */
+ outb(iobase + SCSITEST, 0); /* Doc. recommends to clear these two */
+ outb(iobase + TEST, 0); /* registers before operations commence */
/* Reset SCSI-FIFO and abort any transfers */
- outb(SXFRCTL0, CHEN|CLRCH|CLRSTCNT);
+ outb(iobase + SXFRCTL0, CHEN | CLRCH | CLRSTCNT);
/* Reset DMA-FIFO */
- outb(DMACNTRL0, RSTFIFO);
- outb(DMACNTRL1, 0);
+ outb(iobase + DMACNTRL0, RSTFIFO);
+ outb(iobase + DMACNTRL1, 0);
- outb(SCSISEQ, 0); /* Disable all selection features */
- outb(SXFRCTL1, 0);
+ outb(iobase + SCSISEQ, 0); /* Disable all selection features */
+ outb(iobase + SXFRCTL1, 0);
- outb(SIMODE0, 0x00); /* Disable some interrupts */
- outb(CLRSINT0, 0x7f); /* Clear a slew of interrupts */
+ outb(iobase + SIMODE0, 0x00); /* Disable some interrupts */
+ outb(iobase + CLRSINT0, 0x7f); /* Clear a slew of interrupts */
- outb(SIMODE1, 0x00); /* Disable some more interrupts */
- outb(CLRSINT1, 0xef); /* Clear another slew of interrupts */
+ outb(iobase + SIMODE1, 0x00); /* Disable some more interrupts */
+ outb(iobase + CLRSINT1, 0xef); /* Clear another slew of interrupts */
- outb(SCSIRATE, 0); /* Disable synchronous transfers */
+ outb(iobase + SCSIRATE, 0); /* Disable synchronous transfers */
- outb(CLRSERR, 0x07); /* Haven't seen ant errors (yet) */
+ outb(iobase + CLRSERR, 0x07); /* Haven't seen ant errors (yet) */
- outb(SCSIID, sc->sc_initiator << OID_S); /* Set our SCSI-ID */
- outb(BRSTCNTRL, EISA_BRST_TIM);
+ outb(iobase + SCSIID, sc->sc_initiator << OID_S); /* Set our SCSI-ID */
+ outb(iobase + BRSTCNTRL, EISA_BRST_TIM);
}
/* Pull the SCSI RST line for 500 us */
@@ -815,10 +830,11 @@ void
aic_scsi_reset(sc)
struct aic_softc *sc;
{
+ int iobase = sc->sc_iobase;
- outb(SCSISEQ, SCSIRSTO);
+ outb(iobase + SCSISEQ, SCSIRSTO);
delay(500);
- outb(SCSISEQ, 0);
+ outb(iobase + SCSISEQ, 0);
delay(50);
}
@@ -829,6 +845,7 @@ void
aic_init(sc)
struct aic_softc *sc;
{
+ int iobase = sc->sc_iobase;
struct aic_acb *acb;
int r;
@@ -836,7 +853,7 @@ aic_init(sc)
aic_scsi_reset(sc);
aic_reset(sc);
- if (sc->sc_state == 0) {
+ if (sc->sc_state == AIC_INIT) {
/* First time through; initialize. */
TAILQ_INIT(&sc->ready_list);
TAILQ_INIT(&sc->nexus_list);
@@ -885,7 +902,7 @@ aic_init(sc)
}
sc->sc_state = AIC_IDLE;
- outb(DMACNTRL0, INTEN);
+ outb(iobase + DMACNTRL0, INTEN);
}
void
@@ -898,7 +915,7 @@ aic_free_acb(sc, acb, flags)
s = splbio();
- acb->flags = ACB_FREE;
+ acb->flags = 0;
TAILQ_INSERT_HEAD(&sc->free_list, acb, chain);
/*
@@ -926,7 +943,7 @@ aic_get_acb(sc, flags)
tsleep(&sc->free_list, PRIBIO, "aicacb", 0);
if (acb) {
TAILQ_REMOVE(&sc->free_list, acb, chain);
- acb->flags = ACB_ACTIVE;
+ acb->flags |= ACB_ALLOC;
}
splx(s);
@@ -973,12 +990,6 @@ aic_scsi_cmd(xs)
sc_link->target));
flags = xs->flags;
- if ((flags & (ITSDONE|INUSE)) != INUSE) {
- printf("%s: done or not in use?\n", sc->sc_dev.dv_xname);
- xs->flags &= ~ITSDONE;
- xs->flags |= INUSE;
- }
-
if ((acb = aic_get_acb(sc, flags)) == NULL) {
xs->error = XS_DRIVER_STUFFUP;
return TRY_AGAIN_LATER;
@@ -986,10 +997,18 @@ aic_scsi_cmd(xs)
/* Initialize acb */
acb->xs = xs;
- bcopy(xs->cmd, &acb->scsi_cmd, xs->cmdlen);
- acb->scsi_cmd_length = xs->cmdlen;
- acb->data_addr = xs->data;
- acb->data_length = xs->datalen;
+ acb->timeout = xs->timeout;
+
+ if (xs->flags & SCSI_RESET) {
+ acb->flags |= ACB_RESET;
+ acb->scsi_cmd_length = 0;
+ acb->data_length = 0;
+ } else {
+ bcopy(xs->cmd, &acb->scsi_cmd, xs->cmdlen);
+ acb->scsi_cmd_length = xs->cmdlen;
+ acb->data_addr = xs->data;
+ acb->data_length = xs->datalen;
+ }
acb->target_stat = 0;
s = splbio();
@@ -998,18 +1017,15 @@ aic_scsi_cmd(xs)
if (sc->sc_state == AIC_IDLE)
aic_sched(sc);
- if ((flags & SCSI_POLL) == 0) { /* Almost done. Wait outside */
- timeout(aic_timeout, acb, (xs->timeout * hz) / 1000);
- splx(s);
- return SUCCESSFULLY_QUEUED;
- }
-
splx(s);
+ if ((flags & SCSI_POLL) == 0)
+ return SUCCESSFULLY_QUEUED;
+
/* Not allowed to use interrupts, use polling instead */
- if (aic_poll(sc, xs, xs->timeout)) {
+ if (aic_poll(sc, xs, acb->timeout)) {
aic_timeout(acb);
- if (aic_poll(sc, xs, 2000))
+ if (aic_poll(sc, xs, acb->timeout))
aic_timeout(acb);
}
return COMPLETE;
@@ -1038,6 +1054,7 @@ aic_poll(sc, xs, count)
struct scsi_xfer *xs;
int count;
{
+ int iobase = sc->sc_iobase;
AIC_TRACE(("aic_poll "));
while (count) {
@@ -1045,7 +1062,7 @@ aic_poll(sc, xs, count)
* If we had interrupts enabled, would we
* have got an interrupt?
*/
- if ((inb(DMASTAT) & INTSTAT) != 0)
+ if ((inb(iobase + DMASTAT) & INTSTAT) != 0)
aicintr(sc);
if ((xs->flags & ITSDONE) != 0)
return 0;
@@ -1059,32 +1076,36 @@ aic_poll(sc, xs, count)
* LOW LEVEL SCSI UTILITIES
*/
-#define aic_sched_msgout(m) \
- do { \
- if (sc->sc_msgpriq == 0) \
- outb(SCSISIG, sc->sc_phase|ATNO); \
- sc->sc_msgpriq |= (m); \
- } while (0)
+integrate void
+aic_sched_msgout(sc, m)
+ struct aic_softc *sc;
+ u_char m;
+{
+ int iobase = sc->sc_iobase;
+
+ if (sc->sc_msgpriq == 0)
+ outb(iobase + SCSISIG, sc->sc_phase | ATNO);
+ sc->sc_msgpriq |= m;
+}
-#if AIC_USE_SYNCHRONOUS
/*
* Set synchronous transfer offset and period.
*/
-static inline void
+integrate void
aic_setsync(sc, ti)
struct aic_softc *sc;
struct aic_tinfo *ti;
{
+#if AIC_USE_SYNCHRONOUS
+ int iobase = sc->sc_iobase;
if (ti->offset != 0)
- outb(SCSIRATE,
+ outb(iobase + SCSIRATE,
((ti->period * sc->sc_freq) / 250 - 2) << 4 | ti->offset);
else
- outb(SCSIRATE, 0);
-}
-#else
-#define aic_setsync(sc, ti)
+ outb(iobase + SCSIRATE, 0);
#endif
+}
/*
* Start a selection. This is used by aic_sched() to select an idle target,
@@ -1098,15 +1119,16 @@ aic_select(sc, acb)
struct scsi_link *sc_link = acb->xs->sc_link;
int target = sc_link->target;
struct aic_tinfo *ti = &sc->sc_tinfo[target];
+ int iobase = sc->sc_iobase;
- outb(SCSIID, sc->sc_initiator << OID_S | target);
+ outb(iobase + SCSIID, sc->sc_initiator << OID_S | target);
aic_setsync(sc, ti);
- outb(SXFRCTL1, STIMO_256ms|ENSTIMER);
+ outb(iobase + SXFRCTL1, STIMO_256ms | ENSTIMER);
/* Always enable reselections. */
- outb(SIMODE0, ENSELDI|ENSELDO);
- outb(SIMODE1, ENSCSIRST|ENSELTIMO);
- outb(SCSISEQ, ENRESELI|ENSELO|ENAUTOATNO);
+ outb(iobase + SIMODE0, ENSELDI | ENSELDO);
+ outb(iobase + SIMODE1, ENSCSIRST | ENSELTIMO);
+ outb(iobase + SCSISEQ, ENRESELI | ENSELO | ENAUTOATNO);
sc->sc_state = AIC_SELECTING;
}
@@ -1162,6 +1184,11 @@ aic_reselect(sc, message)
ti->lubusy |= (1 << lun);
aic_setsync(sc, ti);
+ if (acb->flags & ACB_RESET)
+ aic_sched_msgout(sc, SEND_DEV_RESET);
+ else if (acb->flags & ACB_ABORT)
+ aic_sched_msgout(sc, SEND_ABORT);
+
/* Do an implicit RESTORE POINTERS. */
sc->sc_dp = acb->data_addr;
sc->sc_dleft = acb->data_length;
@@ -1171,13 +1198,11 @@ aic_reselect(sc, message)
return (0);
reset:
- sc->sc_flags |= AIC_ABORTING;
- aic_sched_msgout(SEND_DEV_RESET);
+ aic_sched_msgout(sc, SEND_DEV_RESET);
return (1);
abort:
- sc->sc_flags |= AIC_ABORTING;
- aic_sched_msgout(SEND_ABORT);
+ aic_sched_msgout(sc, SEND_ABORT);
return (1);
}
@@ -1194,12 +1219,13 @@ aic_sched(sc)
struct aic_acb *acb;
struct scsi_link *sc_link;
struct aic_tinfo *ti;
+ int iobase = sc->sc_iobase;
/*
* Find first acb in ready queue that is for a target/lunit pair that
* is not busy.
*/
- outb(CLRSINT1, CLRSELTIMO|CLRBUSFREE|CLRSCSIPERR);
+ outb(iobase + CLRSINT1, CLRSELTIMO | CLRBUSFREE | CLRSCSIPERR);
for (acb = sc->ready_list.tqh_first; acb != NULL;
acb = acb->chain.tqe_next) {
sc_link = acb->xs->sc_link;
@@ -1217,11 +1243,44 @@ aic_sched(sc)
}
AIC_MISC(("idle "));
/* Nothing to start; just enable reselections and wait. */
- outb(SIMODE0, ENSELDI);
- outb(SIMODE1, ENSCSIRST);
- outb(SCSISEQ, ENRESELI);
+ outb(iobase + SIMODE0, ENSELDI);
+ outb(iobase + SIMODE1, ENSCSIRST);
+ outb(iobase + SCSISEQ, ENRESELI);
}
+void
+aic_sense(sc, acb)
+ struct aic_softc *sc;
+ struct aic_acb *acb;
+{
+ struct scsi_xfer *xs = acb->xs;
+ struct scsi_link *sc_link = xs->sc_link;
+ struct aic_tinfo *ti = &sc->sc_tinfo[sc_link->target];
+ struct scsi_sense *ss = (void *)&acb->scsi_cmd;
+
+ AIC_MISC(("requesting sense "));
+ /* Next, setup a request sense command block */
+ bzero(ss, sizeof(*ss));
+ ss->opcode = REQUEST_SENSE;
+ ss->byte2 = sc_link->lun << 5;
+ ss->length = sizeof(struct scsi_sense_data);
+ acb->scsi_cmd_length = sizeof(*ss);
+ acb->data_addr = (char *)&xs->sense;
+ acb->data_length = sizeof(struct scsi_sense_data);
+ acb->flags |= ACB_SENSE;
+ ti->senses++;
+ if (acb->flags & ACB_NEXUS)
+ ti->lubusy &= ~(1 << sc_link->lun);
+ if (acb == sc->sc_nexus) {
+ aic_select(sc, acb);
+ } else {
+ aic_dequeue(sc, acb);
+ TAILQ_INSERT_HEAD(&sc->ready_list, acb, chain);
+ if (sc->sc_state == AIC_IDLE)
+ aic_sched(sc);
+ }
+}
+
/*
* POST PROCESSING OF SCSI_CMD (usually current)
*/
@@ -1245,33 +1304,15 @@ aic_done(sc, acb)
* We don't support chk sense conditions for the request sense cmd.
*/
if (xs->error == XS_NOERROR) {
- if (acb->flags == ACB_ABORTED) {
+ if (acb->flags & ACB_ABORT) {
xs->error = XS_DRIVER_STUFFUP;
- } else if (acb->flags == ACB_CHKSENSE) {
+ } else if (acb->flags & ACB_SENSE) {
xs->error = XS_SENSE;
} else if (acb->target_stat == SCSI_CHECK) {
- struct scsi_sense *ss = (void *)&acb->scsi_cmd;
-
- AIC_MISC(("requesting sense "));
/* First, save the return values */
xs->resid = acb->data_length;
xs->status = acb->target_stat;
- /* Next, setup a request sense command block */
- bzero(ss, sizeof(*ss));
- ss->opcode = REQUEST_SENSE;
- ss->byte2 = sc_link->lun << 5;
- ss->length = sizeof(struct scsi_sense_data);
- acb->scsi_cmd_length = sizeof(*ss);
- acb->data_addr = (char *)&xs->sense;
- acb->data_length = sizeof(struct scsi_sense_data);
- acb->flags = ACB_CHKSENSE;
- ti->senses++;
- ti->lubusy &= ~(1<<sc_link->lun);
- if (acb == sc->sc_nexus) {
- aic_select(sc, acb);
- } else {
- TAILQ_INSERT_HEAD(&sc->ready_list, acb, chain);
- }
+ aic_sense(sc, acb);
return;
} else {
xs->resid = acb->data_length;
@@ -1292,16 +1333,13 @@ aic_done(sc, acb)
#endif
/*
- * Remove the ACB from whatever queue it's on. We have to do a bit of
- * a hack to figure out which queue it's on. Note that it is *not*
- * necessary to cdr down the ready queue, but we must cdr down the
- * nexus queue and see if it's there, so we can mark the unit as no
- * longer busy. This code is sickening, but it works.
+ * Remove the ACB from whatever queue it happens to be on.
*/
- if (acb == sc->sc_nexus) {
+ if (acb->flags & ACB_NEXUS)
ti->lubusy &= ~(1 << sc_link->lun);
- sc->sc_state = AIC_IDLE;
+ if (acb == sc->sc_nexus) {
sc->sc_nexus = NULL;
+ sc->sc_state = AIC_IDLE;
aic_sched(sc);
} else
aic_dequeue(sc, acb);
@@ -1316,28 +1354,11 @@ aic_dequeue(sc, acb)
struct aic_softc *sc;
struct aic_acb *acb;
{
- struct scsi_link *sc_link = acb->xs->sc_link;
- struct aic_tinfo *ti = &sc->sc_tinfo[sc_link->target];
- if (sc->ready_list.tqh_last == &acb->chain.tqe_next) {
- TAILQ_REMOVE(&sc->ready_list, acb, chain);
+ if (acb->flags & ACB_NEXUS) {
+ TAILQ_REMOVE(&sc->nexus_list, acb, chain);
} else {
- register struct aic_acb *acb2;
- for (acb2 = sc->nexus_list.tqh_first; acb2 != NULL;
- acb2 = acb2->chain.tqe_next) {
- if (acb2 == acb)
- break;
- }
- if (acb2 != NULL) {
- TAILQ_REMOVE(&sc->nexus_list, acb, chain);
- ti->lubusy &= ~(1 << sc_link->lun);
- } else if (acb->chain.tqe_next) {
- TAILQ_REMOVE(&sc->ready_list, acb, chain);
- } else {
- printf("%s: can't find matching acb\n",
- sc->sc_dev.dv_xname);
- Debugger();
- }
+ TAILQ_REMOVE(&sc->ready_list, acb, chain);
}
}
@@ -1354,10 +1375,11 @@ aic_dequeue(sc, acb)
* The SCSI bus is already in the MSGI phase and there is a message byte
* on the bus, along with an asserted REQ signal.
*/
-int
+void
aic_msgin(sc)
register struct aic_softc *sc;
{
+ int iobase = sc->sc_iobase;
u_char sstat1;
int n;
@@ -1384,34 +1406,34 @@ nextbyte:
*/
for (;;) {
for (;;) {
- sstat1 = inb(SSTAT1);
- if ((sstat1 & (REQINIT|BUSFREE)) != 0)
+ sstat1 = inb(iobase + SSTAT1);
+ if ((sstat1 & (REQINIT | PHASECHG | BUSFREE)) != 0)
break;
/* Wait for REQINIT. XXX Need timeout. */
}
- if ((sstat1 & (PHASECHG|BUSFREE)) != 0) {
+ if ((sstat1 & (PHASECHG | BUSFREE)) != 0) {
/*
* Target left MESSAGE IN, probably because it
* a) noticed our ATN signal, or
* b) ran out of messages.
*/
- return (1);
+ goto out;
}
/* If parity error, just dump everything on the floor. */
if ((sstat1 & SCSIPERR) != 0) {
- aic_sched_msgout(SEND_PARITY_ERROR);
sc->sc_flags |= AIC_DROP_MSGIN;
+ aic_sched_msgout(sc, SEND_PARITY_ERROR);
}
/* Gather incoming message bytes if needed. */
if ((sc->sc_flags & AIC_DROP_MSGIN) == 0) {
if (n >= AIC_MAX_MSG_LEN) {
- (void) inb(SCSIDAT);
- aic_sched_msgout(SEND_REJECT);
+ (void) inb(iobase + SCSIDAT);
sc->sc_flags |= AIC_DROP_MSGIN;
+ aic_sched_msgout(sc, SEND_REJECT);
} else {
- *sc->sc_imp++ = inb(SCSIDAT);
+ *sc->sc_imp++ = inb(iobase + SCSIDAT);
n++;
/*
* This testing is suboptimal, but most
@@ -1428,18 +1450,18 @@ nextbyte:
break;
}
} else
- (void) inb(SCSIDAT);
+ (void) inb(iobase + SCSIDAT);
/*
* If we reach this spot we're either:
* a) in the middle of a multi-byte message, or
* b) dropping bytes.
*/
- outb(SXFRCTL0, CHEN|SPIOEN);
+ outb(iobase + SXFRCTL0, CHEN | SPIOEN);
/* Ack the last byte read. */
- (void) inb(SCSIDAT);
- outb(SXFRCTL0, CHEN);
- while ((inb(SCSISIG) & ACKI) != 0)
+ (void) inb(iobase + SCSIDAT);
+ outb(iobase + SXFRCTL0, CHEN);
+ while ((inb(iobase + SCSISIG) & ACKI) != 0)
;
}
@@ -1471,7 +1493,7 @@ nextbyte:
case MSG_PARITY_ERROR:
/* Resend the last message. */
- aic_sched_msgout(sc->sc_lastmsg);
+ aic_sched_msgout(sc, sc->sc_lastmsg);
break;
case MSG_MESSAGE_REJECT:
@@ -1479,7 +1501,7 @@ nextbyte:
switch (sc->sc_lastmsg) {
#if AIC_USE_SYNCHRONOUS + AIC_USE_WIDE
case SEND_IDENTIFY:
- ti->flags &= ~(DO_SYNC|DO_WIDE);
+ ti->flags &= ~(DO_SYNC | DO_WIDE);
ti->period = ti->offset = 0;
aic_setsync(sc, ti);
ti->width = 0;
@@ -1499,8 +1521,7 @@ nextbyte:
break;
#endif
case SEND_INIT_DET_ERR:
- sc->sc_flags |= AIC_ABORTING;
- aic_sched_msgout(SEND_ABORT);
+ aic_sched_msgout(sc, SEND_ABORT);
break;
}
break;
@@ -1539,7 +1560,7 @@ nextbyte:
ti->period > sc->sc_maxsync ||
ti->offset > 8) {
ti->period = ti->offset = 0;
- aic_sched_msgout(SEND_SDTR);
+ aic_sched_msgout(sc, SEND_SDTR);
} else {
sc_print_addr(acb->xs->sc_link);
printf("sync, offset %d, period %dnsec\n",
@@ -1558,7 +1579,7 @@ nextbyte:
if (ti->width == 0) {
} else if (ti->width > AIC_MAX_WIDTH) {
ti->width = 0;
- aic_sched_msgout(SEND_WDTR);
+ aic_sched_msgout(sc, SEND_WDTR);
} else {
sc_print_addr(acb->xs->sc_link);
printf("wide, width %d\n",
@@ -1580,7 +1601,7 @@ nextbyte:
sc->sc_dev.dv_xname);
AIC_BREAK();
reject:
- aic_sched_msgout(SEND_REJECT);
+ aic_sched_msgout(sc, SEND_REJECT);
break;
}
break;
@@ -1601,21 +1622,19 @@ nextbyte:
sc->sc_dev.dv_xname);
AIC_BREAK();
reset:
- sc->sc_flags |= AIC_ABORTING;
- aic_sched_msgout(SEND_DEV_RESET);
+ aic_sched_msgout(sc, SEND_DEV_RESET);
break;
abort:
- sc->sc_flags |= AIC_ABORTING;
- aic_sched_msgout(SEND_ABORT);
+ aic_sched_msgout(sc, SEND_ABORT);
break;
}
- outb(SXFRCTL0, CHEN|SPIOEN);
+ outb(iobase + SXFRCTL0, CHEN | SPIOEN);
/* Ack the last message byte. */
- (void) inb(SCSIDAT);
- outb(SXFRCTL0, CHEN);
- while ((inb(SCSISIG) & ACKI) != 0)
+ (void) inb(iobase + SCSIDAT);
+ outb(iobase + SXFRCTL0, CHEN);
+ while ((inb(iobase + SCSISIG) & ACKI) != 0)
;
/* Go get the next message, if any. */
@@ -1623,7 +1642,6 @@ nextbyte:
out:
AIC_MISC(("n=%d imess=0x%02x ", n, sc->sc_imess[0]));
- return (0);
}
/*
@@ -1633,22 +1651,17 @@ void
aic_msgout(sc)
register struct aic_softc *sc;
{
- struct aic_acb *acb;
+ int iobase = sc->sc_iobase;
struct aic_tinfo *ti;
u_char sstat1;
int n;
AIC_TRACE(("aic_msgout "));
- /*
- * Set ATN. If we're just sending a trivial 1-byte message, we'll
- * clear ATN later on anyway.
- */
- outb(SCSISIG, PH_MSGOUT|ATNO);
/* Reset the FIFO. */
- outb(DMACNTRL0, RSTFIFO);
+ outb(iobase + DMACNTRL0, RSTFIFO);
/* Enable REQ/ACK protocol. */
- outb(SXFRCTL0, CHEN|SPIOEN);
+ outb(iobase + SXFRCTL0, CHEN | SPIOEN);
if (sc->sc_prevphase == PH_MSGOUT) {
if (sc->sc_omp == sc->sc_omess) {
@@ -1665,6 +1678,11 @@ aic_msgout(sc)
*/
AIC_MISC(("retransmitting "));
sc->sc_msgpriq |= sc->sc_msgoutq;
+ /*
+ * Set ATN. If we're just sending a trivial 1-byte
+ * message, we'll clear ATN later on anyway.
+ */
+ outb(iobase + SCSISIG, PH_MSGOUT | ATNO);
} else {
/* This is a continuation of the previous message. */
n = sc->sc_omp - sc->sc_omess;
@@ -1685,26 +1703,14 @@ nextmsg:
/* Build the outgoing message data. */
switch (sc->sc_currmsg) {
case SEND_IDENTIFY:
- if (sc->sc_state != AIC_CONNECTED) {
- printf("%s: SEND_IDENTIFY while not connected; sending NOOP\n",
- sc->sc_dev.dv_xname);
- AIC_BREAK();
- goto noop;
- }
AIC_ASSERT(sc->sc_nexus != NULL);
- acb = sc->sc_nexus;
- sc->sc_omess[0] = MSG_IDENTIFY(acb->xs->sc_link->lun, 1);
+ sc->sc_omess[0] =
+ MSG_IDENTIFY(sc->sc_nexus->xs->sc_link->lun, 1);
n = 1;
break;
#if AIC_USE_SYNCHRONOUS
case SEND_SDTR:
- if (sc->sc_state != AIC_CONNECTED) {
- printf("%s: SEND_SDTR while not connected; sending NOOP\n",
- sc->sc_dev.dv_xname);
- AIC_BREAK();
- goto noop;
- }
AIC_ASSERT(sc->sc_nexus != NULL);
ti = &sc->sc_tinfo[sc->sc_nexus->xs->sc_link->target];
sc->sc_omess[4] = MSG_EXTENDED;
@@ -1718,12 +1724,6 @@ nextmsg:
#if AIC_USE_WIDE
case SEND_WDTR:
- if (sc->sc_state != AIC_CONNECTED) {
- printf("%s: SEND_WDTR while not connected; sending NOOP\n",
- sc->sc_dev.dv_xname);
- AIC_BREAK();
- goto noop;
- }
AIC_ASSERT(sc->sc_nexus != NULL);
ti = &sc->sc_tinfo[sc->sc_nexus->xs->sc_link->target];
sc->sc_omess[3] = MSG_EXTENDED;
@@ -1735,6 +1735,7 @@ nextmsg:
#endif
case SEND_DEV_RESET:
+ sc->sc_flags |= AIC_ABORTING;
sc->sc_omess[0] = MSG_BUS_DEV_RESET;
n = 1;
break;
@@ -1755,26 +1756,18 @@ nextmsg:
break;
case SEND_ABORT:
+ sc->sc_flags |= AIC_ABORTING;
sc->sc_omess[0] = MSG_ABORT;
n = 1;
break;
- case 0:
-#ifdef AIC_PICKY
+ default:
printf("%s: unexpected MESSAGE OUT; sending NOOP\n",
sc->sc_dev.dv_xname);
AIC_BREAK();
-#endif
- noop:
sc->sc_omess[0] = MSG_NOOP;
n = 1;
break;
-
- default:
- printf("%s: weird MESSAGE OUT; sending NOOP\n",
- sc->sc_dev.dv_xname);
- AIC_BREAK();
- goto noop;
}
sc->sc_omp = &sc->sc_omess[n];
@@ -1782,29 +1775,37 @@ nextbyte:
/* Send message bytes. */
for (;;) {
for (;;) {
- sstat1 = inb(SSTAT1);
- if ((sstat1 & (REQINIT|BUSFREE)) != 0)
+ sstat1 = inb(iobase + SSTAT1);
+ if ((sstat1 & (REQINIT | PHASECHG | BUSFREE)) != 0)
break;
/* Wait for REQINIT. XXX Need timeout. */
}
- if ((sstat1 & (PHASECHG|BUSFREE)) != 0) {
+ if ((sstat1 & (PHASECHG | BUSFREE)) != 0) {
/*
* Target left MESSAGE OUT, possibly to reject
* our message.
+ *
+ * If this is the last message being sent, then we
+ * deassert ATN, since either the target is going to
+ * ignore this message, or it's going to ask for a
+ * retransmission via MESSAGE PARITY ERROR (in which
+ * case we reassert ATN anyway).
*/
+ if (sc->sc_msgpriq == 0)
+ outb(iobase + CLRSINT1, CLRATNO);
goto out;
}
/* Clear ATN before last byte if this is the last message. */
if (n == 1 && sc->sc_msgpriq == 0)
- outb(CLRSINT1, CLRATNO);
+ outb(iobase + CLRSINT1, CLRATNO);
/* Send message byte. */
- outb(SCSIDAT, *--sc->sc_omp);
+ outb(iobase + SCSIDAT, *--sc->sc_omp);
--n;
/* Keep track of the last message we've sent any bytes of. */
sc->sc_lastmsg = sc->sc_currmsg;
/* Wait for ACK to be negated. XXX Need timeout. */
- while ((inb(SCSISIG) & ACKI) != 0)
+ while ((inb(iobase + SCSISIG) & ACKI) != 0)
;
if (n == 0)
@@ -1827,7 +1828,7 @@ nextbyte:
out:
/* Disable REQ/ACK protocol. */
- outb(SXFRCTL0, CHEN);
+ outb(iobase + SXFRCTL0, CHEN);
}
/* aic_dataout_pio: perform a data transfer using the FIFO datapath in the aic6360
@@ -1842,87 +1843,102 @@ aic_dataout_pio(sc, p, n)
u_char *p;
int n;
{
+ int iobase = sc->sc_iobase;
register u_char dmastat;
int out = 0;
#define DOUTAMOUNT 128 /* Full FIFO */
/* Clear host FIFO and counter. */
- outb(DMACNTRL0, RSTFIFO|WRITE);
+ outb(iobase + DMACNTRL0, RSTFIFO | WRITE);
/* Enable FIFOs. */
- outb(SXFRCTL0, SCSIEN|DMAEN|CHEN);
- outb(DMACNTRL0, ENDMA|DWORDPIO|WRITE);
+ outb(iobase + SXFRCTL0, SCSIEN | DMAEN | CHEN);
+ outb(iobase + DMACNTRL0, ENDMA | DWORDPIO | WRITE);
/* Turn off ENREQINIT for now. */
- outb(SIMODE1, ENSCSIRST|ENSCSIPERR|ENBUSFREE|ENPHASECHG);
+ outb(iobase + SIMODE1,
+ ENSCSIRST | ENSCSIPERR | ENBUSFREE | ENPHASECHG);
/* I have tried to make the main loop as tight as possible. This
* means that some of the code following the loop is a bit more
* complex than otherwise.
*/
while (n > 0) {
- int xfer;
-
for (;;) {
- dmastat = inb(DMASTAT);
- if ((dmastat & DFIFOEMP) != 0)
+ dmastat = inb(iobase + DMASTAT);
+ if ((dmastat & (DFIFOEMP | INTSTAT)) != 0)
break;
- if ((dmastat & INTSTAT) != 0)
- goto phasechange;
}
- xfer = min(DOUTAMOUNT, n);
+ if ((dmastat & INTSTAT) != 0)
+ goto phasechange;
+
+ if (n >= DOUTAMOUNT) {
+ n -= DOUTAMOUNT;
+ out += DOUTAMOUNT;
+
+#if AIC_USE_DWORDS
+ outsl(iobase + DMADATALONG, p, DOUTAMOUNT >> 2);
+#else
+ outsw(iobase + DMADATA, p, DOUTAMOUNT >> 1);
+#endif
+
+ p += DOUTAMOUNT;
+ } else {
+ register int xfer;
- AIC_MISC(("%d> ", xfer));
+ xfer = n;
+ AIC_MISC(("%d> ", xfer));
- n -= xfer;
- out += xfer;
+ n -= xfer;
+ out += xfer;
#if AIC_USE_DWORDS
- if (xfer >= 12) {
- outsl(DMADATALONG, p, xfer>>2);
- p += xfer & ~3;
- xfer &= 3;
- }
+ if (xfer >= 12) {
+ outsl(iobase + DMADATALONG, p, xfer >> 2);
+ p += xfer & ~3;
+ xfer &= 3;
+ }
#else
- if (xfer >= 8) {
- outsw(DMADATA, p, xfer>>1);
- p += xfer & ~1;
- xfer &= 1;
- }
+ if (xfer >= 8) {
+ outsw(iobase + DMADATA, p, xfer >> 1);
+ p += xfer & ~1;
+ xfer &= 1;
+ }
#endif
- if (xfer > 0) {
- outb(DMACNTRL0, ENDMA|B8MODE|WRITE);
- outsb(DMADATA, p, xfer);
- p += xfer;
- outb(DMACNTRL0, ENDMA|DWORDPIO|WRITE);
+ if (xfer > 0) {
+ outb(iobase + DMACNTRL0, ENDMA | B8MODE | WRITE);
+ outsb(iobase + DMADATA, p, xfer);
+ p += xfer;
+ outb(iobase + DMACNTRL0, ENDMA | DWORDPIO | WRITE);
+ }
}
}
if (out == 0) {
- outb(SXFRCTL1, BITBUCKET);
+ outb(iobase + SXFRCTL1, BITBUCKET);
for (;;) {
- if ((inb(DMASTAT) & INTSTAT) != 0)
+ if ((inb(iobase + DMASTAT) & INTSTAT) != 0)
break;
}
- outb(SXFRCTL1, 0);
+ outb(iobase + SXFRCTL1, 0);
AIC_MISC(("extra data "));
} else {
/* See the bytes off chip */
for (;;) {
- dmastat = inb(DMASTAT);
- if ((dmastat & DFIFOEMP) != 0 &&
- (inb(SSTAT2) & SEMPTY) != 0)
- break;
+ dmastat = inb(iobase + DMASTAT);
if ((dmastat & INTSTAT) != 0)
goto phasechange;
+ if ((dmastat & DFIFOEMP) != 0 &&
+ (inb(iobase + SSTAT2) & SEMPTY) != 0)
+ break;
}
}
phasechange:
/* Stop the FIFO data path. */
- outb(SXFRCTL0, CHEN);
- while ((inb(SXFRCTL0) & SCSIEN) != 0)
+ outb(iobase + SXFRCTL0, CHEN);
+ while ((inb(iobase + SXFRCTL0) & SCSIEN) != 0)
;
if ((dmastat & INTSTAT) != 0) {
@@ -1930,16 +1946,17 @@ phasechange:
int amount;
/* Stop transfers, do some accounting */
- amount = inb(FIFOSTAT) + (inb(SSTAT2) & 15);
+ amount = inb(iobase + FIFOSTAT) + (inb(iobase + SSTAT2) & 15);
if (amount > 0) {
out -= amount;
- outb(SXFRCTL0, CHEN|CLRSTCNT|CLRCH);
+ outb(iobase + SXFRCTL0, CHEN | CLRSTCNT | CLRCH);
AIC_MISC(("+%d ", amount));
}
}
/* Turn on ENREQINIT again. */
- outb(SIMODE1, ENSCSIRST|ENSCSIPERR|ENBUSFREE|ENREQINIT|ENPHASECHG);
+ outb(iobase + SIMODE1,
+ ENSCSIRST | ENSCSIPERR | ENBUSFREE | ENREQINIT | ENPHASECHG);
return out;
}
@@ -1957,62 +1974,73 @@ aic_datain_pio(sc, p, n)
u_char *p;
int n;
{
+ int iobase = sc->sc_iobase;
register u_char dmastat;
int in = 0;
#define DINAMOUNT 128 /* Full FIFO */
/* Clear host FIFO and counter. */
- outb(DMACNTRL0, RSTFIFO);
- /* Enable FIFOs */
- outb(SXFRCTL0, SCSIEN|DMAEN|CHEN);
- outb(DMACNTRL0, ENDMA|DWORDPIO);
+ outb(iobase + DMACNTRL0, RSTFIFO);
+ /* Enable FIFOs. */
+ outb(iobase + SXFRCTL0, SCSIEN | DMAEN | CHEN);
+ outb(iobase + DMACNTRL0, ENDMA | DWORDPIO);
/* Turn off ENREQINIT for now. */
- outb(SIMODE1, ENSCSIRST|ENSCSIPERR|ENBUSFREE|ENPHASECHG);
+ outb(iobase + SIMODE1,
+ ENSCSIRST | ENSCSIPERR | ENBUSFREE | ENPHASECHG);
/* We leave this loop if one or more of the following is true:
* a) phase != PH_DATAIN && FIFOs are empty
* b) SCSIRSTI is set (a reset has occurred) or busfree is detected.
*/
while (n > 0) {
- int xfer;
-
/* Wait for fifo half full or phase mismatch */
for (;;) {
- dmastat = inb(DMASTAT);
- if ((dmastat & (DFIFOFULL|INTSTAT)) != 0)
+ dmastat = inb(iobase + DMASTAT);
+ if ((dmastat & (DFIFOFULL | INTSTAT)) != 0)
break;
}
- if ((dmastat & DFIFOFULL) != 0)
- xfer = min(DINAMOUNT, n);
- else
- xfer = min(inb(FIFOSTAT), n);
+ if ((dmastat & DFIFOFULL) != 0) {
+ n -= DINAMOUNT;
+ in += DINAMOUNT;
+
+#if AIC_USE_DWORDS
+ insl(iobase + DMADATALONG, p, DINAMOUNT >> 2);
+#else
+ insw(iobase + DMADATA, p, DINAMOUNT >> 1);
+#endif
- AIC_MISC((">%d ", xfer));
+ p += DINAMOUNT;
+ } else {
+ register int xfer;
- n -= xfer;
- in += xfer;
+ xfer = min(inb(iobase + FIFOSTAT), n);
+ AIC_MISC((">%d ", xfer));
+
+ n -= xfer;
+ in += xfer;
#if AIC_USE_DWORDS
- if (xfer >= 12) {
- insl(DMADATALONG, p, xfer>>2);
- p += xfer & ~3;
- xfer &= 3;
- }
+ if (xfer >= 12) {
+ insl(iobase + DMADATALONG, p, xfer >> 2);
+ p += xfer & ~3;
+ xfer &= 3;
+ }
#else
- if (xfer >= 8) {
- insw(DMADATA, p, xfer>>1);
- p += xfer & ~1;
- xfer &= 1;
- }
+ if (xfer >= 8) {
+ insw(iobase + DMADATA, p, xfer >> 1);
+ p += xfer & ~1;
+ xfer &= 1;
+ }
#endif
- if (xfer > 0) {
- outb(DMACNTRL0, ENDMA|B8MODE);
- insb(DMADATA, p, xfer);
- p += xfer;
- outb(DMACNTRL0, ENDMA|DWORDPIO);
+ if (xfer > 0) {
+ outb(iobase + DMACNTRL0, ENDMA | B8MODE);
+ insb(iobase + DMADATA, p, xfer);
+ p += xfer;
+ outb(iobase + DMACNTRL0, ENDMA | DWORDPIO);
+ }
}
if ((dmastat & INTSTAT) != 0)
@@ -2026,23 +2054,24 @@ aic_datain_pio(sc, p, n)
* FIFO is not empty, waste some bytes....
*/
if (in == 0) {
- outb(SXFRCTL1, BITBUCKET);
+ outb(iobase + SXFRCTL1, BITBUCKET);
for (;;) {
- if ((inb(DMASTAT) & INTSTAT) != 0)
+ if ((inb(iobase + DMASTAT) & INTSTAT) != 0)
break;
}
- outb(SXFRCTL1, 0);
+ outb(iobase + SXFRCTL1, 0);
AIC_MISC(("extra data "));
}
phasechange:
/* Stop the FIFO data path. */
- outb(SXFRCTL0, CHEN);
- while ((inb(SXFRCTL0) & SCSIEN) != 0)
+ outb(iobase + SXFRCTL0, CHEN);
+ while ((inb(iobase + SXFRCTL0) & SCSIEN) != 0)
;
/* Turn on ENREQINIT again. */
- outb(SIMODE1, ENSCSIRST|ENSCSIPERR|ENBUSFREE|ENREQINIT|ENPHASECHG);
+ outb(iobase + SIMODE1,
+ ENSCSIRST | ENSCSIPERR | ENBUSFREE | ENREQINIT | ENPHASECHG);
return in;
}
@@ -2057,6 +2086,7 @@ aicintr(arg)
void *arg;
{
register struct aic_softc *sc = arg;
+ int iobase = sc->sc_iobase;
u_char sstat0, sstat1;
register struct aic_acb *acb;
register struct scsi_link *sc_link;
@@ -2067,16 +2097,15 @@ aicintr(arg)
* Clear INTEN. We enable it again before returning. This makes the
* interrupt esssentially level-triggered.
*/
- outb(DMACNTRL0, 0);
+ outb(iobase + DMACNTRL0, 0);
AIC_TRACE(("aicintr "));
loop:
-gotintr:
/*
* First check for abnormal conditions, such as reset.
*/
- sstat1 = inb(SSTAT1);
+ sstat1 = inb(iobase + SSTAT1);
AIC_MISC(("sstat1:0x%02x ", sstat1));
if ((sstat1 & SCSIRSTI) != 0) {
@@ -2089,12 +2118,12 @@ gotintr:
*/
if ((sstat1 & SCSIPERR) != 0) {
printf("%s: SCSI bus parity error\n", sc->sc_dev.dv_xname);
- outb(CLRSINT1, CLRSCSIPERR);
+ outb(iobase + CLRSINT1, CLRSCSIPERR);
if (sc->sc_prevphase == PH_MSGIN) {
- aic_sched_msgout(SEND_PARITY_ERROR);
sc->sc_flags |= AIC_DROP_MSGIN;
+ aic_sched_msgout(sc, SEND_PARITY_ERROR);
} else
- aic_sched_msgout(SEND_INIT_DET_ERR);
+ aic_sched_msgout(sc, SEND_INIT_DET_ERR);
}
/*
@@ -2110,20 +2139,18 @@ gotintr:
switch (sc->sc_state) {
case AIC_IDLE:
case AIC_SELECTING:
- sstat0 = inb(SSTAT0);
+ sstat0 = inb(iobase + SSTAT0);
AIC_MISC(("sstat0:0x%02x ", sstat0));
if ((sstat0 & TARGET) != 0) {
/*
* We don't currently support target mode.
*/
- printf("%s: target mode selected; going to bus free\n",
+ printf("%s: target mode selected; going to BUS FREE\n",
sc->sc_dev.dv_xname);
- outb(SCSISIG, 0);
+ outb(iobase + SCSISIG, 0);
- sc->sc_state = AIC_IDLE;
- aic_sched(sc);
- goto out;
+ goto sched;
} else if ((sstat0 & SELDI) != 0) {
AIC_MISC(("reselected "));
@@ -2140,7 +2167,7 @@ gotintr:
}
/* Save reselection ID. */
- sc->sc_selid = inb(SELID);
+ sc->sc_selid = inb(iobase + SELID);
sc->sc_state = AIC_RESELECTED;
} else if ((sstat0 & SELDO) != 0) {
@@ -2159,27 +2186,26 @@ gotintr:
}
AIC_ASSERT(sc->sc_nexus != NULL);
acb = sc->sc_nexus;
-
sc_link = acb->xs->sc_link;
ti = &sc->sc_tinfo[sc_link->target];
- if ((acb->xs->flags & SCSI_RESET) == 0) {
- sc->sc_msgpriq = SEND_IDENTIFY;
- if (acb->flags != ACB_ABORTED) {
+
+ sc->sc_msgpriq = SEND_IDENTIFY;
+ if (acb->flags & ACB_RESET)
+ sc->sc_msgpriq |= SEND_DEV_RESET;
+ else if (acb->flags & ACB_ABORT)
+ sc->sc_msgpriq |= SEND_ABORT;
+ else {
#if AIC_USE_SYNCHRONOUS
- if ((ti->flags & DO_SYNC) != 0)
- sc->sc_msgpriq |= SEND_SDTR;
+ if ((ti->flags & DO_SYNC) != 0)
+ sc->sc_msgpriq |= SEND_SDTR;
#endif
#if AIC_USE_WIDE
- if ((ti->flags & DO_WIDE) != 0)
- sc->sc_msgpriq |= SEND_WDTR;
+ if ((ti->flags & DO_WIDE) != 0)
+ sc->sc_msgpriq |= SEND_WDTR;
#endif
- } else {
- sc->sc_flags |= AIC_ABORTING;
- sc->sc_msgpriq |= SEND_ABORT;
- }
- } else
- sc->sc_msgpriq = SEND_DEV_RESET;
+ }
+ acb->flags |= ACB_NEXUS;
ti->lubusy |= (1 << sc_link->lun);
/* Do an implicit RESTORE POINTERS. */
@@ -2188,6 +2214,10 @@ gotintr:
sc->sc_cp = (u_char *)&acb->scsi_cmd;
sc->sc_cleft = acb->scsi_cmd_length;
+ /* On our first connection, schedule a timeout. */
+ if ((acb->xs->flags & SCSI_POLL) == 0)
+ timeout(aic_timeout, acb, (acb->timeout * hz) / 1000);
+
sc->sc_state = AIC_CONNECTED;
} else if ((sstat1 & SELTO) != 0) {
AIC_MISC(("selection timeout "));
@@ -2201,119 +2231,143 @@ gotintr:
AIC_ASSERT(sc->sc_nexus != NULL);
acb = sc->sc_nexus;
- outb(SXFRCTL1, 0);
- outb(SCSISEQ, ENRESELI);
- outb(CLRSINT1, CLRSELTIMO);
+ outb(iobase + SXFRCTL1, 0);
+ outb(iobase + SCSISEQ, ENRESELI);
+ outb(iobase + CLRSINT1, CLRSELTIMO);
+ delay(250);
acb->xs->error = XS_SELTIMEOUT;
- untimeout(aic_timeout, acb);
- delay(250);
- aic_done(sc, acb);
- goto out;
+ goto finish;
} else {
-#ifdef AIC_PICKY
if (sc->sc_state != AIC_IDLE) {
printf("%s: BUS FREE while not idle; state=%d\n",
sc->sc_dev.dv_xname, sc->sc_state);
AIC_BREAK();
goto out;
}
-#endif
- aic_sched(sc);
- goto out;
+ goto sched;
}
/*
* Turn off selection stuff, and prepare to catch bus free
* interrupts, parity errors, and phase changes.
*/
- outb(SXFRCTL1, 0);
- outb(SCSISEQ, ENAUTOATNP);
- outb(CLRSINT0, CLRSELDI|CLRSELDO);
- outb(CLRSINT1, CLRBUSFREE|CLRPHASECHG);
- outb(SIMODE0, 0);
- outb(SIMODE1, ENSCSIRST|ENSCSIPERR|ENBUSFREE|ENREQINIT|ENPHASECHG);
+ outb(iobase + SXFRCTL0, CHEN | CLRSTCNT | CLRCH);
+ outb(iobase + SXFRCTL1, 0);
+ outb(iobase + SCSISEQ, ENAUTOATNP);
+ outb(iobase + CLRSINT0, CLRSELDI | CLRSELDO);
+ outb(iobase + CLRSINT1, CLRBUSFREE | CLRPHASECHG);
+ outb(iobase + SIMODE0, 0);
+ outb(iobase + SIMODE1,
+ ENSCSIRST | ENSCSIPERR | ENBUSFREE | ENREQINIT | ENPHASECHG);
sc->sc_flags = 0;
sc->sc_prevphase = PH_INVALID;
goto dophase;
}
- outb(CLRSINT1, CLRPHASECHG);
-
if ((sstat1 & BUSFREE) != 0) {
/* We've gone to BUS FREE phase. */
- outb(CLRSINT1, CLRBUSFREE);
+ outb(iobase + CLRSINT1, CLRBUSFREE | CLRPHASECHG);
switch (sc->sc_state) {
case AIC_RESELECTED:
- sc->sc_state = AIC_IDLE;
- aic_sched(sc);
- break;
+ goto sched;
case AIC_CONNECTED:
+ AIC_ASSERT(sc->sc_nexus != NULL);
+ acb = sc->sc_nexus;
+
+#if AIC_USE_SYNCHRONOUS + AIC_USE_WIDE
+ if (sc->sc_prevphase == PH_MSGOUT) {
+ /*
+ * If the target went to BUS FREE phase during
+ * or immediately after sending a SDTR or WDTR
+ * message, disable negotiation.
+ */
+ sc_link = acb->xs->sc_link;
+ ti = &sc->sc_tinfo[sc_link->target];
+ switch (sc->sc_lastmsg) {
+#if AIC_USE_SYNCHRONOUS
+ case SEND_SDTR:
+ ti->flags &= ~DO_SYNC;
+ ti->period = ti->offset = 0;
+ break;
+#endif
+#if AIC_USE_WIDE
+ case SEND_WDTR:
+ ti->flags &= ~DO_WIDE;
+ ti->width = 0;
+ break;
+#endif
+ }
+ }
+#endif
+
if ((sc->sc_flags & AIC_ABORTING) == 0) {
- printf("%s: unexpected BUS FREE; aborting\n",
+ /*
+ * Section 5.1.1 of the SCSI 2 spec suggests
+ * issuing a REQUEST SENSE following an
+ * unexpected disconnect. Some devices go into
+ * a contingent allegiance condition when
+ * disconnecting, and this is necessary to
+ * clean up their state.
+ */
+ printf("%s: unexpected disconnect; sending REQUEST SENSE\n",
sc->sc_dev.dv_xname);
AIC_BREAK();
+ aic_sense(sc, acb);
+ goto out;
}
- AIC_ASSERT(sc->sc_nexus != NULL);
- acb = sc->sc_nexus;
+
acb->xs->error = XS_DRIVER_STUFFUP;
goto finish;
case AIC_DISCONNECT:
AIC_ASSERT(sc->sc_nexus != NULL);
acb = sc->sc_nexus;
- sc->sc_state = AIC_IDLE;
- sc->sc_nexus = NULL;
TAILQ_INSERT_HEAD(&sc->nexus_list, acb, chain);
- aic_sched(sc);
- break;
+ sc->sc_nexus = NULL;
+ goto sched;
case AIC_CMDCOMPLETE:
AIC_ASSERT(sc->sc_nexus != NULL);
acb = sc->sc_nexus;
- finish:
- untimeout(aic_timeout, acb);
- aic_done(sc, acb);
- break;
+ goto finish;
}
- goto out;
}
+ outb(iobase + CLRSINT1, CLRPHASECHG);
+
dophase:
if ((sstat1 & REQINIT) == 0) {
/* Wait for REQINIT. */
goto out;
}
- sc->sc_phase = inb(SCSISIG) & PH_MASK;
- outb(SCSISIG, sc->sc_phase);
+ sc->sc_phase = inb(iobase + SCSISIG) & PH_MASK;
+ outb(iobase + SCSISIG, sc->sc_phase);
switch (sc->sc_phase) {
case PH_MSGOUT:
- /* If aborting, always handle MESSAGE OUT. */
- if ((sc->sc_state & AIC_CONNECTED) == 0 &&
- (sc->sc_flags & AIC_ABORTING) == 0)
+ if (sc->sc_state != AIC_CONNECTED &&
+ sc->sc_state != AIC_RESELECTED)
break;
aic_msgout(sc);
sc->sc_prevphase = PH_MSGOUT;
goto loop;
case PH_MSGIN:
- if ((sc->sc_state & (AIC_CONNECTED|AIC_RESELECTED)) == 0)
+ if (sc->sc_state != AIC_CONNECTED &&
+ sc->sc_state != AIC_RESELECTED)
break;
- if (aic_msgin(sc)) {
- sc->sc_prevphase = PH_MSGIN;
- goto gotintr;
- }
+ aic_msgin(sc);
sc->sc_prevphase = PH_MSGIN;
goto loop;
case PH_CMD:
- if ((sc->sc_state & AIC_CONNECTED) == 0)
+ if (sc->sc_state != AIC_CONNECTED)
break;
#if AIC_DEBUG
if ((aic_debug & AIC_SHOWMISC) != 0) {
@@ -2330,7 +2384,7 @@ dophase:
goto loop;
case PH_DATAOUT:
- if ((sc->sc_state & AIC_CONNECTED) == 0)
+ if (sc->sc_state != AIC_CONNECTED)
break;
AIC_MISC(("dataout dleft=%d ", sc->sc_dleft));
n = aic_dataout_pio(sc, sc->sc_dp, sc->sc_dleft);
@@ -2340,7 +2394,7 @@ dophase:
goto loop;
case PH_DATAIN:
- if ((sc->sc_state & AIC_CONNECTED) == 0)
+ if (sc->sc_state != AIC_CONNECTED)
break;
AIC_MISC(("datain "));
n = aic_datain_pio(sc, sc->sc_dp, sc->sc_dleft);
@@ -2350,17 +2404,17 @@ dophase:
goto loop;
case PH_STAT:
- if ((sc->sc_state & AIC_CONNECTED) == 0)
+ if (sc->sc_state != AIC_CONNECTED)
break;
AIC_ASSERT(sc->sc_nexus != NULL);
acb = sc->sc_nexus;
/* XXXX Don't clear FIFO. Wait for byte to come in. */
- outb(SXFRCTL0, CHEN|SPIOEN);
- outb(DMACNTRL0, RSTFIFO);
- acb->target_stat = inb(SCSIDAT);
- outb(SXFRCTL0, CHEN);
- outb(DMACNTRL0, RSTFIFO);
- while ((inb(SXFRCTL0) & SCSIEN) != 0)
+ outb(iobase + SXFRCTL0, CHEN | SPIOEN);
+ outb(iobase + DMACNTRL0, RSTFIFO);
+ acb->target_stat = inb(iobase + SCSIDAT);
+ outb(iobase + SXFRCTL0, CHEN);
+ outb(iobase + DMACNTRL0, RSTFIFO);
+ while ((inb(iobase + SXFRCTL0) & SCSIEN) != 0)
;
AIC_MISC(("target_stat=0x%02x ", acb->target_stat));
sc->sc_prevphase = PH_STAT;
@@ -2373,8 +2427,18 @@ reset:
aic_init(sc);
return 1;
+finish:
+ untimeout(aic_timeout, acb);
+ aic_done(sc, acb);
+ goto out;
+
+sched:
+ sc->sc_state = AIC_IDLE;
+ aic_sched(sc);
+ goto out;
+
out:
- outb(DMACNTRL0, INTEN);
+ outb(iobase + DMACNTRL0, INTEN);
return 1;
}
@@ -2384,11 +2448,17 @@ aic_abort(sc, acb)
struct aic_acb *acb;
{
- if (sc->sc_nexus == acb) {
- if (sc->sc_state == AIC_CONNECTED) {
- sc->sc_flags |= AIC_ABORTING;
- aic_sched_msgout(SEND_ABORT);
- }
+ /* 2 secs for the abort */
+ acb->timeout = AIC_ABORT_TIMEOUT;
+ acb->flags |= ACB_ABORT;
+
+ if (acb == sc->sc_nexus) {
+ /*
+ * If we're still selecting, the message will be scheduled
+ * after selection is complete.
+ */
+ if (sc->sc_state == AIC_CONNECTED)
+ aic_sched_msgout(sc, SEND_ABORT);
} else {
aic_dequeue(sc, acb);
TAILQ_INSERT_HEAD(&sc->ready_list, acb, chain);
@@ -2412,20 +2482,15 @@ aic_timeout(arg)
s = splbio();
- if (acb->flags == ACB_ABORTED) {
+ if (acb->flags & ACB_ABORT) {
/* abort timed out */
printf(" AGAIN\n");
- acb->xs->retries = 0;
- aic_done(sc, acb);
+ /* XXX Must reset! */
} else {
/* abort the operation that has timed out */
printf("\n");
acb->xs->error = XS_TIMEOUT;
- acb->flags = ACB_ABORTED;
aic_abort(sc, acb);
- /* 2 secs for the abort */
- if ((xs->flags & SCSI_POLL) == 0)
- timeout(aic_timeout, acb, 2 * hz);
}
splx(s);
@@ -2472,7 +2537,7 @@ void
aic_print_active_acb()
{
struct aic_acb *acb;
- struct aic_softc *sc = aiccd.cd_devs[0];
+ struct aic_softc *sc = aic_cd.cd_devs[0];
printf("ready list:\n");
for (acb = sc->ready_list.tqh_first; acb != NULL;
@@ -2491,16 +2556,20 @@ void
aic_dump6360(sc)
struct aic_softc *sc;
{
+ int iobase = sc->sc_iobase;
printf("aic6360: SCSISEQ=%x SXFRCTL0=%x SXFRCTL1=%x SCSISIG=%x\n",
- inb(SCSISEQ), inb(SXFRCTL0), inb(SXFRCTL1), inb(SCSISIG));
+ inb(iobase + SCSISEQ), inb(iobase + SXFRCTL0),
+ inb(iobase + SXFRCTL1), inb(iobase + SCSISIG));
printf(" SSTAT0=%x SSTAT1=%x SSTAT2=%x SSTAT3=%x SSTAT4=%x\n",
- inb(SSTAT0), inb(SSTAT1), inb(SSTAT2), inb(SSTAT3), inb(SSTAT4));
+ inb(iobase + SSTAT0), inb(iobase + SSTAT1), inb(iobase + SSTAT2),
+ inb(iobase + SSTAT3), inb(iobase + SSTAT4));
printf(" SIMODE0=%x SIMODE1=%x DMACNTRL0=%x DMACNTRL1=%x DMASTAT=%x\n",
- inb(SIMODE0), inb(SIMODE1), inb(DMACNTRL0), inb(DMACNTRL1),
- inb(DMASTAT));
+ inb(iobase + SIMODE0), inb(iobase + SIMODE1),
+ inb(iobase + DMACNTRL0), inb(iobase + DMACNTRL1),
+ inb(iobase + DMASTAT));
printf(" FIFOSTAT=%d SCSIBUS=0x%x\n",
- inb(FIFOSTAT), inb(SCSIBUS));
+ inb(iobase + FIFOSTAT), inb(iobase + SCSIBUS));
}
void
diff --git a/sys/dev/isa/ast.c b/sys/dev/isa/ast.c
index 654c5a77cb3..366e1bf5a4a 100644
--- a/sys/dev/isa/ast.c
+++ b/sys/dev/isa/ast.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: ast.c,v 1.7 1996/04/18 23:47:29 niklas Exp $ */
-/* $NetBSD: ast.c,v 1.22 1996/03/10 09:01:20 cgd Exp $ */
+/* $OpenBSD: ast.c,v 1.8 1996/04/21 22:22:48 deraadt Exp $ */
+/* $NetBSD: ast.c,v 1.26 1996/04/15 18:55:23 cgd Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@@ -36,7 +36,13 @@
#include <sys/param.h>
#include <sys/device.h>
+#include <sys/termios.h>
+#ifdef i386 /* XXX */
+#include <machine/cpu.h> /* XXX */
+#else /* XXX */
+#include <machine/intr.h>
+#endif /* XXX */
#include <machine/bus.h>
#include <dev/isa/isavar.h>
@@ -61,8 +67,12 @@ int astprobe();
void astattach();
int astintr __P((void *));
-struct cfdriver astcd = {
- NULL, "ast", astprobe, astattach, DV_TTY, sizeof(struct ast_softc)
+struct cfattach ast_ca = {
+ sizeof(struct ast_softc), astprobe, astattach
+};
+
+struct cfdriver ast_cd = {
+ NULL, "ast", DV_TTY
};
int
@@ -163,20 +173,13 @@ astattach(parent, self, aux)
ca.ca_iobase = sc->sc_iobase + i * COM_NPORTS;
ca.ca_noien = 1;
- /* mimic config_found(), but with special functionality */
- if ((match = config_search(NULL, self, &ca)) != NULL) {
- subunit = match->cf_unit; /* can change if unit == * */
- config_attach(self, match, &ca, astprint);
- sc->sc_slaves[i] = match->cf_driver->cd_devs[subunit];
+ sc->sc_slaves[i] = config_found(self, &ca, astprint);
+ if (sc->sc_slaves[i] != NULL)
sc->sc_alive |= 1 << i;
- } else {
- astprint(&ca, self->dv_xname);
- printf(" not configured\n");
- }
}
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_TTY, astintr,
- sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_TTY, astintr, sc, sc->sc_dev.dv_xname);
}
int
diff --git a/sys/dev/isa/boca.c b/sys/dev/isa/boca.c
index d05fa84ae6f..c4ece6a26c5 100644
--- a/sys/dev/isa/boca.c
+++ b/sys/dev/isa/boca.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: boca.c,v 1.7 1996/04/18 23:47:30 niklas Exp $ */
-/* $NetBSD: boca.c,v 1.9 1996/03/10 09:01:22 cgd Exp $ */
+/* $OpenBSD: boca.c,v 1.8 1996/04/21 22:22:52 deraadt Exp $ */
+/* $NetBSD: boca.c,v 1.13 1996/04/15 18:55:28 cgd Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@@ -36,7 +36,13 @@
#include <sys/param.h>
#include <sys/device.h>
+#include <sys/termios.h>
+#ifdef i386 /* XXX */
+#include <machine/cpu.h> /* XXX */
+#else /* XXX */
+#include <machine/intr.h>
+#endif /* XXX */
#include <machine/bus.h>
#include <dev/isa/isavar.h>
@@ -61,8 +67,12 @@ int bocaprobe();
void bocaattach();
int bocaintr __P((void *));
-struct cfdriver bocacd = {
- NULL, "boca", bocaprobe, bocaattach, DV_TTY, sizeof(struct boca_softc)
+struct cfattach boca_ca = {
+ sizeof(struct boca_softc), bocaprobe, bocaattach,
+};
+
+struct cfdriver boca_cd = {
+ NULL, "boca", DV_TTY
};
int
@@ -158,20 +168,13 @@ bocaattach(parent, self, aux)
ca.ca_iobase = sc->sc_iobase + i * COM_NPORTS;
ca.ca_noien = 0;
- /* mimic config_found(), but with special functionality */
- if ((match = config_search(NULL, self, &ca)) != NULL) {
- subunit = match->cf_unit; /* can change if unit == * */
- config_attach(self, match, &ca, bocaprint);
- sc->sc_slaves[i] = match->cf_driver->cd_devs[subunit];
+ sc->sc_slaves[i] = config_found(self, &ca, bocaprint);
+ if (sc->sc_slaves[i] != NULL)
sc->sc_alive |= 1 << i;
- } else {
- bocaprint(&ca, self->dv_xname);
- printf(" not configured\n");
- }
}
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_TTY, bocaintr,
- sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_TTY, bocaintr, sc, sc->sc_dev.dv_xname);
}
int
diff --git a/sys/dev/isa/bt.c b/sys/dev/isa/bt.c
index 42638c6607f..1875d60eb93 100644
--- a/sys/dev/isa/bt.c
+++ b/sys/dev/isa/bt.c
@@ -1,8 +1,10 @@
-/* $OpenBSD: bt.c,v 1.7 1996/04/18 23:47:31 niklas Exp $ */
-/* $NetBSD: bt742a.c,v 1.55 1996/03/16 05:33:28 cgd Exp $ */
+/* $NetBSD: bt.c,v 1.7 1996/04/11 22:28:25 cgd Exp $ */
+
+#define BTDIAG
+#define integrate
/*
- * Copyright (c) 1994 Charles Hannum. All rights reserved.
+ * Copyright (c) 1994, 1996 Charles M. Hannum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -14,7 +16,7 @@
* 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 Charles Hannum.
+ * This product includes software developed by Charles M. Hannum.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
@@ -45,10 +47,6 @@
* functioning of this software in any circumstances.
*/
-/*
- * bt742a SCSI driver
- */
-
#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
@@ -63,92 +61,17 @@
#include <machine/pio.h>
-#include <dev/isa/isavar.h>
-#include <dev/isa/isadmavar.h>
#include <scsi/scsi_all.h>
#include <scsi/scsiconf.h>
-/*
- * Note that stdarg.h and the ANSI style va_start macro is used for both
- * ANSI and traditional C compilers.
- */
-#include <machine/stdarg.h>
+#include <dev/isa/isavar.h>
+#include <dev/isa/isadmavar.h>
+#include <dev/isa/btreg.h>
#ifndef DDB
#define Debugger() panic("should call debugger here (bt742a.c)")
#endif /* ! DDB */
-typedef u_long physaddr;
-typedef u_long physlen;
-
-/*
- * I/O Port Interface
- */
-#define BT_CTRL_STAT_PORT 0x0 /* control & status */
-#define BT_CMD_DATA_PORT 0x1 /* cmds and datas */
-#define BT_INTR_PORT 0x2 /* Intr. stat */
-
-/*
- * BT_CTRL_STAT bits (write)
- */
-#define BT_HRST 0x80 /* Hardware reset */
-#define BT_SRST 0x40 /* Software reset */
-#define BT_IRST 0x20 /* Interrupt reset */
-#define BT_SCRST 0x10 /* SCSI bus reset */
-
-/*
- * BT_CTRL_STAT bits (read)
- */
-#define BT_STST 0x80 /* Self test in Progress */
-#define BT_DIAGF 0x40 /* Diagnostic Failure */
-#define BT_INIT 0x20 /* Mbx Init required */
-#define BT_IDLE 0x10 /* Host Adapter Idle */
-#define BT_CDF 0x08 /* cmd/data out port full */
-#define BT_DF 0x04 /* Data in port full */
-#define BT_INVDCMD 0x01 /* Invalid command */
-
-/*
- * BT_CMD_DATA bits (write)
- */
-#define BT_NOP 0x00 /* No operation */
-#define BT_MBX_INIT 0x01 /* Mbx initialization */
-#define BT_START_SCSI 0x02 /* start scsi command */
-#define BT_START_BIOS 0x03 /* start bios command */
-#define BT_INQUIRE 0x04 /* Adapter Inquiry */
-#define BT_MBO_INTR_EN 0x05 /* Enable MBO available interrupt */
-#define BT_SEL_TIMEOUT_SET 0x06 /* set selection time-out */
-#define BT_BUS_ON_TIME_SET 0x07 /* set bus-on time */
-#define BT_BUS_OFF_TIME_SET 0x08 /* set bus-off time */
-#define BT_SPEED_SET 0x09 /* set transfer speed */
-#define BT_DEV_GET 0x0a /* return installed devices */
-#define BT_CONF_GET 0x0b /* return configuration data */
-#define BT_TARGET_EN 0x0c /* enable target mode */
-#define BT_SETUP_GET 0x0d /* return setup data */
-#define BT_WRITE_CH2 0x1a /* write channel 2 buffer */
-#define BT_READ_CH2 0x1b /* read channel 2 buffer */
-#define BT_WRITE_FIFO 0x1c /* write fifo buffer */
-#define BT_READ_FIFO 0x1d /* read fifo buffer */
-#define BT_ECHO 0x1e /* Echo command data */
-#define BT_MBX_INIT_EXTENDED 0x81 /* Mbx initialization */
-#define BT_INQUIRE_REV_THIRD 0x84 /* Get 3rd firmware version byte */
-#define BT_INQUIRE_REV_FOURTH 0x85 /* Get 4th firmware version byte */
-#define BT_GET_BOARD_INFO 0x8b /* Get hardware ID and revision */
-#define BT_INQUIRE_EXTENDED 0x8d /* Adapter Setup Inquiry */
-
-/* Follows command appeared at firmware 3.31 */
-#define BT_ROUND_ROBIN 0x8f /* Enable/Disable(default) round robin */
-#define BT_DISABLE 0x00 /* Parameter value for Disable */
-#define BT_ENABLE 0x01 /* Parameter value for Enable */
-
-/*
- * BT_INTR_PORT bits (read)
- */
-#define BT_ANY_INTR 0x80 /* Any interrupt */
-#define BT_SCRD 0x08 /* SCSI reset detected */
-#define BT_HACC 0x04 /* Command complete */
-#define BT_MBOA 0x02 /* MBX out empty */
-#define BT_MBIF 0x01 /* MBX in full */
-
/*
* Mail box defs etc.
* these could be bigger but we need the bt_softc to fit on a single page..
@@ -166,180 +89,14 @@ typedef u_long physlen;
else \
(wmb)++;
-struct bt_mbx_out {
- physaddr ccb_addr;
- u_char dummy[3];
- u_char cmd;
-};
-
-struct bt_mbx_in {
- physaddr ccb_addr;
- u_char btstat;
- u_char sdstat;
- u_char dummy;
- u_char stat;
-};
-
struct bt_mbx {
struct bt_mbx_out mbo[BT_MBX_SIZE];
struct bt_mbx_in mbi[BT_MBX_SIZE];
+ struct bt_mbx_out *cmbo; /* Collection Mail Box out */
struct bt_mbx_out *tmbo; /* Target Mail Box out */
struct bt_mbx_in *tmbi; /* Target Mail Box in */
};
-/*
- * mbo.cmd values
- */
-#define BT_MBO_FREE 0x0 /* MBO entry is free */
-#define BT_MBO_START 0x1 /* MBO activate entry */
-#define BT_MBO_ABORT 0x2 /* MBO abort entry */
-
-/*
- * mbi.stat values
- */
-#define BT_MBI_FREE 0x0 /* MBI entry is free */
-#define BT_MBI_OK 0x1 /* completed without error */
-#define BT_MBI_ABORT 0x2 /* aborted ccb */
-#define BT_MBI_UNKNOWN 0x3 /* Tried to abort invalid CCB */
-#define BT_MBI_ERROR 0x4 /* Completed with error */
-
-#if defined(BIG_DMA)
-WARNING...THIS WON'T WORK(won't fit on 1 page)
-/* #define BT_NSEG 2048 /* Number of scatter gather segments - to much vm */
-#define BT_NSEG 128
-#else
-#define BT_NSEG 33
-#endif /* BIG_DMA */
-
-struct bt_scat_gath {
- physlen seg_len;
- physaddr seg_addr;
-};
-
-struct bt_ccb {
- u_char opcode;
- u_char:3, data_in:1, data_out:1,:3;
- u_char scsi_cmd_length;
- u_char req_sense_length;
- /*------------------------------------longword boundary */
- physlen data_length;
- /*------------------------------------longword boundary */
- physaddr data_addr;
- /*------------------------------------longword boundary */
- u_char dummy1[2];
- u_char host_stat;
- u_char target_stat;
- /*------------------------------------longword boundary */
- u_char target;
- u_char lun;
- struct scsi_generic scsi_cmd;
- u_char dummy2[1];
- u_char link_id;
- /*------------------------------------longword boundary */
- physaddr link_addr;
- /*------------------------------------longword boundary */
- physaddr sense_ptr;
-/*-----end of HW fields-----------------------longword boundary */
- struct scsi_sense_data scsi_sense;
- /*------------------------------------longword boundary */
- struct bt_scat_gath scat_gath[BT_NSEG];
- /*------------------------------------longword boundary */
- TAILQ_ENTRY(bt_ccb) chain;
- struct bt_ccb *nexthash;
- long hashkey;
- struct scsi_xfer *xs; /* the scsi_xfer for this cmd */
- int flags;
-#define CCB_FREE 0
-#define CCB_ACTIVE 1
-#define CCB_ABORTED 2
- struct bt_mbx_out *mbx; /* pointer to mail box */
-};
-
-/*
- * opcode fields
- */
-#define BT_INITIATOR_CCB 0x00 /* SCSI Initiator CCB */
-#define BT_TARGET_CCB 0x01 /* SCSI Target CCB */
-#define BT_INIT_SCAT_GATH_CCB 0x02 /* SCSI Initiator with scattter gather */
-#define BT_RESET_CCB 0x81 /* SCSI Bus reset */
-
-/*
- * bt_ccb.host_stat values
- */
-#define BT_OK 0x00 /* cmd ok */
-#define BT_LINK_OK 0x0a /* Link cmd ok */
-#define BT_LINK_IT 0x0b /* Link cmd ok + int */
-#define BT_SEL_TIMEOUT 0x11 /* Selection time out */
-#define BT_OVER_UNDER 0x12 /* Data over/under run */
-#define BT_BUS_FREE 0x13 /* Bus dropped at unexpected time */
-#define BT_INV_BUS 0x14 /* Invalid bus phase/sequence */
-#define BT_BAD_MBO 0x15 /* Incorrect MBO cmd */
-#define BT_BAD_CCB 0x16 /* Incorrect ccb opcode */
-#define BT_BAD_LINK 0x17 /* Not same values of LUN for links */
-#define BT_INV_TARGET 0x18 /* Invalid target direction */
-#define BT_CCB_DUP 0x19 /* Duplicate CCB received */
-#define BT_INV_CCB 0x1a /* Invalid CCB or segment list */
-#define BT_ABORTED 42 /* pseudo value from driver */
-
-struct bt_extended_inquire {
- u_char bus_type; /* Type of bus connected to */
-#define BT_BUS_TYPE_24BIT 'A' /* ISA bus */
-#define BT_BUS_TYPE_32BIT 'E' /* EISA/VLB/PCI bus */
-#define BT_BUS_TYPE_MCA 'M' /* MicroChannel bus */
- u_char bios_address; /* Address of adapter BIOS */
- u_short max_segment; /* ? */
-};
-
-struct bt_boardID {
- u_char board_type;
- u_char custom_feture;
- char firm_revision;
- u_char firm_version;
-};
-
-struct bt_board_info {
- u_char id[4]; /* i.e bt742a -> '7','4','2','A' */
- u_char version[2]; /* i.e Board Revision 'H' -> 'H', 0x00 */
-};
-
-struct bt_setup {
- u_char sync_neg:1;
- u_char parity:1;
- u_char :6;
- u_char speed;
- u_char bus_on;
- u_char bus_off;
- u_char num_mbx;
- u_char mbx[3]; /*XXX */
- /* doesn't make sense with 32bit addresses */
- struct {
- u_char offset:4;
- u_char period:3;
- u_char valid:1;
- } sync[8];
- u_char disc_sts;
-};
-
-struct bt_config {
- u_char chan;
- u_char intr;
- u_char scsi_dev:3;
- u_char :5;
-};
-
-#define INT9 0x01
-#define INT10 0x02
-#define INT11 0x04
-#define INT12 0x08
-#define INT14 0x20
-#define INT15 0x40
-
-#define EISADMA 0x00
-#define CHAN0 0x01
-#define CHAN5 0x20
-#define CHAN6 0x40
-#define CHAN7 0x80
-
#define KVTOPHYS(x) vtophys(x)
struct bt_softc {
@@ -350,28 +107,33 @@ struct bt_softc {
int sc_iobase;
int sc_irq, sc_drq;
+ char sc_model[7],
+ sc_firmware[6];
+
struct bt_mbx sc_mbx; /* all our mailboxes */
+#define wmbx (&sc->sc_mbx)
struct bt_ccb *sc_ccbhash[CCB_HASH_SIZE];
- TAILQ_HEAD(, bt_ccb) sc_free_ccb;
- int sc_numccbs;
+ TAILQ_HEAD(, bt_ccb) sc_free_ccb, sc_waiting_ccb;
+ int sc_numccbs, sc_mbofull;
int sc_scsi_dev; /* adapters scsi id */
struct scsi_link sc_link; /* prototype for devs */
};
-/***********debug values *************/
-#define BT_SHOWCCBS 0x01
-#define BT_SHOWINTS 0x02
-#define BT_SHOWCMDS 0x04
-#define BT_SHOWMISC 0x08
+#ifdef BTDEBUG
int bt_debug = 0;
+#endif /* BTDEBUG */
-int bt_cmd __P((int, struct bt_softc *, int, int, int, u_char *,
- unsigned, ...));
+int bt_cmd __P((int, struct bt_softc *, int, u_char *, int, u_char *));
+integrate void bt_finish_ccbs __P((struct bt_softc *));
int btintr __P((void *));
-void bt_free_ccb __P((struct bt_softc *, struct bt_ccb *, int));
+integrate void bt_reset_ccb __P((struct bt_softc *, struct bt_ccb *));
+void bt_free_ccb __P((struct bt_softc *, struct bt_ccb *));
+integrate void bt_init_ccb __P((struct bt_softc *, struct bt_ccb *));
struct bt_ccb *bt_get_ccb __P((struct bt_softc *, int));
struct bt_ccb *bt_ccb_phys_kv __P((struct bt_softc *, u_long));
-struct bt_mbx_out *bt_send_mbo __P((struct bt_softc *, int, struct bt_ccb *));
+void bt_queue_ccb __P((struct bt_softc *, struct bt_ccb *));
+void bt_collect_mbo __P((struct bt_softc *));
+void bt_start_ccbs __P((struct bt_softc *));
void bt_done __P((struct bt_softc *, struct bt_ccb *));
int bt_find __P((struct isa_attach_args *, struct bt_softc *));
void bt_init __P((struct bt_softc *));
@@ -380,10 +142,6 @@ void btminphys __P((struct buf *));
int bt_scsi_cmd __P((struct scsi_xfer *));
int bt_poll __P((struct bt_softc *, struct scsi_xfer *, int));
void bt_timeout __P((void *arg));
-#ifdef UTEST
-void bt_print_ccb __P((struct bt_ccb *));
-void bt_print_active_ccbs __P((struct bt_softc *));
-#endif
struct scsi_adapter bt_switch = {
bt_scsi_cmd,
@@ -404,47 +162,43 @@ int btprobe __P((struct device *, void *, void *));
void btattach __P((struct device *, struct device *, void *));
int btprint __P((void *, char *));
-struct cfdriver btcd = {
- NULL, "bt", btprobe, btattach, DV_DULL, sizeof(struct bt_softc)
+struct cfattach bt_ca = {
+ sizeof(struct bt_softc), btprobe, btattach
+};
+
+struct cfdriver bt_cd = {
+ NULL, "bt", DV_DULL
};
-#define BT_RESET_TIMEOUT 1000
+#define BT_RESET_TIMEOUT 2000 /* time to wait for reset (mSec) */
+#define BT_ABORT_TIMEOUT 2000 /* time to wait for abort (mSec) */
/*
- * bt_cmd(iobase, sc, icnt, ocnt, wait, retval, opcode, ... args ...)
+ * bt_cmd(iobase, sc, icnt, ibuf, ocnt, obuf)
*
* Activate Adapter command
- * icnt: number of args (outbound bytes written after opcode)
+ * icnt: number of args (outbound bytes including opcode)
+ * ibuf: argument buffer
* ocnt: number of expected returned bytes
+ * obuf: result buffer
* wait: number of seconds to wait for response
- * retval: buffer where to place returned bytes
- * opcode: opcode BT_NOP, BT_MBX_INIT, BT_START_SCSI ...
- * args: variable number of parameters
*
* Performs an adapter command through the ports. Not to be confused with a
* scsi command, which is read in via the dma; one of the adapter commands
* tells it to read in a scsi command.
*/
int
-#ifdef __STDC__
-bt_cmd(int iobase, struct bt_softc *sc, int icnt, int ocnt, int wait,
- u_char *retval, unsigned opcode, ...)
-#else
-bt_cmd(iobase, sc, icnt, ocnt, wait, retval, opcode, va_alist)
+bt_cmd(iobase, sc, icnt, ibuf, ocnt, obuf)
int iobase;
struct bt_softc *sc;
- int icnt, ocnt, wait;
- u_char *retval;
- unsigned opcode;
- va_dcl
-#endif
+ int icnt, ocnt;
+ u_char *ibuf, *obuf;
{
- va_list ap;
- unsigned data;
const char *name;
- u_char oc;
- register i;
- int sts;
+ register int i;
+ int wait;
+ u_char sts;
+ u_char opcode = ibuf[0];
if (sc == NULL)
name = sc->sc_dev.dv_xname;
@@ -452,29 +206,31 @@ bt_cmd(iobase, sc, icnt, ocnt, wait, retval, opcode, va_alist)
name = "(probe)";
/*
- * multiply the wait argument by a big constant
- * zero defaults to 1
+ * Calculate a reasonable timeout for the command.
*/
- if (wait)
- wait *= 100000;
- else
- wait = 100000;
+ switch (opcode) {
+ case BT_INQUIRE_DEVICES:
+ wait = 15 * 20000;
+ break;
+ default:
+ wait = 1 * 20000;
+ break;
+ }
+
/*
* Wait for the adapter to go idle, unless it's one of
* the commands which don't need this
*/
- if (opcode != BT_MBX_INIT && opcode != BT_START_SCSI) {
- i = 100000; /* 1 sec? */
- while (--i) {
- sts = inb(iobase + BT_CTRL_STAT_PORT);
- if (sts & BT_IDLE) {
+ if (opcode != BT_MBO_INTR_EN) {
+ for (i = 20000; i; i--) { /* 1 sec? */
+ sts = inb(iobase + BT_STAT_PORT);
+ if (sts & BT_STAT_IDLE)
break;
- }
- delay(10);
+ delay(50);
}
if (!i) {
printf("%s: bt_cmd, host not idle(0x%x)\n",
- name, sts);
+ name, sts);
return ENXIO;
}
}
@@ -483,69 +239,68 @@ bt_cmd(iobase, sc, icnt, ocnt, wait, retval, opcode, va_alist)
* queue feeding to us.
*/
if (ocnt) {
- while ((inb(iobase + BT_CTRL_STAT_PORT)) & BT_DF)
- inb(iobase + BT_CMD_DATA_PORT);
+ while ((inb(iobase + BT_STAT_PORT)) & BT_STAT_DF)
+ inb(iobase + BT_DATA_PORT);
}
/*
* Output the command and the number of arguments given
* for each byte, first check the port is empty.
*/
- va_start(ap, opcode);
- /* test icnt >= 0, to include the command in data sent */
- for (data = opcode; icnt >= 0; icnt--, data = va_arg(ap, u_char)) {
- sts = inb(iobase + BT_CTRL_STAT_PORT);
+ while (icnt--) {
for (i = wait; i; i--) {
- sts = inb(iobase + BT_CTRL_STAT_PORT);
- if (!(sts & BT_CDF))
+ sts = inb(iobase + BT_STAT_PORT);
+ if (!(sts & BT_STAT_CDF))
break;
- delay(10);
+ delay(50);
}
if (!i) {
- printf("%s: bt_cmd, cmd/data port full\n", name);
- outb(iobase + BT_CTRL_STAT_PORT, BT_SRST);
- va_end(ap);
+ if (opcode != BT_INQUIRE_REVISION)
+ printf("%s: bt_cmd, cmd/data port full\n", name);
+ outb(iobase + BT_CTRL_PORT, BT_CTRL_SRST);
return ENXIO;
}
- outb(iobase + BT_CMD_DATA_PORT, data);
+ outb(iobase + BT_CMD_PORT, *ibuf++);
}
- va_end(ap);
/*
* If we expect input, loop that many times, each time,
* looking for the data register to have valid data
*/
while (ocnt--) {
- sts = inb(iobase + BT_CTRL_STAT_PORT);
for (i = wait; i; i--) {
- sts = inb(iobase + BT_CTRL_STAT_PORT);
- if (sts & BT_DF)
+ sts = inb(iobase + BT_STAT_PORT);
+ if (sts & BT_STAT_DF)
break;
- delay(10);
+ delay(50);
}
if (!i) {
- printf("bt%d: bt_cmd, cmd/data port empty %d\n",
- name, ocnt);
+ if (opcode != BT_INQUIRE_REVISION)
+ printf("%s: bt_cmd, cmd/data port empty %d\n",
+ name, ocnt);
+ outb(iobase + BT_CTRL_PORT, BT_CTRL_SRST);
return ENXIO;
}
- oc = inb(iobase + BT_CMD_DATA_PORT);
- if (retval)
- *retval++ = oc;
+ *obuf++ = inb(iobase + BT_DATA_PORT);
}
/*
- * Wait for the board to report a finised instruction
+ * Wait for the board to report a finished instruction.
+ * We may get an extra interrupt for the HACC signal, but this is
+ * unimportant.
*/
- i = 100000; /* 1 sec? */
- while (--i) {
- sts = inb(iobase + BT_INTR_PORT);
- if (sts & BT_HACC)
- break;
- delay(10);
- }
- if (!i) {
- printf("%s: bt_cmd, host not finished(0x%x)\n",
- name, sts);
- return ENXIO;
+ if (opcode != BT_MBO_INTR_EN) {
+ for (i = 20000; i; i--) { /* 1 sec? */
+ sts = inb(iobase + BT_INTR_PORT);
+ /* XXX Need to save this in the interrupt handler? */
+ if (sts & BT_INTR_HACC)
+ break;
+ delay(50);
+ }
+ if (!i) {
+ printf("%s: bt_cmd, host not finished(0x%x)\n",
+ name, sts);
+ return ENXIO;
+ }
}
- outb(iobase + BT_CTRL_STAT_PORT, BT_IRST);
+ outb(iobase + BT_CTRL_PORT, BT_CTRL_IRST);
return 0;
}
@@ -560,7 +315,6 @@ btprobe(parent, match, aux)
struct device *parent;
void *match, *aux;
{
- struct bt_softc *sc = match;
register struct isa_attach_args *ia = aux;
#ifdef NEWCONFIG
@@ -568,16 +322,13 @@ btprobe(parent, match, aux)
return 0;
#endif
- /*
- * Try initialise a unit at this location
- * sets up dma and bus speed, loads sc->sc_irq
- */
+ /* See if there is a unit at this location. */
if (bt_find(ia, NULL) != 0)
return 0;
ia->ia_msize = 0;
ia->ia_iosize = 4;
- /* IRQ and DRQ set by bt_find() */
+ /* IRQ and DRQ set by bt_find(). */
return 1;
}
@@ -586,6 +337,7 @@ btprint(aux, name)
void *aux;
char *name;
{
+
if (name != NULL)
printf("%s: scsibus ", name);
return UNCONF;
@@ -600,7 +352,7 @@ btattach(parent, self, aux)
void *aux;
{
struct isa_attach_args *ia = aux;
- struct bt_softc *sc = (struct bt_softc *)self;
+ struct bt_softc *sc = (void *)self;
if (bt_find(ia, sc) != 0)
panic("btattach: bt_find of %s failed", self->dv_xname);
@@ -609,8 +361,10 @@ btattach(parent, self, aux)
if (sc->sc_drq != DRQUNK)
isa_dmacascade(sc->sc_drq);
+ bt_inquire_setup_information(sc);
bt_init(sc);
TAILQ_INIT(&sc->sc_free_ccb);
+ TAILQ_INIT(&sc->sc_waiting_ccb);
/*
* fill in the prototype scsi_link.
@@ -619,15 +373,13 @@ btattach(parent, self, aux)
sc->sc_link.adapter_target = sc->sc_scsi_dev;
sc->sc_link.adapter = &bt_switch;
sc->sc_link.device = &bt_dev;
- sc->sc_link.openings = 2;
-
- printf("\n");
+ sc->sc_link.openings = 4;
#ifdef NEWCONFIG
isa_establish(&sc->sc_id, &sc->sc_dev);
#endif
- sc->sc_ih = isa_intr_establish(sc->sc_irq, IST_EDGE, IPL_BIO, btintr,
- sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, sc->sc_irq, IST_EDGE,
+ IPL_BIO, btintr, sc, sc->sc_dev.dv_xname);
/*
* ask the adapter what subunits are present
@@ -635,141 +387,162 @@ btattach(parent, self, aux)
config_found(self, &sc->sc_link, btprint);
}
-/*
- * Catch an interrupt from the adaptor
- */
-int
-btintr(arg)
- void *arg;
+integrate void
+bt_finish_ccbs(sc)
+ struct bt_softc *sc;
{
- struct bt_softc *sc = arg;
- int iobase = sc->sc_iobase;
struct bt_mbx_in *wmbi;
- struct bt_mbx *wmbx;
struct bt_ccb *ccb;
- u_char stat;
int i;
- int found = 0;
-#ifdef BTDEBUG
- printf("%s: btintr ", sc->sc_dev.dv_xname);
-#endif /* BTDEBUG */
-
- /*
- * First acknowlege the interrupt, Then if it's
- * not telling about a completed operation
- * just return.
- */
- stat = inb(iobase + BT_INTR_PORT);
- if ((stat & (BT_MBOA | BT_MBIF)) == 0) {
- outb(iobase + BT_CTRL_STAT_PORT, BT_IRST);
- return -1; /* XXX */
- }
+ wmbi = wmbx->tmbi;
- /* Mail box out empty? */
- if (stat & BT_MBOA) {
- /* Disable MBO available interrupt. */
- outb(iobase + BT_CMD_DATA_PORT, BT_MBO_INTR_EN);
- for (i = 100000; i; i--) {
- if (!(inb(iobase + BT_CTRL_STAT_PORT) & BT_CDF))
- break;
- delay(10);
- }
- if (!i) {
- printf("%s: btintr, cmd/data port full\n",
- sc->sc_dev.dv_xname);
- outb(iobase + BT_CTRL_STAT_PORT, BT_SRST);
- return 1;
+ if (wmbi->stat == BT_MBI_FREE) {
+ for (i = 0; i < BT_MBX_SIZE; i++) {
+ if (wmbi->stat != BT_MBI_FREE) {
+ printf("%s: mbi not in round-robin order\n",
+ sc->sc_dev.dv_xname);
+ goto AGAIN;
+ }
+ bt_nextmbx(wmbi, wmbx, mbi);
}
- outb(iobase + BT_CMD_DATA_PORT, 0x00); /* Disable */
- wakeup(&sc->sc_mbx);
+#ifdef BTDIAGnot
+ printf("%s: mbi interrupt with no full mailboxes\n",
+ sc->sc_dev.dv_xname);
+#endif
+ return;
}
- /* Mail box in full? */
- if ((stat & BT_MBIF) == 0)
- return 1;
- wmbx = &sc->sc_mbx;
- wmbi = wmbx->tmbi;
AGAIN:
- while (wmbi->stat != BT_MBI_FREE) {
- ccb = bt_ccb_phys_kv(sc, wmbi->ccb_addr);
+ do {
+ ccb = bt_ccb_phys_kv(sc, phystol(wmbi->ccb_addr));
if (!ccb) {
- wmbi->stat = BT_MBI_FREE;
- printf("%s: BAD CCB ADDR!\n", sc->sc_dev.dv_xname);
- continue;
+ printf("%s: bad mbi ccb pointer; skipping\n",
+ sc->sc_dev.dv_xname);
+ goto next;
+ }
+
+#ifdef BTDEBUG
+ if (bt_debug) {
+ u_char *cp = &ccb->scsi_cmd;
+ printf("op=%x %x %x %x %x %x\n",
+ cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
+ printf("stat %x for mbi addr = 0x%08x, ",
+ wmbi->stat, wmbi);
+ printf("ccb addr = 0x%x\n", ccb);
}
- found++;
+#endif /* BTDEBUG */
+
switch (wmbi->stat) {
case BT_MBI_OK:
case BT_MBI_ERROR:
+ if ((ccb->flags & CCB_ABORT) != 0) {
+ /*
+ * If we already started an abort, wait for it
+ * to complete before clearing the CCB. We
+ * could instead just clear CCB_SENDING, but
+ * what if the mailbox was already received?
+ * The worst that happens here is that we clear
+ * the CCB a bit later than we need to. BFD.
+ */
+ goto next;
+ }
break;
case BT_MBI_ABORT:
- ccb->host_stat = BT_ABORTED;
- break;
-
case BT_MBI_UNKNOWN:
- ccb = 0;
+ /*
+ * Even if the CCB wasn't found, we clear it anyway.
+ * See preceeding comment.
+ */
break;
default:
- panic("Impossible mbxi status");
+ printf("%s: bad mbi status %02x; skipping\n",
+ sc->sc_dev.dv_xname, wmbi->stat);
+ goto next;
}
-#ifdef BTDEBUG
- if (bt_debug && ccb) {
- u_char *cp = &ccb->scsi_cmd;
- printf("op=%x %x %x %x %x %x\n",
- cp[0], cp[1], cp[2],
- cp[3], cp[4], cp[5]);
- printf("stat %x for mbi addr = 0x%08x, ",
- wmbi->stat, wmbi);
- printf("ccb addr = 0x%x\n", ccb);
- }
-#endif /* BTDEBUG */
+
+ untimeout(bt_timeout, ccb);
+ bt_done(sc, ccb);
+
+ next:
wmbi->stat = BT_MBI_FREE;
- if (ccb) {
- untimeout(bt_timeout, ccb);
- bt_done(sc, ccb);
- }
bt_nextmbx(wmbi, wmbx, mbi);
- }
- if (!found) {
- for (i = 0; i < BT_MBX_SIZE; i++) {
- if (wmbi->stat != BT_MBI_FREE) {
- found++;
- break;
- }
- bt_nextmbx(wmbi, wmbx, mbi);
- }
- if (!found) {
-#if 0
- printf("%s: mbi interrupt with no full mailboxes\n",
- sc->sc_dev.dv_xname);
+ } while (wmbi->stat != BT_MBI_FREE);
+
+ wmbx->tmbi = wmbi;
+}
+
+/*
+ * Catch an interrupt from the adaptor
+ */
+int
+btintr(arg)
+ void *arg;
+{
+ struct bt_softc *sc = arg;
+ int iobase = sc->sc_iobase;
+ u_char sts;
+
+#ifdef BTDEBUG
+ printf("%s: btintr ", sc->sc_dev.dv_xname);
+#endif /* BTDEBUG */
+
+ /*
+ * First acknowlege the interrupt, Then if it's not telling about
+ * a completed operation just return.
+ */
+ sts = inb(iobase + BT_INTR_PORT);
+ if ((sts & BT_INTR_ANYINTR) == 0)
+ return 0;
+ outb(iobase + BT_CTRL_PORT, BT_CTRL_IRST);
+
+#ifdef BTDIAG
+ /* Make sure we clear CCB_SENDING before finishing a CCB. */
+ bt_collect_mbo(sc);
#endif
- } else {
- found = 0;
- goto AGAIN;
- }
+
+ /* Mail box out empty? */
+ if (sts & BT_INTR_MBOA) {
+ struct bt_toggle toggle;
+
+ toggle.cmd.opcode = BT_MBO_INTR_EN;
+ toggle.cmd.enable = 0;
+ bt_cmd(iobase, sc, sizeof(toggle.cmd), (u_char *)&toggle.cmd, 0,
+ (u_char *)0);
+ bt_start_ccbs(sc);
}
- wmbx->tmbi = wmbi;
- outb(iobase + BT_CTRL_STAT_PORT, BT_IRST);
+
+ /* Mail box in full? */
+ if (sts & BT_INTR_MBIF)
+ bt_finish_ccbs(sc);
+
return 1;
}
+integrate void
+bt_reset_ccb(sc, ccb)
+ struct bt_softc *sc;
+ struct bt_ccb *ccb;
+{
+
+ ccb->flags = 0;
+}
+
/*
* A ccb is put onto the free list.
*/
void
-bt_free_ccb(sc, ccb, flags)
+bt_free_ccb(sc, ccb)
struct bt_softc *sc;
struct bt_ccb *ccb;
- int flags;
{
int s;
s = splbio();
- ccb->flags = CCB_FREE;
+ bt_reset_ccb(sc, ccb);
TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, chain);
/*
@@ -782,7 +555,7 @@ bt_free_ccb(sc, ccb, flags)
splx(s);
}
-static inline void
+integrate void
bt_init_ccb(sc, ccb)
struct bt_softc *sc;
struct bt_ccb *ccb;
@@ -798,14 +571,7 @@ bt_init_ccb(sc, ccb)
hashnum = CCB_HASH(ccb->hashkey);
ccb->nexthash = sc->sc_ccbhash[hashnum];
sc->sc_ccbhash[hashnum] = ccb;
-}
-
-static inline void
-bt_reset_ccb(sc, ccb)
- struct bt_softc *sc;
- struct bt_ccb *ccb;
-{
-
+ bt_reset_ccb(sc, ccb);
}
/*
@@ -835,15 +601,15 @@ bt_get_ccb(sc, flags)
break;
}
if (sc->sc_numccbs < BT_CCB_MAX) {
- if (ccb = (struct bt_ccb *) malloc(sizeof(struct bt_ccb),
- M_TEMP, M_NOWAIT)) {
- bt_init_ccb(sc, ccb);
- sc->sc_numccbs++;
- } else {
+ ccb = (struct bt_ccb *) malloc(sizeof(struct bt_ccb),
+ M_TEMP, M_NOWAIT);
+ if (!ccb) {
printf("%s: can't malloc ccb\n",
sc->sc_dev.dv_xname);
goto out;
}
+ bt_init_ccb(sc, ccb);
+ sc->sc_numccbs++;
break;
}
if ((flags & SCSI_NOSLEEP) != 0)
@@ -851,8 +617,7 @@ bt_get_ccb(sc, flags)
tsleep(&sc->sc_free_ccb, PRIBIO, "btccb", 0);
}
- bt_reset_ccb(sc, ccb);
- ccb->flags = CCB_ACTIVE;
+ ccb->flags |= CCB_ALLOC;
out:
splx(s);
@@ -860,8 +625,7 @@ out:
}
/*
- * given a physical address, find the ccb that
- * it corresponds to:
+ * Given a physical address, find the ccb that it corresponds to.
*/
struct bt_ccb *
bt_ccb_phys_kv(sc, ccb_phys)
@@ -880,55 +644,97 @@ bt_ccb_phys_kv(sc, ccb_phys)
}
/*
- * Get a mbo and send the ccb.
+ * Queue a CCB to be sent to the controller, and send it if possible.
+ */
+void
+bt_queue_ccb(sc, ccb)
+ struct bt_softc *sc;
+ struct bt_ccb *ccb;
+{
+
+ TAILQ_INSERT_TAIL(&sc->sc_waiting_ccb, ccb, chain);
+ bt_start_ccbs(sc);
+}
+
+/*
+ * Garbage collect mailboxes that are no longer in use.
*/
-struct bt_mbx_out *
-bt_send_mbo(sc, cmd, ccb)
+void
+bt_collect_mbo(sc)
struct bt_softc *sc;
- int cmd;
+{
+ struct bt_mbx_out *wmbo; /* Mail Box Out pointer */
struct bt_ccb *ccb;
+
+ wmbo = wmbx->cmbo;
+
+ while (sc->sc_mbofull > 0) {
+ if (wmbo->cmd != BT_MBO_FREE)
+ break;
+
+#ifdef BTDIAG
+ ccb = bt_ccb_phys_kv(sc, phystol(wmbo->ccb_addr));
+ ccb->flags &= ~CCB_SENDING;
+#endif
+
+ --sc->sc_mbofull;
+ bt_nextmbx(wmbo, wmbx, mbo);
+ }
+
+ wmbx->cmbo = wmbo;
+}
+
+/*
+ * Send as many CCBs as we have empty mailboxes for.
+ */
+void
+bt_start_ccbs(sc)
+ struct bt_softc *sc;
{
int iobase = sc->sc_iobase;
struct bt_mbx_out *wmbo; /* Mail Box Out pointer */
- struct bt_mbx *wmbx; /* Mail Box pointer specified unit */
+ struct bt_ccb *ccb;
int i;
- /* Get the target out mail box pointer and increment. */
- wmbx = &sc->sc_mbx;
wmbo = wmbx->tmbo;
- bt_nextmbx(wmbx->tmbo, wmbx, mbo);
- /*
- * Check the outmail box is free or not.
- * Note: Under the normal operation, it shuld NOT happen to wait.
- */
- while (wmbo->cmd != BT_MBO_FREE) {
- /* Enable mbo available interrupt. */
- outb(iobase + BT_CMD_DATA_PORT, BT_MBO_INTR_EN);
- for (i = 100000; i; i--) {
- if (!(inb(iobase + BT_CTRL_STAT_PORT) & BT_CDF))
+ while (ccb = sc->sc_waiting_ccb.tqh_first) {
+ if (sc->sc_mbofull >= BT_MBX_SIZE) {
+ bt_collect_mbo(sc);
+ if (sc->sc_mbofull >= BT_MBX_SIZE) {
+ struct bt_toggle toggle;
+
+ toggle.cmd.opcode = BT_MBO_INTR_EN;
+ toggle.cmd.enable = 1;
+ bt_cmd(iobase, sc, sizeof(toggle.cmd),
+ (u_char *)&toggle.cmd, 0, (u_char *)0);
break;
- delay(10);
- }
- if (!i) {
- printf("%s: bt_send_mbo, cmd/data port full\n",
- sc->sc_dev.dv_xname);
- outb(iobase + BT_CTRL_STAT_PORT, BT_SRST);
- return NULL;
+ }
}
- outb(iobase + BT_CMD_DATA_PORT, 0x01); /* Enable */
- tsleep(wmbx, PRIBIO, "btsnd", 0);/*XXX can't do this */
- }
- /* Link ccb to mbo. */
- wmbo->ccb_addr = KVTOPHYS(ccb);
- ccb->mbx = wmbo;
- wmbo->cmd = cmd;
+ TAILQ_REMOVE(&sc->sc_waiting_ccb, ccb, chain);
+#ifdef BTDIAG
+ ccb->flags |= CCB_SENDING;
+#endif
+
+ /* Link ccb to mbo. */
+ ltophys(KVTOPHYS(ccb), wmbo->ccb_addr);
+ if (ccb->flags & CCB_ABORT)
+ wmbo->cmd = BT_MBO_ABORT;
+ else
+ wmbo->cmd = BT_MBO_START;
+
+ /* Tell the card to poll immediately. */
+ outb(iobase + BT_CMD_PORT, BT_START_SCSI);
+
+ if ((ccb->xs->flags & SCSI_POLL) == 0)
+ timeout(bt_timeout, ccb, (ccb->timeout * hz) / 1000);
- /* Send it! */
- outb(iobase + BT_CMD_DATA_PORT, BT_START_SCSI);
+ ++sc->sc_mbofull;
+ bt_nextmbx(wmbo, wmbx, mbo);
+ }
- return wmbo;
+ wmbx->tmbo = wmbo;
}
/*
@@ -949,16 +755,21 @@ bt_done(sc, ccb)
* Otherwise, put the results of the operation
* into the xfer and call whoever started it
*/
- if ((xs->flags & INUSE) == 0) {
- printf("%s: exiting but not in use!\n", sc->sc_dev.dv_xname);
+#ifdef BTDIAG
+ if (ccb->flags & CCB_SENDING) {
+ printf("%s: exiting ccb still in transit!\n", sc->sc_dev.dv_xname);
Debugger();
+ return;
+ }
+#endif
+ if ((ccb->flags & CCB_ALLOC) == 0) {
+ printf("%s: exiting ccb not allocated!\n", sc->sc_dev.dv_xname);
+ Debugger();
+ return;
}
if (xs->error == XS_NOERROR) {
if (ccb->host_stat != BT_OK) {
switch (ccb->host_stat) {
- case BT_ABORTED:
- xs->error = XS_DRIVER_STUFFUP;
- break;
case BT_SEL_TIMEOUT: /* No response */
xs->error = XS_SELTIMEOUT;
break;
@@ -966,6 +777,7 @@ bt_done(sc, ccb)
printf("%s: host_stat %x\n",
sc->sc_dev.dv_xname, ccb->host_stat);
xs->error = XS_DRIVER_STUFFUP;
+ break;
}
} else if (ccb->target_stat != SCSI_OK) {
switch (ccb->target_stat) {
@@ -982,12 +794,13 @@ bt_done(sc, ccb)
printf("%s: target_stat %x\n",
sc->sc_dev.dv_xname, ccb->target_stat);
xs->error = XS_DRIVER_STUFFUP;
+ break;
}
} else
xs->resid = 0;
}
+ bt_free_ccb(sc, ccb);
xs->flags |= ITSDONE;
- bt_free_ccb(sc, ccb, xs->flags);
scsi_done(xs);
}
@@ -1000,10 +813,10 @@ bt_find(ia, sc)
struct bt_softc *sc;
{
int iobase = ia->ia_iobase;
- u_char ad[4];
- volatile int i, sts;
- struct bt_extended_inquire info;
- struct bt_config conf;
+ int i;
+ u_char sts;
+ struct bt_extended_inquire inquire;
+ struct bt_config config;
int irq, drq;
/*
@@ -1011,18 +824,20 @@ bt_find(ia, sc)
* that it's not there.. good for the probe
*/
- outb(iobase + BT_CTRL_STAT_PORT, BT_HRST | BT_SRST);
+ outb(iobase + BT_CTRL_PORT, BT_CTRL_HRST | BT_CTRL_SRST);
+ delay(100);
for (i = BT_RESET_TIMEOUT; i; i--) {
- sts = inb(iobase + BT_CTRL_STAT_PORT);
- if (sts == (BT_IDLE | BT_INIT))
+ sts = inb(iobase + BT_STAT_PORT);
+ if (sts == (BT_STAT_IDLE | BT_STAT_INIT))
break;
delay(1000);
}
if (!i) {
-#ifdef UTEST
- printf("bt_find: No answer from bt742a board\n");
-#endif
+#ifdef BTDEBUG
+ if (bt_debug)
+ printf("bt_find: No answer from buslogic board\n");
+#endif /* BTDEBUG */
return 1;
}
@@ -1030,9 +845,11 @@ bt_find(ia, sc)
* Check that we actually know how to use this board.
*/
delay(1000);
- bt_cmd(iobase, sc, 1, sizeof(info), 0, (u_char *)&info,
- BT_INQUIRE_EXTENDED, sizeof(info));
- switch (info.bus_type) {
+ inquire.cmd.opcode = BT_INQUIRE_EXTENDED;
+ inquire.cmd.len = sizeof(inquire.reply);
+ bt_cmd(iobase, sc, sizeof(inquire.cmd), (u_char *)&inquire.cmd,
+ sizeof(inquire.reply), (u_char *)&inquire.reply);
+ switch (inquire.reply.bus_type) {
case BT_BUS_TYPE_24BIT:
/* XXXX How do we avoid conflicting with the aha1542 probe? */
case BT_BUS_TYPE_32BIT:
@@ -1041,7 +858,7 @@ bt_find(ia, sc)
/* We don't grok MicroChannel (yet). */
return 1;
default:
- printf("bt_find: illegal bus type %c\n", info.bus_type);
+ printf("bt_find: illegal bus type %c\n", inquire.reply.bus_type);
return 1;
}
@@ -1050,8 +867,10 @@ bt_find(ia, sc)
* jumpers and save int level
*/
delay(1000);
- bt_cmd(iobase, sc, 0, sizeof(conf), 0, (u_char *)&conf, BT_CONF_GET);
- switch (conf.chan) {
+ config.cmd.opcode = BT_INQUIRE_CONFIG;
+ bt_cmd(iobase, sc, sizeof(config.cmd), (u_char *)&config.cmd,
+ sizeof(config.reply), (u_char *)&config.reply);
+ switch (config.reply.chan) {
case EISADMA:
drq = DRQUNK;
break;
@@ -1068,11 +887,11 @@ bt_find(ia, sc)
drq = 7;
break;
default:
- printf("bt_find: illegal dma setting %x\n", conf.chan);
+ printf("bt_find: illegal drq setting %x\n", config.reply.chan);
return 1;
}
- switch (conf.intr) {
+ switch (config.reply.intr) {
case INT9:
irq = 9;
break;
@@ -1092,13 +911,13 @@ bt_find(ia, sc)
irq = 15;
break;
default:
- printf("bt_find: illegal int setting %x\n", conf.intr);
+ printf("bt_find: illegal irq setting %x\n", config.reply.intr);
return 1;
}
if (sc != NULL) {
/* who are we on the scsi bus? */
- sc->sc_scsi_dev = conf.scsi_dev;
+ sc->sc_scsi_dev = config.reply.scsi_dev;
sc->sc_iobase = iobase;
sc->sc_irq = irq;
@@ -1125,29 +944,74 @@ bt_init(sc)
struct bt_softc *sc;
{
int iobase = sc->sc_iobase;
- u_char ad[4];
+ struct bt_devices devices;
+ struct bt_setup setup;
+ struct bt_mailbox mailbox;
+ struct bt_period period;
int i;
- /*
- * Initialize mail box
- */
- *((physaddr *)ad) = KVTOPHYS(&sc->sc_mbx);
+ /* Enable round-robin scheme - appeared at firmware rev. 3.31. */
+ if (strcmp(sc->sc_firmware, "3.31") >= 0) {
+ struct bt_toggle toggle;
- bt_cmd(iobase, sc, 5, 0, 0, 0, BT_MBX_INIT_EXTENDED, BT_MBX_SIZE,
- ad[0], ad[1], ad[2], ad[3]);
+ toggle.cmd.opcode = BT_ROUND_ROBIN;
+ toggle.cmd.enable = 1;
+ bt_cmd(iobase, sc, sizeof(toggle.cmd), (u_char *)&toggle.cmd,
+ 0, (u_char *)0);
+ }
- for (i = 0; i < BT_MBX_SIZE; i++) {
- sc->sc_mbx.mbo[i].cmd = BT_MBO_FREE;
- sc->sc_mbx.mbi[i].stat = BT_MBI_FREE;
+ /* Inquire Installed Devices (to force synchronous negotiation). */
+ devices.cmd.opcode = BT_INQUIRE_DEVICES;
+ bt_cmd(iobase, sc, sizeof(devices.cmd), (u_char *)&devices.cmd,
+ sizeof(devices.reply), (u_char *)&devices.reply);
+
+ /* Obtain setup information from. */
+ setup.cmd.opcode = BT_INQUIRE_SETUP;
+ setup.cmd.len = sizeof(setup.reply);
+ bt_cmd(iobase, sc, sizeof(setup.cmd), (u_char *)&setup.cmd,
+ sizeof(setup.reply), (u_char *)&setup.reply);
+
+ printf("%s: %s, %s\n",
+ sc->sc_dev.dv_xname,
+ setup.reply.sync_neg ? "sync" : "async",
+ setup.reply.parity ? "parity" : "no parity");
+
+ for (i = 0; i < 8; i++)
+ period.reply.period[i] = setup.reply.sync[i].period * 5 + 20;
+
+ if (sc->sc_firmware[0] >= '3') {
+ period.cmd.opcode = BT_INQUIRE_PERIOD;
+ period.cmd.len = sizeof(period.reply);
+ bt_cmd(iobase, sc, sizeof(period.cmd), (u_char *)&period.cmd,
+ sizeof(period.reply), (u_char *)&period.reply);
+ }
+
+ for (i = 0; i < 8; i++) {
+ if (!setup.reply.sync[i].valid ||
+ (!setup.reply.sync[i].offset && !setup.reply.sync[i].period))
+ continue;
+ printf("%s targ %d: sync, offset %d, period %dnsec\n",
+ sc->sc_dev.dv_xname, i,
+ setup.reply.sync[i].offset, period.reply.period[i] * 10);
}
/*
* Set up initial mail box for round-robin operation.
*/
- sc->sc_mbx.tmbo = &sc->sc_mbx.mbo[0];
- sc->sc_mbx.tmbi = &sc->sc_mbx.mbi[0];
-
- bt_inquire_setup_information(sc);
+ for (i = 0; i < BT_MBX_SIZE; i++) {
+ wmbx->mbo[i].cmd = BT_MBO_FREE;
+ wmbx->mbi[i].stat = BT_MBI_FREE;
+ }
+ wmbx->cmbo = wmbx->tmbo = &wmbx->mbo[0];
+ wmbx->tmbi = &wmbx->mbi[0];
+ sc->sc_mbofull = 0;
+
+ /* Initialize mail box. */
+ mailbox.cmd.opcode = BT_MBX_INIT_EXTENDED;
+ mailbox.cmd.nmbx = BT_MBX_SIZE;
+ ltophys(KVTOPHYS(wmbx), mailbox.cmd.addr);
+ bt_cmd(iobase, sc, sizeof(mailbox.cmd), (u_char *)&mailbox.cmd,
+ 0, (u_char *)0);
}
void
@@ -1155,72 +1019,61 @@ bt_inquire_setup_information(sc)
struct bt_softc *sc;
{
int iobase = sc->sc_iobase;
- struct bt_boardID bID;
- struct bt_board_info binfo;
- char dummy[8], sub_ver[3];
- struct bt_setup setup;
- int i, ver;
+ struct bt_model model;
+ struct bt_revision revision;
+ struct bt_digit digit;
+ char dummy[8];
+ char *p;
/*
- * Get and print board hardware information.
+ * Get the firmware revision.
*/
- bt_cmd(iobase, sc, 1, sizeof(binfo), 0, (u_char *)&binfo,
- BT_GET_BOARD_INFO, sizeof(binfo));
- printf(": Bt%c%c%c", binfo.id[0], binfo.id[1], binfo.id[2]);
- if (binfo.id[3] != ' ')
- printf("%c", binfo.id[3]);
- if (binfo.version[0] != ' ')
- printf("%c%s", binfo.version[0], binfo.version[1]);
- printf("\n");
-
- /*
- * Inquire Board ID to Bt742 for board type and firmware version.
- */
- bt_cmd(iobase, sc, 0, sizeof(bID), 0, (u_char *)&bID, BT_INQUIRE);
- ver = (bID.firm_revision - '0') * 10 + (bID.firm_version - '0');
+ p = sc->sc_firmware;
+ revision.cmd.opcode = BT_INQUIRE_REVISION;
+ bt_cmd(iobase, sc, sizeof(revision.cmd), (u_char *)&revision.cmd,
+ sizeof(revision.reply), (u_char *)&revision.reply);
+ *p++ = revision.reply.firm_revision;
+ *p++ = '.';
+ *p++ = revision.reply.firm_version;
+ digit.cmd.opcode = BT_INQUIRE_REVISION_3;
+ bt_cmd(iobase, sc, sizeof(digit.cmd), (u_char *)&digit.cmd,
+ sizeof(digit.reply), (u_char *)&digit.reply);
+ *p++ = digit.reply.digit;
+ if (revision.reply.firm_revision >= '3' ||
+ (revision.reply.firm_revision == '3' && revision.reply.firm_version >= '3')) {
+ digit.cmd.opcode = BT_INQUIRE_REVISION_4;
+ bt_cmd(iobase, sc, sizeof(digit.cmd), (u_char *)&digit.cmd,
+ sizeof(digit.reply), (u_char *)&digit.reply);
+ *p++ = digit.reply.digit;
+ }
+ while (p > sc->sc_firmware && (p[-1] == ' ' || p[-1] == '\0'))
+ p--;
+ *p = '\0';
/*
- * Get the rest of the firmware version. Firmware revisions
- * before 3.3 apparently don't accept the BT_INQUIRE_REV_FOURTH
- * command.
+ * Get the model number.
*/
- i = 0;
- bt_cmd(iobase, sc, 0, 1, 0, &sub_ver[i++], BT_INQUIRE_REV_THIRD);
- if (ver >= 33)
- bt_cmd(iobase, sc, 0, 1, 0, &sub_ver[i++],
- BT_INQUIRE_REV_FOURTH);
- if (sub_ver[i - 1] == ' ')
- i--;
- sub_ver[i] = '\0';
-
- printf("%s: firmware version %c.%c%s, ", sc->sc_dev.dv_xname,
- bID.firm_revision, bID.firm_version, sub_ver);
-
- /* Enable round-robin scheme - appeared at firmware rev. 3.31 */
- if (ver > 33 || (ver == 33 && sub_ver[0] >= 1)) {
- bt_cmd(iobase, sc, 1, 0, 0, 0, BT_ROUND_ROBIN, BT_ENABLE);
- }
-
- /* Inquire Installed Devices (to force synchronous negotiation) */
- bt_cmd(iobase, sc, 0, sizeof(dummy), 10, dummy, BT_DEV_GET);
-
- /* Obtain setup information from Bt742. */
- bt_cmd(iobase, sc, 1, sizeof(setup), 0, (u_char *)&setup, BT_SETUP_GET,
- sizeof(setup));
-
- printf("%s, %s, %d mailboxes",
- setup.sync_neg ? "sync" : "async",
- setup.parity ? "parity" : "no parity",
- setup.num_mbx);
-
- for (i = 0; i < 8; i++) {
- if (!setup.sync[i].valid ||
- (!setup.sync[i].offset && !setup.sync[i].period))
- continue;
- printf("\n%s targ %d: sync, offset %d, period %dnsec",
- sc->sc_dev.dv_xname, i,
- setup.sync[i].offset, setup.sync[i].period * 50 + 200);
- }
+ if (revision.reply.firm_revision >= '3') {
+ p = sc->sc_model;
+ model.cmd.opcode = BT_INQUIRE_MODEL;
+ model.cmd.len = sizeof(model.reply);
+ bt_cmd(iobase, sc, sizeof(model.cmd), (u_char *)&model.cmd,
+ sizeof(model.reply), (u_char *)&model.reply);
+ *p++ = model.reply.id[0];
+ *p++ = model.reply.id[1];
+ *p++ = model.reply.id[2];
+ *p++ = model.reply.id[3];
+ while (p > sc->sc_model && (p[-1] == ' ' || p[-1] == '\0'))
+ p--;
+ *p++ = model.reply.version[0];
+ *p++ = model.reply.version[1];
+ while (p > sc->sc_model && (p[-1] == ' ' || p[-1] == '\0'))
+ p--;
+ *p = '\0';
+ } else
+ strcpy(sc->sc_model, "542B");
+
+ printf(": model BT-%s, firmware %s\n", sc->sc_model, sc->sc_firmware);
}
void
@@ -1246,11 +1099,9 @@ bt_scsi_cmd(xs)
struct bt_ccb *ccb;
struct bt_scat_gath *sg;
int seg; /* scatter gather seg being worked on */
- int thiskv;
- physaddr thisphys, nextphys;
+ u_long thiskv, thisphys, nextphys;
int bytes_this_seg, bytes_this_page, datalen, flags;
struct iovec *iovp;
- struct bt_mbx_out *mbo;
int s;
SC_DEBUG(sc_link, SDEV_DB2, ("bt_scsi_cmd\n"));
@@ -1260,39 +1111,28 @@ bt_scsi_cmd(xs)
* then we can't allow it to sleep
*/
flags = xs->flags;
- if ((flags & (ITSDONE|INUSE)) != INUSE) {
- printf("%s: done or not in use?\n", sc->sc_dev.dv_xname);
- xs->flags &= ~ITSDONE;
- xs->flags |= INUSE;
- }
if ((ccb = bt_get_ccb(sc, flags)) == NULL) {
xs->error = XS_DRIVER_STUFFUP;
return TRY_AGAIN_LATER;
}
ccb->xs = xs;
+ ccb->timeout = xs->timeout;
/*
* Put all the arguments for the xfer in the ccb
*/
if (flags & SCSI_RESET) {
ccb->opcode = BT_RESET_CCB;
+ ccb->scsi_cmd_length = 0;
} else {
/* can't use S/G if zero length */
ccb->opcode = (xs->datalen ? BT_INIT_SCAT_GATH_CCB
: BT_INITIATOR_CCB);
+ bcopy(xs->cmd, &ccb->scsi_cmd,
+ ccb->scsi_cmd_length = xs->cmdlen);
}
- ccb->data_out = 0;
- ccb->data_in = 0;
- ccb->target = sc_link->target;
- ccb->lun = sc_link->lun;
- ccb->scsi_cmd_length = xs->cmdlen;
- ccb->sense_ptr = KVTOPHYS(&ccb->scsi_sense);
- ccb->req_sense_length = sizeof(ccb->scsi_sense);
- ccb->host_stat = 0x00;
- ccb->target_stat = 0x00;
- if (xs->datalen && (flags & SCSI_RESET) == 0) {
- ccb->data_addr = KVTOPHYS(ccb->scat_gath);
+ if (xs->datalen) {
sg = ccb->scat_gath;
seg = 0;
#ifdef TFS
@@ -1301,8 +1141,8 @@ bt_scsi_cmd(xs)
datalen = ((struct uio *)xs->data)->uio_iovcnt;
xs->datalen = 0;
while (datalen && seg < BT_NSEG) {
- sg->seg_addr = (physaddr)iovp->iov_base;
- sg->seg_len = iovp->iov_len;
+ ltophys(iovp->iov_base, sg->seg_addr);
+ ltophys(iovp->iov_len, sg->seg_len);
xs->datalen += iovp->iov_len;
SC_DEBUGN(sc_link, SDEV_DB4, ("(0x%x@0x%x)",
iovp->iov_len, iovp->iov_base));
@@ -1315,19 +1155,20 @@ bt_scsi_cmd(xs)
#endif /* TFS */
{
/*
- * Set up the scatter gather block
+ * Set up the scatter-gather block.
*/
SC_DEBUG(sc_link, SDEV_DB4,
("%d @0x%x:- ", xs->datalen, xs->data));
+
datalen = xs->datalen;
- thiskv = (int) xs->data;
+ thiskv = (int)xs->data;
thisphys = KVTOPHYS(thiskv);
while (datalen && seg < BT_NSEG) {
bytes_this_seg = 0;
/* put in the base address */
- sg->seg_addr = thisphys;
+ ltophys(thisphys, sg->seg_addr);
SC_DEBUGN(sc_link, SDEV_DB4, ("0x%x", thisphys));
@@ -1358,13 +1199,12 @@ bt_scsi_cmd(xs)
*/
SC_DEBUGN(sc_link, SDEV_DB4,
("(0x%x)", bytes_this_seg));
- sg->seg_len = bytes_this_seg;
+ ltophys(bytes_this_seg, sg->seg_len);
sg++;
seg++;
}
}
/* end of iov/kv decision */
- ccb->data_length = seg * sizeof(struct bt_scat_gath);
SC_DEBUGN(sc_link, SDEV_DB4, ("\n"));
if (datalen) {
/*
@@ -1372,53 +1212,51 @@ bt_scsi_cmd(xs)
*/
printf("%s: bt_scsi_cmd, more than %d dma segs\n",
sc->sc_dev.dv_xname, BT_NSEG);
- xs->error = XS_DRIVER_STUFFUP;
- bt_free_ccb(sc, ccb, flags);
- return COMPLETE;
+ goto bad;
}
+ ltophys(KVTOPHYS(ccb->scat_gath), ccb->data_addr);
+ ltophys(seg * sizeof(struct bt_scat_gath), ccb->data_length);
} else { /* No data xfer, use non S/G values */
- ccb->data_addr = (physaddr)0;
- ccb->data_length = 0;
+ ltophys(0, ccb->data_addr);
+ ltophys(0, ccb->data_length);
}
- ccb->link_id = 0;
- ccb->link_addr = (physaddr)0;
- /*
- * Put the scsi command in the ccb and start it
- */
- if ((flags & SCSI_RESET) == 0)
- bcopy(xs->cmd, &ccb->scsi_cmd, ccb->scsi_cmd_length);
+ ccb->data_out = 0;
+ ccb->data_in = 0;
+ ccb->target = sc_link->target;
+ ccb->lun = sc_link->lun;
+ ltophys(KVTOPHYS(&ccb->scsi_sense), ccb->sense_ptr);
+ ccb->req_sense_length = sizeof(ccb->scsi_sense);
+ ccb->host_stat = 0x00;
+ ccb->target_stat = 0x00;
+ ccb->link_id = 0;
+ ltophys(0, ccb->link_addr);
s = splbio();
-
- if (bt_send_mbo(sc, BT_MBO_START, ccb) == NULL) {
- splx(s);
- xs->error = XS_DRIVER_STUFFUP;
- bt_free_ccb(sc, ccb, flags);
- return TRY_AGAIN_LATER;
- }
+ bt_queue_ccb(sc, ccb);
+ splx(s);
/*
* Usually return SUCCESSFULLY QUEUED
*/
SC_DEBUG(sc_link, SDEV_DB3, ("cmd_sent\n"));
- if ((flags & SCSI_POLL) == 0) {
- timeout(bt_timeout, ccb, (xs->timeout * hz) / 1000);
- splx(s);
+ if ((flags & SCSI_POLL) == 0)
return SUCCESSFULLY_QUEUED;
- }
-
- splx(s);
/*
* If we can't use interrupts, poll on completion
*/
- if (bt_poll(sc, xs, xs->timeout)) {
+ if (bt_poll(sc, xs, ccb->timeout)) {
bt_timeout(ccb);
- if (bt_poll(sc, xs, 2000))
+ if (bt_poll(sc, xs, ccb->timeout))
bt_timeout(ccb);
}
return COMPLETE;
+
+bad:
+ xs->error = XS_DRIVER_STUFFUP;
+ bt_free_ccb(sc, ccb);
+ return COMPLETE;
}
/*
@@ -1438,7 +1276,7 @@ bt_poll(sc, xs, count)
* If we had interrupts enabled, would we
* have got an interrupt?
*/
- if (inb(iobase + BT_INTR_PORT) & BT_ANY_INTR)
+ if (inb(iobase + BT_INTR_PORT) & BT_INTR_ANYINTR)
btintr(sc);
if (xs->flags & ITSDONE)
return 0;
@@ -1463,66 +1301,34 @@ bt_timeout(arg)
s = splbio();
+#ifdef BTDIAG
/*
* If the ccb's mbx is not free, then the board has gone Far East?
*/
- if (bt_ccb_phys_kv(sc, ccb->mbx->ccb_addr) == ccb &&
- ccb->mbx->cmd != BT_MBO_FREE) {
+ bt_collect_mbo(sc);
+ if (ccb->flags & CCB_SENDING) {
printf("%s: not taking commands!\n", sc->sc_dev.dv_xname);
Debugger();
}
+#endif
/*
* If it has been through before, then
* a previous abort has failed, don't
* try abort again
*/
- if (ccb->flags == CCB_ABORTED) {
+ if (ccb->flags & CCB_ABORT) {
/* abort timed out */
printf(" AGAIN\n");
- ccb->xs->retries = 0;
- bt_done(sc, ccb);
+ /* XXX Must reset! */
} else {
/* abort the operation that has timed out */
printf("\n");
ccb->xs->error = XS_TIMEOUT;
- ccb->flags = CCB_ABORTED;
- bt_send_mbo(sc, BT_MBO_ABORT, ccb);
- /* 2 secs for the abort */
- if ((xs->flags & SCSI_POLL) == 0)
- timeout(bt_timeout, ccb, 2 * hz);
+ ccb->timeout = BT_ABORT_TIMEOUT;
+ ccb->flags |= CCB_ABORT;
+ bt_queue_ccb(sc, ccb);
}
splx(s);
}
-
-#ifdef UTEST
-void
-bt_print_ccb(ccb)
- struct bt_ccb *ccb;
-{
-
- printf("ccb:%x op:%x cmdlen:%d senlen:%d\n",
- ccb, ccb->opcode, ccb->scsi_cmd_length, ccb->req_sense_length);
- printf(" datlen:%d hstat:%x tstat:%x flags:%x\n",
- ccb->data_length, ccb->host_stat, ccb->target_stat, ccb->flags);
-}
-
-void
-bt_print_active_ccbs(sc)
- struct bt_softc *sc;
-{
- struct bt_ccb *ccb;
- int i = 0;
-
- while (i < CCB_HASH_SIZE) {
- ccb = sc->sc_ccbhash[i];
- while (ccb) {
- if (ccb->flags != CCB_FREE)
- bt_print_ccb(ccb);
- ccb = ccb->nexthash;
- }
- i++;
- }
-}
-#endif /*UTEST */
diff --git a/sys/dev/isa/bt742a.c b/sys/dev/isa/bt742a.c
deleted file mode 100644
index 13798720e74..00000000000
--- a/sys/dev/isa/bt742a.c
+++ /dev/null
@@ -1,1528 +0,0 @@
-/* $OpenBSD: bt742a.c,v 1.7 1996/04/18 23:47:31 niklas Exp $ */
-/* $NetBSD: bt742a.c,v 1.55 1996/03/16 05:33:28 cgd Exp $ */
-
-/*
- * Copyright (c) 1994 Charles Hannum. 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 Charles Hannum.
- * 4. 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.
- */
-
-/*
- * Originally written by Julian Elischer (julian@tfs.com)
- * for TRW Financial Systems for use under the MACH(2.5) operating system.
- *
- * TRW Financial Systems, in accordance with their agreement with Carnegie
- * Mellon University, makes this software available to CMU to distribute
- * or use in any manner that they see fit as long as this message is kept with
- * the software. For this reason TFS also grants any other persons or
- * organisations permission to use or modify this software.
- *
- * TFS supplies this software to be publicly redistributed
- * on the understanding that TFS is not responsible for the correct
- * functioning of this software in any circumstances.
- */
-
-/*
- * bt742a SCSI driver
- */
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/errno.h>
-#include <sys/ioctl.h>
-#include <sys/device.h>
-#include <sys/malloc.h>
-#include <sys/buf.h>
-#include <sys/proc.h>
-#include <sys/user.h>
-
-#include <machine/pio.h>
-
-#include <dev/isa/isavar.h>
-#include <dev/isa/isadmavar.h>
-#include <scsi/scsi_all.h>
-#include <scsi/scsiconf.h>
-
-/*
- * Note that stdarg.h and the ANSI style va_start macro is used for both
- * ANSI and traditional C compilers.
- */
-#include <machine/stdarg.h>
-
-#ifndef DDB
-#define Debugger() panic("should call debugger here (bt742a.c)")
-#endif /* ! DDB */
-
-typedef u_long physaddr;
-typedef u_long physlen;
-
-/*
- * I/O Port Interface
- */
-#define BT_CTRL_STAT_PORT 0x0 /* control & status */
-#define BT_CMD_DATA_PORT 0x1 /* cmds and datas */
-#define BT_INTR_PORT 0x2 /* Intr. stat */
-
-/*
- * BT_CTRL_STAT bits (write)
- */
-#define BT_HRST 0x80 /* Hardware reset */
-#define BT_SRST 0x40 /* Software reset */
-#define BT_IRST 0x20 /* Interrupt reset */
-#define BT_SCRST 0x10 /* SCSI bus reset */
-
-/*
- * BT_CTRL_STAT bits (read)
- */
-#define BT_STST 0x80 /* Self test in Progress */
-#define BT_DIAGF 0x40 /* Diagnostic Failure */
-#define BT_INIT 0x20 /* Mbx Init required */
-#define BT_IDLE 0x10 /* Host Adapter Idle */
-#define BT_CDF 0x08 /* cmd/data out port full */
-#define BT_DF 0x04 /* Data in port full */
-#define BT_INVDCMD 0x01 /* Invalid command */
-
-/*
- * BT_CMD_DATA bits (write)
- */
-#define BT_NOP 0x00 /* No operation */
-#define BT_MBX_INIT 0x01 /* Mbx initialization */
-#define BT_START_SCSI 0x02 /* start scsi command */
-#define BT_START_BIOS 0x03 /* start bios command */
-#define BT_INQUIRE 0x04 /* Adapter Inquiry */
-#define BT_MBO_INTR_EN 0x05 /* Enable MBO available interrupt */
-#define BT_SEL_TIMEOUT_SET 0x06 /* set selection time-out */
-#define BT_BUS_ON_TIME_SET 0x07 /* set bus-on time */
-#define BT_BUS_OFF_TIME_SET 0x08 /* set bus-off time */
-#define BT_SPEED_SET 0x09 /* set transfer speed */
-#define BT_DEV_GET 0x0a /* return installed devices */
-#define BT_CONF_GET 0x0b /* return configuration data */
-#define BT_TARGET_EN 0x0c /* enable target mode */
-#define BT_SETUP_GET 0x0d /* return setup data */
-#define BT_WRITE_CH2 0x1a /* write channel 2 buffer */
-#define BT_READ_CH2 0x1b /* read channel 2 buffer */
-#define BT_WRITE_FIFO 0x1c /* write fifo buffer */
-#define BT_READ_FIFO 0x1d /* read fifo buffer */
-#define BT_ECHO 0x1e /* Echo command data */
-#define BT_MBX_INIT_EXTENDED 0x81 /* Mbx initialization */
-#define BT_INQUIRE_REV_THIRD 0x84 /* Get 3rd firmware version byte */
-#define BT_INQUIRE_REV_FOURTH 0x85 /* Get 4th firmware version byte */
-#define BT_GET_BOARD_INFO 0x8b /* Get hardware ID and revision */
-#define BT_INQUIRE_EXTENDED 0x8d /* Adapter Setup Inquiry */
-
-/* Follows command appeared at firmware 3.31 */
-#define BT_ROUND_ROBIN 0x8f /* Enable/Disable(default) round robin */
-#define BT_DISABLE 0x00 /* Parameter value for Disable */
-#define BT_ENABLE 0x01 /* Parameter value for Enable */
-
-/*
- * BT_INTR_PORT bits (read)
- */
-#define BT_ANY_INTR 0x80 /* Any interrupt */
-#define BT_SCRD 0x08 /* SCSI reset detected */
-#define BT_HACC 0x04 /* Command complete */
-#define BT_MBOA 0x02 /* MBX out empty */
-#define BT_MBIF 0x01 /* MBX in full */
-
-/*
- * Mail box defs etc.
- * these could be bigger but we need the bt_softc to fit on a single page..
- */
-#define BT_MBX_SIZE 32 /* mail box size (MAX 255 MBxs) */
- /* don't need that many really */
-#define BT_CCB_MAX 32 /* store up to 32 CCBs at one time */
-#define CCB_HASH_SIZE 32 /* hash table size for phystokv */
-#define CCB_HASH_SHIFT 9
-#define CCB_HASH(x) ((((long)(x))>>CCB_HASH_SHIFT) & (CCB_HASH_SIZE - 1))
-
-#define bt_nextmbx(wmb, mbx, mbio) \
- if ((wmb) == &(mbx)->mbio[BT_MBX_SIZE - 1]) \
- (wmb) = &(mbx)->mbio[0]; \
- else \
- (wmb)++;
-
-struct bt_mbx_out {
- physaddr ccb_addr;
- u_char dummy[3];
- u_char cmd;
-};
-
-struct bt_mbx_in {
- physaddr ccb_addr;
- u_char btstat;
- u_char sdstat;
- u_char dummy;
- u_char stat;
-};
-
-struct bt_mbx {
- struct bt_mbx_out mbo[BT_MBX_SIZE];
- struct bt_mbx_in mbi[BT_MBX_SIZE];
- struct bt_mbx_out *tmbo; /* Target Mail Box out */
- struct bt_mbx_in *tmbi; /* Target Mail Box in */
-};
-
-/*
- * mbo.cmd values
- */
-#define BT_MBO_FREE 0x0 /* MBO entry is free */
-#define BT_MBO_START 0x1 /* MBO activate entry */
-#define BT_MBO_ABORT 0x2 /* MBO abort entry */
-
-/*
- * mbi.stat values
- */
-#define BT_MBI_FREE 0x0 /* MBI entry is free */
-#define BT_MBI_OK 0x1 /* completed without error */
-#define BT_MBI_ABORT 0x2 /* aborted ccb */
-#define BT_MBI_UNKNOWN 0x3 /* Tried to abort invalid CCB */
-#define BT_MBI_ERROR 0x4 /* Completed with error */
-
-#if defined(BIG_DMA)
-WARNING...THIS WON'T WORK(won't fit on 1 page)
-/* #define BT_NSEG 2048 /* Number of scatter gather segments - to much vm */
-#define BT_NSEG 128
-#else
-#define BT_NSEG 33
-#endif /* BIG_DMA */
-
-struct bt_scat_gath {
- physlen seg_len;
- physaddr seg_addr;
-};
-
-struct bt_ccb {
- u_char opcode;
- u_char:3, data_in:1, data_out:1,:3;
- u_char scsi_cmd_length;
- u_char req_sense_length;
- /*------------------------------------longword boundary */
- physlen data_length;
- /*------------------------------------longword boundary */
- physaddr data_addr;
- /*------------------------------------longword boundary */
- u_char dummy1[2];
- u_char host_stat;
- u_char target_stat;
- /*------------------------------------longword boundary */
- u_char target;
- u_char lun;
- struct scsi_generic scsi_cmd;
- u_char dummy2[1];
- u_char link_id;
- /*------------------------------------longword boundary */
- physaddr link_addr;
- /*------------------------------------longword boundary */
- physaddr sense_ptr;
-/*-----end of HW fields-----------------------longword boundary */
- struct scsi_sense_data scsi_sense;
- /*------------------------------------longword boundary */
- struct bt_scat_gath scat_gath[BT_NSEG];
- /*------------------------------------longword boundary */
- TAILQ_ENTRY(bt_ccb) chain;
- struct bt_ccb *nexthash;
- long hashkey;
- struct scsi_xfer *xs; /* the scsi_xfer for this cmd */
- int flags;
-#define CCB_FREE 0
-#define CCB_ACTIVE 1
-#define CCB_ABORTED 2
- struct bt_mbx_out *mbx; /* pointer to mail box */
-};
-
-/*
- * opcode fields
- */
-#define BT_INITIATOR_CCB 0x00 /* SCSI Initiator CCB */
-#define BT_TARGET_CCB 0x01 /* SCSI Target CCB */
-#define BT_INIT_SCAT_GATH_CCB 0x02 /* SCSI Initiator with scattter gather */
-#define BT_RESET_CCB 0x81 /* SCSI Bus reset */
-
-/*
- * bt_ccb.host_stat values
- */
-#define BT_OK 0x00 /* cmd ok */
-#define BT_LINK_OK 0x0a /* Link cmd ok */
-#define BT_LINK_IT 0x0b /* Link cmd ok + int */
-#define BT_SEL_TIMEOUT 0x11 /* Selection time out */
-#define BT_OVER_UNDER 0x12 /* Data over/under run */
-#define BT_BUS_FREE 0x13 /* Bus dropped at unexpected time */
-#define BT_INV_BUS 0x14 /* Invalid bus phase/sequence */
-#define BT_BAD_MBO 0x15 /* Incorrect MBO cmd */
-#define BT_BAD_CCB 0x16 /* Incorrect ccb opcode */
-#define BT_BAD_LINK 0x17 /* Not same values of LUN for links */
-#define BT_INV_TARGET 0x18 /* Invalid target direction */
-#define BT_CCB_DUP 0x19 /* Duplicate CCB received */
-#define BT_INV_CCB 0x1a /* Invalid CCB or segment list */
-#define BT_ABORTED 42 /* pseudo value from driver */
-
-struct bt_extended_inquire {
- u_char bus_type; /* Type of bus connected to */
-#define BT_BUS_TYPE_24BIT 'A' /* ISA bus */
-#define BT_BUS_TYPE_32BIT 'E' /* EISA/VLB/PCI bus */
-#define BT_BUS_TYPE_MCA 'M' /* MicroChannel bus */
- u_char bios_address; /* Address of adapter BIOS */
- u_short max_segment; /* ? */
-};
-
-struct bt_boardID {
- u_char board_type;
- u_char custom_feture;
- char firm_revision;
- u_char firm_version;
-};
-
-struct bt_board_info {
- u_char id[4]; /* i.e bt742a -> '7','4','2','A' */
- u_char version[2]; /* i.e Board Revision 'H' -> 'H', 0x00 */
-};
-
-struct bt_setup {
- u_char sync_neg:1;
- u_char parity:1;
- u_char :6;
- u_char speed;
- u_char bus_on;
- u_char bus_off;
- u_char num_mbx;
- u_char mbx[3]; /*XXX */
- /* doesn't make sense with 32bit addresses */
- struct {
- u_char offset:4;
- u_char period:3;
- u_char valid:1;
- } sync[8];
- u_char disc_sts;
-};
-
-struct bt_config {
- u_char chan;
- u_char intr;
- u_char scsi_dev:3;
- u_char :5;
-};
-
-#define INT9 0x01
-#define INT10 0x02
-#define INT11 0x04
-#define INT12 0x08
-#define INT14 0x20
-#define INT15 0x40
-
-#define EISADMA 0x00
-#define CHAN0 0x01
-#define CHAN5 0x20
-#define CHAN6 0x40
-#define CHAN7 0x80
-
-#define KVTOPHYS(x) vtophys(x)
-
-struct bt_softc {
- struct device sc_dev;
- struct isadev sc_id;
- void *sc_ih;
-
- int sc_iobase;
- int sc_irq, sc_drq;
-
- struct bt_mbx sc_mbx; /* all our mailboxes */
- struct bt_ccb *sc_ccbhash[CCB_HASH_SIZE];
- TAILQ_HEAD(, bt_ccb) sc_free_ccb;
- int sc_numccbs;
- int sc_scsi_dev; /* adapters scsi id */
- struct scsi_link sc_link; /* prototype for devs */
-};
-
-/***********debug values *************/
-#define BT_SHOWCCBS 0x01
-#define BT_SHOWINTS 0x02
-#define BT_SHOWCMDS 0x04
-#define BT_SHOWMISC 0x08
-int bt_debug = 0;
-
-int bt_cmd __P((int, struct bt_softc *, int, int, int, u_char *,
- unsigned, ...));
-int btintr __P((void *));
-void bt_free_ccb __P((struct bt_softc *, struct bt_ccb *, int));
-struct bt_ccb *bt_get_ccb __P((struct bt_softc *, int));
-struct bt_ccb *bt_ccb_phys_kv __P((struct bt_softc *, u_long));
-struct bt_mbx_out *bt_send_mbo __P((struct bt_softc *, int, struct bt_ccb *));
-void bt_done __P((struct bt_softc *, struct bt_ccb *));
-int bt_find __P((struct isa_attach_args *, struct bt_softc *));
-void bt_init __P((struct bt_softc *));
-void bt_inquire_setup_information __P((struct bt_softc *));
-void btminphys __P((struct buf *));
-int bt_scsi_cmd __P((struct scsi_xfer *));
-int bt_poll __P((struct bt_softc *, struct scsi_xfer *, int));
-void bt_timeout __P((void *arg));
-#ifdef UTEST
-void bt_print_ccb __P((struct bt_ccb *));
-void bt_print_active_ccbs __P((struct bt_softc *));
-#endif
-
-struct scsi_adapter bt_switch = {
- bt_scsi_cmd,
- btminphys,
- 0,
- 0,
-};
-
-/* the below structure is so we have a default dev struct for out link struct */
-struct scsi_device bt_dev = {
- NULL, /* Use default error handler */
- NULL, /* have a queue, served by this */
- NULL, /* have no async handler */
- NULL, /* Use default 'done' routine */
-};
-
-int btprobe __P((struct device *, void *, void *));
-void btattach __P((struct device *, struct device *, void *));
-int btprint __P((void *, char *));
-
-struct cfdriver btcd = {
- NULL, "bt", btprobe, btattach, DV_DULL, sizeof(struct bt_softc)
-};
-
-#define BT_RESET_TIMEOUT 1000
-
-/*
- * bt_cmd(iobase, sc, icnt, ocnt, wait, retval, opcode, ... args ...)
- *
- * Activate Adapter command
- * icnt: number of args (outbound bytes written after opcode)
- * ocnt: number of expected returned bytes
- * wait: number of seconds to wait for response
- * retval: buffer where to place returned bytes
- * opcode: opcode BT_NOP, BT_MBX_INIT, BT_START_SCSI ...
- * args: variable number of parameters
- *
- * Performs an adapter command through the ports. Not to be confused with a
- * scsi command, which is read in via the dma; one of the adapter commands
- * tells it to read in a scsi command.
- */
-int
-#ifdef __STDC__
-bt_cmd(int iobase, struct bt_softc *sc, int icnt, int ocnt, int wait,
- u_char *retval, unsigned opcode, ...)
-#else
-bt_cmd(iobase, sc, icnt, ocnt, wait, retval, opcode, va_alist)
- int iobase;
- struct bt_softc *sc;
- int icnt, ocnt, wait;
- u_char *retval;
- unsigned opcode;
- va_dcl
-#endif
-{
- va_list ap;
- unsigned data;
- const char *name;
- u_char oc;
- register i;
- int sts;
-
- if (sc == NULL)
- name = sc->sc_dev.dv_xname;
- else
- name = "(probe)";
-
- /*
- * multiply the wait argument by a big constant
- * zero defaults to 1
- */
- if (wait)
- wait *= 100000;
- else
- wait = 100000;
- /*
- * Wait for the adapter to go idle, unless it's one of
- * the commands which don't need this
- */
- if (opcode != BT_MBX_INIT && opcode != BT_START_SCSI) {
- i = 100000; /* 1 sec? */
- while (--i) {
- sts = inb(iobase + BT_CTRL_STAT_PORT);
- if (sts & BT_IDLE) {
- break;
- }
- delay(10);
- }
- if (!i) {
- printf("%s: bt_cmd, host not idle(0x%x)\n",
- name, sts);
- return ENXIO;
- }
- }
- /*
- * Now that it is idle, if we expect output, preflush the
- * queue feeding to us.
- */
- if (ocnt) {
- while ((inb(iobase + BT_CTRL_STAT_PORT)) & BT_DF)
- inb(iobase + BT_CMD_DATA_PORT);
- }
- /*
- * Output the command and the number of arguments given
- * for each byte, first check the port is empty.
- */
- va_start(ap, opcode);
- /* test icnt >= 0, to include the command in data sent */
- for (data = opcode; icnt >= 0; icnt--, data = va_arg(ap, u_char)) {
- sts = inb(iobase + BT_CTRL_STAT_PORT);
- for (i = wait; i; i--) {
- sts = inb(iobase + BT_CTRL_STAT_PORT);
- if (!(sts & BT_CDF))
- break;
- delay(10);
- }
- if (!i) {
- printf("%s: bt_cmd, cmd/data port full\n", name);
- outb(iobase + BT_CTRL_STAT_PORT, BT_SRST);
- va_end(ap);
- return ENXIO;
- }
- outb(iobase + BT_CMD_DATA_PORT, data);
- }
- va_end(ap);
- /*
- * If we expect input, loop that many times, each time,
- * looking for the data register to have valid data
- */
- while (ocnt--) {
- sts = inb(iobase + BT_CTRL_STAT_PORT);
- for (i = wait; i; i--) {
- sts = inb(iobase + BT_CTRL_STAT_PORT);
- if (sts & BT_DF)
- break;
- delay(10);
- }
- if (!i) {
- printf("bt%d: bt_cmd, cmd/data port empty %d\n",
- name, ocnt);
- return ENXIO;
- }
- oc = inb(iobase + BT_CMD_DATA_PORT);
- if (retval)
- *retval++ = oc;
- }
- /*
- * Wait for the board to report a finised instruction
- */
- i = 100000; /* 1 sec? */
- while (--i) {
- sts = inb(iobase + BT_INTR_PORT);
- if (sts & BT_HACC)
- break;
- delay(10);
- }
- if (!i) {
- printf("%s: bt_cmd, host not finished(0x%x)\n",
- name, sts);
- return ENXIO;
- }
- outb(iobase + BT_CTRL_STAT_PORT, BT_IRST);
- return 0;
-}
-
-/*
- * Check if the device can be found at the port given
- * and if so, set it up ready for further work
- * as an argument, takes the isa_device structure from
- * autoconf.c
- */
-int
-btprobe(parent, match, aux)
- struct device *parent;
- void *match, *aux;
-{
- struct bt_softc *sc = match;
- register struct isa_attach_args *ia = aux;
-
-#ifdef NEWCONFIG
- if (ia->ia_iobase == IOBASEUNK)
- return 0;
-#endif
-
- /*
- * Try initialise a unit at this location
- * sets up dma and bus speed, loads sc->sc_irq
- */
- if (bt_find(ia, NULL) != 0)
- return 0;
-
- ia->ia_msize = 0;
- ia->ia_iosize = 4;
- /* IRQ and DRQ set by bt_find() */
- return 1;
-}
-
-int
-btprint(aux, name)
- void *aux;
- char *name;
-{
- if (name != NULL)
- printf("%s: scsibus ", name);
- return UNCONF;
-}
-
-/*
- * Attach all the sub-devices we can find
- */
-void
-btattach(parent, self, aux)
- struct device *parent, *self;
- void *aux;
-{
- struct isa_attach_args *ia = aux;
- struct bt_softc *sc = (struct bt_softc *)self;
-
- if (bt_find(ia, sc) != 0)
- panic("btattach: bt_find of %s failed", self->dv_xname);
- sc->sc_iobase = ia->ia_iobase;
-
- if (sc->sc_drq != DRQUNK)
- isa_dmacascade(sc->sc_drq);
-
- bt_init(sc);
- TAILQ_INIT(&sc->sc_free_ccb);
-
- /*
- * fill in the prototype scsi_link.
- */
- sc->sc_link.adapter_softc = sc;
- sc->sc_link.adapter_target = sc->sc_scsi_dev;
- sc->sc_link.adapter = &bt_switch;
- sc->sc_link.device = &bt_dev;
- sc->sc_link.openings = 2;
-
- printf("\n");
-
-#ifdef NEWCONFIG
- isa_establish(&sc->sc_id, &sc->sc_dev);
-#endif
- sc->sc_ih = isa_intr_establish(sc->sc_irq, IST_EDGE, IPL_BIO, btintr,
- sc, sc->sc_dev.dv_xname);
-
- /*
- * ask the adapter what subunits are present
- */
- config_found(self, &sc->sc_link, btprint);
-}
-
-/*
- * Catch an interrupt from the adaptor
- */
-int
-btintr(arg)
- void *arg;
-{
- struct bt_softc *sc = arg;
- int iobase = sc->sc_iobase;
- struct bt_mbx_in *wmbi;
- struct bt_mbx *wmbx;
- struct bt_ccb *ccb;
- u_char stat;
- int i;
- int found = 0;
-
-#ifdef BTDEBUG
- printf("%s: btintr ", sc->sc_dev.dv_xname);
-#endif /* BTDEBUG */
-
- /*
- * First acknowlege the interrupt, Then if it's
- * not telling about a completed operation
- * just return.
- */
- stat = inb(iobase + BT_INTR_PORT);
- if ((stat & (BT_MBOA | BT_MBIF)) == 0) {
- outb(iobase + BT_CTRL_STAT_PORT, BT_IRST);
- return -1; /* XXX */
- }
-
- /* Mail box out empty? */
- if (stat & BT_MBOA) {
- /* Disable MBO available interrupt. */
- outb(iobase + BT_CMD_DATA_PORT, BT_MBO_INTR_EN);
- for (i = 100000; i; i--) {
- if (!(inb(iobase + BT_CTRL_STAT_PORT) & BT_CDF))
- break;
- delay(10);
- }
- if (!i) {
- printf("%s: btintr, cmd/data port full\n",
- sc->sc_dev.dv_xname);
- outb(iobase + BT_CTRL_STAT_PORT, BT_SRST);
- return 1;
- }
- outb(iobase + BT_CMD_DATA_PORT, 0x00); /* Disable */
- wakeup(&sc->sc_mbx);
- }
-
- /* Mail box in full? */
- if ((stat & BT_MBIF) == 0)
- return 1;
- wmbx = &sc->sc_mbx;
- wmbi = wmbx->tmbi;
-AGAIN:
- while (wmbi->stat != BT_MBI_FREE) {
- ccb = bt_ccb_phys_kv(sc, wmbi->ccb_addr);
- if (!ccb) {
- wmbi->stat = BT_MBI_FREE;
- printf("%s: BAD CCB ADDR!\n", sc->sc_dev.dv_xname);
- continue;
- }
- found++;
- switch (wmbi->stat) {
- case BT_MBI_OK:
- case BT_MBI_ERROR:
- break;
-
- case BT_MBI_ABORT:
- ccb->host_stat = BT_ABORTED;
- break;
-
- case BT_MBI_UNKNOWN:
- ccb = 0;
- break;
-
- default:
- panic("Impossible mbxi status");
- }
-#ifdef BTDEBUG
- if (bt_debug && ccb) {
- u_char *cp = &ccb->scsi_cmd;
- printf("op=%x %x %x %x %x %x\n",
- cp[0], cp[1], cp[2],
- cp[3], cp[4], cp[5]);
- printf("stat %x for mbi addr = 0x%08x, ",
- wmbi->stat, wmbi);
- printf("ccb addr = 0x%x\n", ccb);
- }
-#endif /* BTDEBUG */
- wmbi->stat = BT_MBI_FREE;
- if (ccb) {
- untimeout(bt_timeout, ccb);
- bt_done(sc, ccb);
- }
- bt_nextmbx(wmbi, wmbx, mbi);
- }
- if (!found) {
- for (i = 0; i < BT_MBX_SIZE; i++) {
- if (wmbi->stat != BT_MBI_FREE) {
- found++;
- break;
- }
- bt_nextmbx(wmbi, wmbx, mbi);
- }
- if (!found) {
-#if 0
- printf("%s: mbi interrupt with no full mailboxes\n",
- sc->sc_dev.dv_xname);
-#endif
- } else {
- found = 0;
- goto AGAIN;
- }
- }
- wmbx->tmbi = wmbi;
- outb(iobase + BT_CTRL_STAT_PORT, BT_IRST);
- return 1;
-}
-
-/*
- * A ccb is put onto the free list.
- */
-void
-bt_free_ccb(sc, ccb, flags)
- struct bt_softc *sc;
- struct bt_ccb *ccb;
- int flags;
-{
- int s;
-
- s = splbio();
-
- ccb->flags = CCB_FREE;
- TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, chain);
-
- /*
- * If there were none, wake anybody waiting for one to come free,
- * starting with queued entries.
- */
- if (ccb->chain.tqe_next == 0)
- wakeup(&sc->sc_free_ccb);
-
- splx(s);
-}
-
-static inline void
-bt_init_ccb(sc, ccb)
- struct bt_softc *sc;
- struct bt_ccb *ccb;
-{
- int hashnum;
-
- bzero(ccb, sizeof(struct bt_ccb));
- /*
- * put in the phystokv hash table
- * Never gets taken out.
- */
- ccb->hashkey = KVTOPHYS(ccb);
- hashnum = CCB_HASH(ccb->hashkey);
- ccb->nexthash = sc->sc_ccbhash[hashnum];
- sc->sc_ccbhash[hashnum] = ccb;
-}
-
-static inline void
-bt_reset_ccb(sc, ccb)
- struct bt_softc *sc;
- struct bt_ccb *ccb;
-{
-
-}
-
-/*
- * Get a free ccb
- *
- * If there are none, see if we can allocate a new one. If so, put it in
- * the hash table too otherwise either return an error or sleep.
- */
-struct bt_ccb *
-bt_get_ccb(sc, flags)
- struct bt_softc *sc;
- int flags;
-{
- struct bt_ccb *ccb;
- int s;
-
- s = splbio();
-
- /*
- * If we can and have to, sleep waiting for one to come free
- * but only if we can't allocate a new one.
- */
- for (;;) {
- ccb = sc->sc_free_ccb.tqh_first;
- if (ccb) {
- TAILQ_REMOVE(&sc->sc_free_ccb, ccb, chain);
- break;
- }
- if (sc->sc_numccbs < BT_CCB_MAX) {
- if (ccb = (struct bt_ccb *) malloc(sizeof(struct bt_ccb),
- M_TEMP, M_NOWAIT)) {
- bt_init_ccb(sc, ccb);
- sc->sc_numccbs++;
- } else {
- printf("%s: can't malloc ccb\n",
- sc->sc_dev.dv_xname);
- goto out;
- }
- break;
- }
- if ((flags & SCSI_NOSLEEP) != 0)
- goto out;
- tsleep(&sc->sc_free_ccb, PRIBIO, "btccb", 0);
- }
-
- bt_reset_ccb(sc, ccb);
- ccb->flags = CCB_ACTIVE;
-
-out:
- splx(s);
- return ccb;
-}
-
-/*
- * given a physical address, find the ccb that
- * it corresponds to:
- */
-struct bt_ccb *
-bt_ccb_phys_kv(sc, ccb_phys)
- struct bt_softc *sc;
- u_long ccb_phys;
-{
- int hashnum = CCB_HASH(ccb_phys);
- struct bt_ccb *ccb = sc->sc_ccbhash[hashnum];
-
- while (ccb) {
- if (ccb->hashkey == ccb_phys)
- break;
- ccb = ccb->nexthash;
- }
- return ccb;
-}
-
-/*
- * Get a mbo and send the ccb.
- */
-struct bt_mbx_out *
-bt_send_mbo(sc, cmd, ccb)
- struct bt_softc *sc;
- int cmd;
- struct bt_ccb *ccb;
-{
- int iobase = sc->sc_iobase;
- struct bt_mbx_out *wmbo; /* Mail Box Out pointer */
- struct bt_mbx *wmbx; /* Mail Box pointer specified unit */
- int i;
-
- /* Get the target out mail box pointer and increment. */
- wmbx = &sc->sc_mbx;
- wmbo = wmbx->tmbo;
- bt_nextmbx(wmbx->tmbo, wmbx, mbo);
-
- /*
- * Check the outmail box is free or not.
- * Note: Under the normal operation, it shuld NOT happen to wait.
- */
- while (wmbo->cmd != BT_MBO_FREE) {
- /* Enable mbo available interrupt. */
- outb(iobase + BT_CMD_DATA_PORT, BT_MBO_INTR_EN);
- for (i = 100000; i; i--) {
- if (!(inb(iobase + BT_CTRL_STAT_PORT) & BT_CDF))
- break;
- delay(10);
- }
- if (!i) {
- printf("%s: bt_send_mbo, cmd/data port full\n",
- sc->sc_dev.dv_xname);
- outb(iobase + BT_CTRL_STAT_PORT, BT_SRST);
- return NULL;
- }
- outb(iobase + BT_CMD_DATA_PORT, 0x01); /* Enable */
- tsleep(wmbx, PRIBIO, "btsnd", 0);/*XXX can't do this */
- }
-
- /* Link ccb to mbo. */
- wmbo->ccb_addr = KVTOPHYS(ccb);
- ccb->mbx = wmbo;
- wmbo->cmd = cmd;
-
- /* Send it! */
- outb(iobase + BT_CMD_DATA_PORT, BT_START_SCSI);
-
- return wmbo;
-}
-
-/*
- * We have a ccb which has been processed by the
- * adaptor, now we look to see how the operation
- * went. Wake up the owner if waiting
- */
-void
-bt_done(sc, ccb)
- struct bt_softc *sc;
- struct bt_ccb *ccb;
-{
- struct scsi_sense_data *s1, *s2;
- struct scsi_xfer *xs = ccb->xs;
-
- SC_DEBUG(xs->sc_link, SDEV_DB2, ("bt_done\n"));
- /*
- * Otherwise, put the results of the operation
- * into the xfer and call whoever started it
- */
- if ((xs->flags & INUSE) == 0) {
- printf("%s: exiting but not in use!\n", sc->sc_dev.dv_xname);
- Debugger();
- }
- if (xs->error == XS_NOERROR) {
- if (ccb->host_stat != BT_OK) {
- switch (ccb->host_stat) {
- case BT_ABORTED:
- xs->error = XS_DRIVER_STUFFUP;
- break;
- case BT_SEL_TIMEOUT: /* No response */
- xs->error = XS_SELTIMEOUT;
- break;
- default: /* Other scsi protocol messes */
- printf("%s: host_stat %x\n",
- sc->sc_dev.dv_xname, ccb->host_stat);
- xs->error = XS_DRIVER_STUFFUP;
- }
- } else if (ccb->target_stat != SCSI_OK) {
- switch (ccb->target_stat) {
- case SCSI_CHECK:
- s1 = &ccb->scsi_sense;
- s2 = &xs->sense;
- *s2 = *s1;
- xs->error = XS_SENSE;
- break;
- case SCSI_BUSY:
- xs->error = XS_BUSY;
- break;
- default:
- printf("%s: target_stat %x\n",
- sc->sc_dev.dv_xname, ccb->target_stat);
- xs->error = XS_DRIVER_STUFFUP;
- }
- } else
- xs->resid = 0;
- }
- xs->flags |= ITSDONE;
- bt_free_ccb(sc, ccb, xs->flags);
- scsi_done(xs);
-}
-
-/*
- * Find the board and find it's irq/drq
- */
-int
-bt_find(ia, sc)
- struct isa_attach_args *ia;
- struct bt_softc *sc;
-{
- int iobase = ia->ia_iobase;
- u_char ad[4];
- volatile int i, sts;
- struct bt_extended_inquire info;
- struct bt_config conf;
- int irq, drq;
-
- /*
- * reset board, If it doesn't respond, assume
- * that it's not there.. good for the probe
- */
-
- outb(iobase + BT_CTRL_STAT_PORT, BT_HRST | BT_SRST);
-
- for (i = BT_RESET_TIMEOUT; i; i--) {
- sts = inb(iobase + BT_CTRL_STAT_PORT);
- if (sts == (BT_IDLE | BT_INIT))
- break;
- delay(1000);
- }
- if (!i) {
-#ifdef UTEST
- printf("bt_find: No answer from bt742a board\n");
-#endif
- return 1;
- }
-
- /*
- * Check that we actually know how to use this board.
- */
- delay(1000);
- bt_cmd(iobase, sc, 1, sizeof(info), 0, (u_char *)&info,
- BT_INQUIRE_EXTENDED, sizeof(info));
- switch (info.bus_type) {
- case BT_BUS_TYPE_24BIT:
- /* XXXX How do we avoid conflicting with the aha1542 probe? */
- case BT_BUS_TYPE_32BIT:
- break;
- case BT_BUS_TYPE_MCA:
- /* We don't grok MicroChannel (yet). */
- return 1;
- default:
- printf("bt_find: illegal bus type %c\n", info.bus_type);
- return 1;
- }
-
- /*
- * Assume we have a board at this stage setup dma channel from
- * jumpers and save int level
- */
- delay(1000);
- bt_cmd(iobase, sc, 0, sizeof(conf), 0, (u_char *)&conf, BT_CONF_GET);
- switch (conf.chan) {
- case EISADMA:
- drq = DRQUNK;
- break;
- case CHAN0:
- drq = 0;
- break;
- case CHAN5:
- drq = 5;
- break;
- case CHAN6:
- drq = 6;
- break;
- case CHAN7:
- drq = 7;
- break;
- default:
- printf("bt_find: illegal dma setting %x\n", conf.chan);
- return 1;
- }
-
- switch (conf.intr) {
- case INT9:
- irq = 9;
- break;
- case INT10:
- irq = 10;
- break;
- case INT11:
- irq = 11;
- break;
- case INT12:
- irq = 12;
- break;
- case INT14:
- irq = 14;
- break;
- case INT15:
- irq = 15;
- break;
- default:
- printf("bt_find: illegal int setting %x\n", conf.intr);
- return 1;
- }
-
- if (sc != NULL) {
- /* who are we on the scsi bus? */
- sc->sc_scsi_dev = conf.scsi_dev;
-
- sc->sc_iobase = iobase;
- sc->sc_irq = irq;
- sc->sc_drq = drq;
- } else {
- if (ia->ia_irq == IRQUNK)
- ia->ia_irq = irq;
- else if (ia->ia_irq != irq)
- return 1;
- if (ia->ia_drq == DRQUNK)
- ia->ia_drq = drq;
- else if (ia->ia_drq != drq)
- return 1;
- }
-
- return 0;
-}
-
-/*
- * Start the board, ready for normal operation
- */
-void
-bt_init(sc)
- struct bt_softc *sc;
-{
- int iobase = sc->sc_iobase;
- u_char ad[4];
- int i;
-
- /*
- * Initialize mail box
- */
- *((physaddr *)ad) = KVTOPHYS(&sc->sc_mbx);
-
- bt_cmd(iobase, sc, 5, 0, 0, 0, BT_MBX_INIT_EXTENDED, BT_MBX_SIZE,
- ad[0], ad[1], ad[2], ad[3]);
-
- for (i = 0; i < BT_MBX_SIZE; i++) {
- sc->sc_mbx.mbo[i].cmd = BT_MBO_FREE;
- sc->sc_mbx.mbi[i].stat = BT_MBI_FREE;
- }
-
- /*
- * Set up initial mail box for round-robin operation.
- */
- sc->sc_mbx.tmbo = &sc->sc_mbx.mbo[0];
- sc->sc_mbx.tmbi = &sc->sc_mbx.mbi[0];
-
- bt_inquire_setup_information(sc);
-}
-
-void
-bt_inquire_setup_information(sc)
- struct bt_softc *sc;
-{
- int iobase = sc->sc_iobase;
- struct bt_boardID bID;
- struct bt_board_info binfo;
- char dummy[8], sub_ver[3];
- struct bt_setup setup;
- int i, ver;
-
- /*
- * Get and print board hardware information.
- */
- bt_cmd(iobase, sc, 1, sizeof(binfo), 0, (u_char *)&binfo,
- BT_GET_BOARD_INFO, sizeof(binfo));
- printf(": Bt%c%c%c", binfo.id[0], binfo.id[1], binfo.id[2]);
- if (binfo.id[3] != ' ')
- printf("%c", binfo.id[3]);
- if (binfo.version[0] != ' ')
- printf("%c%s", binfo.version[0], binfo.version[1]);
- printf("\n");
-
- /*
- * Inquire Board ID to Bt742 for board type and firmware version.
- */
- bt_cmd(iobase, sc, 0, sizeof(bID), 0, (u_char *)&bID, BT_INQUIRE);
- ver = (bID.firm_revision - '0') * 10 + (bID.firm_version - '0');
-
- /*
- * Get the rest of the firmware version. Firmware revisions
- * before 3.3 apparently don't accept the BT_INQUIRE_REV_FOURTH
- * command.
- */
- i = 0;
- bt_cmd(iobase, sc, 0, 1, 0, &sub_ver[i++], BT_INQUIRE_REV_THIRD);
- if (ver >= 33)
- bt_cmd(iobase, sc, 0, 1, 0, &sub_ver[i++],
- BT_INQUIRE_REV_FOURTH);
- if (sub_ver[i - 1] == ' ')
- i--;
- sub_ver[i] = '\0';
-
- printf("%s: firmware version %c.%c%s, ", sc->sc_dev.dv_xname,
- bID.firm_revision, bID.firm_version, sub_ver);
-
- /* Enable round-robin scheme - appeared at firmware rev. 3.31 */
- if (ver > 33 || (ver == 33 && sub_ver[0] >= 1)) {
- bt_cmd(iobase, sc, 1, 0, 0, 0, BT_ROUND_ROBIN, BT_ENABLE);
- }
-
- /* Inquire Installed Devices (to force synchronous negotiation) */
- bt_cmd(iobase, sc, 0, sizeof(dummy), 10, dummy, BT_DEV_GET);
-
- /* Obtain setup information from Bt742. */
- bt_cmd(iobase, sc, 1, sizeof(setup), 0, (u_char *)&setup, BT_SETUP_GET,
- sizeof(setup));
-
- printf("%s, %s, %d mailboxes",
- setup.sync_neg ? "sync" : "async",
- setup.parity ? "parity" : "no parity",
- setup.num_mbx);
-
- for (i = 0; i < 8; i++) {
- if (!setup.sync[i].valid ||
- (!setup.sync[i].offset && !setup.sync[i].period))
- continue;
- printf("\n%s targ %d: sync, offset %d, period %dnsec",
- sc->sc_dev.dv_xname, i,
- setup.sync[i].offset, setup.sync[i].period * 50 + 200);
- }
-}
-
-void
-btminphys(bp)
- struct buf *bp;
-{
-
- if (bp->b_bcount > ((BT_NSEG - 1) << PGSHIFT))
- bp->b_bcount = ((BT_NSEG - 1) << PGSHIFT);
- minphys(bp);
-}
-
-/*
- * start a scsi operation given the command and the data address. Also needs
- * the unit, target and lu.
- */
-int
-bt_scsi_cmd(xs)
- struct scsi_xfer *xs;
-{
- struct scsi_link *sc_link = xs->sc_link;
- struct bt_softc *sc = sc_link->adapter_softc;
- struct bt_ccb *ccb;
- struct bt_scat_gath *sg;
- int seg; /* scatter gather seg being worked on */
- int thiskv;
- physaddr thisphys, nextphys;
- int bytes_this_seg, bytes_this_page, datalen, flags;
- struct iovec *iovp;
- struct bt_mbx_out *mbo;
- int s;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("bt_scsi_cmd\n"));
- /*
- * get a ccb to use. If the transfer
- * is from a buf (possibly from interrupt time)
- * then we can't allow it to sleep
- */
- flags = xs->flags;
- if ((flags & (ITSDONE|INUSE)) != INUSE) {
- printf("%s: done or not in use?\n", sc->sc_dev.dv_xname);
- xs->flags &= ~ITSDONE;
- xs->flags |= INUSE;
- }
- if ((ccb = bt_get_ccb(sc, flags)) == NULL) {
- xs->error = XS_DRIVER_STUFFUP;
- return TRY_AGAIN_LATER;
- }
- ccb->xs = xs;
-
- /*
- * Put all the arguments for the xfer in the ccb
- */
- if (flags & SCSI_RESET) {
- ccb->opcode = BT_RESET_CCB;
- } else {
- /* can't use S/G if zero length */
- ccb->opcode = (xs->datalen ? BT_INIT_SCAT_GATH_CCB
- : BT_INITIATOR_CCB);
- }
- ccb->data_out = 0;
- ccb->data_in = 0;
- ccb->target = sc_link->target;
- ccb->lun = sc_link->lun;
- ccb->scsi_cmd_length = xs->cmdlen;
- ccb->sense_ptr = KVTOPHYS(&ccb->scsi_sense);
- ccb->req_sense_length = sizeof(ccb->scsi_sense);
- ccb->host_stat = 0x00;
- ccb->target_stat = 0x00;
-
- if (xs->datalen && (flags & SCSI_RESET) == 0) {
- ccb->data_addr = KVTOPHYS(ccb->scat_gath);
- sg = ccb->scat_gath;
- seg = 0;
-#ifdef TFS
- if (flags & SCSI_DATA_UIO) {
- iovp = ((struct uio *)xs->data)->uio_iov;
- datalen = ((struct uio *)xs->data)->uio_iovcnt;
- xs->datalen = 0;
- while (datalen && seg < BT_NSEG) {
- sg->seg_addr = (physaddr)iovp->iov_base;
- sg->seg_len = iovp->iov_len;
- xs->datalen += iovp->iov_len;
- SC_DEBUGN(sc_link, SDEV_DB4, ("(0x%x@0x%x)",
- iovp->iov_len, iovp->iov_base));
- sg++;
- iovp++;
- seg++;
- datalen--;
- }
- } else
-#endif /* TFS */
- {
- /*
- * Set up the scatter gather block
- */
- SC_DEBUG(sc_link, SDEV_DB4,
- ("%d @0x%x:- ", xs->datalen, xs->data));
- datalen = xs->datalen;
- thiskv = (int) xs->data;
- thisphys = KVTOPHYS(thiskv);
-
- while (datalen && seg < BT_NSEG) {
- bytes_this_seg = 0;
-
- /* put in the base address */
- sg->seg_addr = thisphys;
-
- SC_DEBUGN(sc_link, SDEV_DB4, ("0x%x", thisphys));
-
- /* do it at least once */
- nextphys = thisphys;
- while (datalen && thisphys == nextphys) {
- /*
- * This page is contiguous (physically)
- * with the the last, just extend the
- * length
- */
- /* how far to the end of the page */
- nextphys = (thisphys & ~PGOFSET) + NBPG;
- bytes_this_page = nextphys - thisphys;
- /**** or the data ****/
- bytes_this_page = min(bytes_this_page,
- datalen);
- bytes_this_seg += bytes_this_page;
- datalen -= bytes_this_page;
-
- /* get more ready for the next page */
- thiskv = (thiskv & ~PGOFSET) + NBPG;
- if (datalen)
- thisphys = KVTOPHYS(thiskv);
- }
- /*
- * next page isn't contiguous, finish the seg
- */
- SC_DEBUGN(sc_link, SDEV_DB4,
- ("(0x%x)", bytes_this_seg));
- sg->seg_len = bytes_this_seg;
- sg++;
- seg++;
- }
- }
- /* end of iov/kv decision */
- ccb->data_length = seg * sizeof(struct bt_scat_gath);
- SC_DEBUGN(sc_link, SDEV_DB4, ("\n"));
- if (datalen) {
- /*
- * there's still data, must have run out of segs!
- */
- printf("%s: bt_scsi_cmd, more than %d dma segs\n",
- sc->sc_dev.dv_xname, BT_NSEG);
- xs->error = XS_DRIVER_STUFFUP;
- bt_free_ccb(sc, ccb, flags);
- return COMPLETE;
- }
- } else { /* No data xfer, use non S/G values */
- ccb->data_addr = (physaddr)0;
- ccb->data_length = 0;
- }
- ccb->link_id = 0;
- ccb->link_addr = (physaddr)0;
-
- /*
- * Put the scsi command in the ccb and start it
- */
- if ((flags & SCSI_RESET) == 0)
- bcopy(xs->cmd, &ccb->scsi_cmd, ccb->scsi_cmd_length);
-
- s = splbio();
-
- if (bt_send_mbo(sc, BT_MBO_START, ccb) == NULL) {
- splx(s);
- xs->error = XS_DRIVER_STUFFUP;
- bt_free_ccb(sc, ccb, flags);
- return TRY_AGAIN_LATER;
- }
-
- /*
- * Usually return SUCCESSFULLY QUEUED
- */
- SC_DEBUG(sc_link, SDEV_DB3, ("cmd_sent\n"));
- if ((flags & SCSI_POLL) == 0) {
- timeout(bt_timeout, ccb, (xs->timeout * hz) / 1000);
- splx(s);
- return SUCCESSFULLY_QUEUED;
- }
-
- splx(s);
-
- /*
- * If we can't use interrupts, poll on completion
- */
- if (bt_poll(sc, xs, xs->timeout)) {
- bt_timeout(ccb);
- if (bt_poll(sc, xs, 2000))
- bt_timeout(ccb);
- }
- return COMPLETE;
-}
-
-/*
- * Poll a particular unit, looking for a particular xs
- */
-int
-bt_poll(sc, xs, count)
- struct bt_softc *sc;
- struct scsi_xfer *xs;
- int count;
-{
- int iobase = sc->sc_iobase;
-
- /* timeouts are in msec, so we loop in 1000 usec cycles */
- while (count) {
- /*
- * If we had interrupts enabled, would we
- * have got an interrupt?
- */
- if (inb(iobase + BT_INTR_PORT) & BT_ANY_INTR)
- btintr(sc);
- if (xs->flags & ITSDONE)
- return 0;
- delay(1000); /* only happens in boot so ok */
- count--;
- }
- return 1;
-}
-
-void
-bt_timeout(arg)
- void *arg;
-{
- struct bt_ccb *ccb = arg;
- struct scsi_xfer *xs = ccb->xs;
- struct scsi_link *sc_link = xs->sc_link;
- struct bt_softc *sc = sc_link->adapter_softc;
- int s;
-
- sc_print_addr(sc_link);
- printf("timed out");
-
- s = splbio();
-
- /*
- * If the ccb's mbx is not free, then the board has gone Far East?
- */
- if (bt_ccb_phys_kv(sc, ccb->mbx->ccb_addr) == ccb &&
- ccb->mbx->cmd != BT_MBO_FREE) {
- printf("%s: not taking commands!\n", sc->sc_dev.dv_xname);
- Debugger();
- }
-
- /*
- * If it has been through before, then
- * a previous abort has failed, don't
- * try abort again
- */
- if (ccb->flags == CCB_ABORTED) {
- /* abort timed out */
- printf(" AGAIN\n");
- ccb->xs->retries = 0;
- bt_done(sc, ccb);
- } else {
- /* abort the operation that has timed out */
- printf("\n");
- ccb->xs->error = XS_TIMEOUT;
- ccb->flags = CCB_ABORTED;
- bt_send_mbo(sc, BT_MBO_ABORT, ccb);
- /* 2 secs for the abort */
- if ((xs->flags & SCSI_POLL) == 0)
- timeout(bt_timeout, ccb, 2 * hz);
- }
-
- splx(s);
-}
-
-#ifdef UTEST
-void
-bt_print_ccb(ccb)
- struct bt_ccb *ccb;
-{
-
- printf("ccb:%x op:%x cmdlen:%d senlen:%d\n",
- ccb, ccb->opcode, ccb->scsi_cmd_length, ccb->req_sense_length);
- printf(" datlen:%d hstat:%x tstat:%x flags:%x\n",
- ccb->data_length, ccb->host_stat, ccb->target_stat, ccb->flags);
-}
-
-void
-bt_print_active_ccbs(sc)
- struct bt_softc *sc;
-{
- struct bt_ccb *ccb;
- int i = 0;
-
- while (i < CCB_HASH_SIZE) {
- ccb = sc->sc_ccbhash[i];
- while (ccb) {
- if (ccb->flags != CCB_FREE)
- bt_print_ccb(ccb);
- ccb = ccb->nexthash;
- }
- i++;
- }
-}
-#endif /*UTEST */
diff --git a/sys/dev/isa/btreg.h b/sys/dev/isa/btreg.h
new file mode 100644
index 00000000000..886911afa7f
--- /dev/null
+++ b/sys/dev/isa/btreg.h
@@ -0,0 +1,304 @@
+typedef u_int8_t physaddr[4];
+typedef u_int8_t physlen[4];
+#define ltophys _lto4l
+#define phystol _4ltol
+
+/*
+ * I/O port offsets
+ */
+#define BT_CTRL_PORT 0 /* control (wo) */
+#define BT_STAT_PORT 0 /* status (ro) */
+#define BT_CMD_PORT 1 /* command (wo) */
+#define BT_DATA_PORT 1 /* data (ro) */
+#define BT_INTR_PORT 2 /* interrupt status (ro) */
+
+/*
+ * BT_CTRL bits
+ */
+#define BT_CTRL_HRST 0x80 /* Hardware reset */
+#define BT_CTRL_SRST 0x40 /* Software reset */
+#define BT_CTRL_IRST 0x20 /* Interrupt reset */
+#define BT_CTRL_SCRST 0x10 /* SCSI bus reset */
+
+/*
+ * BT_STAT bits
+ */
+#define BT_STAT_STST 0x80 /* Self test in Progress */
+#define BT_STAT_DIAGF 0x40 /* Diagnostic Failure */
+#define BT_STAT_INIT 0x20 /* Mbx Init required */
+#define BT_STAT_IDLE 0x10 /* Host Adapter Idle */
+#define BT_STAT_CDF 0x08 /* cmd/data out port full */
+#define BT_STAT_DF 0x04 /* Data in port full */
+#define BT_STAT_INVDCMD 0x01 /* Invalid command */
+
+/*
+ * BT_CMD opcodes
+ */
+#define BT_NOP 0x00 /* No operation */
+#define BT_MBX_INIT 0x01 /* Mbx initialization */
+#define BT_START_SCSI 0x02 /* start scsi command */
+#define BT_INQUIRE_REVISION 0x04 /* Adapter Inquiry */
+#define BT_MBO_INTR_EN 0x05 /* Enable MBO available interrupt */
+/*#define BT_SEL_TIMEOUT_SET 0x06 /* set selection time-out */
+/*#define BT_BUS_ON_TIME_SET 0x07 /* set bus-on time */
+/*#define BT_BUS_OFF_TIME_SET 0x08 /* set bus-off time */
+/*#define BT_SPEED_SET 0x09 /* set transfer speed */
+#define BT_INQUIRE_DEVICES 0x0a /* return installed devices 0-7 */
+#define BT_INQUIRE_CONFIG 0x0b /* return configuration data */
+#define BT_TARGET_EN 0x0c /* enable target mode */
+#define BT_INQUIRE_SETUP 0x0d /* return setup data */
+#define BT_ECHO 0x1e /* Echo command data */
+#define BT_INQUIRE_DEVICES_2 0x23 /* return installed devices 8-15 */
+#define BT_MBX_INIT_EXTENDED 0x81 /* Mbx initialization */
+#define BT_INQUIRE_REVISION_3 0x84 /* Get 3rd firmware version byte */
+#define BT_INQUIRE_REVISION_4 0x85 /* Get 4th firmware version byte */
+#define BT_INQUIRE_MODEL 0x8b /* Get hardware ID and revision */
+#define BT_INQUIRE_PERIOD 0x8c /* Get synchronous period */
+#define BT_INQUIRE_EXTENDED 0x8d /* Adapter Setup Inquiry */
+#define BT_ROUND_ROBIN 0x8f /* Enable/Disable(default) round robin */
+
+/*
+ * BT_INTR bits
+ */
+#define BT_INTR_ANYINTR 0x80 /* Any interrupt */
+#define BT_INTR_SCRD 0x08 /* SCSI reset detected */
+#define BT_INTR_HACC 0x04 /* Command complete */
+#define BT_INTR_MBOA 0x02 /* MBX out empty */
+#define BT_INTR_MBIF 0x01 /* MBX in full */
+
+struct bt_mbx_out {
+ physaddr ccb_addr;
+ u_char dummy[3];
+ u_char cmd;
+};
+
+struct bt_mbx_in {
+ physaddr ccb_addr;
+ u_char dummy[3];
+ u_char stat;
+};
+
+/*
+ * mbo.cmd values
+ */
+#define BT_MBO_FREE 0x0 /* MBO entry is free */
+#define BT_MBO_START 0x1 /* MBO activate entry */
+#define BT_MBO_ABORT 0x2 /* MBO abort entry */
+
+/*
+ * mbi.stat values
+ */
+#define BT_MBI_FREE 0x0 /* MBI entry is free */
+#define BT_MBI_OK 0x1 /* completed without error */
+#define BT_MBI_ABORT 0x2 /* aborted ccb */
+#define BT_MBI_UNKNOWN 0x3 /* Tried to abort invalid CCB */
+#define BT_MBI_ERROR 0x4 /* Completed with error */
+
+#if defined(BIG_DMA)
+WARNING...THIS WON'T WORK(won't fit on 1 page)
+/* #define BT_NSEG 2048 /* Number of scatter gather segments - to much vm */
+#define BT_NSEG 128
+#else
+#define BT_NSEG 33
+#endif /* BIG_DMA */
+
+struct bt_scat_gath {
+ physlen seg_len;
+ physaddr seg_addr;
+};
+
+struct bt_ccb {
+ u_char opcode;
+ u_char:3, data_in:1, data_out:1,:3;
+ u_char scsi_cmd_length;
+ u_char req_sense_length;
+ /*------------------------------------longword boundary */
+ physlen data_length;
+ /*------------------------------------longword boundary */
+ physaddr data_addr;
+ /*------------------------------------longword boundary */
+ u_char dummy1[2];
+ u_char host_stat;
+ u_char target_stat;
+ /*------------------------------------longword boundary */
+ u_char target;
+ u_char lun;
+ struct scsi_generic scsi_cmd;
+ u_char dummy2[1];
+ u_char link_id;
+ /*------------------------------------longword boundary */
+ physaddr link_addr;
+ /*------------------------------------longword boundary */
+ physaddr sense_ptr;
+/*-----end of HW fields-----------------------longword boundary */
+ struct scsi_sense_data scsi_sense;
+ /*------------------------------------longword boundary */
+ struct bt_scat_gath scat_gath[BT_NSEG];
+ /*------------------------------------longword boundary */
+ TAILQ_ENTRY(bt_ccb) chain;
+ struct bt_ccb *nexthash;
+ long hashkey;
+ struct scsi_xfer *xs; /* the scsi_xfer for this cmd */
+ int flags;
+#define CCB_ALLOC 0x01
+#define CCB_ABORT 0x02
+#ifdef BTDIAG
+#define CCB_SENDING 0x04
+#endif
+ int timeout;
+};
+
+/*
+ * opcode fields
+ */
+#define BT_INITIATOR_CCB 0x00 /* SCSI Initiator CCB */
+#define BT_TARGET_CCB 0x01 /* SCSI Target CCB */
+#define BT_INIT_SCAT_GATH_CCB 0x02 /* SCSI Initiator with scattter gather */
+#define BT_RESET_CCB 0x81 /* SCSI Bus reset */
+
+/*
+ * bt_ccb.host_stat values
+ */
+#define BT_OK 0x00 /* cmd ok */
+#define BT_LINK_OK 0x0a /* Link cmd ok */
+#define BT_LINK_IT 0x0b /* Link cmd ok + int */
+#define BT_SEL_TIMEOUT 0x11 /* Selection time out */
+#define BT_OVER_UNDER 0x12 /* Data over/under run */
+#define BT_BUS_FREE 0x13 /* Bus dropped at unexpected time */
+#define BT_INV_BUS 0x14 /* Invalid bus phase/sequence */
+#define BT_BAD_MBO 0x15 /* Incorrect MBO cmd */
+#define BT_BAD_CCB 0x16 /* Incorrect ccb opcode */
+#define BT_BAD_LINK 0x17 /* Not same values of LUN for links */
+#define BT_INV_TARGET 0x18 /* Invalid target direction */
+#define BT_CCB_DUP 0x19 /* Duplicate CCB received */
+#define BT_INV_CCB 0x1a /* Invalid CCB or segment list */
+
+struct bt_extended_inquire {
+ struct {
+ u_char opcode;
+ u_char len;
+ } cmd;
+ struct {
+ u_char bus_type; /* Type of bus connected to */
+#define BT_BUS_TYPE_24BIT 'A' /* ISA bus */
+#define BT_BUS_TYPE_32BIT 'E' /* EISA/VLB/PCI bus */
+#define BT_BUS_TYPE_MCA 'M' /* MicroChannel bus */
+ u_char bios_address; /* Address of adapter BIOS */
+ u_short max_segment; /* ? */
+ } reply;
+};
+
+struct bt_config {
+ struct {
+ u_char opcode;
+ } cmd;
+ struct {
+ u_char chan;
+ u_char intr;
+ u_char scsi_dev:3;
+ u_char :5;
+ } reply;
+};
+
+struct bt_toggle {
+ struct {
+ u_char opcode;
+ u_char enable;
+ } cmd;
+};
+
+struct bt_mailbox {
+ struct {
+ u_char opcode;
+ u_char nmbx;
+ physaddr addr;
+ } cmd;
+};
+
+struct bt_model {
+ struct {
+ u_char opcode;
+ u_char len;
+ } cmd;
+ struct {
+ u_char id[4]; /* i.e bt742a -> '7','4','2','A' */
+ u_char version[2]; /* i.e Board Revision 'H' -> 'H', 0x00 */
+ } reply;
+};
+
+struct bt_revision {
+ struct {
+ u_char opcode;
+ } cmd;
+ struct {
+ u_char board_type;
+ u_char custom_feature;
+ char firm_revision;
+ u_char firm_version;
+ } reply;
+};
+
+struct bt_digit {
+ struct {
+ u_char opcode;
+ } cmd;
+ struct {
+ u_char digit;
+ } reply;
+};
+
+struct bt_devices {
+ struct {
+ u_char opcode;
+ } cmd;
+ struct {
+ u_char junk[8];
+ } reply;
+};
+
+struct bt_setup {
+ struct {
+ u_char opcode;
+ u_char len;
+ } cmd;
+ struct {
+ u_char sync_neg:1;
+ u_char parity:1;
+ u_char :6;
+ u_char speed;
+ u_char bus_on;
+ u_char bus_off;
+ u_char num_mbx;
+ u_char mbx[3]; /*XXX */
+ /* doesn't make sense with 32bit addresses */
+ struct {
+ u_char offset:4;
+ u_char period:3;
+ u_char valid:1;
+ } sync[8];
+ u_char disc_sts;
+ } reply;
+};
+
+struct bt_period {
+ struct {
+ u_char opcode;
+ u_char len;
+ } cmd;
+ struct {
+ u_char period[8];
+ } reply;
+};
+
+#define INT9 0x01
+#define INT10 0x02
+#define INT11 0x04
+#define INT12 0x08
+#define INT14 0x20
+#define INT15 0x40
+
+#define EISADMA 0x00
+#define CHAN0 0x01
+#define CHAN5 0x20
+#define CHAN6 0x40
+#define CHAN7 0x80
diff --git a/sys/dev/isa/com.c b/sys/dev/isa/com.c
index d34ba82a096..77dd24748f4 100644
--- a/sys/dev/isa/com.c
+++ b/sys/dev/isa/com.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: com.c,v 1.10 1996/04/18 23:47:32 niklas Exp $ */
-/* $NetBSD: com.c,v 1.75 1996/03/10 09:01:24 cgd Exp $ */
+/* $OpenBSD: com.c,v 1.11 1996/04/21 22:23:15 deraadt Exp $ */
+/* $NetBSD: com.c,v 1.79 1996/04/15 18:54:31 cgd Exp $ */
/*-
* Copyright (c) 1993, 1994, 1995, 1996
@@ -57,7 +57,11 @@
#include <sys/types.h>
#include <sys/device.h>
-#include <machine/cpu.h>
+#ifdef i386 /* XXX */
+#include <machine/cpu.h> /* XXX */
+#else /* XXX */
+#include <machine/intr.h>
+#endif /* XXX */
#include <machine/bus.h>
#include <dev/isa/isavar.h>
@@ -69,6 +73,8 @@
#endif
#define com_lcr com_cfcr
+#include "com.h"
+
#define COM_IBUFSIZE (2 * 512)
#define COM_IHIGHWATER ((3 * COM_IBUFSIZE) / 4)
@@ -109,11 +115,9 @@ struct com_softc {
u_char sc_ibufs[2][COM_IBUFSIZE];
};
-int comprobe __P((struct device *, void *, void *));
#ifdef COM_HAYESP
int comprobeHAYESP __P((bus_io_handle_t hayespioh, struct com_softc *sc));
#endif
-void comattach __P((struct device *, struct device *, void *));
int comopen __P((dev_t, int, int, struct proc *));
int comclose __P((dev_t, int, int, struct proc *));
void comdiag __P((void *));
@@ -122,11 +126,30 @@ void compoll __P((void *));
int comparam __P((struct tty *, struct termios *));
void comstart __P((struct tty *));
-int cominit __P((bus_chipset_tag_t, bus_io_handle_t, int));
+/*
+ * XXX the following two cfattach structs should be different, and possibly
+ * XXX elsewhere.
+ */
+int comprobe __P((struct device *, void *, void *));
+void comattach __P((struct device *, struct device *, void *));
+
+#if NCOM_ISA
+struct cfattach com_isa_ca = {
+ sizeof(struct com_softc), comprobe, comattach
+};
+#endif
-struct cfdriver comcd = {
- NULL, "com", comprobe, comattach, DV_TTY, sizeof(struct com_softc)
+#if NCOM_COMMULTI
+struct cfattach com_commulti_ca = {
+ sizeof(struct com_softc), comprobe, comattach
};
+#endif
+
+struct cfdriver com_cd = {
+ NULL, "com", DV_TTY
+};
+
+int cominit __P((bus_chipset_tag_t, bus_io_handle_t, int));
#ifdef COMCONSOLE
int comdefaultrate = CONSPEED; /* XXX why set default? */
@@ -138,6 +161,7 @@ int comconsinit;
int comconsattached;
bus_chipset_tag_t comconsbc;
bus_io_handle_t comconsioh;
+tcflag_t comconscflag = TTYDEF_CFLAG;
int commajor;
int comsopen = 0;
@@ -157,7 +181,7 @@ extern int kgdb_debug_init;
#define CLR(t, f) (t) &= ~(f)
#define ISSET(t, f) ((t) & (f))
-#include "pcmciabus.h"
+/*#include "pcmciabus.h"*/
#if NPCMCIABUS >0
/* additional setup needed for pcmcia devices */
#include <dev/pcmcia/pcmciabus.h>
@@ -327,13 +351,22 @@ comprobe(parent, match, aux)
int iobase, needioh;
int rv = 1;
+ /*
+ * XXX should be broken out into functions for isa probe and
+ * XXX for commulti probe, with a helper function that contains
+ * XXX most of the interesting stuff.
+ */
+#if NCOM_ISA
if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
struct isa_attach_args *ia = aux;
bc = ia->ia_bc;
iobase = ia->ia_iobase;
needioh = 1;
- } else {
+ } else
+#endif
+#if NCOM_COMMULTI
+ if (1) {
struct commulti_attach_args *ca = aux;
if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ca->ca_slave)
@@ -343,7 +376,9 @@ comprobe(parent, match, aux)
iobase = ca->ca_iobase;
ioh = ca->ca_ioh;
needioh = 0;
- }
+ } else
+#endif
+ return(0); /* This cannot happen */
/* if it's in use as console, it's there. */
if (iobase == comconsaddr && !comconsattached)
@@ -358,12 +393,14 @@ comprobe(parent, match, aux)
bus_io_unmap(bc, ioh, COM_NPORTS);
out:
+#if NCOM_ISA
if (rv && !strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
struct isa_attach_args *ia = aux;
ia->ia_iosize = COM_NPORTS;
ia->ia_msize = 0;
}
+#endif
return (rv);
}
@@ -383,8 +420,14 @@ comattach(parent, self, aux)
int *hayespp;
#endif
+ /*
+ * XXX should be broken out into functions for isa attach and
+ * XXX for commulti attach, with a helper function that contains
+ * XXX most of the interesting stuff.
+ */
sc->sc_hwflags = 0;
sc->sc_swflags = 0;
+#if NCOM_ISA
if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
struct isa_attach_args *ia = aux;
@@ -399,7 +442,10 @@ comattach(parent, self, aux)
} else
ioh = comconsioh;
irq = ia->ia_irq;
- } else {
+ } else
+#endif
+#if NCOM_COMMULTI
+ if (1) {
struct commulti_attach_args *ca = aux;
/*
@@ -412,7 +458,9 @@ comattach(parent, self, aux)
if (ca->ca_noien)
sc->sc_hwflags |= COM_HW_NOIEN;
- }
+ } else
+#endif
+ panic("comattach: impossible");
sc->sc_bc = bc;
sc->sc_ioh = ioh;
@@ -473,9 +521,18 @@ comattach(parent, self, aux)
bus_io_write_1(bc, ioh, com_ier, 0);
bus_io_write_1(bc, ioh, com_mcr, 0);
- if (irq != IRQUNK)
- sc->sc_ih = isa_intr_establish(irq, IST_EDGE, IPL_TTY,
- comintr, sc, sc->sc_dev.dv_xname);
+ if (irq != IRQUNK) {
+#if NCOM_ISA
+ if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
+ struct isa_attach_args *ia = aux;
+
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, irq,
+ IST_EDGE, IPL_TTY, comintr, sc,
+ sc->sc_dev.dv_xname);
+ } else
+#endif
+ panic("comattach: IRQ but can't have one");
+ }
#ifdef KGDB
if (kgdb_dev == makedev(commajor, unit)) {
@@ -516,9 +573,9 @@ comopen(dev, flag, mode, p)
int s;
int error = 0;
- if (unit >= comcd.cd_ndevs)
+ if (unit >= com_cd.cd_ndevs)
return ENXIO;
- sc = comcd.cd_devs[unit];
+ sc = com_cd.cd_devs[unit];
if (!sc)
return ENXIO;
@@ -535,7 +592,10 @@ comopen(dev, flag, mode, p)
ttychars(tp);
tp->t_iflag = TTYDEF_IFLAG;
tp->t_oflag = TTYDEF_OFLAG;
- tp->t_cflag = TTYDEF_CFLAG;
+ if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
+ tp->t_cflag = comconscflag;
+ else
+ tp->t_cflag = TTYDEF_CFLAG;
if (ISSET(sc->sc_swflags, COM_SW_CLOCAL))
SET(tp->t_cflag, CLOCAL);
if (ISSET(sc->sc_swflags, COM_SW_CRTSCTS))
@@ -644,7 +704,7 @@ comclose(dev, flag, mode, p)
struct proc *p;
{
int unit = COMUNIT(dev);
- struct com_softc *sc = comcd.cd_devs[unit];
+ struct com_softc *sc = com_cd.cd_devs[unit];
struct tty *tp = sc->sc_tty;
bus_chipset_tag_t bc = sc->sc_bc;
bus_io_handle_t ioh = sc->sc_ioh;
@@ -684,7 +744,7 @@ comread(dev, uio, flag)
struct uio *uio;
int flag;
{
- struct com_softc *sc = comcd.cd_devs[COMUNIT(dev)];
+ struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
struct tty *tp = sc->sc_tty;
return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
@@ -696,7 +756,7 @@ comwrite(dev, uio, flag)
struct uio *uio;
int flag;
{
- struct com_softc *sc = comcd.cd_devs[COMUNIT(dev)];
+ struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
struct tty *tp = sc->sc_tty;
return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
@@ -706,7 +766,7 @@ struct tty *
comtty(dev)
dev_t dev;
{
- struct com_softc *sc = comcd.cd_devs[COMUNIT(dev)];
+ struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
struct tty *tp = sc->sc_tty;
return (tp);
@@ -734,7 +794,7 @@ comioctl(dev, cmd, data, flag, p)
struct proc *p;
{
int unit = COMUNIT(dev);
- struct com_softc *sc = comcd.cd_devs[unit];
+ struct com_softc *sc = com_cd.cd_devs[unit];
struct tty *tp = sc->sc_tty;
bus_chipset_tag_t bc = sc->sc_bc;
bus_io_handle_t ioh = sc->sc_ioh;
@@ -846,7 +906,7 @@ comparam(tp, t)
struct tty *tp;
struct termios *t;
{
- struct com_softc *sc = comcd.cd_devs[COMUNIT(tp->t_dev)];
+ struct com_softc *sc = com_cd.cd_devs[COMUNIT(tp->t_dev)];
bus_chipset_tag_t bc = sc->sc_bc;
bus_io_handle_t ioh = sc->sc_ioh;
int ospeed = comspeed(t->c_ospeed);
@@ -985,7 +1045,7 @@ void
comstart(tp)
struct tty *tp;
{
- struct com_softc *sc = comcd.cd_devs[COMUNIT(tp->t_dev)];
+ struct com_softc *sc = com_cd.cd_devs[COMUNIT(tp->t_dev)];
bus_chipset_tag_t bc = sc->sc_bc;
bus_io_handle_t ioh = sc->sc_ioh;
int s;
@@ -1106,8 +1166,8 @@ compoll(arg)
comevents = 0;
splx(s);
- for (unit = 0; unit < comcd.cd_ndevs; unit++) {
- sc = comcd.cd_devs[unit];
+ for (unit = 0; unit < com_cd.cd_ndevs; unit++) {
+ sc = com_cd.cd_devs[unit];
if (sc == 0 || sc->sc_ibufp == sc->sc_ibuf)
continue;
diff --git a/sys/dev/isa/comvar.h b/sys/dev/isa/comvar.h
index 9b412b06936..c3f8068caec 100644
--- a/sys/dev/isa/comvar.h
+++ b/sys/dev/isa/comvar.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: comvar.h,v 1.1 1996/04/19 16:08:34 niklas Exp $ */
-/* $NetBSD: comvar.h,v 1.3 1996/03/10 09:01:26 cgd Exp $ */
+/* $OpenBSD: comvar.h,v 1.2 1996/04/21 22:23:20 deraadt Exp $ */
+/* $NetBSD: comvar.h,v 1.4 1996/04/15 18:54:35 cgd Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@@ -46,3 +46,4 @@ extern int comconsaddr;
extern int comconsattached;
extern bus_chipset_tag_t comconsbc;
extern bus_io_handle_t comconsioh;
+extern tcflag_t comconscflag;
diff --git a/sys/dev/isa/fd.c b/sys/dev/isa/fd.c
index 45564bd20b9..a7b07df07c7 100644
--- a/sys/dev/isa/fd.c
+++ b/sys/dev/isa/fd.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: fd.c,v 1.12 1996/04/18 17:12:13 niklas Exp $ */
-/* $NetBSD: fd.c,v 1.85 1996/03/04 04:01:03 mycroft Exp $ */
+/* $OpenBSD: fd.c,v 1.13 1996/04/21 22:16:52 deraadt Exp $ */
+/* $NetBSD: fd.c,v 1.87 1996/04/11 22:15:16 cgd Exp $ */
/*-
* Copyright (c) 1993, 1994, 1995 Charles Hannum.
@@ -112,8 +112,12 @@ void fdcforceintr __P((void *));
#endif
void fdcattach __P((struct device *, struct device *, void *));
-struct cfdriver fdccd = {
- NULL, "fdc", fdcprobe, fdcattach, DV_DULL, sizeof(struct fdc_softc)
+struct cfattach fdc_ca = {
+ sizeof(struct fdc_softc), fdcprobe, fdcattach
+};
+
+struct cfdriver fdc_cd = {
+ NULL, "fdc", DV_DULL
};
/*
@@ -179,8 +183,12 @@ struct fd_softc {
int fdprobe __P((struct device *, void *, void *));
void fdattach __P((struct device *, struct device *, void *));
-struct cfdriver fdcd = {
- NULL, "fd", fdprobe, fdattach, DV_DISK, sizeof(struct fd_softc)
+struct cfattach fd_ca = {
+ sizeof(struct fd_softc), fdprobe, fdattach
+};
+
+struct cfdriver fd_cd = {
+ NULL, "fd", DV_DISK
};
void fdgetdisklabel __P((struct fd_softc *));
@@ -308,8 +316,8 @@ fdcattach(parent, self, aux)
at_setup_dmachan(fdc->sc_drq, FDC_MAXIOSIZE);
isa_establish(&fdc->sc_id, &fdc->sc_dev);
#endif
- fdc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_BIO, fdcintr,
- fdc, fdc->sc_dev.dv_xname);
+ fdc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_BIO, fdcintr, fdc, fdc->sc_dev.dv_xname);
/*
* The NVRAM info only tells us about the first two disks on the
@@ -477,8 +485,8 @@ fdstrategy(bp)
int s;
/* Valid unit, controller, and request? */
- if (unit >= fdcd.cd_ndevs ||
- (fd = fdcd.cd_devs[unit]) == 0 ||
+ if (unit >= fd_cd.cd_ndevs ||
+ (fd = fd_cd.cd_devs[unit]) == 0 ||
bp->b_blkno < 0 ||
(bp->b_bcount % FDC_BSIZE) != 0) {
bp->b_error = EINVAL;
@@ -705,9 +713,9 @@ Fdopen(dev, flags)
struct fd_type *type;
unit = FDUNIT(dev);
- if (unit >= fdcd.cd_ndevs)
+ if (unit >= fd_cd.cd_ndevs)
return ENXIO;
- fd = fdcd.cd_devs[unit];
+ fd = fd_cd.cd_devs[unit];
if (fd == 0)
return ENXIO;
type = fd_dev_to_type(fd, dev);
@@ -730,7 +738,7 @@ fdclose(dev, flags)
dev_t dev;
int flags;
{
- struct fd_softc *fd = fdcd.cd_devs[FDUNIT(dev)];
+ struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
fd->sc_flags &= ~FD_OPEN;
return 0;
@@ -1169,7 +1177,7 @@ fdioctl(dev, cmd, addr, flag)
caddr_t addr;
int flag;
{
- struct fd_softc *fd = fdcd.cd_devs[FDUNIT(dev)];
+ struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
struct disklabel buffer;
int error;
diff --git a/sys/dev/isa/files.isa b/sys/dev/isa/files.isa
index 02c45fce533..47e4237a8b2 100644
--- a/sys/dev/isa/files.isa
+++ b/sys/dev/isa/files.isa
@@ -1,5 +1,5 @@
-# $OpenBSD: files.isa,v 1.7 1996/04/18 23:47:33 niklas Exp $
-# $NetBSD: files.isa,v 1.12 1996/03/04 03:29:16 cgd Exp $
+# $OpenBSD: files.isa,v 1.8 1996/04/21 22:23:23 deraadt Exp $
+# $NetBSD: files.isa,v 1.17 1996/03/29 20:53:30 mycroft Exp $
#
# Config.new file and device description for machine-independent ISA code.
# Included by ports that need it. Requires that the SCSI files be
@@ -9,11 +9,10 @@
# devices:
# mcd, scd, wd, wt
-define isa {[port = -1], [size = 0],
- [iomem = -1], [iosiz = 0],
- [irq = -1], [drq = -1]}
-
-device isa at isabus: isa
+device isa {[port = -1], [size = 0],
+ [iomem = -1], [iosiz = 0],
+ [irq = -1], [drq = -1]}
+attach isa at isabus
file dev/isa/isa.c isa needs-flag
# ISA DMA controller
@@ -28,7 +27,8 @@ file dev/isa/isadma.c isadma needs-flag
define pcicbus {[iomem = -1], [iosiz = 0]}
-device pcic at isa: pcicbus
+device pcic: pcicbus
+attach pcic at isa
file dev/isa/pcmcia_pcic.c pcic
file dev/isa/pcmcia_isa.c pcmcia
@@ -47,15 +47,18 @@ include "../../../dev/pcmcia/files.pcmcia"
define commulti {[slave = -1]}
# AST 4-port board
-device ast at isa: commulti
+device ast: commulti
+attach ast at isa
file dev/isa/ast.c ast
# BOCA 8-port board
-device boca at isa: commulti
+device boca: commulti
+attach boca at isa
file dev/isa/boca.c boca
# IBM RT PC 4-port board
-device rtfps at isa: commulti
+device rtfps: commulti
+attach rtfps at isa
file dev/isa/rtfps.c rtfps
#
@@ -63,16 +66,20 @@ file dev/isa/rtfps.c rtfps
#
# 8250/16[45]50-based "com" ports
-device com at isa, commulti: tty
-file dev/isa/com.c com needs-flag
+device com: tty
+attach com at isa with com_isa
+attach com at commulti with com_commulti
+file dev/isa/com.c com & (com_isa | com_commulti) needs-flag
# Cyclades Cyclom multiport serial cards
# XXX currently broken
-device cy at isa: tty
+device cy: tty
+attach cy at isa
file dev/isa/cy.c cy needs-count
# PC parallel ports (XXX what chip?)
-device lpt at isa
+device lpt
+attach lpt at isa
file dev/isa/lpt.c lpt needs-flag
#
@@ -80,53 +87,64 @@ file dev/isa/lpt.c lpt needs-flag
#
# Adaptec AHA-154x family
-device aha at isa: scsi, isadma
-file dev/isa/aha1542.c aha
+device aha: scsi, isadma
+attach aha at isa
+file dev/isa/aha.c aha
# Adapctec AIC-6[32]60 ICs
-device aic at isa: scsi, isadma
+device aic: scsi, isadma
+attach aic at isa
file dev/isa/aic6360.c aic
# Adaptec 7770-based EISA, VLB, etc. controllers
-device ahe at isa: scsi, aic7xxx
+device ahe: scsi, aic7xxx
+attach ahe at isa
file dev/isa/aha284x.c ahe
# BusLogic BT-74x EISA family (XXX; should be EISA. it's special)
-device bt at isa: scsi, isadma
-file dev/isa/bt742a.c bt
+device bt: scsi, isadma
+attach bt at isa
+file dev/isa/bt.c bt
# Seagate ST0[12] ICs
-device sea at isa: scsi, isadma
+device sea: scsi, isadma
+attach sea at isa
file dev/isa/seagate.c sea
# UltraStor UHA-[13]4f boards
-device uha at isa: scsi, isadma
+device uha: scsi, isadma
+attach uha at isa
file dev/isa/ultra14f.c uha
-# Western Digital WD7000 boards (XXX incomplete description)
-# XXX not yet working
-device wds at isa: scsi, isadma
-file dev/isa/wd7000.c wds
+# Western Digital WD7000 and Future Domain TMC-7000 boards
+device wds: scsi, isadma
+attach wds at isa
+file dev/isa/wds.c wds
#
# Other ISA disk controllers
#
# Mitsumi CD-ROM controllers
-device mcd at isa: disk
+device mcd: disk
+attach mcd at isa
file dev/isa/mcd.c mcd needs-flag
# Sony CDU-3[13]A CD-ROM drives
-device scd at isa: disk
+device scd: disk
+attach scd at isa
file dev/isa/scd.c scd needs-flag
# ISA "wd" (ESDI/IDE/etc.) controllers
-device wdc at isa {drive = -1}
-device wd at wdc: disk, isadma
+device wdc {drive = -1}
+attach wdc at isa
+device wd: disk, isadma
+attach wd at wdc
file dev/isa/wd.c wdc needs-flag
# Wangtek- and Archive-compatible tape controller boards
-device wt at isa: tape, isadma
+device wt: tape, isadma
+attach wt at isa
file dev/isa/wt.c wt needs-flag
#
@@ -140,45 +158,55 @@ file dev/isa/elink.c elink
# National Semiconductor DS8390/WD83C690-based boards
# (WD/SMC 80x3 family, SMC Ultra [8216], 3Com 3C503, NE[12]000, and clones)
# XXX conflicts with amiga if_ed.c
-#device ed at isa, pcmcia: ether, ifnet
-#file dev/isa/if_ed.c ed needs-flag
+device ed: ether, ifnet
+attach ed at isa
+file dev/isa/if_ed.c ed needs-flag
# 3Com 3C505
-device eg at isa: ether, ifnet
+device eg: ether, ifnet
+attach eg at isa
file dev/isa/if_eg.c eg
# 3Com 3C501
-device el at isa: ether, ifnet
+device el: ether, ifnet
+attach el at isa
file dev/isa/if_el.c el
# 3Com 3C5x9, 3c59x (EtherLink III) family
-device ep at isa, pci: ether, ifnet, elink
+device ep: ether, ifnet, elink
+attach ep at isa with ep_isa
+attach ep at pci with ep_pci
file dev/isa/if_ep.c ep needs-flag
# Fujitsu MB8696[05]-based boards
# (Allied Telesis AT1700)
-device fe at isa: ether, ifnet
+device fe: ether, ifnet
+attach fe at isa
file dev/isa/if_fe.c fe
# HP Lan Ethernet controllers
# XXX currently broken
-#device hp at isa: ether, ifnet
+#device hp: ether, ifnet
+#attach hp at isa
#file dev/isa/if_hp.c hp
# Intel i82586-based boards
# (AT&T StarLAN 10, AT&T EN100, AT&T StarLAN Fiber, 3Com 3C507)
-device ie at isa: ether, ifnet, elink
+device ie: ether, ifnet, elink
+attach ie at isa
file dev/isa/if_ie.c ie
# XXX ???
# XXX NOT IN TREE?
-#device ix at isa: ether, ifnet
+#device ix: ether, ifnet
+#attach ix at isa
#file dev/isa/if_ix.c ix
# AMD am7990 (Lance) -based boards
# (BICC Isolan, NE2100, DEPCA)
# XXX conflicts with alpha if_le.c
-#device le at isa: ether, ifnet, isadma
+#device le: ether, ifnet, isadma
+#attach le at isa with le_isa
#file dev/isa/if_le.c le
#
@@ -190,11 +218,13 @@ define sbdsp
file dev/isa/sbdsp.c sbdsp
# SoundBlaster family
-device sb at isa: audio, isadma, sbdsp, mulaw
+device sb: audio, isadma, sbdsp, mulaw
+attach sb at isa
file dev/isa/sb.c sb needs-flag
# ProAudio Spectrum
-device pas at isa: audio, isadma, sbdsp, mulaw
+device pas: audio, isadma, sbdsp, mulaw
+attach pas at isa
file dev/isa/pas.c pas needs-flag
# AD1848 (CS4248, CS4231, AD1845) audio codec support; used by other drivers
@@ -207,18 +237,22 @@ file dev/isa/ics2101.c ics2101
# Audio systems based on Echo Speech Corp. ESC61[45] ASICs
-device pss at isa {[port = -1], [size = 0],
- [iomem = -1], [iosiz = 0],
- [irq = -1], [drq = -1]}
-device sp at pss: audio, isadma, ad1848
+device pss {[port = -1], [size = 0],
+ [iomem = -1], [iosiz = 0],
+ [irq = -1], [drq = -1]}
+attach pss at isa
+device sp: audio, isadma, ad1848
+attach sp at pss
file dev/isa/pss.c pss needs-flag
# Microsoft Windows Sound System
-device wss at isa: audio, isadma, ad1848
+device wss: audio, isadma, ad1848
+attach wss at isa
file dev/isa/wss.c wss needs-flag
# Gravis UltraSound & UltraSound MAX.
# Use the "flags" keyword in a config file to specify an extra DMA
# channel for full-duplex operation.
-device gus at isa: audio, isadma, ics2101, ad1848, mulaw
+device gus: audio, isadma, ics2101, ad1848, mulaw
+attach gus at isa
file dev/isa/gus.c gus needs-flag
diff --git a/sys/dev/isa/gus.c b/sys/dev/isa/gus.c
index a2c1b4f2014..9a72f7a6182 100644
--- a/sys/dev/isa/gus.c
+++ b/sys/dev/isa/gus.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: gus.c,v 1.8 1996/04/18 23:47:34 niklas Exp $ */
-/* $NetBSD: gus.c,v 1.10 1996/03/01 04:08:31 mycroft Exp $ */
+/* $OpenBSD: gus.c,v 1.9 1996/04/21 22:23:28 deraadt Exp $ */
+/* $NetBSD: gus.c,v 1.13 1996/04/11 22:28:42 cgd Exp $ */
/*-
* Copyright (c) 1996 The NetBSD Foundation, Inc.
@@ -126,6 +126,7 @@
#include <dev/ic/ad1848reg.h>
#include <dev/isa/ics2101var.h>
#include <dev/isa/ad1848var.h>
+#include <dev/isa/cs4231var.h>
#include "gusreg.h"
#ifdef AUDIO_DEBUG
@@ -458,8 +459,12 @@ STATIC void gusics_cd_mute __P((struct ics2101_softc *, int));
int gusprobe __P((struct device *, void *, void *));
void gusattach __P((struct device *, struct device *, void *));
-struct cfdriver guscd = {
- NULL, "gus", gusprobe, gusattach, DV_DULL, sizeof(struct gus_softc)
+struct cfattach gus_ca = {
+ sizeof(struct gus_softc), gusprobe, gusattach,
+};
+
+struct cfdriver gus_cd = {
+ NULL, "gus", DV_DULL
};
@@ -927,8 +932,8 @@ gusattach(parent, self, aux)
/* XXX we shouldn't have to use splgus == splclock, nor should
* we use IPL_CLOCK.
*/
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_AUDIO, gusintr,
- sc /* sc->sc_gusdsp */, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_AUDIO, gusintr, sc /* sc->sc_gusdsp */, sc->sc_dev.dv_xname);
/*
* Set some default values
@@ -974,9 +979,9 @@ gusopen(dev, flags)
DPRINTF(("gusopen() called\n"));
- if (unit >= guscd.cd_ndevs)
+ if (unit >= gus_cd.cd_ndevs)
return ENXIO;
- sc = guscd.cd_devs[unit];
+ sc = gus_cd.cd_devs[unit];
if (!sc)
return ENXIO;
diff --git a/sys/dev/isa/if_ed.c b/sys/dev/isa/if_ed.c
index dc5993a34b7..b385c61d95a 100644
--- a/sys/dev/isa/if_ed.c
+++ b/sys/dev/isa/if_ed.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: if_ed.c,v 1.9 1996/04/18 23:47:37 niklas Exp $ */
-/* $NetBSD: if_ed.c,v 1.90 1996/03/16 07:24:15 cgd Exp $ */
+/* $OpenBSD: if_ed.c,v 1.10 1996/04/21 22:23:41 deraadt Exp $ */
+/* $NetBSD: if_ed.c,v 1.93 1996/04/11 22:28:55 cgd Exp $ */
/*
* Device driver for National Semiconductor DS8390/WD83C690 based ethernet
@@ -18,7 +18,6 @@
* similar clones.
*/
-#include "pcmciabus.h"
#include "bpfilter.h"
#include <sys/param.h>
@@ -54,11 +53,10 @@
#endif
#include <machine/cpu.h>
-#include <machine/pio.h>
+#include <machine/bus.h>
#include <dev/isa/isareg.h>
#include <dev/isa/isavar.h>
-#include <i386/isa/isa_machdep.h> /* XXX USES ISA HOLE DIRECTLY */
#define ED_BYTE_ORDER LITTLE_ENDIAN
#include <dev/ic/dp8390reg.h>
#include <dev/isa/if_edreg.h>
@@ -81,8 +79,12 @@ struct ed_softc {
#define ED_NOTPRESENT 0x0002 /* card not present; do not allow
reconfiguration */
- int asic_base; /* Base ASIC I/O port */
- int nic_base; /* Base NIC (DS8390) I/O port */
+ bus_chipset_tag_t sc_bc; /* bus identifier */
+ bus_io_handle_t sc_ioh; /* io handle */
+ bus_mem_handle_t sc_memh; /* bus memory handle */
+
+ bus_io_size_t asic_base; /* offset of ASIC I/O port */
+ bus_io_size_t nic_base; /* offset of NIC (DS8390) I/O port */
/*
* The following 'proto' variable is part of a work-around for 8013EBT asics
@@ -98,10 +100,10 @@ struct ed_softc {
u_char isa16bit; /* width of access to card 0=8 or 1=16 */
u_char is790; /* set by probe if NIC is a 790 */
- caddr_t mem_start; /* NIC memory start address */
- caddr_t mem_end; /* NIC memory end address */
- u_long mem_size; /* total NIC memory size */
- caddr_t mem_ring; /* start of RX ring-buffer (in NIC mem) */
+ int mem_start; /* offset of NIC memory */
+ int mem_end; /* offset of NIC memory end */
+ int mem_size; /* total NIC memory size */
+ int mem_ring; /* offset of RX ring-buffer (in NIC mem) */
u_char mem_shared; /* NIC memory is shared with host */
u_char txb_cnt; /* number of transmit buffers */
@@ -120,7 +122,7 @@ int edprobe __P((struct device *, void *, void *));
void edattach __P((struct device *, struct device *, void *));
int ed_find __P((struct ed_softc *, struct cfdata *,
struct isa_attach_args *ia));
-int ed_probe_generic8390 __P((int));
+int ed_probe_generic8390 __P((bus_chipset_tag_t, bus_io_handle_t, int));
int ed_find_WD80x3 __P((struct ed_softc *, struct cfdata *,
struct isa_attach_args *ia));
int ed_find_3Com __P((struct ed_softc *, struct cfdata *,
@@ -135,31 +137,41 @@ void edreset __P((struct ed_softc *));
void edinit __P((struct ed_softc *));
void edstop __P((struct ed_softc *));
+void ed_shared_writemem __P((struct ed_softc *, caddr_t, int, int));
+void ed_shared_readmem __P((struct ed_softc *, int, caddr_t, int));
+
#define inline /* XXX for debugging porpoises */
void ed_getmcaf __P((struct arpcom *, u_long *));
-void edread __P((struct ed_softc *, caddr_t, int));
-struct mbuf *edget __P((struct ed_softc *, caddr_t, int));
+void edread __P((struct ed_softc *, int, int));
+struct mbuf *edget __P((struct ed_softc *, int, int));
static inline void ed_rint __P((struct ed_softc *));
static inline void ed_xmit __P((struct ed_softc *));
-static inline caddr_t ed_ring_copy __P((struct ed_softc *, caddr_t, caddr_t,
+static inline int ed_ring_copy __P((struct ed_softc *, int, caddr_t,
u_short));
void ed_pio_readmem __P((struct ed_softc *, u_short, caddr_t, u_short));
void ed_pio_writemem __P((struct ed_softc *, caddr_t, u_short, u_short));
u_short ed_pio_write_mbufs __P((struct ed_softc *, struct mbuf *, u_short));
-struct cfdriver edcd = {
- NULL, "ed", edprobe, edattach, DV_IFNET, sizeof(struct ed_softc)
+struct cfattach ed_ca = {
+ sizeof(struct ed_softc), edprobe, edattach
+};
+
+struct cfdriver ed_cd = {
+ NULL, "ed", DV_IFNET
};
#define ETHER_MIN_LEN 64
#define ETHER_MAX_LEN 1518
#define ETHER_ADDR_LEN 6
-#define NIC_PUT(base, off, val) outb((base) + (off), (val))
-#define NIC_GET(base, off) inb((base) + (off))
+#define NIC_PUT(bc, ioh, nic, reg, val) \
+ bus_io_write_1((bc), (ioh), ((nic) + (reg)), (val))
+#define NIC_GET(bc, ioh, nic, reg) \
+ bus_io_read_1((bc), (ioh), ((nic) + (reg)))
+/*#include "pcmciabus.h"*/
#if NPCMCIABUS > 0
#include <dev/pcmcia/pcmciabus.h>
@@ -359,15 +371,17 @@ ed_find(sc, cf, ia)
* Return 1 if 8390 was found, 0 if not.
*/
int
-ed_probe_generic8390(nicbase)
+ed_probe_generic8390(bc, ioh, nicbase)
+ bus_chipset_tag_t bc;
+ bus_io_handle_t ioh;
int nicbase;
{
- if ((NIC_GET(nicbase, ED_P0_CR) &
+ if ((NIC_GET(bc, ioh, nicbase, ED_P0_CR) &
(ED_CR_RD2 | ED_CR_TXP | ED_CR_STA | ED_CR_STP)) !=
(ED_CR_RD2 | ED_CR_STP))
return (0);
- if ((NIC_GET(nicbase, ED_P0_ISR) & ED_ISR_RST) != ED_ISR_RST)
+ if ((NIC_GET(bc, ioh, nicbase, ED_P0_ISR) & ED_ISR_RST) != ED_ISR_RST)
return (0);
return (1);
@@ -385,17 +399,26 @@ ed_find_WD80x3(sc, cf, ia)
struct cfdata *cf;
struct isa_attach_args *ia;
{
- int i;
+ bus_chipset_tag_t bc;
+ bus_io_handle_t ioh;
+ bus_mem_handle_t memh;
u_int memsize;
u_char iptr, isa16bit, sum;
+ int i, rv, mapped_mem = 0;
int asicbase, nicbase;
- sc->asic_base = asicbase = ia->ia_iobase;
+ bc = ia->ia_bc;
+ rv = 0;
+
+ if (bus_io_map(bc, ia->ia_iobase, ED_WD_IO_PORTS, &ioh))
+ return (0);
+
+ sc->asic_base = asicbase = 0;
sc->nic_base = nicbase = asicbase + ED_WD_NIC_OFFSET;
sc->is790 = 0;
#ifdef TOSH_ETHER
- outb(asicbase + ED_WD_MSR, ED_WD_MSR_POW);
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_MSR, ED_WD_MSR_POW);
delay(10000);
#endif
@@ -406,7 +429,7 @@ ed_find_WD80x3(sc, cf, ia)
* Danpex boards for one.
*/
for (sum = 0, i = 0; i < 8; ++i)
- sum += inb(asicbase + ED_WD_PROM + i);
+ sum += bus_io_read_1(bc, ioh, asicbase + ED_WD_PROM + i);
if (sum != ED_WD_ROM_CHECKSUM_TOTAL) {
/*
@@ -414,25 +437,27 @@ ed_find_WD80x3(sc, cf, ia)
* clones. In this case, the checksum byte (the eighth byte)
* seems to always be zero.
*/
- if (inb(asicbase + ED_WD_CARD_ID) != ED_TYPE_WD8003E ||
- inb(asicbase + ED_WD_PROM + 7) != 0)
- return (0);
+ if (bus_io_read_1(bc, ioh, asicbase + ED_WD_CARD_ID) !=
+ ED_TYPE_WD8003E ||
+ bus_io_read_1(bc, ioh, asicbase + ED_WD_PROM + 7) != 0)
+ goto out;
}
/* Reset card to force it into a known state. */
#ifdef TOSH_ETHER
- outb(asicbase + ED_WD_MSR, ED_WD_MSR_RST | ED_WD_MSR_POW);
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_MSR,
+ ED_WD_MSR_RST | ED_WD_MSR_POW);
#else
- outb(asicbase + ED_WD_MSR, ED_WD_MSR_RST);
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_MSR, ED_WD_MSR_RST);
#endif
delay(100);
- outb(asicbase + ED_WD_MSR,
- inb(asicbase + ED_WD_MSR) & ~ED_WD_MSR_RST);
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_MSR,
+ bus_io_read_1(bc, ioh, asicbase + ED_WD_MSR) & ~ED_WD_MSR_RST);
/* Wait in the case this card is reading it's EEROM. */
delay(5000);
sc->vendor = ED_VENDOR_WD_SMC;
- sc->type = inb(asicbase + ED_WD_CARD_ID);
+ sc->type = bus_io_read_1(bc, ioh, asicbase + ED_WD_CARD_ID);
/* Set initial values for width/size. */
memsize = 8192;
@@ -487,9 +512,11 @@ ed_find_WD80x3(sc, cf, ia)
case ED_TYPE_SMC8216T:
sc->type_str = (sc->type == ED_TYPE_SMC8216C) ?
"SMC8216/SMC8216C" : "SMC8216T";
- outb(asicbase + ED_WD790_HWR,
- inb(asicbase + ED_WD790_HWR) | ED_WD790_HWR_SWH);
- switch (inb(asicbase + ED_WD790_RAR) & ED_WD790_RAR_SZ64) {
+ bus_io_write_1(bc, ioh, asicbase + ED_WD790_HWR,
+ bus_io_read_1(bc, ioh, asicbase + ED_WD790_HWR)
+ | ED_WD790_HWR_SWH);
+ switch (bus_io_read_1(bc, ioh, asicbase + ED_WD790_RAR) &
+ ED_WD790_RAR_SZ64) {
case ED_WD790_RAR_SZ64:
memsize = 65536;
break;
@@ -506,8 +533,9 @@ ed_find_WD80x3(sc, cf, ia)
memsize = 8192;
break;
}
- outb(asicbase + ED_WD790_HWR,
- inb(asicbase + ED_WD790_HWR) & ~ED_WD790_HWR_SWH);
+ bus_io_write_1(bc, ioh, asicbase + ED_WD790_HWR,
+ bus_io_read_1(bc, ioh,
+ asicbase + ED_WD790_HWR) & ~ED_WD790_HWR_SWH);
isa16bit = 1;
sc->is790 = 1;
@@ -536,7 +564,8 @@ ed_find_WD80x3(sc, cf, ia)
#ifdef TOSH_ETHER
(sc->type != ED_TYPE_TOSHIBA1) && (sc->type != ED_TYPE_TOSHIBA4) &&
#endif
- ((inb(asicbase + ED_WD_ICR) & ED_WD_ICR_16BIT) == 0)) {
+ ((bus_io_read_1(bc, ioh,
+ asicbase + ED_WD_ICR) & ED_WD_ICR_16BIT) == 0)) {
isa16bit = 0;
memsize = 8192;
}
@@ -567,13 +596,13 @@ ed_find_WD80x3(sc, cf, ia)
if (sc->is790) {
u_char x;
/* Assemble together the encoded interrupt number. */
- outb(ia->ia_iobase + ED_WD790_HWR,
- inb(ia->ia_iobase + ED_WD790_HWR) | ED_WD790_HWR_SWH);
- x = inb(ia->ia_iobase + ED_WD790_GCR);
+ bus_io_write_1(bc, ioh, ED_WD790_HWR,
+ bus_io_read_1(bc, ioh, ED_WD790_HWR) | ED_WD790_HWR_SWH);
+ x = bus_io_read_1(bc, ioh, ED_WD790_GCR);
iptr = ((x & ED_WD790_GCR_IR2) >> 4) |
((x & (ED_WD790_GCR_IR1|ED_WD790_GCR_IR0)) >> 2);
- outb(ia->ia_iobase + ED_WD790_HWR,
- inb(ia->ia_iobase + ED_WD790_HWR) & ~ED_WD790_HWR_SWH);
+ bus_io_write_1(bc, ioh, ED_WD790_HWR,
+ bus_io_read_1(bc, ioh, ED_WD790_HWR) & ~ED_WD790_HWR_SWH);
/*
* Translate it using translation table, and check for
* correctness.
@@ -583,17 +612,17 @@ ed_find_WD80x3(sc, cf, ia)
printf("%s: irq mismatch; kernel configured %d != board configured %d\n",
sc->sc_dev.dv_xname, ia->ia_irq,
ed_wd790_irq[iptr]);
- return (0);
+ goto out;
}
} else
ia->ia_irq = ed_wd790_irq[iptr];
/* Enable the interrupt. */
- outb(ia->ia_iobase + ED_WD790_ICR,
- inb(ia->ia_iobase + ED_WD790_ICR) | ED_WD790_ICR_EIL);
+ bus_io_write_1(bc, ioh, ED_WD790_ICR,
+ bus_io_read_1(bc, ioh, ED_WD790_ICR) | ED_WD790_ICR_EIL);
} else if (sc->type & ED_WD_SOFTCONFIG) {
/* Assemble together the encoded interrupt number. */
- iptr = (inb(ia->ia_iobase + ED_WD_ICR) & ED_WD_ICR_IR2) |
- ((inb(ia->ia_iobase + ED_WD_IRR) &
+ iptr = (bus_io_read_1(bc, ioh, ED_WD_ICR) & ED_WD_ICR_IR2) |
+ ((bus_io_read_1(bc, ioh, ED_WD_IRR) &
(ED_WD_IRR_IR0 | ED_WD_IRR_IR1)) >> 5);
/*
* Translate it using translation table, and check for
@@ -604,18 +633,18 @@ ed_find_WD80x3(sc, cf, ia)
printf("%s: irq mismatch; kernel configured %d != board configured %d\n",
sc->sc_dev.dv_xname, ia->ia_irq,
ed_wd584_irq[iptr]);
- return (0);
+ goto out;
}
} else
ia->ia_irq = ed_wd584_irq[iptr];
/* Enable the interrupt. */
- outb(ia->ia_iobase + ED_WD_IRR,
- inb(ia->ia_iobase + ED_WD_IRR) | ED_WD_IRR_IEN);
+ bus_io_write_1(bc, ioh, ED_WD_IRR,
+ bus_io_read_1(bc, ioh, ED_WD_IRR) | ED_WD_IRR_IEN);
} else {
if (ia->ia_irq == IRQUNK) {
printf("%s: %s does not have soft configuration\n",
sc->sc_dev.dv_xname, sc->type_str);
- return (0);
+ goto out;
}
}
@@ -624,7 +653,10 @@ ed_find_WD80x3(sc, cf, ia)
sc->isa16bit = isa16bit;
sc->mem_shared = 1;
ia->ia_msize = memsize;
- sc->mem_start = ISA_HOLE_VADDR(ia->ia_maddr);
+ if (bus_mem_map(bc, ia->ia_maddr, memsize, 0, &memh))
+ goto out;
+ mapped_mem = 1;
+ sc->mem_start = 0; /* offset */
/* Allocate one xmit buffer if < 16k, two buffers otherwise. */
if ((memsize < 16384) || (cf->cf_flags & ED_FLAGS_NO_MULTI_BUFFERING))
@@ -642,7 +674,7 @@ ed_find_WD80x3(sc, cf, ia)
/* Get station address from on-board ROM. */
for (i = 0; i < ETHER_ADDR_LEN; ++i)
sc->sc_arpcom.ac_enaddr[i] =
- inb(asicbase + ED_WD_PROM + i);
+ bus_io_read_1(bc, ioh, asicbase + ED_WD_PROM + i);
/*
* Set upper address bits and 8/16 bit access to shared memory.
@@ -650,15 +682,15 @@ ed_find_WD80x3(sc, cf, ia)
if (isa16bit) {
if (sc->is790) {
sc->wd_laar_proto =
- inb(asicbase + ED_WD_LAAR) &
+ bus_io_read_1(bc, ioh, asicbase + ED_WD_LAAR) &
~ED_WD_LAAR_M16EN;
} else {
sc->wd_laar_proto =
ED_WD_LAAR_L16EN |
- ((kvtop(sc->mem_start) >> 19) &
+ ((ia->ia_maddr >> 19) &
ED_WD_LAAR_ADDRHI);
}
- outb(asicbase + ED_WD_LAAR,
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_LAAR,
sc->wd_laar_proto | ED_WD_LAAR_M16EN);
} else {
if ((sc->type & ED_WD_SOFTCONFIG) ||
@@ -668,9 +700,9 @@ ed_find_WD80x3(sc, cf, ia)
#endif
(sc->type == ED_TYPE_WD8013EBT) && !sc->is790) {
sc->wd_laar_proto =
- ((kvtop(sc->mem_start) >> 19) &
+ ((ia->ia_maddr >> 19) &
ED_WD_LAAR_ADDRHI);
- outb(asicbase + ED_WD_LAAR,
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_LAAR,
sc->wd_laar_proto);
}
}
@@ -680,52 +712,53 @@ ed_find_WD80x3(sc, cf, ia)
*/
if (!sc->is790) {
#ifdef TOSH_ETHER
- outb(asicbase + ED_WD_MSR + 1,
- ((kvtop(sc->mem_start) >> 8) & 0xe0) | 4);
- outb(asicbase + ED_WD_MSR + 2,
- ((kvtop(sc->mem_start) >> 16) & 0x0f));
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_MSR + 1,
+ ((ia->ia_maddr >> 8) & 0xe0) | 4);
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_MSR + 2,
+ ((ia->ia_maddr >> 16) & 0x0f));
sc->wd_msr_proto = ED_WD_MSR_POW;
#else
sc->wd_msr_proto =
- (kvtop(sc->mem_start) >> 13) & ED_WD_MSR_ADDR;
+ (ia->ia_maddr >> 13) & ED_WD_MSR_ADDR;
#endif
sc->cr_proto = ED_CR_RD2;
} else {
- outb(asicbase + 0x04,
- inb(asicbase + 0x04) | 0x80);
- outb(asicbase + 0x0b,
- ((kvtop(sc->mem_start) >> 13) & 0x0f) |
- ((kvtop(sc->mem_start) >> 11) & 0x40) |
- (inb(asicbase + 0x0b) & 0xb0));
- outb(asicbase + 0x04,
- inb(asicbase + 0x04) & ~0x80);
+ bus_io_write_1(bc, ioh, asicbase + 0x04,
+ bus_io_read_1(bc, ioh, asicbase + 0x04) | 0x80);
+ bus_io_write_1(bc, ioh, asicbase + 0x0b,
+ ((ia->ia_maddr >> 13) & 0x0f) |
+ ((ia->ia_maddr >> 11) & 0x40) |
+ (bus_io_read_1(bc, ioh, asicbase + 0x0b) & 0xb0));
+ bus_io_write_1(bc, ioh, asicbase + 0x04,
+ bus_io_read_1(bc, ioh, asicbase + 0x04) & ~0x80);
sc->wd_msr_proto = 0x00;
sc->cr_proto = 0;
}
- outb(asicbase + ED_WD_MSR,
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_MSR,
sc->wd_msr_proto | ED_WD_MSR_MENB);
- (void) inb(0x84);
- (void) inb(0x84);
+ (void) bus_io_read_1(bc, ioh, 0x84); /* XXX */
+ (void) bus_io_read_1(bc, ioh, 0x84); /* XXX */
/* Now zero memory and verify that it is clear. */
- bzero(sc->mem_start, memsize);
+ for (i = 0; i < memsize; ++i)
+ bus_mem_write_1(bc, memh, sc->mem_start + i, 0);
for (i = 0; i < memsize; ++i)
- if (sc->mem_start[i]) {
+ if (bus_mem_read_1(bc, memh, sc->mem_start + i)) {
printf("%s: failed to clear shared memory at %x - check configuration\n",
sc->sc_dev.dv_xname,
- kvtop(sc->mem_start + i));
+ (ia->ia_maddr + sc->mem_start + i));
/* Disable 16 bit access to shared memory. */
- outb(asicbase + ED_WD_MSR,
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_MSR,
sc->wd_msr_proto);
if (isa16bit)
- outb(asicbase + ED_WD_LAAR,
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_LAAR,
sc->wd_laar_proto);
- (void) inb(0x84);
- (void) inb(0x84);
- return (0);
+ (void) bus_io_read_1(bc, ioh, 0x84); /* XXX */
+ (void) bus_io_read_1(bc, ioh, 0x84); /* XXX */
+ goto out;
}
/*
@@ -736,14 +769,32 @@ ed_find_WD80x3(sc, cf, ia)
* and 2) so that other 8 bit devices with shared memory can be
* used in this 128k region, too.
*/
- outb(asicbase + ED_WD_MSR, sc->wd_msr_proto);
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_MSR, sc->wd_msr_proto);
if (isa16bit)
- outb(asicbase + ED_WD_LAAR, sc->wd_laar_proto);
- (void) inb(0x84);
- (void) inb(0x84);
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_LAAR,
+ sc->wd_laar_proto);
+ (void) bus_io_read_1(bc, ioh, 0x84); /* XXX */
+ (void) bus_io_read_1(bc, ioh, 0x84); /* XXX */
ia->ia_iosize = ED_WD_IO_PORTS;
- return (1);
+ rv = 1;
+
+ out:
+ /*
+ * XXX Sould always unmap, but we can't yet.
+ * XXX Need to squish "indirect" first.
+ */
+ if (rv == 0) {
+ bus_io_unmap(bc, ioh, ED_WD_IO_PORTS);
+ if (mapped_mem)
+ bus_mem_unmap(bc, memh, memsize);
+ } else {
+ /* XXX this is all "indirect" brokenness */
+ sc->sc_bc = bc;
+ sc->sc_ioh = ioh;
+ sc->sc_memh = memh;
+ }
+ return (rv);
}
int ed_3com_iobase[] = {0x2e0, 0x2a0, 0x280, 0x250, 0x350, 0x330, 0x310, 0x300};
@@ -761,13 +812,22 @@ ed_find_3Com(sc, cf, ia)
struct cfdata *cf;
struct isa_attach_args *ia;
{
- int i;
+ bus_chipset_tag_t bc;
+ bus_io_handle_t ioh;
+ bus_mem_handle_t memh;
+ int i, rv, mapped_mem = 0;
u_int memsize;
u_char isa16bit, sum, x;
int ptr, asicbase, nicbase;
- sc->asic_base = asicbase = ia->ia_iobase + ED_3COM_ASIC_OFFSET;
- sc->nic_base = nicbase = ia->ia_iobase + ED_3COM_NIC_OFFSET;
+ bc = ia->ia_bc;
+ rv = 0;
+
+ if (bus_io_map(bc, ia->ia_iobase, ED_WD_IO_PORTS, &ioh))
+ return (0);
+
+ sc->asic_base = asicbase = ED_3COM_ASIC_OFFSET;
+ sc->nic_base = nicbase = ED_3COM_NIC_OFFSET;
/*
* Verify that the kernel configured I/O address matches the board
@@ -777,45 +837,46 @@ ed_find_3Com(sc, cf, ia)
* board is there; after all, we are already talking it at that
* address.
*/
- x = inb(asicbase + ED_3COM_BCFR);
+ x = bus_io_read_1(bc, ioh, asicbase + ED_3COM_BCFR);
if (x == 0 || (x & (x - 1)) != 0)
- return (0);
+ goto out;
ptr = ffs(x) - 1;
if (ia->ia_iobase != IOBASEUNK) {
if (ia->ia_iobase != ed_3com_iobase[ptr]) {
printf("%s: %s mismatch; kernel configured %x != board configured %x\n",
"iobase", sc->sc_dev.dv_xname, ia->ia_iobase,
ed_3com_iobase[ptr]);
- return (0);
+ goto out;
}
} else
- ia->ia_iobase = ed_3com_iobase[ptr];
+ ia->ia_iobase = ed_3com_iobase[ptr]; /* XXX --thorpej */
- x = inb(asicbase + ED_3COM_PCFR);
+ x = bus_io_read_1(bc, ioh, asicbase + ED_3COM_PCFR);
if (x == 0 || (x & (x - 1)) != 0)
- return (0);
+ goto out;
ptr = ffs(x) - 1;
if (ia->ia_maddr != MADDRUNK) {
if (ia->ia_maddr != ed_3com_maddr[ptr]) {
printf("%s: %s mismatch; kernel configured %x != board configured %x\n",
"maddr", sc->sc_dev.dv_xname, ia->ia_maddr,
ed_3com_maddr[ptr]);
- return (0);
+ goto out;
}
} else
ia->ia_maddr = ed_3com_maddr[ptr];
#if 0
- x = inb(asicbase + ED_3COM_IDCFR) & ED_3COM_IDCFR_IRQ;
+ x = bus_io_read_1(bc, ioh, asicbase + ED_3COM_IDCFR) &
+ ED_3COM_IDCFR_IRQ;
if (x == 0 || (x & (x - 1)) != 0)
- return (0);
+ goto out;
ptr = ffs(x) - 1;
if (ia->ia_irq != IRQUNK) {
if (ia->ia_irq != ed_3com_irq[ptr]) {
printf("%s: irq mismatch; kernel configured %d != board configured %d\n",
sc->sc_dev.dv_xname, ia->ia_irq,
ed_3com_irq[ptr]);
- return (0);
+ goto out;
}
} else
ia->ia_irq = ed_3com_irq[ptr];
@@ -826,7 +887,8 @@ ed_find_3Com(sc, cf, ia)
* sequence because it'll lock up if the cable isn't connected if we
* don't.
*/
- outb(asicbase + ED_3COM_CR, ED_3COM_CR_RST | ED_3COM_CR_XSEL);
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_CR,
+ ED_3COM_CR_RST | ED_3COM_CR_XSEL);
/* Wait for a while, then un-reset it. */
delay(50);
@@ -836,7 +898,7 @@ ed_find_3Com(sc, cf, ia)
* reset - it's important to set it again after the following outb
* (this is done when we map the PROM below).
*/
- outb(asicbase + ED_3COM_CR, ED_3COM_CR_XSEL);
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_CR, ED_3COM_CR_XSEL);
/* Wait a bit for the NIC to recover from the reset. */
delay(5000);
@@ -858,42 +920,49 @@ ed_find_3Com(sc, cf, ia)
* First, map ethernet address PROM over the top of where the NIC
* registers normally appear.
*/
- outb(asicbase + ED_3COM_CR, ED_3COM_CR_EALO | ED_3COM_CR_XSEL);
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_CR,
+ ED_3COM_CR_EALO | ED_3COM_CR_XSEL);
for (i = 0; i < ETHER_ADDR_LEN; ++i)
- sc->sc_arpcom.ac_enaddr[i] = NIC_GET(nicbase, i);
+ sc->sc_arpcom.ac_enaddr[i] = NIC_GET(bc, ioh, nicbase, i);
/*
* Unmap PROM - select NIC registers. The proper setting of the
* tranceiver is set in edinit so that the attach code is given a
* chance to set the default based on a compile-time config option.
*/
- outb(asicbase + ED_3COM_CR, ED_3COM_CR_XSEL);
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_CR, ED_3COM_CR_XSEL);
/* Determine if this is an 8bit or 16bit board. */
/* Select page 0 registers. */
- NIC_PUT(nicbase, ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STP);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
+ ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STP);
/*
* Attempt to clear WTS bit. If it doesn't clear, then this is a
* 16-bit board.
*/
- NIC_PUT(nicbase, ED_P0_DCR, 0);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_DCR, 0);
/* Select page 2 registers. */
- NIC_PUT(nicbase, ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_2 | ED_CR_STP);
+ NIC_PUT(bc, ioh, nicbase,
+ ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_2 | ED_CR_STP);
/* The 3c503 forces the WTS bit to a one if this is a 16bit board. */
- if (NIC_GET(nicbase, ED_P2_DCR) & ED_DCR_WTS)
+ if (NIC_GET(bc, ioh, nicbase, ED_P2_DCR) & ED_DCR_WTS)
isa16bit = 1;
else
isa16bit = 0;
/* Select page 0 registers. */
- NIC_PUT(nicbase, ED_P2_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STP);
+ NIC_PUT(bc, ioh, nicbase, ED_P2_CR,
+ ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STP);
- sc->mem_start = ISA_HOLE_VADDR(ia->ia_maddr);
+ if (bus_mem_map(bc, ia->ia_maddr, memsize, 0, &memh))
+ goto out;
+ mapped_mem = 1;
+ sc->mem_start = 0; /* offset */
sc->mem_size = memsize;
sc->mem_end = sc->mem_start + memsize;
@@ -934,34 +1003,38 @@ ed_find_3Com(sc, cf, ia)
* Initialize GA page start/stop registers. Probably only needed if
* doing DMA, but what the Hell.
*/
- outb(asicbase + ED_3COM_PSTR, sc->rec_page_start);
- outb(asicbase + ED_3COM_PSPR, sc->rec_page_stop);
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_PSTR, sc->rec_page_start);
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_PSPR, sc->rec_page_stop);
/* Set IRQ. 3c503 only allows a choice of irq 3-5 or 9. */
switch (ia->ia_irq) {
case 9:
- outb(asicbase + ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ2);
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_IDCFR,
+ ED_3COM_IDCFR_IRQ2);
break;
case 3:
- outb(asicbase + ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ3);
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_IDCFR,
+ ED_3COM_IDCFR_IRQ3);
break;
case 4:
- outb(asicbase + ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ4);
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_IDCFR,
+ ED_3COM_IDCFR_IRQ4);
break;
case 5:
- outb(asicbase + ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ5);
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_IDCFR,
+ ED_3COM_IDCFR_IRQ5);
break;
default:
printf("%s: invalid irq configuration (%d) must be 3-5 or 9 for 3c503\n",
sc->sc_dev.dv_xname, ia->ia_irq);
- return (0);
+ goto out;
}
/*
* Initialize GA configuration register. Set bank and enable shared
* mem.
*/
- outb(asicbase + ED_3COM_GACFR,
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_GACFR,
ED_3COM_GACFR_RSEL | ED_3COM_GACFR_MBS0);
/*
@@ -970,23 +1043,42 @@ ed_find_3Com(sc, cf, ia)
* shared memory is disabled. We set them to 0xffff0...allegedly the
* reset vector.
*/
- outb(asicbase + ED_3COM_VPTR2, 0xff);
- outb(asicbase + ED_3COM_VPTR1, 0xff);
- outb(asicbase + ED_3COM_VPTR0, 0x00);
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_VPTR2, 0xff);
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_VPTR1, 0xff);
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_VPTR0, 0x00);
/* Zero memory and verify that it is clear. */
- bzero(sc->mem_start, memsize);
+ for (i = 0; i < memsize; ++i)
+ bus_mem_write_1(bc, memh, sc->mem_start + i, 0);
for (i = 0; i < memsize; ++i)
- if (sc->mem_start[i]) {
+ if (bus_mem_read_1(bc, memh, sc->mem_start + i)) {
printf("%s: failed to clear shared memory at %x - check configuration\n",
- sc->sc_dev.dv_xname, kvtop(sc->mem_start + i));
- return (0);
+ sc->sc_dev.dv_xname,
+ (ia->ia_maddr + sc->mem_start + i));
+ goto out;
}
ia->ia_msize = memsize;
ia->ia_iosize = ED_3COM_IO_PORTS;
- return (1);
+ rv = 1;
+
+ out:
+ /*
+ * XXX Sould always unmap, but we can't yet.
+ * XXX Need to squish "indirect" first.
+ */
+ if (rv == 0) {
+ bus_io_unmap(bc, ioh, ED_3COM_IO_PORTS);
+ if (mapped_mem)
+ bus_mem_unmap(bc, memh, memsize);
+ } else {
+ /* XXX this is all "indirect" brokenness */
+ sc->sc_bc = bc;
+ sc->sc_ioh = ioh;
+ sc->sc_memh = memh;
+ }
+ return (rv);
}
/*
@@ -998,23 +1090,32 @@ ed_find_Novell(sc, cf, ia)
struct cfdata *cf;
struct isa_attach_args *ia;
{
+ bus_chipset_tag_t bc;
+ bus_io_handle_t ioh;
+ bus_mem_handle_t memh;
u_int memsize, n;
u_char romdata[16], isa16bit = 0, tmp;
static u_char test_pattern[32] = "THIS is A memory TEST pattern";
u_char test_buffer[32];
- int asicbase, nicbase;
+ int rv, asicbase, nicbase;
- sc->asic_base = asicbase = ia->ia_iobase + ED_NOVELL_ASIC_OFFSET;
- sc->nic_base = nicbase = ia->ia_iobase + ED_NOVELL_NIC_OFFSET;
+ bc = ia->ia_bc;
+ rv = 0;
+
+ if (bus_io_map(bc, ia->ia_iobase, ED_NOVELL_IO_PORTS, &ioh))
+ return (0);
+
+ sc->asic_base = asicbase = ED_NOVELL_ASIC_OFFSET;
+ sc->nic_base = nicbase = ED_NOVELL_NIC_OFFSET;
/* XXX - do Novell-specific probe here */
/* Reset the board. */
#ifdef GWETHER
- outb(asicbase + ED_NOVELL_RESET, 0);
+ bus_io_write_1(bc, ioh, asicbase + ED_NOVELL_RESET, 0);
delay(200);
#endif /* GWETHER */
- tmp = inb(asicbase + ED_NOVELL_RESET);
+ tmp = bus_io_read_1(bc, ioh, asicbase + ED_NOVELL_RESET);
/*
* I don't know if this is necessary; probably cruft leftover from
@@ -1024,7 +1125,7 @@ ed_find_Novell(sc, cf, ia)
* complete documentation on what the 'right' thing to do is...so we do
* the invasive thing for now. Yuck.]
*/
- outb(asicbase + ED_NOVELL_RESET, tmp);
+ bus_io_write_1(bc, ioh, asicbase + ED_NOVELL_RESET, tmp);
delay(5000);
/*
@@ -1033,13 +1134,14 @@ ed_find_Novell(sc, cf, ia)
* XXX - this makes the probe invasive! ...Done against my better
* judgement. -DLG
*/
- NIC_PUT(nicbase, ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STP);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
+ ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STP);
delay(5000);
/* Make sure that we really have an 8390 based board. */
- if (!ed_probe_generic8390(nicbase))
- return (0);
+ if (!ed_probe_generic8390(bc, ioh, nicbase))
+ goto out;
sc->vendor = ED_VENDOR_NOVELL;
sc->mem_shared = 0;
@@ -1055,17 +1157,23 @@ ed_find_Novell(sc, cf, ia)
* This prevents packets from being stored in the NIC memory when the
* readmem routine turns on the start bit in the CR.
*/
- NIC_PUT(nicbase, ED_P0_RCR, ED_RCR_MON);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RCR, ED_RCR_MON);
/* Temporarily initialize DCR for byte operations. */
- NIC_PUT(nicbase, ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS);
- NIC_PUT(nicbase, ED_P0_PSTART, 8192 >> ED_PAGE_SHIFT);
- NIC_PUT(nicbase, ED_P0_PSTOP, 16384 >> ED_PAGE_SHIFT);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_PSTART, 8192 >> ED_PAGE_SHIFT);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_PSTOP, 16384 >> ED_PAGE_SHIFT);
sc->isa16bit = 0;
/*
+ * XXX indirect brokenness, used by ed_pio{read,write}mem()
+ */
+ sc->sc_bc = bc;
+ sc->sc_ioh = ioh;
+
+ /*
* Write a test pattern in byte mode. If this fails, then there
* probably isn't any memory at 8k - which likely means that the board
* is an NE2000.
@@ -1076,10 +1184,10 @@ ed_find_Novell(sc, cf, ia)
if (bcmp(test_pattern, test_buffer, sizeof(test_pattern))) {
/* not an NE1000 - try NE2000 */
- NIC_PUT(nicbase, ED_P0_DCR,
+ NIC_PUT(bc, ioh, nicbase, ED_P0_DCR,
ED_DCR_WTS | ED_DCR_FT1 | ED_DCR_LS);
- NIC_PUT(nicbase, ED_P0_PSTART, 16384 >> ED_PAGE_SHIFT);
- NIC_PUT(nicbase, ED_P0_PSTOP, 32768 >> ED_PAGE_SHIFT);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_PSTART, 16384 >> ED_PAGE_SHIFT);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_PSTOP, 32768 >> ED_PAGE_SHIFT);
sc->isa16bit = 1;
@@ -1091,7 +1199,7 @@ ed_find_Novell(sc, cf, ia)
ed_pio_readmem(sc, 16384, test_buffer, sizeof(test_pattern));
if (bcmp(test_pattern, test_buffer, sizeof(test_pattern)))
- return (0); /* not an NE2000 either */
+ goto out; /* not an NE2000 either */
sc->type = ED_TYPE_NE2000;
sc->type_str = "NE2000";
@@ -1103,7 +1211,7 @@ ed_find_Novell(sc, cf, ia)
if (ia->ia_irq == IRQUNK) {
printf("%s: %s does not have soft configuration\n",
sc->sc_dev.dv_xname, sc->type_str);
- return (0);
+ goto out;
}
/* 8k of memory plus an additional 8k if 16-bit. */
@@ -1117,7 +1225,7 @@ ed_find_Novell(sc, cf, ia)
/* NIC memory doesn't start at zero on an NE board. */
/* The start address is tied to the bus width. */
- sc->mem_start = (caddr_t)(8192 + sc->isa16bit * 8192);
+ sc->mem_start = (8192 + sc->isa16bit * 8192);
sc->tx_page_start = memsize >> ED_PAGE_SHIFT;
#ifdef GWETHER
@@ -1148,7 +1256,7 @@ ed_find_Novell(sc, cf, ia)
if (mstart == 0) {
printf("%s: cannot find start of RAM\n",
sc->sc_dev.dv_xname);
- return (0);
+ goto out;
}
/* Search for the end of RAM. */
@@ -1204,10 +1312,25 @@ ed_find_Novell(sc, cf, ia)
#endif /* GWETHER */
/* Clear any pending interrupts that might have occurred above. */
- NIC_PUT(nicbase, ED_P0_ISR, 0xff);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_ISR, 0xff);
ia->ia_iosize = ED_NOVELL_IO_PORTS;
- return (1);
+ rv = 1;
+
+ out:
+ /*
+ * XXX Sould always unmap, but we can't yet.
+ * XXX Need to squish "indirect" first.
+ */
+ if (rv == 0)
+ bus_io_unmap(bc, ioh, ED_NOVELL_IO_PORTS);
+ else {
+ /* XXX this is all "indirect" brokenness */
+ sc->sc_bc = bc;
+ sc->sc_ioh = ioh;
+ sc->sc_memh = memh;
+ }
+ return (rv);
}
/*
@@ -1218,12 +1341,20 @@ edattach(parent, self, aux)
struct device *parent, *self;
void *aux;
{
+ bus_chipset_tag_t bc;
+ bus_io_handle_t ioh;
struct ed_softc *sc = (void *)self;
struct isa_attach_args *ia = aux;
struct cfdata *cf = sc->sc_dev.dv_cfdata;
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
int asicbase;
+ /*
+ * XXX Should re-map io and mem, but can't
+ * XXX until we squish "indirect" brokenness.
+ */
+ bc = sc->sc_bc; /* XXX */
+ ioh = sc->sc_ioh; /* XXX */
asicbase = sc->asic_base;
@@ -1232,7 +1363,7 @@ edattach(parent, self, aux)
/* Initialize ifnet structure. */
ifp->if_unit = sc->sc_dev.dv_unit;
- ifp->if_name = edcd.cd_name;
+ ifp->if_name = ed_cd.cd_name;
ifp->if_start = edstart;
ifp->if_ioctl = edioctl;
ifp->if_watchdog = edwatchdog;
@@ -1251,7 +1382,8 @@ edattach(parent, self, aux)
case ED_VENDOR_WD_SMC:
if ((sc->type & ED_WD_SOFTCONFIG) == 0)
break;
- if ((inb(asicbase + ED_WD_IRR) & ED_WD_IRR_OUT2) == 0)
+ if ((bus_io_read_1(bc, ioh, asicbase + ED_WD_IRR) &
+ ED_WD_IRR_OUT2) == 0)
ifp->if_flags |= IFF_LINK0;
break;
}
@@ -1264,7 +1396,8 @@ edattach(parent, self, aux)
ether_ifattach(ifp);
/* Print additional info when attached. */
- printf(": address %s, ", ether_sprintf(sc->sc_arpcom.ac_enaddr));
+ printf("\n%s: address %s, ", sc->sc_dev.dv_xname,
+ ether_sprintf(sc->sc_arpcom.ac_enaddr));
if (sc->type_str)
printf("type %s ", sc->type_str);
@@ -1293,8 +1426,8 @@ edattach(parent, self, aux)
sizeof(struct ether_header));
#endif
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_NET, edintr,
- sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_NET, edintr, sc, sc->sc_dev.dv_xname);
sc->sc_sh = shutdownhook_establish((void (*)(void *))edstop, sc);
}
@@ -1320,18 +1453,22 @@ void
edstop(sc)
struct ed_softc *sc;
{
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_io_handle_t ioh = sc->sc_ioh;
int nicbase = sc->nic_base;
int n = 5000;
/* Stop everything on the interface, and select page 0 registers. */
- NIC_PUT(nicbase, ED_P0_CR, sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STP);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
+ sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STP);
/*
* Wait for interface to enter stopped state, but limit # of checks to
* 'n' (about 5ms). It shouldn't even take 5us on modern DS8390's, but
* just in case it's an old one.
*/
- while (((NIC_GET(nicbase, ED_P0_ISR) & ED_ISR_RST) == 0) && --n);
+ while (((NIC_GET(bc, ioh, nicbase,
+ ED_P0_ISR) & ED_ISR_RST) == 0) && --n);
}
/*
@@ -1342,7 +1479,7 @@ void
edwatchdog(unit)
int unit;
{
- struct ed_softc *sc = edcd.cd_devs[unit];
+ struct ed_softc *sc = ed_cd.cd_devs[unit];
log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
++sc->sc_arpcom.ac_if.if_oerrors;
@@ -1357,6 +1494,8 @@ void
edinit(sc)
struct ed_softc *sc;
{
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_io_handle_t ioh = sc->sc_ioh;
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
int nicbase = sc->nic_base, asicbase = sc->asic_base;
int i;
@@ -1377,44 +1516,45 @@ edinit(sc)
sc->txb_next_tx = 0;
/* Set interface for page 0, remote DMA complete, stopped. */
- NIC_PUT(nicbase, ED_P0_CR, sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STP);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
+ sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STP);
if (sc->isa16bit) {
/*
* Set FIFO threshold to 8, No auto-init Remote DMA, byte
* order=80x86, word-wide DMA xfers,
*/
- NIC_PUT(nicbase, ED_P0_DCR,
+ NIC_PUT(bc, ioh, nicbase, ED_P0_DCR,
ED_DCR_FT1 | ED_DCR_WTS | ED_DCR_LS);
} else {
/* Same as above, but byte-wide DMA xfers. */
- NIC_PUT(nicbase, ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS);
}
/* Clear remote byte count registers. */
- NIC_PUT(nicbase, ED_P0_RBCR0, 0);
- NIC_PUT(nicbase, ED_P0_RBCR1, 0);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RBCR0, 0);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RBCR1, 0);
/* Tell RCR to do nothing for now. */
- NIC_PUT(nicbase, ED_P0_RCR, ED_RCR_MON);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RCR, ED_RCR_MON);
/* Place NIC in internal loopback mode. */
- NIC_PUT(nicbase, ED_P0_TCR, ED_TCR_LB0);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_TCR, ED_TCR_LB0);
/* Set lower bits of byte addressable framing to 0. */
if (sc->is790)
- NIC_PUT(nicbase, 0x09, 0);
+ NIC_PUT(bc, ioh, nicbase, 0x09, 0);
/* Initialize receive buffer ring. */
- NIC_PUT(nicbase, ED_P0_BNRY, sc->rec_page_start);
- NIC_PUT(nicbase, ED_P0_PSTART, sc->rec_page_start);
- NIC_PUT(nicbase, ED_P0_PSTOP, sc->rec_page_stop);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_BNRY, sc->rec_page_start);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_PSTART, sc->rec_page_start);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_PSTOP, sc->rec_page_stop);
/*
* Clear all interrupts. A '1' in each bit position clears the
* corresponding flag.
*/
- NIC_PUT(nicbase, ED_P0_ISR, 0xff);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_ISR, 0xff);
/*
* Enable the following interrupts: receive/transmit complete,
@@ -1422,31 +1562,34 @@ edinit(sc)
*
* Counter overflow and Remote DMA complete are *not* enabled.
*/
- NIC_PUT(nicbase, ED_P0_IMR,
+ NIC_PUT(bc, ioh, nicbase, ED_P0_IMR,
ED_IMR_PRXE | ED_IMR_PTXE | ED_IMR_RXEE | ED_IMR_TXEE |
ED_IMR_OVWE);
/* Program command register for page 1. */
- NIC_PUT(nicbase, ED_P0_CR, sc->cr_proto | ED_CR_PAGE_1 | ED_CR_STP);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
+ sc->cr_proto | ED_CR_PAGE_1 | ED_CR_STP);
/* Copy out our station address. */
for (i = 0; i < ETHER_ADDR_LEN; ++i)
- NIC_PUT(nicbase, ED_P1_PAR0 + i, sc->sc_arpcom.ac_enaddr[i]);
+ NIC_PUT(bc, ioh, nicbase, ED_P1_PAR0 + i,
+ sc->sc_arpcom.ac_enaddr[i]);
/* Set multicast filter on chip. */
ed_getmcaf(&sc->sc_arpcom, mcaf);
for (i = 0; i < 8; i++)
- NIC_PUT(nicbase, ED_P1_MAR0 + i, ((u_char *)mcaf)[i]);
+ NIC_PUT(bc, ioh, nicbase, ED_P1_MAR0 + i, ((u_char *)mcaf)[i]);
/*
* Set current page pointer to one page after the boundary pointer, as
* recommended in the National manual.
*/
sc->next_packet = sc->rec_page_start + 1;
- NIC_PUT(nicbase, ED_P1_CURR, sc->next_packet);
+ NIC_PUT(bc, ioh, nicbase, ED_P1_CURR, sc->next_packet);
/* Program command register for page 0. */
- NIC_PUT(nicbase, ED_P1_CR, sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STP);
+ NIC_PUT(bc, ioh, nicbase, ED_P1_CR,
+ sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STP);
i = ED_RCR_AB | ED_RCR_AM;
if (ifp->if_flags & IFF_PROMISC) {
@@ -1456,10 +1599,10 @@ edinit(sc)
*/
i |= ED_RCR_PRO | ED_RCR_AR | ED_RCR_SEP;
}
- NIC_PUT(nicbase, ED_P0_RCR, i);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RCR, i);
/* Take interface out of loopback. */
- NIC_PUT(nicbase, ED_P0_TCR, 0);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_TCR, 0);
/*
* If this is a 3Com board, the tranceiver must be software enabled
@@ -1469,24 +1612,26 @@ edinit(sc)
u_char x;
case ED_VENDOR_3COM:
if (ifp->if_flags & IFF_LINK0)
- outb(asicbase + ED_3COM_CR, 0);
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_CR, 0);
else
- outb(asicbase + ED_3COM_CR, ED_3COM_CR_XSEL);
+ bus_io_write_1(bc, ioh, asicbase + ED_3COM_CR,
+ ED_3COM_CR_XSEL);
break;
case ED_VENDOR_WD_SMC:
if ((sc->type & ED_WD_SOFTCONFIG) == 0)
break;
- x = inb(asicbase + ED_WD_IRR);
+ x = bus_io_read_1(bc, ioh, asicbase + ED_WD_IRR);
if (ifp->if_flags & IFF_LINK0)
x &= ~ED_WD_IRR_OUT2;
else
x |= ED_WD_IRR_OUT2;
- outb(asicbase + ED_WD_IRR, x);
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_IRR, x);
break;
}
/* Fire up the interface. */
- NIC_PUT(nicbase, ED_P0_CR, sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
+ sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
/* Set 'running' flag, and clear output active flag. */
ifp->if_flags |= IFF_RUNNING;
@@ -1503,6 +1648,8 @@ static inline void
ed_xmit(sc)
struct ed_softc *sc;
{
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_io_handle_t ioh = sc->sc_ioh;
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
int nicbase = sc->nic_base;
u_short len;
@@ -1510,18 +1657,19 @@ ed_xmit(sc)
len = sc->txb_len[sc->txb_next_tx];
/* Set NIC for page 0 register access. */
- NIC_PUT(nicbase, ED_P0_CR, sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
+ sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
/* Set TX buffer start page. */
- NIC_PUT(nicbase, ED_P0_TPSR, sc->tx_page_start +
+ NIC_PUT(bc, ioh, nicbase, ED_P0_TPSR, sc->tx_page_start +
sc->txb_next_tx * ED_TXBUF_SIZE);
/* Set TX length. */
- NIC_PUT(nicbase, ED_P0_TBCR0, len);
- NIC_PUT(nicbase, ED_P0_TBCR1, len >> 8);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_TBCR0, len);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_TBCR1, len >> 8);
/* Set page 0, remote DMA complete, transmit packet, and *start*. */
- NIC_PUT(nicbase, ED_P0_CR,
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
sc->cr_proto | ED_CR_PAGE_0 | ED_CR_TXP | ED_CR_STA);
/* Point to next transmit buffer slot and wrap if necessary. */
@@ -1546,11 +1694,13 @@ void
edstart(ifp)
struct ifnet *ifp;
{
- struct ed_softc *sc = edcd.cd_devs[ifp->if_unit];
+ struct ed_softc *sc = ed_cd.cd_devs[ifp->if_unit];
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_io_handle_t ioh = sc->sc_ioh;
struct mbuf *m0, *m;
- caddr_t buffer;
+ int buffer;
int asicbase = sc->asic_base;
- int len;
+ int len, i;
if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
return;
@@ -1578,7 +1728,8 @@ outloop:
#endif
/* txb_new points to next open buffer slot. */
- buffer = sc->mem_start + ((sc->txb_new * ED_TXBUF_SIZE) << ED_PAGE_SHIFT);
+ buffer = sc->mem_start +
+ ((sc->txb_new * ED_TXBUF_SIZE) << ED_PAGE_SHIFT);
if (sc->mem_shared) {
/* Special case setup for 16 bit boards... */
@@ -1590,7 +1741,8 @@ outloop:
*/
case ED_VENDOR_3COM:
if (sc->isa16bit)
- outb(asicbase + ED_3COM_GACFR,
+ bus_io_write_1(bc, ioh,
+ asicbase + ED_3COM_GACFR,
ED_3COM_GACFR_RSEL);
break;
/*
@@ -1599,17 +1751,18 @@ outloop:
*/
case ED_VENDOR_WD_SMC:
if (sc->isa16bit)
- outb(asicbase + ED_WD_LAAR,
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_LAAR,
sc->wd_laar_proto | ED_WD_LAAR_M16EN);
- outb(asicbase + ED_WD_MSR,
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_MSR,
sc->wd_msr_proto | ED_WD_MSR_MENB);
- (void) inb(0x84);
- (void) inb(0x84);
+ (void) bus_io_read_1(bc, ioh, 0x84); /* XXX */
+ (void) bus_io_read_1(bc, ioh, 0x84); /* XXX */
break;
}
for (m = m0; m != 0; m = m->m_next) {
- bcopy(mtod(m, caddr_t), buffer, m->m_len);
+ ed_shared_writemem(sc, mtod(m, caddr_t), buffer,
+ m->m_len);
buffer += m->m_len;
}
len = m0->m_pkthdr.len;
@@ -1618,17 +1771,18 @@ outloop:
switch (sc->vendor) {
case ED_VENDOR_3COM:
if (sc->isa16bit)
- outb(asicbase + ED_3COM_GACFR,
+ bus_io_write_1(bc, ioh,
+ asicbase + ED_3COM_GACFR,
ED_3COM_GACFR_RSEL | ED_3COM_GACFR_MBS0);
break;
case ED_VENDOR_WD_SMC:
- outb(asicbase + ED_WD_MSR,
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_MSR,
sc->wd_msr_proto);
if (sc->isa16bit)
- outb(asicbase + ED_WD_LAAR,
+ bus_io_write_1(bc, ioh, asicbase + ED_WD_LAAR,
sc->wd_laar_proto);
- (void) inb(0x84);
- (void) inb(0x84);
+ (void) bus_io_read_1(bc, ioh, 0x84); /* XXX */
+ (void) bus_io_read_1(bc, ioh, 0x84); /* XXX */
break;
}
} else
@@ -1657,16 +1811,19 @@ static inline void
ed_rint(sc)
struct ed_softc *sc;
{
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_io_handle_t ioh = sc->sc_ioh;
int nicbase = sc->nic_base;
u_char boundary, current;
u_short len;
u_char nlen;
struct ed_ring packet_hdr;
- caddr_t packet_ptr;
+ int packet_ptr;
loop:
/* Set NIC to page 1 registers to get 'current' pointer. */
- NIC_PUT(nicbase, ED_P0_CR, sc->cr_proto | ED_CR_PAGE_1 | ED_CR_STA);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
+ sc->cr_proto | ED_CR_PAGE_1 | ED_CR_STA);
/*
* 'sc->next_packet' is the logical beginning of the ring-buffer - i.e.
@@ -1676,12 +1833,13 @@ loop:
* until the logical beginning equals the logical end (or in other
* words, until the ring-buffer is empty).
*/
- current = NIC_GET(nicbase, ED_P1_CURR);
+ current = NIC_GET(bc, ioh, nicbase, ED_P1_CURR);
if (sc->next_packet == current)
return;
/* Set NIC to page 0 registers to update boundary register. */
- NIC_PUT(nicbase, ED_P1_CR, sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_PUT(bc, ioh, nicbase, ED_P1_CR,
+ sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
do {
/* Get pointer to this buffer's header structure. */
@@ -1693,7 +1851,8 @@ loop:
* the NIC.
*/
if (sc->mem_shared)
- packet_hdr = *(struct ed_ring *)packet_ptr;
+ ed_shared_readmem(sc, packet_ptr, (caddr_t)&packet_hdr,
+ sizeof(packet_hdr));
else
ed_pio_readmem(sc, (long)packet_ptr,
(caddr_t) &packet_hdr, sizeof(packet_hdr));
@@ -1761,7 +1920,7 @@ loop:
boundary = sc->next_packet - 1;
if (boundary < sc->rec_page_start)
boundary = sc->rec_page_stop - 1;
- NIC_PUT(nicbase, ED_P0_BNRY, boundary);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_BNRY, boundary);
} while (sc->next_packet != current);
goto loop;
@@ -1773,14 +1932,17 @@ edintr(arg)
void *arg;
{
struct ed_softc *sc = arg;
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_io_handle_t ioh = sc->sc_ioh;
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
int nicbase = sc->nic_base, asicbase = sc->asic_base;
u_char isr;
/* Set NIC to page 0 registers. */
- NIC_PUT(nicbase, ED_P0_CR, sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
+ sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
- isr = NIC_GET(nicbase, ED_P0_ISR);
+ isr = NIC_GET(bc, ioh, nicbase, ED_P0_ISR);
if (!isr)
return (0);
@@ -1791,14 +1953,15 @@ edintr(arg)
* '1' to each bit position that was set.
* (Writing a '1' *clears* the bit.)
*/
- NIC_PUT(nicbase, ED_P0_ISR, isr);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_ISR, isr);
/*
* Handle transmitter interrupts. Handle these first because
* the receiver will reset the board under some conditions.
*/
if (isr & (ED_ISR_PTX | ED_ISR_TXE)) {
- u_char collisions = NIC_GET(nicbase, ED_P0_NCR) & 0x0f;
+ u_char collisions = NIC_GET(bc, ioh, nicbase,
+ ED_P0_NCR) & 0x0f;
/*
* Check for transmit error. If a TX completed with an
@@ -1809,13 +1972,13 @@ edintr(arg)
* course, with UDP we're screwed, but this is expected
* when a network is heavily loaded.
*/
- (void) NIC_GET(nicbase, ED_P0_TSR);
+ (void) NIC_GET(bc, ioh, nicbase, ED_P0_TSR);
if (isr & ED_ISR_TXE) {
/*
* Excessive collisions (16).
*/
- if ((NIC_GET(nicbase, ED_P0_TSR) & ED_TSR_ABT)
- && (collisions == 0)) {
+ if ((NIC_GET(bc, ioh, nicbase, ED_P0_TSR) &
+ ED_TSR_ABT) && (collisions == 0)) {
/*
* When collisions total 16, the P0_NCR
* will indicate 0, and the TSR_ABT is
@@ -1907,25 +2070,32 @@ edintr(arg)
*/
if (sc->vendor == ED_VENDOR_WD_SMC) {
if (sc->isa16bit)
- outb(asicbase + ED_WD_LAAR,
- sc->wd_laar_proto | ED_WD_LAAR_M16EN);
- outb(asicbase + ED_WD_MSR,
+ bus_io_write_1(bc, ioh,
+ asicbase + ED_WD_LAAR,
+ sc->wd_laar_proto |
+ ED_WD_LAAR_M16EN);
+ bus_io_write_1(bc, ioh,
+ asicbase + ED_WD_MSR,
sc->wd_msr_proto | ED_WD_MSR_MENB);
- (void) inb(0x84);
- (void) inb(0x84);
+ /* XXX */
+ (void) bus_io_read_1(bc, ioh, 0x84);
+ (void) bus_io_read_1(bc, ioh, 0x84);
}
ed_rint(sc);
/* Disable 16-bit access. */
if (sc->vendor == ED_VENDOR_WD_SMC) {
- outb(asicbase + ED_WD_MSR,
+ bus_io_write_1(bc, ioh,
+ asicbase + ED_WD_MSR,
sc->wd_msr_proto);
if (sc->isa16bit)
- outb(asicbase + ED_WD_LAAR,
+ bus_io_write_1(bc, ioh,
+ asicbase + ED_WD_LAAR,
sc->wd_laar_proto);
- (void) inb(0x84);
- (void) inb(0x84);
+ /* XXX */
+ (void) bus_io_read_1(bc, ioh, 0x84);
+ (void) bus_io_read_1(bc, ioh, 0x84);
}
}
}
@@ -1943,7 +2113,7 @@ edintr(arg)
* set in the transmit routine, is *okay* - it is 'edge'
* triggered from low to high).
*/
- NIC_PUT(nicbase, ED_P0_CR,
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
/*
@@ -1952,12 +2122,12 @@ edintr(arg)
* otherwise - resulting in an infinite loop.
*/
if (isr & ED_ISR_CNT) {
- (void) NIC_GET(nicbase, ED_P0_CNTR0);
- (void) NIC_GET(nicbase, ED_P0_CNTR1);
- (void) NIC_GET(nicbase, ED_P0_CNTR2);
+ (void) NIC_GET(bc, ioh, nicbase, ED_P0_CNTR0);
+ (void) NIC_GET(bc, ioh, nicbase, ED_P0_CNTR1);
+ (void) NIC_GET(bc, ioh, nicbase, ED_P0_CNTR2);
}
- isr = NIC_GET(nicbase, ED_P0_ISR);
+ isr = NIC_GET(bc, ioh, nicbase, ED_P0_ISR);
if (!isr)
return (1);
}
@@ -1972,7 +2142,7 @@ edioctl(ifp, cmd, data)
u_long cmd;
caddr_t data;
{
- struct ed_softc *sc = edcd.cd_devs[ifp->if_unit];
+ struct ed_softc *sc = ed_cd.cd_devs[ifp->if_unit];
register struct ifaddr *ifa = (struct ifaddr *)data;
struct ifreq *ifr = (struct ifreq *)data;
int s, error = 0;
@@ -2081,8 +2251,7 @@ edioctl(ifp, cmd, data)
void
edread(sc, buf, len)
struct ed_softc *sc;
- caddr_t buf;
- int len;
+ int buf, len;
{
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
struct mbuf *m;
@@ -2145,29 +2314,35 @@ ed_pio_readmem(sc, src, dst, amount)
caddr_t dst;
u_short amount;
{
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_io_handle_t ioh = sc->sc_ioh;
int nicbase = sc->nic_base;
/* Select page 0 registers. */
- NIC_PUT(nicbase, ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
+ ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
/* Round up to a word. */
if (amount & 1)
++amount;
/* Set up DMA byte count. */
- NIC_PUT(nicbase, ED_P0_RBCR0, amount);
- NIC_PUT(nicbase, ED_P0_RBCR1, amount >> 8);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RBCR0, amount);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RBCR1, amount >> 8);
/* Set up source address in NIC mem. */
- NIC_PUT(nicbase, ED_P0_RSAR0, src);
- NIC_PUT(nicbase, ED_P0_RSAR1, src >> 8);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RSAR0, src);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RSAR1, src >> 8);
- NIC_PUT(nicbase, ED_P0_CR, ED_CR_RD0 | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
+ ED_CR_RD0 | ED_CR_PAGE_0 | ED_CR_STA);
if (sc->isa16bit)
- insw(sc->asic_base + ED_NOVELL_DATA, dst, amount / 2);
+ bus_io_read_multi_2(bc, ioh, sc->asic_base + ED_NOVELL_DATA,
+ dst, amount / 2);
else
- insb(sc->asic_base + ED_NOVELL_DATA, dst, amount);
+ bus_io_read_multi_1(bc, ioh, sc->asic_base + ED_NOVELL_DATA,
+ dst, amount);
}
/*
@@ -2181,30 +2356,36 @@ ed_pio_writemem(sc, src, dst, len)
u_short dst;
u_short len;
{
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_io_handle_t ioh = sc->sc_ioh;
int nicbase = sc->nic_base;
int maxwait = 100; /* about 120us */
/* Select page 0 registers. */
- NIC_PUT(nicbase, ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
+ ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
/* Reset remote DMA complete flag. */
- NIC_PUT(nicbase, ED_P0_ISR, ED_ISR_RDC);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_ISR, ED_ISR_RDC);
/* Set up DMA byte count. */
- NIC_PUT(nicbase, ED_P0_RBCR0, len);
- NIC_PUT(nicbase, ED_P0_RBCR1, len >> 8);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RBCR0, len);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RBCR1, len >> 8);
/* Set up destination address in NIC mem. */
- NIC_PUT(nicbase, ED_P0_RSAR0, dst);
- NIC_PUT(nicbase, ED_P0_RSAR1, dst >> 8);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RSAR0, dst);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RSAR1, dst >> 8);
/* Set remote DMA write. */
- NIC_PUT(nicbase, ED_P0_CR, ED_CR_RD1 | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
+ ED_CR_RD1 | ED_CR_PAGE_0 | ED_CR_STA);
if (sc->isa16bit)
- outsw(sc->asic_base + ED_NOVELL_DATA, src, len / 2);
+ bus_io_write_multi_2(bc, ioh, sc->asic_base + ED_NOVELL_DATA,
+ src, len / 2);
else
- outsb(sc->asic_base + ED_NOVELL_DATA, src, len);
+ bus_io_write_multi_1(bc, ioh, sc->asic_base + ED_NOVELL_DATA,
+ src, len);
/*
* Wait for remote DMA complete. This is necessary because on the
@@ -2213,8 +2394,8 @@ ed_pio_writemem(sc, src, dst, len)
* waiting causes really bad things to happen - like the NIC
* irrecoverably jamming the ISA bus.
*/
- while (((NIC_GET(nicbase, ED_P0_ISR) & ED_ISR_RDC) != ED_ISR_RDC) &&
- --maxwait);
+ while (((NIC_GET(bc, ioh, nicbase, ED_P0_ISR) & ED_ISR_RDC) !=
+ ED_ISR_RDC) && --maxwait);
}
/*
@@ -2227,6 +2408,8 @@ ed_pio_write_mbufs(sc, m, dst)
struct mbuf *m;
u_short dst;
{
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_io_handle_t ioh = sc->sc_ioh;
int nicbase = sc->nic_base, asicbase = sc->asic_base;
u_short len;
struct mbuf *mp;
@@ -2235,21 +2418,23 @@ ed_pio_write_mbufs(sc, m, dst)
len = m->m_pkthdr.len;
/* Select page 0 registers. */
- NIC_PUT(nicbase, ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
+ ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
/* Reset remote DMA complete flag. */
- NIC_PUT(nicbase, ED_P0_ISR, ED_ISR_RDC);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_ISR, ED_ISR_RDC);
/* Set up DMA byte count. */
- NIC_PUT(nicbase, ED_P0_RBCR0, len);
- NIC_PUT(nicbase, ED_P0_RBCR1, len >> 8);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RBCR0, len);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RBCR1, len >> 8);
/* Set up destination address in NIC mem. */
- NIC_PUT(nicbase, ED_P0_RSAR0, dst);
- NIC_PUT(nicbase, ED_P0_RSAR1, dst >> 8);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RSAR0, dst);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_RSAR1, dst >> 8);
/* Set remote DMA write. */
- NIC_PUT(nicbase, ED_P0_CR, ED_CR_RD1 | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_PUT(bc, ioh, nicbase, ED_P0_CR,
+ ED_CR_RD1 | ED_CR_PAGE_0 | ED_CR_STA);
/*
* Transfer the mbuf chain to the NIC memory.
@@ -2261,13 +2446,14 @@ ed_pio_write_mbufs(sc, m, dst)
/* NE1000s are easy. */
for (; m != 0; m = m->m_next) {
if (m->m_len) {
- outsb(asicbase + ED_NOVELL_DATA,
+ bus_io_write_multi_1(bc, ioh,
+ asicbase + ED_NOVELL_DATA,
mtod(m, u_char *), m->m_len);
}
}
} else {
/* NE2000s are a bit trickier. */
- u_char *data, savebyte[2];
+ u_int8_t *data, savebyte[2];
int len, wantbyte;
wantbyte = 0;
@@ -2275,20 +2461,23 @@ ed_pio_write_mbufs(sc, m, dst)
len = m->m_len;
if (len == 0)
continue;
- data = mtod(m, u_char *);
+ data = mtod(m, u_int8_t *);
/* Finish the last word. */
if (wantbyte) {
savebyte[1] = *data;
- outw(asicbase + ED_NOVELL_DATA,
- *(u_short *)savebyte);
+ bus_io_write_2(bc, ioh,
+ asicbase + ED_NOVELL_DATA,
+ *(u_int16_t *)savebyte);
data++;
len--;
wantbyte = 0;
}
/* Output contiguous words. */
- if (len > 1)
- outsw(asicbase + ED_NOVELL_DATA,
+ if (len > 1) {
+ bus_io_write_multi_2(bc, ioh,
+ asicbase + ED_NOVELL_DATA,
data, len >> 1);
+ }
/* Save last byte, if necessary. */
if (len & 1) {
data += len & ~1;
@@ -2299,7 +2488,8 @@ ed_pio_write_mbufs(sc, m, dst)
if (wantbyte) {
savebyte[1] = 0;
- outw(asicbase + ED_NOVELL_DATA, *(u_short *)savebyte);
+ bus_io_write_2(bc, ioh, asicbase + ED_NOVELL_DATA,
+ *(u_int16_t *)savebyte);
}
}
@@ -2310,8 +2500,8 @@ ed_pio_write_mbufs(sc, m, dst)
* waiting causes really bad things to happen - like the NIC
* irrecoverably jamming the ISA bus.
*/
- while (((NIC_GET(nicbase, ED_P0_ISR) & ED_ISR_RDC) != ED_ISR_RDC) &&
- --maxwait);
+ while (((NIC_GET(bc, ioh, nicbase, ED_P0_ISR) & ED_ISR_RDC) !=
+ ED_ISR_RDC) && --maxwait);
if (!maxwait) {
log(LOG_WARNING,
@@ -2327,10 +2517,11 @@ ed_pio_write_mbufs(sc, m, dst)
* Given a source and destination address, copy 'amount' of a packet from the
* ring buffer into a linear destination buffer. Takes into account ring-wrap.
*/
-static inline caddr_t
+static inline int
ed_ring_copy(sc, src, dst, amount)
struct ed_softc *sc;
- caddr_t src, dst;
+ int src;
+ caddr_t dst;
u_short amount;
{
u_short tmp_amount;
@@ -2341,7 +2532,7 @@ ed_ring_copy(sc, src, dst, amount)
/* Copy amount up to end of NIC memory. */
if (sc->mem_shared)
- bcopy(src, dst, tmp_amount);
+ ed_shared_readmem(sc, src, dst, tmp_amount);
else
ed_pio_readmem(sc, (long)src, dst, tmp_amount);
@@ -2351,7 +2542,7 @@ ed_ring_copy(sc, src, dst, amount)
}
if (sc->mem_shared)
- bcopy(src, dst, amount);
+ ed_shared_readmem(sc, src, dst, amount);
else
ed_pio_readmem(sc, (long)src, dst, amount);
@@ -2369,7 +2560,7 @@ ed_ring_copy(sc, src, dst, amount)
struct mbuf *
edget(sc, src, total_len)
struct ed_softc *sc;
- caddr_t src;
+ int src;
u_short total_len;
{
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
@@ -2480,3 +2671,37 @@ ed_getmcaf(ac, af)
}
ifp->if_flags &= ~IFF_ALLMULTI;
}
+
+void
+ed_shared_writemem(sc, buf, card, len)
+ struct ed_softc *sc;
+ caddr_t buf;
+ int card, len;
+{
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_mem_handle_t memh = sc->sc_memh;
+ u_int8_t *ptr = (u_int8_t *)buf;
+ int i;
+
+ /* XXX should have bus_mem_copyout_{1,2,4,8}() */
+
+ for (i = 0; i < len; ++i)
+ bus_mem_write_1(bc, memh, card + i, ptr[i]);
+}
+
+void
+ed_shared_readmem(sc, card, buf, len)
+ struct ed_softc *sc;
+ caddr_t buf;
+ int card, len;
+{
+ bus_chipset_tag_t bc = sc->sc_bc;
+ bus_mem_handle_t memh = sc->sc_memh;
+ u_int8_t *ptr = (u_int8_t *)buf;
+ int i;
+
+ /* XXX should have bus_mem_copyin_{1,2,4,8}() */
+
+ for (i = 0; i < len; ++i)
+ ptr[i] = bus_mem_read_1(bc, memh, card + i);
+}
diff --git a/sys/dev/isa/if_eg.c b/sys/dev/isa/if_eg.c
index 3ecd3de9390..6a52e9d6f55 100644
--- a/sys/dev/isa/if_eg.c
+++ b/sys/dev/isa/if_eg.c
@@ -1,4 +1,4 @@
-/* $NetBSD: if_eg.c,v 1.22 1996/01/10 18:21:52 hpeyerl Exp $ */
+/* $NetBSD: if_eg.c,v 1.24 1996/04/11 22:29:03 cgd Exp $ */
/*
* Copyright (c) 1993 Dean Huxley <dean@fsa.ca>
@@ -117,8 +117,12 @@ struct eg_softc {
int egprobe __P((struct device *, void *, void *));
void egattach __P((struct device *, struct device *, void *));
-struct cfdriver egcd = {
- NULL, "eg", egprobe, egattach, DV_IFNET, sizeof(struct eg_softc)
+struct cfattach eg_ca = {
+ sizeof(struct eg_softc), egprobe, egattach
+};
+
+struct cfdriver eg_cd = {
+ NULL, "eg", DV_IFNET
};
int egintr __P((void *));
@@ -398,7 +402,7 @@ egattach(parent, self, aux)
/* Initialize ifnet structure. */
ifp->if_unit = sc->sc_dev.dv_unit;
- ifp->if_name = egcd.cd_name;
+ ifp->if_name = eg_cd.cd_name;
ifp->if_start = egstart;
ifp->if_ioctl = egioctl;
ifp->if_watchdog = egwatchdog;
@@ -412,8 +416,8 @@ egattach(parent, self, aux)
bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
#endif
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_NET, egintr,
- sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_NET, egintr, sc, sc->sc_dev.dv_xname);
}
void
@@ -490,7 +494,7 @@ void
egstart(ifp)
struct ifnet *ifp;
{
- register struct eg_softc *sc = egcd.cd_devs[ifp->if_unit];
+ register struct eg_softc *sc = eg_cd.cd_devs[ifp->if_unit];
struct mbuf *m0, *m;
caddr_t buffer;
int len;
@@ -729,7 +733,7 @@ egioctl(ifp, cmd, data)
u_long cmd;
caddr_t data;
{
- struct eg_softc *sc = egcd.cd_devs[ifp->if_unit];
+ struct eg_softc *sc = eg_cd.cd_devs[ifp->if_unit];
struct ifaddr *ifa = (struct ifaddr *)data;
struct ifreq *ifr = (struct ifreq *)data;
int s, error = 0;
@@ -826,7 +830,7 @@ void
egwatchdog(unit)
int unit;
{
- struct eg_softc *sc = egcd.cd_devs[unit];
+ struct eg_softc *sc = eg_cd.cd_devs[unit];
log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
sc->sc_arpcom.ac_if.if_oerrors++;
diff --git a/sys/dev/isa/if_el.c b/sys/dev/isa/if_el.c
index b7f889b7c22..ea751159744 100644
--- a/sys/dev/isa/if_el.c
+++ b/sys/dev/isa/if_el.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: if_el.c,v 1.6 1996/03/20 01:00:48 mickey Exp $ */
-/* $NetBSD: if_el.c,v 1.34 1995/12/24 02:31:25 mycroft Exp $ */
+/* $OpenBSD: if_el.c,v 1.7 1996/04/21 22:23:48 deraadt Exp $ */
+/* $NetBSD: if_el.c,v 1.36 1996/04/11 22:29:07 cgd Exp $ */
/*
* Copyright (c) 1994, Matthew E. Kimmel. Permission is hereby granted
@@ -97,9 +97,12 @@ static inline void el_hardreset __P((struct el_softc *));
int elprobe __P((struct device *, void *, void *));
void elattach __P((struct device *, struct device *, void *));
-/* isa_driver structure for autoconf */
-struct cfdriver elcd = {
- NULL, "el", elprobe, elattach, DV_IFNET, sizeof(struct el_softc)
+struct cfattach el_ca = {
+ sizeof(struct el_softc), elprobe, elattach
+};
+
+struct cfdriver el_cd = {
+ NULL, "el", DV_IFNET
};
/*
@@ -186,7 +189,7 @@ elattach(parent, self, aux)
/* Initialize ifnet structure. */
ifp->if_unit = sc->sc_dev.dv_unit;
- ifp->if_name = elcd.cd_name;
+ ifp->if_name = el_cd.cd_name;
ifp->if_start = elstart;
ifp->if_ioctl = elioctl;
ifp->if_watchdog = elwatchdog;
@@ -206,8 +209,8 @@ elattach(parent, self, aux)
bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
#endif
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_NET, elintr,
- sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_NET, elintr, sc, sc->sc_dev.dv_xname);
dprintf(("elattach() finished.\n"));
}
@@ -304,7 +307,7 @@ void
elstart(ifp)
struct ifnet *ifp;
{
- struct el_softc *sc = elcd.cd_devs[ifp->if_unit];
+ struct el_softc *sc = el_cd.cd_devs[ifp->if_unit];
int iobase = sc->sc_iobase;
struct mbuf *m, *m0;
int s, i, off, retries;
@@ -616,7 +619,7 @@ elioctl(ifp, cmd, data)
u_long cmd;
caddr_t data;
{
- struct el_softc *sc = elcd.cd_devs[ifp->if_unit];
+ struct el_softc *sc = el_cd.cd_devs[ifp->if_unit];
struct ifaddr *ifa = (struct ifaddr *)data;
struct ifreq *ifr = (struct ifreq *)data;
int s, error = 0;
@@ -700,7 +703,7 @@ void
elwatchdog(unit)
int unit;
{
- struct el_softc *sc = elcd.cd_devs[unit];
+ struct el_softc *sc = el_cd.cd_devs[unit];
log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
sc->sc_arpcom.ac_if.if_oerrors++;
diff --git a/sys/dev/isa/if_ep.c b/sys/dev/isa/if_ep.c
index 887bb575548..4102ad294e4 100644
--- a/sys/dev/isa/if_ep.c
+++ b/sys/dev/isa/if_ep.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: if_ep.c,v 1.10 1996/04/18 23:47:40 niklas Exp $ */
-/* $NetBSD: if_ep.c,v 1.87 1996/02/19 20:18:40 christos Exp $ */
+/* $OpenBSD: if_ep.c,v 1.11 1996/04/21 22:23:52 deraadt Exp $ */
+/* $NetBSD: if_ep.c,v 1.90 1996/04/11 22:29:15 cgd Exp $ */
/*
* Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca>
@@ -31,7 +31,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "pcmciabus.h"
+/*#include "pcmciabus.h"*/
#include "bpfilter.h"
#include <sys/param.h>
@@ -119,8 +119,17 @@ struct ep_softc {
static int epprobe __P((struct device *, void *, void *));
static void epattach __P((struct device *, struct device *, void *));
-struct cfdriver epcd = {
- NULL, "ep", epprobe, epattach, DV_IFNET, sizeof(struct ep_softc)
+/* XXX the following two structs should be different. */
+struct cfattach ep_isa_ca = {
+ sizeof(struct ep_softc), epprobe, epattach
+};
+
+struct cfattach ep_pci_ca = {
+ sizeof(struct ep_softc), epprobe, epattach
+};
+
+struct cfdriver ep_cd = {
+ NULL, "ep", DV_IFNET
};
int epintr __P((void *));
@@ -326,9 +335,9 @@ epprobe(parent, match, aux)
int k, k2;
#if NPCI > 0
- extern struct cfdriver pcicd;
+ extern struct cfdriver pci_cd;
- if (parent->dv_cfdata->cf_driver == &pcicd) {
+ if (parent->dv_cfdata->cf_driver == &pci_cd) {
struct pci_attach_args *pa = (struct pci_attach_args *) aux;
if (PCI_VENDORID(pa->pa_id) != PCI_VENDOR_3COM)
@@ -497,7 +506,7 @@ epconfig(sc, conn)
printf(" address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
ifp->if_unit = sc->sc_dev.dv_unit;
- ifp->if_name = epcd.cd_name;
+ ifp->if_name = ep_cd.cd_name;
ifp->if_start = epstart;
ifp->if_ioctl = epioctl;
ifp->if_watchdog = epwatchdog;
@@ -523,9 +532,9 @@ epattach(parent, self, aux)
struct ep_softc *sc = (void *)self;
u_short conn = 0;
#if NPCI > 0
- extern struct cfdriver pcicd;
+ extern struct cfdriver pci_cd;
- if (parent->dv_cfdata->cf_driver == &pcicd) {
+ if (parent->dv_cfdata->cf_driver == &pci_cd) {
struct pci_attach_args *pa = aux;
int iobase;
u_short i;
@@ -536,7 +545,7 @@ epattach(parent, self, aux)
}
sc->bustype = EP_BUS_PCI;
sc->ep_iobase = iobase; /* & 0xfffffff0 */
- i = pci_conf_read(pa->pa_tag, PCI_CONN);
+ i = pci_conf_read(pa->pa_bc, pa->pa_tag, PCI_CONN);
/*
* Bits 13,12,9 of the isa adapter are the same as bits
@@ -565,16 +574,15 @@ epattach(parent, self, aux)
#if NPCI > 0
- if (parent->dv_cfdata->cf_driver == &pcicd) {
+ if (parent->dv_cfdata->cf_driver == &pci_cd) {
struct pci_attach_args *pa = aux;
- pci_conf_write(pa->pa_tag, PCI_COMMAND_STATUS_REG,
- pci_conf_read(pa->pa_tag,
+ pci_conf_write(pa->pa_bc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
+ pci_conf_read(pa->pa_bc, pa->pa_tag,
PCI_COMMAND_STATUS_REG) |
PCI_COMMAND_MASTER_ENABLE);
- sc->sc_ih = pci_map_int(pa->pa_tag, IPL_NET, epintr, sc,
- sc->sc_dev.dv_xname);
+ sc->sc_ih = pci_map_int(pa->pa_tag, IPL_NET, epintr, sc);
if (sc->sc_ih == NULL) {
printf("%s: couldn't map interrupt\n",
sc->sc_dev.dv_xname);
@@ -586,8 +594,8 @@ epattach(parent, self, aux)
#endif
{
struct isa_attach_args *ia = aux;
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_NET,
- epintr, sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq,
+ IST_EDGE, IPL_NET, epintr, sc, sc->sc_dev.dv_xname);
}
}
@@ -721,7 +729,7 @@ void
epstart(ifp)
struct ifnet *ifp;
{
- register struct ep_softc *sc = epcd.cd_devs[ifp->if_unit];
+ register struct ep_softc *sc = ep_cd.cd_devs[ifp->if_unit];
struct mbuf *m, *m0;
int sh, len, pad;
@@ -1205,7 +1213,7 @@ epioctl(ifp, cmd, data)
u_long cmd;
caddr_t data;
{
- struct ep_softc *sc = epcd.cd_devs[ifp->if_unit];
+ struct ep_softc *sc = ep_cd.cd_devs[ifp->if_unit];
struct ifaddr *ifa = (struct ifaddr *)data;
struct ifreq *ifr = (struct ifreq *)data;
int s, error = 0;
@@ -1315,7 +1323,7 @@ void
epwatchdog(unit)
int unit;
{
- struct ep_softc *sc = epcd.cd_devs[unit];
+ struct ep_softc *sc = ep_cd.cd_devs[unit];
log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
++sc->sc_arpcom.ac_if.if_oerrors;
diff --git a/sys/dev/isa/if_fe.c b/sys/dev/isa/if_fe.c
index 6201923066a..3c8a4f7ae91 100644
--- a/sys/dev/isa/if_fe.c
+++ b/sys/dev/isa/if_fe.c
@@ -227,8 +227,12 @@ void fe_loadmar __P((struct fe_softc *));
void fe_dump __P((int, struct fe_softc *));
#endif
-struct cfdriver fecd = {
- NULL, "fe", feprobe, feattach, DV_IFNET, sizeof(struct fe_softc)
+struct cfattach fe_ca = {
+ sizeof(struct fe_softc), feprobe, feattach
+};
+
+struct cfdriver fe_cd = {
+ NULL, "fe", DV_IFNET
};
/* Ethernet constants. To be defined in if_ehter.h? FIXME. */
@@ -993,7 +997,7 @@ feattach(parent, self, aux)
/* Initialize ifnet structure. */
ifp->if_unit = sc->sc_dev.dv_unit;
- ifp->if_name = fecd.cd_name;
+ ifp->if_name = fe_cd.cd_name;
ifp->if_start = fe_start;
ifp->if_ioctl = fe_ioctl;
ifp->if_watchdog = fe_watchdog;
@@ -1124,8 +1128,8 @@ feattach(parent, self, aux)
bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
#endif
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_NET, feintr,
- sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_NET, feintr, sc, sc->sc_dev.dv_xname);
}
/*
@@ -1198,7 +1202,7 @@ void
fe_watchdog(unit)
int unit;
{
- struct fe_softc *sc = fecd.cd_devs[unit];
+ struct fe_softc *sc = fe_cd.cd_devs[unit];
log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
#if FE_DEBUG >= 3
@@ -1420,7 +1424,7 @@ void
fe_start(ifp)
struct ifnet *ifp;
{
- struct fe_softc *sc = fecd.cd_devs[ifp->if_unit];
+ struct fe_softc *sc = fe_cd.cd_devs[ifp->if_unit];
struct mbuf *m;
#if FE_DEBUG >= 1
@@ -1679,7 +1683,9 @@ fe_tint(sc, tstat)
*/
ifp->if_opackets += sc->txb_sched;
sc->txb_sched = 0;
+ }
+ if (sc->txb_sched == 0) {
/*
* The transmitter is no more active.
* Reset output active flag and watchdog timer.
@@ -1919,7 +1925,7 @@ fe_ioctl(ifp, command, data)
u_long command;
caddr_t data;
{
- struct fe_softc *sc = fecd.cd_devs[ifp->if_unit];
+ struct fe_softc *sc = fe_cd.cd_devs[ifp->if_unit];
register struct ifaddr *ifa = (struct ifaddr *)data;
struct ifreq *ifr = (struct ifreq *)data;
int s, error = 0;
diff --git a/sys/dev/isa/if_ie.c b/sys/dev/isa/if_ie.c
index 033d71b7bf3..49cd7b27064 100644
--- a/sys/dev/isa/if_ie.c
+++ b/sys/dev/isa/if_ie.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: if_ie.c,v 1.6 1996/03/20 01:00:52 mickey Exp $ */
-/* $NetBSD: if_ie.c,v 1.45 1995/12/24 02:31:33 mycroft Exp $ */
+/* $OpenBSD: if_ie.c,v 1.7 1996/04/21 22:24:03 deraadt Exp $ */
+/* $NetBSD: if_ie.c,v 1.47 1996/04/11 22:29:27 cgd Exp $ */
/*-
* Copyright (c) 1993, 1994, 1995 Charles Hannum.
@@ -310,8 +310,12 @@ int in_ietint = 0;
int ieprobe __P((struct device *, void *, void *));
void ieattach __P((struct device *, struct device *, void *));
-struct cfdriver iecd = {
- NULL, "ie", ieprobe, ieattach, DV_IFNET, sizeof(struct ie_softc)
+struct cfattach ie_ca = {
+ sizeof(struct ie_softc), ieprobe, ieattach
+};
+
+struct cfdriver ie_cd = {
+ NULL, "ie", DV_IFNET
};
#define MK_24(base, ptr) ((caddr_t)((u_long)ptr - (u_long)base))
@@ -757,7 +761,7 @@ ieattach(parent, self, aux)
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
ifp->if_unit = sc->sc_dev.dv_unit;
- ifp->if_name = iecd.cd_name;
+ ifp->if_name = ie_cd.cd_name;
ifp->if_start = iestart;
ifp->if_ioctl = ieioctl;
ifp->if_watchdog = iewatchdog;
@@ -777,8 +781,8 @@ ieattach(parent, self, aux)
sizeof(struct ether_header));
#endif
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_NET, ieintr,
- sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_NET, ieintr, sc, sc->sc_dev.dv_xname);
}
/*
@@ -789,7 +793,7 @@ void
iewatchdog(unit)
int unit;
{
- struct ie_softc *sc = iecd.cd_devs[unit];
+ struct ie_softc *sc = ie_cd.cd_devs[unit];
log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
++sc->sc_arpcom.ac_if.if_oerrors;
@@ -1441,7 +1445,7 @@ void
iestart(ifp)
struct ifnet *ifp;
{
- struct ie_softc *sc = iecd.cd_devs[ifp->if_unit];
+ struct ie_softc *sc = ie_cd.cd_devs[ifp->if_unit];
struct mbuf *m0, *m;
u_char *buffer;
u_short len;
@@ -2111,7 +2115,7 @@ ieioctl(ifp, cmd, data)
u_long cmd;
caddr_t data;
{
- struct ie_softc *sc = iecd.cd_devs[ifp->if_unit];
+ struct ie_softc *sc = ie_cd.cd_devs[ifp->if_unit];
struct ifaddr *ifa = (struct ifaddr *)data;
struct ifreq *ifr = (struct ifreq *)data;
int s, error = 0;
diff --git a/sys/dev/isa/if_le.c b/sys/dev/isa/if_le.c
index 61c47031e92..b6016b092cd 100644
--- a/sys/dev/isa/if_le.c
+++ b/sys/dev/isa/if_le.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: if_le.c,v 1.7 1996/03/20 01:00:54 mickey Exp $ */
-/* $NetBSD: if_le.c,v 1.38 1995/12/24 02:31:35 mycroft Exp $ */
+/* $OpenBSD: if_le.c,v 1.8 1996/04/21 22:24:09 deraadt Exp $ */
+/* $NetBSD: if_le.c,v 1.41 1996/04/11 22:29:34 cgd Exp $ */
/*-
* Copyright (c) 1995 Charles M. Hannum. All rights reserved.
@@ -83,7 +83,7 @@
char *card_type[] = {"unknown", "BICC Isolan", "NE2100", "DEPCA", "PCnet-ISA", "PCnet-PCI"};
-#define LE_SOFTC(unit) lecd.cd_devs[unit]
+#define LE_SOFTC(unit) le_cd.cd_devs[unit]
#define LE_DELAY(x) delay(x)
int leprobe __P((struct device *, void *, void *));
@@ -96,8 +96,17 @@ int leintr __P((void *));
int leintredge __P((void *));
void leshutdown __P((void *));
-struct cfdriver lecd = {
- NULL, "le", leprobe, leattach, DV_IFNET, sizeof(struct le_softc)
+/* XXX the following two structs should be different. */
+struct cfattach le_isa_ca = {
+ sizeof(struct le_softc), leprobe, leattach
+};
+
+struct cfattach le_pci_ca = {
+ sizeof(struct le_softc), leprobe, leattach
+};
+
+struct cfdriver le_cd = {
+ NULL, "le", DV_IFNET
};
integrate void
@@ -128,10 +137,10 @@ leprobe(parent, match, aux)
void *match, *aux;
{
struct le_softc *sc = match;
- extern struct cfdriver isacd, pcicd;
+ extern struct cfdriver isa_cd, pci_cd;
#if NISA > 0
- if (parent->dv_cfdata->cf_driver == &isacd) {
+ if (parent->dv_cfdata->cf_driver == &isa_cd) {
struct isa_attach_args *ia = aux;
if (bicc_probe(sc, ia))
@@ -144,7 +153,7 @@ leprobe(parent, match, aux)
#endif
#if NPCI > 0
- if (parent->dv_cfdata->cf_driver == &pcicd) {
+ if (parent->dv_cfdata->cf_driver == &pci_cd) {
struct pci_attach_args *pa = aux;
if (pa->pa_id == 0x20001022)
@@ -313,10 +322,10 @@ leattach(parent, self, aux)
void *aux;
{
struct le_softc *sc = (void *)self;
- extern struct cfdriver isacd, pcicd;
+ extern struct cfdriver isa_cd, pci_cd;
#if NPCI > 0
- if (parent->dv_cfdata->cf_driver == &pcicd) {
+ if (parent->dv_cfdata->cf_driver == &pci_cd) {
struct pci_attach_args *pa = aux;
int iobase;
@@ -386,33 +395,34 @@ leattach(parent, self, aux)
sc->sc_copyfrombuf = copyfrombuf_contig;
sc->sc_zerobuf = zerobuf_contig;
- sc->sc_arpcom.ac_if.if_name = lecd.cd_name;
+ sc->sc_arpcom.ac_if.if_name = le_cd.cd_name;
leconfig(sc);
printf("%s: type %s\n", sc->sc_dev.dv_xname, card_type[sc->sc_card]);
#if NISA > 0
- if (parent->dv_cfdata->cf_driver == &isacd) {
+ if (parent->dv_cfdata->cf_driver == &isa_cd) {
struct isa_attach_args *ia = aux;
if (ia->ia_drq != DRQUNK)
isa_dmacascade(ia->ia_drq);
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_NET,
- leintredge, sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_NET, leintredge, sc, sc->sc_dev.dv_xname);
}
#endif
#if NPCI > 0
- if (parent->dv_cfdata->cf_driver == &pcicd) {
+ if (parent->dv_cfdata->cf_driver == &pci_cd) {
struct pci_attach_args *pa = aux;
+ pcireg_t csr;
- pci_conf_write(pa->pa_tag, PCI_COMMAND_STATUS_REG,
- pci_conf_read(pa->pa_tag, PCI_COMMAND_STATUS_REG) |
- PCI_COMMAND_MASTER_ENABLE);
+ csr = pci_conf_read(pa->pa_bc, pa->pa_tag,
+ PCI_COMMAND_STATUS_REG);
+ pci_conf_write(pa->pa_bc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
+ csr | PCI_COMMAND_MASTER_ENABLE);
- sc->sc_ih = pci_map_int(pa->pa_tag, IPL_NET, leintr, sc,
- sc->sc_dev.dv_xname);
+ sc->sc_ih = pci_map_int(pa->pa_tag, IPL_NET, leintr, sc);
}
#endif
diff --git a/sys/dev/isa/isa.c b/sys/dev/isa/isa.c
index 5f55324d434..fa14cc051ff 100644
--- a/sys/dev/isa/isa.c
+++ b/sys/dev/isa/isa.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: isa.c,v 1.5 1996/04/18 23:47:41 niklas Exp $ */
-/* $NetBSD: isa.c,v 1.78 1996/03/08 20:36:21 cgd Exp $ */
+/* $OpenBSD: isa.c,v 1.6 1996/04/21 22:24:12 deraadt Exp $ */
+/* $NetBSD: isa.c,v 1.80 1996/04/11 22:25:44 cgd Exp $ */
/*-
* Copyright (c) 1993, 1994 Charles Hannum. All rights reserved.
@@ -36,6 +36,9 @@
#include <sys/conf.h>
#include <sys/malloc.h>
#include <sys/device.h>
+#ifndef i386 /* XXX */
+#include <machine/intr.h>
+#endif /* XXX */
#include <dev/isa/isareg.h>
#include <dev/isa/isavar.h>
@@ -43,8 +46,12 @@
int isamatch __P((struct device *, void *, void *));
void isaattach __P((struct device *, struct device *, void *));
-struct cfdriver isacd = {
- NULL, "isa", isamatch, isaattach, DV_DULL, sizeof(struct isa_softc), 1
+struct cfattach isa_ca = {
+ sizeof(struct isa_softc), isamatch, isaattach
+};
+
+struct cfdriver isa_cd = {
+ NULL, "isa", DV_DULL, 1
};
int
@@ -71,9 +78,11 @@ isaattach(parent, self, aux)
struct isa_softc *sc = (struct isa_softc *)self;
struct isabus_attach_args *iba = aux;
+ isa_attach_hook(parent, self, iba);
printf("\n");
sc->sc_bc = iba->iba_bc;
+ sc->sc_ic = iba->iba_ic;
TAILQ_INIT(&sc->sc_subdevs);
config_scan(isascan, self);
@@ -115,6 +124,7 @@ isascan(parent, match)
panic("clone devices not supported on ISA bus");
ia.ia_bc = sc->sc_bc;
+ ia.ia_ic = sc->sc_ic;
ia.ia_iobase = cf->cf_loc[0];
ia.ia_iosize = 0x666;
ia.ia_maddr = cf->cf_loc[2];
@@ -122,7 +132,7 @@ isascan(parent, match)
ia.ia_irq = cf->cf_loc[4] == 2 ? 9 : cf->cf_loc[4];
ia.ia_drq = cf->cf_loc[5];
- if ((*cf->cf_driver->cd_match)(parent, dev, &ia) > 0)
+ if ((*cf->cf_attach->ca_match)(parent, dev, &ia) > 0)
config_attach(parent, dev, &ia, isaprint);
else
free(dev, M_DEVBUF);
diff --git a/sys/dev/isa/isadma.c b/sys/dev/isa/isadma.c
index 37a0795745a..a1d5778dda8 100644
--- a/sys/dev/isa/isadma.c
+++ b/sys/dev/isa/isadma.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: isadma.c,v 1.3 1996/04/18 23:47:41 niklas Exp $ */
-/* $NetBSD: isadma.c,v 1.17 1996/03/01 04:35:27 mycroft Exp $ */
+/* $OpenBSD: isadma.c,v 1.4 1996/04/21 22:24:14 deraadt Exp $ */
+/* $NetBSD: isadma.c,v 1.18 1996/03/31 20:51:43 mycroft Exp $ */
#include <sys/param.h>
#include <sys/systm.h>
@@ -28,8 +28,9 @@ static struct dma_info dma_info[8];
static u_int8_t dma_finished;
/* high byte of address is stored in this port for i-th dma channel */
-static int dmapageport[8] = {
- 0x87, 0x83, 0x81, 0x82, 0x8f, 0x8b, 0x89, 0x8a
+static int dmapageport[2][4] = {
+ {0x87, 0x83, 0x81, 0x82},
+ {0x8f, 0x8b, 0x89, 0x8a}
};
static u_int8_t dmamode[4] = {
@@ -123,7 +124,7 @@ isadma_start(addr, nbytes, chan, flags)
/* send start address */
waport = DMA1_CHN(chan);
- outb(dmapageport[chan], di->phys[0].addr>>16);
+ outb(dmapageport[0][chan], di->phys[0].addr>>16);
outb(waport, di->phys[0].addr);
outb(waport, di->phys[0].addr>>8);
@@ -144,7 +145,7 @@ isadma_start(addr, nbytes, chan, flags)
/* send start address */
waport = DMA2_CHN(chan & 3);
- outb(dmapageport[chan], di->phys[0].addr>>16);
+ outb(dmapageport[1][chan], di->phys[0].addr>>16);
outb(waport, di->phys[0].addr>>1);
outb(waport, di->phys[0].addr>>9);
diff --git a/sys/dev/isa/isavar.h b/sys/dev/isa/isavar.h
index 551375712f0..78b950248a9 100644
--- a/sys/dev/isa/isavar.h
+++ b/sys/dev/isa/isavar.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: isavar.h,v 1.7 1996/04/18 23:47:43 niklas Exp $ */
-/* $NetBSD: isavar.h,v 1.20 1996/03/16 02:00:43 cgd Exp $ */
+/* $OpenBSD: isavar.h,v 1.8 1996/04/21 22:24:16 deraadt Exp $ */
+/* $NetBSD: isavar.h,v 1.21 1996/04/11 22:20:50 cgd Exp $ */
/*
* Copyright (c) 1995 Chris G. Demetriou
@@ -47,19 +47,36 @@
#include <sys/queue.h>
#include <machine/bus.h>
+/*
+ * Structures and definitions needed by the machine-dependent header.
+ */
+struct isabus_attach_args;
+
+#if (alpha + i386 != 1)
+ERROR: COMPILING FOR UNSUPPORTED MACHINE, OR MORE THAN ONE.
+#endif
+#if alpha
+#include <alpha/isa/isa_machdep.h>
+#endif
+#if i386
+#include <i386/isa/isa_machdep.h>
+#endif
+
/*
* ISA bus attach arguments
*/
struct isabus_attach_args {
char *iba_busname; /* XXX should be common */
bus_chipset_tag_t iba_bc; /* XXX should be common */
+ isa_chipset_tag_t iba_ic;
};
/*
* ISA driver attach arguments
*/
struct isa_attach_args {
- bus_chipset_tag_t ia_bc; /* bus chipset tag */
+ bus_chipset_tag_t ia_bc;
+ isa_chipset_tag_t ia_ic;
int ia_iobase; /* base i/o address */
int ia_iosize; /* span of ports used */
@@ -92,7 +109,8 @@ struct isa_softc {
TAILQ_HEAD(, isadev)
sc_subdevs; /* list of all children */
- bus_chipset_tag_t sc_bc; /* bus chipset tag */
+ bus_chipset_tag_t sc_bc;
+ isa_chipset_tag_t sc_ic;
};
#define cf_iobase cf_loc[0]
@@ -120,9 +138,6 @@ struct isa_softc {
/* ISA interrupt sharing types */
void isascan __P((struct device *parent, void *match));
-void *isa_intr_establish __P((int intr, int type, int level,
- int (*ih_fun)(void *), void *ih_arg, char *));
-void isa_intr_disestablish __P((void *handler));
char *isa_intr_typename __P((int type));
#ifdef NEWCONFIG
diff --git a/sys/dev/isa/lpt.c b/sys/dev/isa/lpt.c
index 3bcfd6ad241..24499ddbc45 100644
--- a/sys/dev/isa/lpt.c
+++ b/sys/dev/isa/lpt.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: lpt.c,v 1.8 1996/04/18 23:47:43 niklas Exp $ */
-/* $NetBSD: lpt.c,v 1.32 1996/03/08 22:17:58 cgd Exp $ */
+/* $OpenBSD: lpt.c,v 1.9 1996/04/21 22:24:18 deraadt Exp $ */
+/* $NetBSD: lpt.c,v 1.37 1996/04/11 22:29:37 cgd Exp $ */
/*
* Copyright (c) 1993, 1994 Charles Hannum.
@@ -65,7 +65,11 @@
#include <sys/device.h>
#include <sys/syslog.h>
-#include <machine/cpu.h>
+#ifdef i386 /* XXX */
+#include <machine/cpu.h> /* XXX */
+#else /* XXX */
+#include <machine/intr.h>
+#endif /* XXX */
#include <machine/bus.h>
#include <dev/isa/isavar.h>
@@ -112,8 +116,12 @@ int lptprobe __P((struct device *, void *, void *));
void lptattach __P((struct device *, struct device *, void *));
int lptintr __P((void *));
-struct cfdriver lptcd = {
- NULL, "lpt", lptprobe, lptattach, DV_TTY, sizeof(struct lpt_softc)
+struct cfattach lpt_ca = {
+ sizeof(struct lpt_softc), lptprobe, lptattach
+};
+
+struct cfdriver lpt_cd = {
+ NULL, "lpt", DV_TTY
};
#define LPTUNIT(s) (minor(s) & 0x1f)
@@ -128,15 +136,19 @@ static int not_ready __P((u_char, struct lpt_softc *));
static void lptwakeup __P((void *arg));
static int pushbytes __P((struct lpt_softc *));
+int lpt_port_test __P((bus_chipset_tag_t, bus_io_handle_t, bus_io_addr_t,
+ bus_io_size_t, u_char, u_char));
+
/*
* Internal routine to lptprobe to do port tests of one byte value.
*/
int
-lpt_port_test(ioh, off, data, mask, base)
+lpt_port_test(bc, ioh, base, off, data, mask)
+ bus_chipset_tag_t bc;
bus_io_handle_t ioh;
- size_t off;
+ bus_io_addr_t base;
+ bus_io_size_t off;
u_char data, mask;
- u_long base;
{
int timeout;
u_char temp;
@@ -202,22 +214,22 @@ lptprobe(parent, match, aux)
mask = 0xff;
data = 0x55; /* Alternating zeros */
- if (!lpt_port_test(ioh, lpt_data, data, mask, base))
+ if (!lpt_port_test(bc, ioh, base, lpt_data, data, mask))
ABORT;
data = 0xaa; /* Alternating ones */
- if (!lpt_port_test(ioh, lpt_data, data, mask, base))
+ if (!lpt_port_test(bc, ioh, base, lpt_data, data, mask))
ABORT;
for (i = 0; i < CHAR_BIT; i++) { /* Walking zero */
data = ~(1 << i);
- if (!lpt_port_test(ioh, lpt_data, data, mask, base))
+ if (!lpt_port_test(bc, ioh, base, lpt_data, data, mask))
ABORT;
}
for (i = 0; i < CHAR_BIT; i++) { /* Walking one */
data = (1 << i);
- if (!lpt_port_test(ioh, lpt_data, data, mask, base))
+ if (!lpt_port_test(bc, ioh, base, lpt_data, data, mask))
ABORT;
}
@@ -261,8 +273,8 @@ lptattach(parent, self, aux)
bus_io_write_1(bc, ioh, lpt_control, LPC_NINIT);
if (ia->ia_irq != IRQUNK)
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_NONE,
- lptintr, sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_TTY, lptintr, sc, sc->sc_dev.dv_xname);
}
/*
@@ -282,9 +294,9 @@ lptopen(dev, flag)
int error;
int spin;
- if (unit >= lptcd.cd_ndevs)
+ if (unit >= lpt_cd.cd_ndevs)
return ENXIO;
- sc = lptcd.cd_devs[unit];
+ sc = lpt_cd.cd_devs[unit];
if (!sc)
return ENXIO;
@@ -386,12 +398,13 @@ lptwakeup(arg)
/*
* Close the device, and free the local line buffer.
*/
+int
lptclose(dev, flag)
dev_t dev;
int flag;
{
int unit = LPTUNIT(dev);
- struct lpt_softc *sc = lptcd.cd_devs[unit];
+ struct lpt_softc *sc = lpt_cd.cd_devs[unit];
bus_chipset_tag_t bc = sc->sc_bc;
bus_io_handle_t ioh = sc->sc_ioh;
@@ -476,11 +489,12 @@ pushbytes(sc)
* Copy a line from user space to a local buffer, then call putc to get the
* chars moved to the output queue.
*/
+int
lptwrite(dev, uio)
dev_t dev;
struct uio *uio;
{
- struct lpt_softc *sc = lptcd.cd_devs[LPTUNIT(dev)];
+ struct lpt_softc *sc = lpt_cd.cd_devs[LPTUNIT(dev)];
size_t n;
int error = 0;
diff --git a/sys/dev/isa/mcd.c b/sys/dev/isa/mcd.c
index 8fce277ec1d..cf5eeb3a812 100644
--- a/sys/dev/isa/mcd.c
+++ b/sys/dev/isa/mcd.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: mcd.c,v 1.8 1996/03/20 01:00:56 mickey Exp $ */
-/* $NetBSD: mcd.c,v 1.45 1996/01/30 18:28:05 thorpej Exp $ */
+/* $OpenBSD: mcd.c,v 1.9 1996/04/21 22:24:21 deraadt Exp $ */
+/* $NetBSD: mcd.c,v 1.47 1996/04/11 22:29:43 cgd Exp $ */
/*
* Copyright (c) 1993, 1994, 1995 Charles M. Hannum. All rights reserved.
@@ -178,8 +178,12 @@ int mcd_setlock __P((struct mcd_softc *, int));
int mcdprobe __P((struct device *, void *, void *));
void mcdattach __P((struct device *, struct device *, void *));
-struct cfdriver mcdcd = {
- NULL, "mcd", mcdprobe, mcdattach, DV_DISK, sizeof(struct mcd_softc)
+struct cfattach mcd_ca = {
+ sizeof(struct mcd_softc), mcdprobe, mcdattach
+};
+
+struct cfdriver mcd_cd = {
+ NULL, "mcd", DV_DISK
};
void mcdgetdisklabel __P((struct mcd_softc *));
@@ -228,8 +232,8 @@ mcdattach(parent, self, aux)
mcd_soft_reset(sc);
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_BIO, mcdintr,
- sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_BIO, mcdintr, sc, sc->sc_dev.dv_xname);
}
/*
@@ -279,9 +283,9 @@ mcdopen(dev, flag, fmt, p)
struct mcd_softc *sc;
unit = MCDUNIT(dev);
- if (unit >= mcdcd.cd_ndevs)
+ if (unit >= mcd_cd.cd_ndevs)
return ENXIO;
- sc = mcdcd.cd_devs[unit];
+ sc = mcd_cd.cd_devs[unit];
if (!sc)
return ENXIO;
@@ -379,7 +383,7 @@ mcdclose(dev, flag, fmt)
dev_t dev;
int flag, fmt;
{
- struct mcd_softc *sc = mcdcd.cd_devs[MCDUNIT(dev)];
+ struct mcd_softc *sc = mcd_cd.cd_devs[MCDUNIT(dev)];
int part = MCDPART(dev);
int error;
@@ -415,7 +419,7 @@ void
mcdstrategy(bp)
struct buf *bp;
{
- struct mcd_softc *sc = mcdcd.cd_devs[MCDUNIT(bp->b_dev)];
+ struct mcd_softc *sc = mcd_cd.cd_devs[MCDUNIT(bp->b_dev)];
int s;
/* Test validity. */
@@ -548,7 +552,7 @@ mcdioctl(dev, cmd, addr, flag, p)
int flag;
struct proc *p;
{
- struct mcd_softc *sc = mcdcd.cd_devs[MCDUNIT(dev)];
+ struct mcd_softc *sc = mcd_cd.cd_devs[MCDUNIT(dev)];
int error;
MCD_TRACE("ioctl: cmd=0x%x\n", cmd, 0, 0, 0);
diff --git a/sys/dev/isa/pas.c b/sys/dev/isa/pas.c
index 0d0fe136538..4227615cb36 100644
--- a/sys/dev/isa/pas.c
+++ b/sys/dev/isa/pas.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: pas.c,v 1.8 1996/04/18 23:47:44 niklas Exp $ */
-/* $NetBSD: pas.c,v 1.13 1996/03/01 04:08:43 mycroft Exp $ */
+/* $OpenBSD: pas.c,v 1.9 1996/04/21 22:24:23 deraadt Exp $ */
+/* $NetBSD: pas.c,v 1.15 1996/04/11 22:29:48 cgd Exp $ */
/*
* Copyright (c) 1991-1993 Regents of the University of California.
@@ -250,8 +250,12 @@ pasconf(int model, int sbbase, int sbirq, int sbdrq)
int pasprobe __P((struct device *, void *, void *));
void pasattach __P((struct device *, struct device *, void *));
-struct cfdriver pascd = {
- NULL, "pas", pasprobe, pasattach, DV_DULL, sizeof(struct pas_softc)
+struct cfattach pas_ca = {
+ sizeof(struct pas_softc), pasprobe, pasattach
+};
+
+struct cfdriver pas_cd = {
+ NULL, "pas", DV_DULL
};
/*
@@ -431,8 +435,8 @@ pasattach(parent, self, aux)
int err;
sc->sc_iobase = iobase;
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_AUDIO,
- sbdsp_intr, &sc->sc_sbdsp, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_AUDIO, sbdsp_intr, &sc->sc_sbdsp, sc->sc_dev.dv_xname);
printf(" ProAudio Spectrum %s [rev %d] ", pasnames[sc->model], sc->rev);
@@ -453,10 +457,10 @@ pasopen(dev, flags)
struct pas_softc *sc;
int unit = AUDIOUNIT(dev);
- if (unit >= pascd.cd_ndevs)
+ if (unit >= pas_cd.cd_ndevs)
return ENODEV;
- sc = pascd.cd_devs[unit];
+ sc = pas_cd.cd_devs[unit];
if (!sc)
return ENXIO;
diff --git a/sys/dev/isa/pss.c b/sys/dev/isa/pss.c
index 909db507342..9e551882061 100644
--- a/sys/dev/isa/pss.c
+++ b/sys/dev/isa/pss.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: pss.c,v 1.7 1996/03/20 01:00:59 mickey Exp $ */
-/* $NetBSD: pss.c,v 1.11 1995/12/24 02:31:45 mycroft Exp $ */
+/* $OpenBSD: pss.c,v 1.8 1996/04/21 22:24:26 deraadt Exp $ */
+/* $NetBSD: pss.c,v 1.13 1996/04/11 22:29:52 cgd Exp $ */
/*
* Copyright (c) 1994 John Brezak
@@ -238,20 +238,36 @@ static u_char wss_dma_bits[4] = {1, 2, 0, 3};
#define at_dma(flags, ptr, cc, chan) isa_dmastart(flags, ptr, cc, chan)
#endif
-struct cfdriver psscd = {
- NULL, "pss", pssprobe, pssattach, DV_DULL, sizeof(struct pss_softc), 1
+struct cfattach pss_ca = {
+ sizeof(struct pss_softc), pssprobe, pssattach
};
-struct cfdriver spcd = {
- NULL, "sp", spprobe, spattach, DV_DULL, sizeof(struct ad1848_softc)
+struct cfdriver pss_cd = {
+ NULL, "pss", DV_DULL, 1
};
-struct cfdriver mpucd = {
- NULL, "mpu", mpuprobe, mpuattach, DV_DULL, sizeof(struct mpu_softc)
+struct cfattach sp_ca = {
+ sizeof(struct ad1848_softc), spprobe, spattach
};
-struct cfdriver pcdcd = {
- NULL, "pcd", pcdprobe, pcdattach, DV_DULL, sizeof(struct cd_softc)
+struct cfdriver sp_cd = {
+ NULL, "sp", DV_DULL
+};
+
+struct cfattach mpu_ca = {
+ sizeof(struct mpu_softc), mpuprobe, mpuattach
+};
+
+struct cfdriver mpu_cd = {
+ NULL, "mpu", DV_DULL
+};
+
+struct cfattach pcd_ca = {
+ sizeof(struct cd_softc), pcdprobe, pcdattach
+};
+
+struct cfdriver pcd_cd = {
+ NULL, "pcd", DV_DULL
};
struct audio_device pss_device = {
@@ -1005,13 +1021,13 @@ pssattach(parent, self, aux)
#endif
/* Setup interrupt handler for PSS */
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_AUDIO, pssintr,
- sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE, IPL_AUDIO,
+ pssintr, sc, sc->sc_dev.dv_xname);
vers = (inw(sc->sc_iobase+PSS_ID_VERS)&0xff) - 1;
printf(": ESC614%c\n", (vers > 0)?'A'+vers:' ');
- (void)config_found(self, NULL, NULL);
+ (void)config_found(self, ia->ia_ic, NULL); /* XXX */
sc->out_port = PSS_MASTER_VOL;
@@ -1031,6 +1047,7 @@ spattach(parent, self, aux)
{
struct ad1848_softc *sc = (struct ad1848_softc *)self;
struct cfdata *cf = (void *)sc->sc_dev.dv_cfdata;
+ isa_chipset_tag_t ic = aux; /* XXX */
int iobase = cf->cf_iobase;
sc->sc_iobase = iobase;
@@ -1040,8 +1057,8 @@ spattach(parent, self, aux)
isa_establish(&sc->sc_id, &sc->sc_dev);
#endif
- sc->sc_ih = isa_intr_establish(cf->cf_irq, IST_EDGE, IPL_AUDIO, ad1848_intr,
- sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ic, cf->cf_irq, IST_EDGE, IPL_AUDIO,
+ ad1848_intr, sc, sc->sc_dev.dv_xname);
/* XXX might use pssprint func ?? */
printf(" port 0x%x-0x%x irq %d drq %d",
@@ -1060,6 +1077,7 @@ mpuattach(parent, self, aux)
{
struct mpu_softc *sc = (struct mpu_softc *)self;
struct cfdata *cf = (void *)sc->sc_dev.dv_cfdata;
+ isa_chipset_tag_t ic = aux; /* XXX */
int iobase = cf->cf_iobase;
sc->sc_iobase = iobase;
@@ -1068,8 +1086,8 @@ mpuattach(parent, self, aux)
isa_establish(&sc->sc_id, &sc->sc_dev);
#endif
- sc->sc_ih = isa_intr_establish(cf->cf_irq, IST_EDGE, IPL_AUDIO, mpuintr,
- sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ic, cf->cf_irq, IST_EDGE, IPL_AUDIO,
+ mpuintr, sc, sc->sc_dev.dv_xname);
/* XXX might use pssprint func ?? */
printf(" port 0x%x-0x%x irq %d\n",
@@ -1145,10 +1163,10 @@ spopen(dev, flags)
struct ad1848_softc *sc;
int unit = AUDIOUNIT(dev);
- if (unit >= spcd.cd_ndevs)
+ if (unit >= sp_cd.cd_ndevs)
return ENODEV;
- sc = spcd.cd_devs[unit];
+ sc = sp_cd.cd_devs[unit];
if (!sc)
return ENXIO;
diff --git a/sys/dev/isa/rtfps.c b/sys/dev/isa/rtfps.c
index e0f7ef2abf4..1afdc1ccfda 100644
--- a/sys/dev/isa/rtfps.c
+++ b/sys/dev/isa/rtfps.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: rtfps.c,v 1.7 1996/04/18 23:47:45 niklas Exp $ */
-/* $NetBSD: rtfps.c,v 1.17 1996/03/10 09:01:28 cgd Exp $ */
+/* $OpenBSD: rtfps.c,v 1.8 1996/04/21 22:24:28 deraadt Exp $ */
+/* $NetBSD: rtfps.c,v 1.21 1996/04/15 18:55:31 cgd Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@@ -36,7 +36,13 @@
#include <sys/param.h>
#include <sys/device.h>
+#include <sys/termios.h>
+#ifdef i386 /* XXX */
+#include <machine/cpu.h> /* XXX */
+#else /* XXX */
+#include <machine/intr.h>
+#endif /* XXX */
#include <machine/bus.h>
#include <dev/isa/isavar.h>
@@ -63,8 +69,12 @@ int rtfpsprobe();
void rtfpsattach();
int rtfpsintr __P((void *));
-struct cfdriver rtfpscd = {
- NULL, "rtfps", rtfpsprobe, rtfpsattach, DV_TTY, sizeof(struct rtfps_softc)
+struct cfattach rtfps_ca = {
+ sizeof(struct rtfps_softc), rtfpsprobe, rtfpsattach
+};
+
+struct cfdriver rtfps_cd = {
+ NULL, "rtfps", DV_TTY
};
int
@@ -176,20 +186,13 @@ rtfpsattach(parent, self, aux)
ca.ca_iobase = sc->sc_iobase + i * COM_NPORTS;
ca.ca_noien = 0;
- /* mimic config_found(), but with special functionality */
- if ((match = config_search(NULL, self, &ca)) != NULL) {
- subunit = match->cf_unit; /* can change if unit == * */
- config_attach(self, match, &ca, rtfpsprint);
- sc->sc_slaves[i] = match->cf_driver->cd_devs[subunit];
+ sc->sc_slaves[i] = config_found(self, &ca, rtfpsprint);
+ if (sc->sc_slaves[i] != NULL)
sc->sc_alive |= 1 << i;
- } else {
- rtfpsprint(&ca, self->dv_xname);
- printf(" not configured\n");
- }
}
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_TTY,
- rtfpsintr, sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_TTY, rtfpsintr, sc, sc->sc_dev.dv_xname);
}
int
diff --git a/sys/dev/isa/sb.c b/sys/dev/isa/sb.c
index 976eada8cc7..09fd816e061 100644
--- a/sys/dev/isa/sb.c
+++ b/sys/dev/isa/sb.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: sb.c,v 1.8 1996/04/18 23:47:46 niklas Exp $ */
-/* $NetBSD: sb.c,v 1.32 1996/03/16 04:00:09 jtk Exp $ */
+/* $OpenBSD: sb.c,v 1.9 1996/04/21 22:24:30 deraadt Exp $ */
+/* $NetBSD: sb.c,v 1.34 1996/04/11 22:30:01 cgd Exp $ */
/*
* Copyright (c) 1991-1993 Regents of the University of California.
@@ -75,8 +75,18 @@ struct sb_softc {
int sbprobe __P((struct device *, void *, void *));
void sbattach __P((struct device *, struct device *, void *));
-struct cfdriver sbcd = {
- NULL, "sb", sbprobe, sbattach, DV_DULL, sizeof(struct sbdsp_softc)
+struct cfattach sb_ca = {
+ sizeof(struct sbdsp_softc), sbprobe, sbattach
+};
+
+struct cfdriver sb_cd = {
+ NULL, "sb", DV_DULL
+};
+
+struct audio_device sb_device = {
+ "SoundBlaster",
+ "x",
+ "sb"
};
int sbopen __P((dev_t, int));
@@ -264,8 +274,8 @@ sbattach(parent, self, aux)
register int iobase = ia->ia_iobase;
int err;
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_AUDIO,
- sbdsp_intr, sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_AUDIO, sbdsp_intr, sc, sc->sc_dev.dv_xname);
sbdsp_attach(sc);
@@ -285,10 +295,10 @@ sbopen(dev, flags)
struct sbdsp_softc *sc;
int unit = AUDIOUNIT(dev);
- if (unit >= sbcd.cd_ndevs)
+ if (unit >= sb_cd.cd_ndevs)
return ENODEV;
- sc = sbcd.cd_devs[unit];
+ sc = sb_cd.cd_devs[unit];
if (!sc)
return ENXIO;
diff --git a/sys/dev/isa/seagate.c b/sys/dev/isa/seagate.c
index ccb16aa9165..67e70d04696 100644
--- a/sys/dev/isa/seagate.c
+++ b/sys/dev/isa/seagate.c
@@ -303,8 +303,12 @@ int seaprobe __P((struct device *, void *, void *));
void seaattach __P((struct device *, struct device *, void *));
int seaprint __P((void *, char *));
-struct cfdriver seacd = {
- NULL, "sea", seaprobe, seaattach, DV_DULL, sizeof(struct sea_softc)
+struct cfattach sea_ca = {
+ sizeof(struct sea_softc), seaprobe, seaattach
+};
+
+struct cfdriver sea_cd = {
+ NULL, "sea", DV_DULL
};
#ifdef SEA_DEBUGQUEUE
@@ -438,8 +442,8 @@ seaattach(parent, self, aux)
#ifdef NEWCONFIG
isa_establish(&sea->sc_id, &sea->sc_deV);
#endif
- sea->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_BIO, seaintr,
- sea, sc->sc_dev.dv_xname);
+ sea->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_BIO, seaintr, sea, sea->sc_dev.dv_xname);
/*
* ask the adapter what subunits are present
@@ -685,8 +689,8 @@ sea_main()
*/
loop:
done = 1;
- for (unit = 0; unit < seacd.cd_ndevs; unit++) {
- sea = seacd.cd_devs[unit];
+ for (unit = 0; unit < sea_cd.cd_ndevs; unit++) {
+ sea = sea_cd.cd_devs[unit];
if (!sea)
continue;
s = splbio();
diff --git a/sys/dev/isa/ultra14f.c b/sys/dev/isa/ultra14f.c
index 948a2966654..79464cc4d6c 100644
--- a/sys/dev/isa/ultra14f.c
+++ b/sys/dev/isa/ultra14f.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: ultra14f.c,v 1.12 1996/04/18 23:47:50 niklas Exp $ */
-/* $NetBSD: ultra14f.c,v 1.62 1996/02/24 05:27:49 mycroft Exp $ */
+/* $OpenBSD: ultra14f.c,v 1.13 1996/04/21 22:24:36 deraadt Exp $ */
+/* $NetBSD: ultra14f.c,v 1.64 1996/04/11 22:30:20 cgd Exp $ */
/*
* Copyright (c) 1994 Charles Hannum. All rights reserved.
@@ -328,8 +328,12 @@ int uhaprobe __P((struct device *, void *, void *));
void uhaattach __P((struct device *, struct device *, void *));
int uhaprint __P((void *, char *));
-struct cfdriver uhacd = {
- NULL, "uha", uhaprobe, uhaattach, DV_DULL, sizeof(struct uha_softc)
+struct cfattach uha_ca = {
+ sizeof(struct uha_softc), uhaprobe, uhaattach
+};
+
+struct cfdriver uha_cd = {
+ NULL, "uha", DV_DULL
};
/*
@@ -608,8 +612,8 @@ uhaattach(parent, self, aux)
#ifdef NEWCONFIG
isa_establish(&uha->sc_id, &uha->sc_dev);
#endif
- uha->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_BIO,
- uha->intr, uha, uha->sc_dev.dv_xname);
+ uha->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_BIO, uha->intr, uha, uha->sc_dev.dv_xname);
/*
* ask the adapter what subunits are present
diff --git a/sys/dev/isa/wd.c b/sys/dev/isa/wd.c
index 96fedd9de01..76267053725 100644
--- a/sys/dev/isa/wd.c
+++ b/sys/dev/isa/wd.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: wd.c,v 1.9 1996/04/18 23:47:51 niklas Exp $ */
-/* $NetBSD: wd.c,v 1.146 1996/03/01 04:08:51 mycroft Exp $ */
+/* $OpenBSD: wd.c,v 1.10 1996/04/21 22:24:40 deraadt Exp $ */
+/* $NetBSD: wd.c,v 1.148 1996/04/11 22:30:31 cgd Exp $ */
/*
* Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved.
@@ -139,15 +139,23 @@ struct wdc_softc {
int wdcprobe __P((struct device *, void *, void *));
void wdcattach __P((struct device *, struct device *, void *));
-struct cfdriver wdccd = {
- NULL, "wdc", wdcprobe, wdcattach, DV_DULL, sizeof(struct wdc_softc)
+struct cfattach wdc_ca = {
+ sizeof(struct wdc_softc), wdcprobe, wdcattach
+};
+
+struct cfdriver wdc_cd = {
+ NULL, "wdc", DV_DULL
};
int wdprobe __P((struct device *, void *, void *));
void wdattach __P((struct device *, struct device *, void *));
-struct cfdriver wdcd = {
- NULL, "wd", wdprobe, wdattach, DV_DISK, sizeof(struct wd_softc)
+struct cfattach wd_ca = {
+ sizeof(struct wd_softc), wdprobe, wdattach
+};
+
+struct cfdriver wd_cd = {
+ NULL, "wd", DV_DISK
};
void wdgetdisklabel __P((struct wd_softc *));
@@ -249,8 +257,8 @@ wdcattach(parent, self, aux)
printf("\n");
- wdc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_BIO, wdcintr,
- wdc, wdc->sc_dev.dv_xname);
+ wdc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_BIO, wdcintr, wdc, wdc->sc_dev.dv_xname);
for (wa.wa_drive = 0; wa.wa_drive < 2; wa.wa_drive++)
(void)config_found(self, (void *)&wa, wdprint);
@@ -354,7 +362,7 @@ void
wdstrategy(bp)
struct buf *bp;
{
- struct wd_softc *wd = wdcd.cd_devs[WDUNIT(bp->b_dev)];
+ struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(bp->b_dev)];
int s;
/* Valid request? */
@@ -889,9 +897,9 @@ wdopen(dev, flag, fmt)
int error;
unit = WDUNIT(dev);
- if (unit >= wdcd.cd_ndevs)
+ if (unit >= wd_cd.cd_ndevs)
return ENXIO;
- wd = wdcd.cd_devs[unit];
+ wd = wd_cd.cd_devs[unit];
if (wd == 0)
return ENXIO;
@@ -963,7 +971,7 @@ wdclose(dev, flag, fmt)
dev_t dev;
int flag, fmt;
{
- struct wd_softc *wd = wdcd.cd_devs[WDUNIT(dev)];
+ struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(dev)];
int part = WDPART(dev);
int error;
@@ -1308,7 +1316,7 @@ wdioctl(dev, cmd, addr, flag, p)
int flag;
struct proc *p;
{
- struct wd_softc *wd = wdcd.cd_devs[WDUNIT(dev)];
+ struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(dev)];
int error;
if ((wd->sc_flags & WDF_LOADED) == 0)
@@ -1424,7 +1432,7 @@ wdsize(dev)
if (wdopen(dev, 0, S_IFBLK) != 0)
return -1;
- wd = wdcd.cd_devs[WDUNIT(dev)];
+ wd = wd_cd.cd_devs[WDUNIT(dev)];
part = WDPART(dev);
if (wd->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP)
size = -1;
@@ -1463,9 +1471,9 @@ wddump(dev, blkno, va, size)
wddoingadump = 1;
unit = WDUNIT(dev);
- if (unit >= wdcd.cd_ndevs)
+ if (unit >= wd_cd.cd_ndevs)
return ENXIO;
- wd = wdcd.cd_devs[unit];
+ wd = wd_cd.cd_devs[unit];
if (wd == 0)
return ENXIO;
@@ -1657,8 +1665,8 @@ wdcunwedge(wdc)
(void) wdcreset(wdc);
/* Schedule recalibrate for all drives on this controller. */
- for (unit = 0; unit < wdcd.cd_ndevs; unit++) {
- struct wd_softc *wd = wdcd.cd_devs[unit];
+ for (unit = 0; unit < wd_cd.cd_ndevs; unit++) {
+ struct wd_softc *wd = wd_cd.cd_devs[unit];
if (!wd || (void *)wd->sc_dev.dv_parent != wdc)
continue;
if (wd->sc_state > RECAL)
diff --git a/sys/dev/isa/wd7000.c b/sys/dev/isa/wd7000.c
deleted file mode 100644
index cd86dd0e8ef..00000000000
--- a/sys/dev/isa/wd7000.c
+++ /dev/null
@@ -1,747 +0,0 @@
-/* $NetBSD: wd7000.c,v 1.22 1995/08/12 20:31:32 mycroft Exp $ */
-
-/* XXX THIS DRIVER IS BROKEN. IT WILL NOT EVEN COMPILE. */
-
-/*
- * UNFINISHED! UNFINISHED! UNFINISHED! UNFINISHED! UNFINISHED! UNFINISHED!
- *
- * deraadt@fsa.ca 93/04/02
- *
- * I was writing this driver for a wd7000-ASC. Yeah, the "-ASC" not the
- * "-FASST2". The difference is that the "-ASC" is missing scatter gather
- * support.
- *
- * In any case, the real reason why I never finished it is because the
- * motherboard I have has broken DMA. This card wants 8MHz 1 wait state
- * operation, and my board munges about 30% of the words transferred.
- *
- * Hopefully someone can finish this for the wd7000-FASST2. It should be
- * quite easy to do. Look at the Linux wd7000 device driver to see how
- * scatter gather is done by the board, then look at one of the Adaptec
- * drivers to finish off the job..
- */
-#include "wds.h"
-#if NWDS > 0
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/errno.h>
-#include <sys/ioctl.h>
-#include <sys/buf.h>
-#include <sys/proc.h>
-#include <sys/user.h>
-#include <sys/dkbad.h>
-#include <sys/disklabel.h>
-
-#include <scsi/scsi_all.h>
-#include <scsi/scsiconf.h>
-
-#include <machine/cpu.h>
-#include <machine/pio.h>
-
-#include <dev/isa/isadmavar.h>
-#include <i386/isa/isa_device.h> /* XXX BROKEN */
-
-extern int delaycount; /* from clock setup code */
-
-#define PHYSTOKV(x) ((x) + KERNBASE)
-#define KVTOPHYS(x) vtophys(x)
-#define PAGESIZ 4096
-
-
-/* WD7000 registers */
-#define WDS_STAT 0 /* read */
-#define WDS_IRQSTAT 1 /* read */
-
-#define WDS_CMD 0 /* write */
-#define WDS_IRQACK 1 /* write */
-#define WDS_HCR 2 /* write */
-
-/* WDS_STAT (read) defs */
-#define WDS_IRQ 0x80
-#define WDS_RDY 0x40
-#define WDS_REJ 0x20
-#define WDS_INIT 0x10
-
-/* WDS_IRQSTAT (read) defs */
-#define WDSI_MASK 0xc0
-#define WDSI_ERR 0x00
-#define WDSI_MFREE 0x80
-#define WDSI_MSVC 0xc0
-
-/* WDS_CMD (write) defs */
-#define WDSC_NOOP 0x00
-#define WDSC_INIT 0x01
-#define WDSC_DISUNSOL 0x02
-#define WDSC_ENAUNSOL 0x03
-#define WDSC_IRQMFREE 0x04
-#define WDSC_SCSIRESETSOFT 0x05
-#define WDSC_SCSIRESETHARD 0x06
-#define WDSC_MSTART(m) (0x80 + (m))
-#define WDSC_MMSTART(m) (0xc0 + (m))
-
-/* WDS_HCR (write) defs */
-#define WDSH_IRQEN 0x08
-#define WDSH_DRQEN 0x04
-#define WDSH_SCSIRESET 0x02
-#define WDSH_ASCRESET 0x01
-
-struct wds_cmd {
- u_char cmd;
- u_char targ;
- struct scsi_generic scb; /*u_char scb[12];*/
- u_char stat;
- u_char venderr;
- u_char len[3];
- u_char data[3];
- u_char next[3];
- u_char write;
- u_char xx[6];
-};
-
-struct wds_req {
- struct wds_cmd cmd;
- struct wds_cmd sense;
- struct scsi_xfer *sxp;
- int busy, polled;
- int done, ret, ombn;
-};
-
-#define WDSX_SCSICMD 0x00
-#define WDSX_OPEN_RCVBUF 0x80
-#define WDSX_RCV_CMD 0x81
-#define WDSX_RCV_DATA 0x82
-#define WDSX_RCV_DATASTAT 0x83
-#define WDSX_SND_DATA 0x84
-#define WDSX_SND_DATASTAT 0x85
-#define WDSX_SND_CMDSTAT 0x86
-#define WDSX_READINIT 0x88
-#define WDSX_READSCSIID 0x89
-#define WDSX_SETUNSOLIRQMASK 0x8a
-#define WDSX_GETUNSOLIRQMASK 0x8b
-#define WDSX_GETFIRMREV 0x8c
-#define WDSX_EXECDIAG 0x8d
-#define WDSX_SETEXECPARM 0x8e
-#define WDSX_GETEXECPARM 0x8f
-
-struct wds_mb {
- u_char stat;
- u_char addr[3];
-};
-/* ICMB status value */
-#define ICMB_OK 0x01
-#define ICMB_OKERR 0x02
-#define ICMB_ETIME 0x04
-#define ICMB_ERESET 0x05
-#define ICMB_ETARCMD 0x06
-#define ICMB_ERESEL 0x80
-#define ICMB_ESEL 0x81
-#define ICMB_EABORT 0x82
-#define ICMB_ESRESET 0x83
-#define ICMB_EHRESET 0x84
-
-struct wds_setup {
- u_char cmd;
- u_char scsi_id;
- u_char buson_t;
- u_char busoff_t;
- u_char xx;
- u_char mbaddr[3];
- u_char nomb;
- u_char nimb;
-};
-
-#define WDS_NOMB 16
-#define WDS_NIMB 8
-#define MAXSIMUL 8
-struct wds {
- int addr;
- struct wds_req wdsr[MAXSIMUL];
- struct wds_mb ombs[WDS_NOMB], imbs[WDS_NIMB];
-} wds[NWDS];
-
-static int wdsunit = 0;
-int wds_debug = 0;
-
-void p2x(u_char *, u_long);
-u_char *x2p(u_char *);
-int wdsprobe(struct isa_device *);
-void wds_minphys(struct buf *);
-struct wds_req *wdsr_alloc(int);
-int wds_scsi_cmd(struct scsi_xfer *);
-long wds_adapter_info(int);
-int wdsintr(int);
-int wds_done(int, struct wds_cmd *, u_char);
-int wdsattach(struct isa_device *);
-int wds_init(struct isa_device *);
-int wds_cmd(int, u_char *, int);
-void wds_wait(int, int, int);
-
-
-struct scsi_switch wds_switch[NWDS];
-
-struct isa_driver wdsdriver = {
- wdsprobe,
- wdsattach,
- "wds",
-};
-
-
-void
-flushcache(void)
-{
- extern main();
- volatile char *p, c;
- int i;
-
- for(p=(char *)main, i=0; i<256*1024; i++)
- c = *p++;
-}
-
-void
-p2x(u_char *p, u_long x)
-{
- p[0] = (x & 0x00ff0000) >> 16;
- p[1] = (x & 0x0000ff00) >> 8;
- p[2] = (x & 0x000000ff);
-}
-
-u_char *
-x2p(u_char *x)
-{
- u_long q;
-
- q = ((x[0]<<16) & 0x00ff0000) + ((x[1]<<8) & 0x0000ff00) + (x[2] & 0x000000ff);
- return (u_char *)q;
-}
-
-int
-wdsprobe(struct isa_device *dev)
-{
- /*scsi_debug = PRINTROUTINES | TRACEOPENS | TRACEINTERRUPTS |
- SHOWREQUESTS | SHOWSCATGATH | SHOWINQUIRY | SHOWCOMMANDS;*/
-
- if (dev->id_parent)
- return 1;
-
- if(wdsunit > NWDS)
- return 0;
-
- dev->id_unit = wdsunit;
- wds[wdsunit].addr = dev->id_iobase;
-
- if(wds_init(dev) != 0)
- return 0;
- wdsunit++;
- return 8;
-}
-
-void
-wds_minphys(struct buf *bp)
-{
- int base = (int)bp->b_data & (PAGESIZ-1);
-
- if (base + bp->b_bcount > PAGESIZ)
- bp->b_bcount = PAGESIZ - base;
- minphys(bp);
-}
-
-struct wds_req *
-wdsr_alloc(int unit)
-{
- struct wds_req *r;
- int x;
- int i;
-
- r = NULL;
- x = splbio();
- for(i=0; i<MAXSIMUL; i++)
- if(wds[unit].wdsr[i].busy == 0) {
- r = &wds[unit].wdsr[i];
- r->busy = 1;
- break;
- }
- if(r == NULL) {
- splx(x);
- return NULL;
- }
-
- r->ombn = -1;
- for(i=0; i<WDS_NOMB; i++)
- if(wds[unit].ombs[i].stat==0) {
- wds[unit].ombs[i].stat = 1;
- r->ombn = i;
- break;
- }
- if(r->ombn == -1 ) {
- r->busy = 0;
- splx(x);
- return NULL;
- }
- splx(x);
- return r;
-}
-
-int
-wds_scsi_cmd(struct scsi_xfer *sxp)
-{
- struct wds_req *r;
- int unit = sxp->adapter;
- int base;
- u_char c, *p;
- int i;
-
- base = wds[unit].addr;
-
- /*printf("scsi_cmd\n");*/
-
- if( sxp->flags & SCSI_RESET) {
- printf("reset!\n");
- return COMPLETE;
- }
-
- r = wdsr_alloc(unit);
- if(r==NULL) {
- printf("no request slot available!\n");
- sxp->error = XS_DRIVER_STUFFUP;
- return TRY_AGAIN_LATER;
- }
- r->done = 0;
- r->sxp = sxp;
-
- printf("wds%d: target %d/%d req %8x flags %08x len %d: ", unit,
- sxp->targ, sxp->lu, r, sxp->flags, sxp->cmdlen);
- for(i=0, p=(u_char *)sxp->cmd; i<sxp->cmdlen; i++)
- printf("%02x ", p[i]);
- printf("\n");
- printf(" data %08x datalen %08x\n", sxp->data, sxp->datalen);
-
- if(sxp->flags & SCSI_DATA_UIO) {
- printf("UIO!\n");
- sxp->error = XS_DRIVER_STUFFUP;
- return TRY_AGAIN_LATER;
- }
-
- p2x(&wds[unit].ombs[r->ombn].addr[0], KVTOPHYS(&r->cmd));
- printf("%08x/%08x mbox@%08x: %02x %02x %02x %02x\n",
- &r->cmd, KVTOPHYS(&r->cmd), &wds[unit].ombs[0],
- wds[unit].ombs[r->ombn].stat, wds[unit].ombs[r->ombn].addr[0],
- wds[unit].ombs[r->ombn].addr[1], wds[unit].ombs[r->ombn].addr[2]);
-
- bzero(&r->cmd, sizeof r->cmd);
- r->cmd.cmd = WDSX_SCSICMD;
- r->cmd.targ = (sxp->targ << 5) | sxp->lu;
- bcopy(sxp->cmd, &r->cmd.scb, sxp->cmdlen<12 ? sxp->cmdlen : 12);
- p2x(&r->cmd.len[0], sxp->datalen);
- p2x(&r->cmd.data[0], sxp->datalen ? KVTOPHYS(sxp->data) : 0);
- r->cmd.write = (sxp->flags&SCSI_DATA_IN)? 0x80 : 0x00;
- p2x(&r->cmd.next[0], KVTOPHYS(&r->sense));
-
- bzero(&r->sense, sizeof r->sense);
- r->sense.cmd = r->cmd.cmd;
- r->sense.targ = r->cmd.targ;
- r->sense.scb.opcode = REQUEST_SENSE;
- p2x(&r->sense.data[0], KVTOPHYS(&sxp->sense));
- p2x(&r->sense.len[0], sizeof sxp->sense);
- r->sense.write = 0x80;
-
- /*printf("wdscmd: ");
- for(i=0, p=(u_char *)&r->cmd; i<sizeof r->cmd; i++)
- printf("%02x ", p[i]);
- printf("\n");*/
-
- if(sxp->flags & SCSI_NOMASK) {
- outb(base+WDS_HCR, WDSH_DRQEN);
- r->polled = 1;
- } else
- r->polled = 0;
-
- c = WDSC_MSTART(r->ombn);
- flushcache();
- if( wds_cmd(base, &c, sizeof c) != 0) {
- printf("wds%d: unable to start outgoing mbox\n", unit);
- r->busy = 0;
- /* XXX need to free mailbox */
- return TRY_AGAIN_LATER;
- }
-
- delay(10000);
- /*printf("%08x/%08x mbox: %02x %02x %02x %02x\n", &r->cmd, KVTOPHYS(&r->cmd),
- wds[unit].ombs[r->ombn].stat, wds[unit].ombs[r->ombn].addr[0],
- wds[unit].ombs[r->ombn].addr[1], wds[unit].ombs[r->ombn].addr[2]);*/
-
- if(sxp->flags & SCSI_NOMASK) {
-repoll: printf("wds%d: polling.", unit);
- i = 0;
- while( (inb(base+WDS_STAT) & WDS_IRQ) == 0) {
- printf(".");
- delay(10000);
- if(++i == 10) {
- printf("failed %02x\n", inb(base+WDS_IRQSTAT));
- /*r->busy = 0;*/
- sxp->error = XS_TIMEOUT;
- return HAD_ERROR;
- }
- }
- flushcache();
- printf("got one!\n");
- wdsintr(unit);
- if(r->done) {
- r->sxp->flags |= ITSDONE;
- if(r->sxp->when_done)
- (*r->sxp->when_done)(r->sxp->done_arg,
- r->sxp->done_arg2);
- r->busy = 0;
- return r->ret;
- }
- goto repoll;
- }
-
- outb(base+WDS_HCR, WDSH_IRQEN|WDSH_DRQEN);
- printf("wds%d: successfully queued\n", unit);
- return SUCCESSFULLY_QUEUED;
-}
-
-long
-wds_adapter_info(int unit)
-{
- return 1;
-}
-
-int
-wdsintr(int unit)
-{
- struct wds_cmd *pc, *vc;
- struct wds_mb *in;
- u_char stat;
- u_char c;
-
- /*printf("stat=%02x\n", inb(wds[unit].addr + WDS_STAT));*/
- delay(1000);
- c = inb(wds[unit].addr + WDS_IRQSTAT);
- printf("wdsintr: %02x\n", c);
- if( (c&WDSI_MASK) == WDSI_MSVC) {
- delay(1000);
- c = c & ~WDSI_MASK;
- flushcache();
- in = &wds[unit].imbs[c];
-
- printf("incoming mailbox %02x@%08x: ", c, in);
- printf("%02x %02x %02x %02x\n",
- in->stat, in->addr[0], in->addr[1], in->addr[2]);
- pc = (struct wds_cmd *)x2p(&in->addr[0]);
- vc = (struct wds_cmd *)PHYSTOKV(pc);
- stat = in->stat;
- printf("p=%08x v=%08x stat %02x\n", pc, vc, stat);
- wds_done(unit, vc, stat);
- in->stat = 0;
-
- outb(wds[unit].addr + WDS_IRQACK, 0xff);
- }
- return 1;
-}
-
-int
-wds_done(int unit, struct wds_cmd *c, u_char stat)
-{
- struct wds_req *r;
- int i;
-
- r = (struct wds_req *)NULL;
- for(i=0; i<MAXSIMUL; i++)
- if( c == &wds[unit].wdsr[i].cmd ) {
- /*printf("found at req slot %d\n", i);*/
- r = &wds[unit].wdsr[i];
- break;
- }
- if(r == (struct wds_req *)NULL) {
- printf("failed to find request!\n");
- return 1;
- }
-
- printf("wds%d: cmd %8x stat %2x/%2x %2x/%2x\n", unit, c,
- r->cmd.stat, r->cmd.venderr, r->sense.stat, r->sense.venderr);
-
- r->done = 1;
- /* XXX need to free mailbox */
- r->ret = HAD_ERROR;
- switch(r->cmd.stat) {
- case ICMB_OK:
- /*XXX r->sxp->sense.valid = 0;
- r->sxp->error = 0;*/
- r->ret = COMPLETE;
- break;
- case ICMB_OKERR:
- printf("scsi err %02x\n", c->venderr);
- /*XXX r->sxp->sense.error_code = c->venderr;
- r->sxp->sense.valid = 1;*/
- r->ret = COMPLETE;
- break;
- case ICMB_ETIME:
- r->sxp->error = XS_TIMEOUT;
- r->ret = HAD_ERROR;
- break;
- case ICMB_ERESET:
- case ICMB_ETARCMD:
- case ICMB_ERESEL:
- case ICMB_ESEL:
- case ICMB_EABORT:
- case ICMB_ESRESET:
- case ICMB_EHRESET:
- r->sxp->error = XS_DRIVER_STUFFUP;
- r->ret = HAD_ERROR;
- break;
- }
- if(r->polled==0) {
- r->sxp->flags |= ITSDONE;
- if(r->sxp->when_done)
- (*r->sxp->when_done)(r->sxp->done_arg, r->sxp->done_arg2);
- r->busy = 0;
- }
- return 0;
-}
-
-int
-wds_getvers(int unit)
-{
- struct wds_req *r;
- int base;
- u_char c, *p;
- int i;
-
- base = wds[unit].addr;
-
- /*printf("scsi_cmd\n");*/
-
- r = wdsr_alloc(unit);
- if(r==NULL) {
- printf("wds%d: no request slot available!\n", unit);
- return -1;
- }
- r->done = 0;
- r->sxp = NULL;
-
- printf("wds%d: getvers req %8x\n", unit, r);
-
- p2x(&wds[unit].ombs[r->ombn].addr[0], KVTOPHYS(&r->cmd));
- printf("%08x/%08x mbox@%08x: %02x %02x %02x %02x\n",
- &r->cmd, KVTOPHYS(&r->cmd), &wds[unit].ombs[0],
- wds[unit].ombs[r->ombn].stat, wds[unit].ombs[r->ombn].addr[0],
- wds[unit].ombs[r->ombn].addr[1], wds[unit].ombs[r->ombn].addr[2]);
-
- bzero(&r->cmd, sizeof r->cmd);
- r->cmd.cmd = WDSX_GETFIRMREV;
- r->cmd.write = 0x80;
-
- printf("wdscmd: ");
- for(i=0, p=(u_char *)&r->cmd; i<sizeof r->cmd; i++)
- printf("%02x ", p[i]);
- printf("\n");
-
- outb(base+WDS_HCR, WDSH_DRQEN);
- r->polled = 1;
-
- c = WDSC_MSTART(r->ombn);
- flushcache();
- if( wds_cmd(base, &c, sizeof c) != 0) {
- printf("wds%d: unable to start outgoing mbox\n", unit);
- r->busy = 0;
- /* XXX need to free mailbox */
- return -1;
- }
-
- delay(10000);
- /*printf("%08x/%08x mbox: %02x %02x %02x %02x\n", &r->cmd, KVTOPHYS(&r->cmd),
- wds[unit].ombs[r->ombn].stat, wds[unit].ombs[r->ombn].addr[0],
- wds[unit].ombs[r->ombn].addr[1], wds[unit].ombs[r->ombn].addr[2]);*/
-
- while(1) {
- printf("wds%d: polling.", unit);
- i = 0;
- while( (inb(base+WDS_STAT) & WDS_IRQ) == 0) {
- printf(".");
- delay(10000);
- if(++i == 10) {
- printf("failed %02x\n", inb(base+WDS_IRQSTAT));
- /*r->busy = 0;*/
- return -1;
- }
- }
- flushcache();
- printf("got one!\n");
- wdsintr(unit);
- if(r->done) {
- printf("wds%d: version %02x %02x\n", unit,
- r->cmd.targ, r->cmd.scb.opcode);
- r->busy = 0;
- return 0;
- }
- }
-}
-
-int
-wdsattach(struct isa_device *dev)
-{
- int masunit;
- static int firstswitch[NWDS];
- static u_long versprobe /* max 32 controllers */
- int r;
-
- if (!dev->id_parent)
- return 1;
- masunit = dev->id_parent->id_unit;
-
- if( !(versprobe & (1<<masunit))) {
- versprobe |= (1<<masunit);
- if(wds_getvers(masunit)==-1)
- printf("wds%d: getvers failed\n", masunit);
- }
-
- if (!firstswitch[masunit]) {
- firstswitch[masunit] = 1;
- wds_switch[masunit].name = "wds";
- wds_switch[masunit].scsi_cmd = wds_scsi_cmd;
- wds_switch[masunit].scsi_minphys = wdsminphys;
- wds_switch[masunit].open_target_lu = 0;
- wds_switch[masunit].close_target_lu = 0;
- wds_switch[masunit].adapter_info = wds_adapter_info;
- for (r = 0; r < 8; r++) {
- wds_switch[masunit].empty[r] = 0;
- wds_switch[masunit].used[r] = 0;
- wds_switch[masunit].printed[r] = 0;
- }
- }
- r = scsi_attach(masunit, &wds_switch[masunit], &dev->id_physid,
- &dev->id_unit, dev->id_flags);
- return r;
-}
-
-int
-wds_init(struct isa_device *dev)
-{
- struct wds_setup init;
- int base;
- u_char *p, c;
- int unit, i;
-
- unit = dev->id_unit;
- base = wds[unit].addr;
-
- /*
- * Sending a command causes the CMDRDY bit to clear.
- */
- c = inb(base+WDS_STAT);
- for(i=0; i<4; i++)
- if( (inb(base+WDS_STAT) & WDS_RDY) != 0) {
- goto ready;
- delay(10);
- }
- return 1;
-
-ready:
- outb(base+WDS_CMD, WDSC_NOOP);
- if( inb(base+WDS_STAT) & WDS_RDY)
- return 1;
-
- /*
- * the controller exists. reset and init.
- */
- outb(base+WDS_HCR, WDSH_SCSIRESET|WDSH_ASCRESET);
- delay(3);
- outb(base+WDS_HCR, WDSH_DRQEN);
- delay(20000);
-
-#if 1
- outb(0xd6, 0xc3);
- outb(0xd4, 0x03);
-#else
- isa_dmacascade(dev->id_drq);
-#endif
-
- if( (inb(base+WDS_STAT) & (WDS_RDY)) != WDS_RDY) {
- printf("wds%d: waiting for controller to become ready", unit);
- for(i=0; i<6; i++) {
- if( (inb(base+WDS_STAT) & (WDS_RDY)) == WDS_RDY)
- break;
- printf(".");
- delay(10000);
- }
- if( (inb(base+WDS_STAT) & (WDS_RDY)) != WDS_RDY) {
- printf("failed\n");
- return 1;
- }
- }
-
- bzero(&init, sizeof init);
- init.cmd = WDSC_INIT;
- init.scsi_id = 0;
- init.buson_t = 24;
- init.busoff_t = 48;
- p2x(&init.mbaddr[0], KVTOPHYS(&wds[unit].ombs[0]));
- init.xx = 0;
- init.nomb = WDS_NOMB;
- init.nimb = WDS_NIMB;
-
- /*p = (u_char *)&init;
- printf("wds%d: %08x %08x init: ", unit,
- &wds[unit].ombs[0], KVTOPHYS(&wds[unit].ombs[0]));
- for(i=0; i<sizeof init; i++)
- printf("%02x ", p[i]);
- printf("\n");*/
-
- wds_wait(base+WDS_STAT, WDS_RDY, WDS_RDY);
- flushcache();
- if( wds_cmd(base, (u_char *)&init, sizeof init) != 0) {
- printf("wds%d: wds_cmd failed\n", unit);
- return 1;
- }
- wds_wait(base+WDS_STAT, WDS_INIT, WDS_INIT);
-
- wds_wait(base+WDS_STAT, WDS_RDY, WDS_RDY);
- c = WDSC_DISUNSOL;
- if( wds_cmd(base, &c, sizeof c) != 0) {
- printf("wds%d: wds_cmd failed\n", unit);
- return 1;
- }
-
- return 0;
-}
-
-int
-wds_cmd(int base, u_char *p, int l)
-{
- int i;
- u_char c;
-
- i = 0;
- while(i < l) {
- while( ((c=inb(base+WDS_STAT)) & WDS_RDY) == 0)
- ;
-
- outb(base+WDS_CMD, *p);
-
- while( ((c=inb(base+WDS_STAT)) & WDS_RDY) == 0)
- ;
-
- if(c & WDS_REJ)
- return 1;
- p++;
- i++;
- }
- while( ((c=inb(base+WDS_STAT)) & WDS_RDY) == 0)
- ;
- if(c & WDS_REJ)
- return 1;
- /*printf("wds_cmd: %02x\n", inb(base+WDS_STAT));*/
- return 0;
-}
-
-void
-wds_wait(int reg, int mask, int val)
-{
- while( (inb(reg) & mask) != val)
- ;
-}
-
-#endif
diff --git a/sys/dev/isa/wds.c b/sys/dev/isa/wds.c
new file mode 100644
index 00000000000..c102f7008af
--- /dev/null
+++ b/sys/dev/isa/wds.c
@@ -0,0 +1,1306 @@
+/* $NetBSD: wds.c,v 1.4 1996/04/11 22:30:38 cgd Exp $ */
+
+#define WDSDIAG
+#define integrate
+
+/*
+ * XXX
+ * sense data
+ * aborts
+ * resets
+ */
+
+/*
+ * Copyright (c) 1994, 1995 Julian Highfield. All rights reserved.
+ * Portions copyright (c) 1994, 1996 Charles M. Hannum. 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 Julian Highfield.
+ * 4. 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.
+ */
+
+/*
+ * This driver is for the WD7000 family of SCSI controllers:
+ * the WD7000-ASC, a bus-mastering DMA controller,
+ * the WD7000-FASST2, an -ASC with new firmware and scatter-gather,
+ * and the WD7000-ASE, which was custom manufactured for Apollo
+ * workstations and seems to include an -ASC as well as floppy
+ * and ESDI interfaces.
+ *
+ * Loosely based on Theo Deraadt's unfinished attempt.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/buf.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+
+#include <machine/pio.h>
+
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+
+#include <dev/isa/isavar.h>
+#include <dev/isa/isadmavar.h>
+#include <dev/isa/wdsreg.h>
+
+#ifndef DDB
+#define Debugger() panic("should call debugger here (wds.c)")
+#endif /* ! DDB */
+
+#define WDS_MBX_SIZE 16
+
+#define WDS_SCB_MAX 32
+#define SCB_HASH_SIZE 32 /* hash table size for phystokv */
+#define SCB_HASH_SHIFT 9
+#define SCB_HASH(x) ((((long)(x))>>SCB_HASH_SHIFT) & (SCB_HASH_SIZE - 1))
+
+#define wds_nextmbx(wmb, mbx, mbio) \
+ if ((wmb) == &(mbx)->mbio[WDS_MBX_SIZE - 1]) \
+ (wmb) = &(mbx)->mbio[0]; \
+ else \
+ (wmb)++;
+
+struct wds_mbx {
+ struct wds_mbx_out mbo[WDS_MBX_SIZE];
+ struct wds_mbx_in mbi[WDS_MBX_SIZE];
+ struct wds_mbx_out *cmbo; /* Collection Mail Box out */
+ struct wds_mbx_out *tmbo; /* Target Mail Box out */
+ struct wds_mbx_in *tmbi; /* Target Mail Box in */
+};
+
+#define KVTOPHYS(x) vtophys(x)
+
+struct wds_softc {
+ struct device sc_dev;
+ struct isadev sc_id;
+ void *sc_ih;
+
+ int sc_iobase;
+ int sc_irq, sc_drq;
+
+ int sc_revision;
+
+ struct wds_mbx sc_mbx;
+#define wmbx (&sc->sc_mbx)
+ struct wds_scb *sc_scbhash[SCB_HASH_SIZE];
+ TAILQ_HEAD(, wds_scb) sc_free_scb, sc_waiting_scb;
+ int sc_numscbs, sc_mbofull;
+ int sc_scsi_dev;
+ struct scsi_link sc_link; /* prototype for subdevs */
+};
+
+/* Define the bounce buffer length... */
+#define BUFLEN (64*1024)
+/* ..and how many there are. One per device! Non-FASST boards need these. */
+#define BUFCNT 8
+/* The macro for deciding whether the board needs a buffer. */
+#define NEEDBUFFER(sc) (sc->sc_revision < 0x800)
+
+struct wds_buf {
+ u_char data[BUFLEN];
+ int busy;
+ TAILQ_ENTRY(wds_buf) chain;
+} wds_buffer[BUFCNT];
+
+TAILQ_HEAD(, wds_buf) wds_free_buffer;
+
+integrate void wds_wait __P((int, int, int));
+int wds_cmd __P((int, u_char *, int));
+integrate void wds_finish_scbs __P((struct wds_softc *));
+int wdsintr __P((void *));
+integrate void wds_reset_scb __P((struct wds_softc *, struct wds_scb *));
+void wds_free_scb __P((struct wds_softc *, struct wds_scb *));
+void wds_free_buf __P((struct wds_softc *, struct wds_buf *));
+integrate void wds_init_scb __P((struct wds_softc *, struct wds_scb *));
+struct wds_scb *wds_get_scb __P((struct wds_softc *, int, int));
+struct wds_buf *wds_get_buf __P((struct wds_softc *, int));
+struct wds_scb *wds_scb_phys_kv __P((struct wds_softc *, u_long));
+void wds_queue_scb __P((struct wds_softc *, struct wds_scb *));
+void wds_collect_mbo __P((struct wds_softc *));
+void wds_start_scbs __P((struct wds_softc *));
+void wds_done __P((struct wds_softc *, struct wds_scb *, u_char));
+int wds_find __P((struct isa_attach_args *, struct wds_softc *));
+void wds_init __P((struct wds_softc *));
+void wds_inquire_setup_information __P((struct wds_softc *));
+void wdsminphys __P((struct buf *));
+int wds_scsi_cmd __P((struct scsi_xfer *));
+void wds_sense __P((struct wds_softc *, struct wds_scb *));
+int wds_poll __P((struct wds_softc *, struct scsi_xfer *, int));
+int wds_ipoll __P((struct wds_softc *, struct wds_scb *, int));
+void wds_timeout __P((void *));
+
+struct scsi_adapter wds_switch = {
+ wds_scsi_cmd,
+ wdsminphys,
+ 0,
+ 0,
+};
+
+/* the below structure is so we have a default dev struct for our link struct */
+struct scsi_device wds_dev = {
+ NULL, /* Use default error handler */
+ NULL, /* have a queue, served by this */
+ NULL, /* have no async handler */
+ NULL, /* Use default 'done' routine */
+};
+
+int wdsprobe __P((struct device *, void *, void *));
+void wdsattach __P((struct device *, struct device *, void *));
+int wdsprint __P((void *, char *));
+
+struct cfattach wds_ca = {
+ sizeof(struct wds_softc), wdsprobe, wdsattach
+};
+
+struct cfdriver wds_cd = {
+ NULL, "wds", DV_DULL
+};
+
+#define WDS_ABORT_TIMEOUT 2000 /* time to wait for abort (mSec) */
+
+integrate void
+wds_wait(port, mask, val)
+ int port;
+ int mask;
+ int val;
+{
+
+ while ((inb(port) & mask) != val)
+ ;
+}
+
+/*
+ * Write a command to the board's I/O ports.
+ */
+int
+wds_cmd(iobase, ibuf, icnt)
+ int iobase;
+ u_char *ibuf;
+ int icnt;
+{
+ u_char c;
+
+ wds_wait(iobase + WDS_STAT, WDSS_RDY, WDSS_RDY);
+
+ while (icnt--) {
+ outb(iobase + WDS_CMD, *ibuf++);
+ wds_wait(iobase + WDS_STAT, WDSS_RDY, WDSS_RDY);
+ c = inb(iobase + WDS_STAT);
+ if (c & WDSS_REJ)
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Check for the presence of a WD7000 SCSI controller.
+ */
+int
+wdsprobe(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ register struct isa_attach_args *ia = aux;
+
+#ifdef NEWCONFIG
+ if (ia->ia_iobase == IOBASEUNK)
+ return 0;
+#endif
+
+ /* See if there is a unit at this location. */
+ if (wds_find(ia, NULL) != 0)
+ return 0;
+
+ ia->ia_msize = 0;
+ ia->ia_iosize = 8;
+ return 1;
+}
+
+int
+wdsprint(aux, name)
+ void *aux;
+ char *name;
+{
+
+ if (name != NULL)
+ printf("%s: scsibus ", name);
+ return UNCONF;
+}
+
+/*
+ * Attach all available units.
+ */
+void
+wdsattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct isa_attach_args *ia = aux;
+ struct wds_softc *sc = (void *)self;
+
+ if (wds_find(ia, sc) != 0)
+ panic("wdsattach: wds_find of %s failed", self->dv_xname);
+ sc->sc_iobase = ia->ia_iobase;
+
+ if (sc->sc_drq != DRQUNK)
+ isa_dmacascade(sc->sc_drq);
+
+ wds_init(sc);
+ TAILQ_INIT(&sc->sc_free_scb);
+ TAILQ_INIT(&sc->sc_waiting_scb);
+ wds_inquire_setup_information(sc);
+
+ /*
+ * fill in the prototype scsi_link.
+ */
+ sc->sc_link.adapter_softc = sc;
+ sc->sc_link.adapter_target = sc->sc_scsi_dev;
+ sc->sc_link.adapter = &wds_switch;
+ sc->sc_link.device = &wds_dev;
+ /* XXX */
+ /* I don't think the -ASE can handle openings > 1. */
+ /* It gives Vendor Error 26 whenever I try it. */
+ sc->sc_link.openings = 1;
+
+#ifdef NEWCONFIG
+ isa_establish(&sc->sc_id, &sc->sc_dev);
+#endif
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, sc->sc_irq, IST_EDGE,
+ IPL_BIO, wdsintr, sc, sc->sc_dev.dv_xname);
+
+ /*
+ * ask the adapter what subunits are present
+ */
+ config_found(self, &sc->sc_link, wdsprint);
+}
+
+integrate void
+wds_finish_scbs(sc)
+ struct wds_softc *sc;
+{
+ struct wds_mbx_in *wmbi;
+ struct wds_scb *scb;
+ int i;
+
+ wmbi = wmbx->tmbi;
+
+ if (wmbi->stat == WDS_MBI_FREE) {
+ for (i = 0; i < WDS_MBX_SIZE; i++) {
+ if (wmbi->stat != WDS_MBI_FREE) {
+ printf("%s: mbi not in round-robin order\n",
+ sc->sc_dev.dv_xname);
+ goto AGAIN;
+ }
+ wds_nextmbx(wmbi, wmbx, mbi);
+ }
+#ifdef WDSDIAGnot
+ printf("%s: mbi interrupt with no full mailboxes\n",
+ sc->sc_dev.dv_xname);
+#endif
+ return;
+ }
+
+AGAIN:
+ do {
+ scb = wds_scb_phys_kv(sc, phystol(wmbi->scb_addr));
+ if (!scb) {
+ printf("%s: bad mbi scb pointer; skipping\n",
+ sc->sc_dev.dv_xname);
+ goto next;
+ }
+
+#ifdef WDSDEBUG
+ if (wds_debug) {
+ u_char *cp = &scb->scsi_cmd;
+ printf("op=%x %x %x %x %x %x\n",
+ cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
+ printf("stat %x for mbi addr = 0x%08x, ",
+ wmbi->stat, wmbi);
+ printf("scb addr = 0x%x\n", scb);
+ }
+#endif /* WDSDEBUG */
+
+ untimeout(wds_timeout, scb);
+ wds_done(sc, scb, wmbi->stat);
+
+ next:
+ wmbi->stat = WDS_MBI_FREE;
+ wds_nextmbx(wmbi, wmbx, mbi);
+ } while (wmbi->stat != WDS_MBI_FREE);
+
+ wmbx->tmbi = wmbi;
+}
+
+/*
+ * Process an interrupt.
+ */
+int
+wdsintr(arg)
+ void *arg;
+{
+ struct wds_softc *sc = arg;
+ int iobase = sc->sc_iobase;
+ u_char sts;
+
+ struct wds_mbx_in *in;
+ struct wds_scb *scb;
+ u_char stat, c;
+
+ /* Was it really an interrupt from the board? */
+ if ((inb(iobase + WDS_STAT) & WDSS_IRQ) == 0)
+ return 0;
+
+ /* Get the interrupt status byte. */
+ c = inb(iobase + WDS_IRQSTAT) & WDSI_MASK;
+
+ /* Acknowledge (which resets) the interrupt. */
+ outb(iobase + WDS_IRQACK, 0x00);
+
+ switch (c) {
+ case WDSI_MSVC:
+ wds_finish_scbs(sc);
+ break;
+
+ case WDSI_MFREE:
+ wds_start_scbs(sc);
+ break;
+
+ default:
+ printf("%s: unrecognized interrupt type %02x", c);
+ break;
+ }
+
+ return 1;
+}
+
+integrate void
+wds_reset_scb(sc, scb)
+ struct wds_softc *sc;
+ struct wds_scb *scb;
+{
+
+ scb->flags = 0;
+}
+
+/*
+ * Free the command structure, the outgoing mailbox and the data buffer.
+ */
+void
+wds_free_scb(sc, scb)
+ struct wds_softc *sc;
+ struct wds_scb *scb;
+{
+ int s;
+
+ if (scb->buf != 0) {
+ wds_free_buf(sc, scb->buf);
+ scb->buf = 0;
+ }
+
+ s = splbio();
+
+ wds_reset_scb(sc, scb);
+ TAILQ_INSERT_HEAD(&sc->sc_free_scb, scb, chain);
+
+ /*
+ * If there were none, wake anybody waiting for one to come free,
+ * starting with queued entries.
+ */
+ if (scb->chain.tqe_next == 0)
+ wakeup(&sc->sc_free_scb);
+
+ splx(s);
+}
+
+void
+wds_free_buf(sc, buf)
+ struct wds_softc *sc;
+ struct wds_buf *buf;
+{
+ int s;
+
+ s = splbio();
+
+ buf->busy = 0;
+ TAILQ_INSERT_HEAD(&wds_free_buffer, buf, chain);
+
+ /*
+ * If there were none, wake anybody waiting for one to come free,
+ * starting with queued entries.
+ */
+ if (buf->chain.tqe_next == 0)
+ wakeup(&wds_free_buffer);
+
+ splx(s);
+}
+
+integrate void
+wds_init_scb(sc, scb)
+ struct wds_softc *sc;
+ struct wds_scb *scb;
+{
+ int hashnum;
+
+ bzero(scb, sizeof(struct wds_scb));
+ /*
+ * put in the phystokv hash table
+ * Never gets taken out.
+ */
+ scb->hashkey = KVTOPHYS(scb);
+ hashnum = SCB_HASH(scb->hashkey);
+ scb->nexthash = sc->sc_scbhash[hashnum];
+ sc->sc_scbhash[hashnum] = scb;
+ wds_reset_scb(sc, scb);
+}
+
+/*
+ * Get a free scb
+ *
+ * If there are none, see if we can allocate a new one. If so, put it in
+ * the hash table too otherwise either return an error or sleep.
+ */
+struct wds_scb *
+wds_get_scb(sc, flags, needbuffer)
+ struct wds_softc *sc;
+ int flags;
+ int needbuffer;
+{
+ struct wds_scb *scb;
+ int s;
+
+ s = splbio();
+
+ /*
+ * If we can and have to, sleep waiting for one to come free
+ * but only if we can't allocate a new one.
+ */
+ for (;;) {
+ scb = sc->sc_free_scb.tqh_first;
+ if (scb) {
+ TAILQ_REMOVE(&sc->sc_free_scb, scb, chain);
+ break;
+ }
+ if (sc->sc_numscbs < WDS_SCB_MAX) {
+ scb = (struct wds_scb *) malloc(sizeof(struct wds_scb),
+ M_TEMP, M_NOWAIT);
+ if (!scb) {
+ printf("%s: can't malloc scb\n",
+ sc->sc_dev.dv_xname);
+ goto out;
+ }
+ wds_init_scb(sc, scb);
+ sc->sc_numscbs++;
+ break;
+ }
+ if ((flags & SCSI_NOSLEEP) != 0)
+ goto out;
+ tsleep(&sc->sc_free_scb, PRIBIO, "wdsscb", 0);
+ }
+
+ scb->flags |= SCB_ALLOC;
+
+ if (needbuffer) {
+ scb->buf = wds_get_buf(sc, flags);
+ if (scb->buf == 0)
+ wds_free_scb(sc, scb);
+ scb = 0;
+ }
+
+out:
+ splx(s);
+ return (scb);
+}
+
+struct wds_buf *
+wds_get_buf(sc, flags)
+ struct wds_softc *sc;
+ int flags;
+{
+ struct wds_buf *buf;
+ int s;
+
+ s = splbio();
+
+ for (;;) {
+ buf = wds_free_buffer.tqh_first;
+ if (buf) {
+ TAILQ_REMOVE(&wds_free_buffer, buf, chain);
+ break;
+ }
+ if ((flags & SCSI_NOSLEEP) != 0)
+ goto out;
+ tsleep(&wds_free_buffer, PRIBIO, "wdsbuf", 0);
+ }
+
+ buf->busy = 1;
+
+out:
+ splx(s);
+ return (buf);
+}
+
+struct wds_scb *
+wds_scb_phys_kv(sc, scb_phys)
+ struct wds_softc *sc;
+ u_long scb_phys;
+{
+ int hashnum = SCB_HASH(scb_phys);
+ struct wds_scb *scb = sc->sc_scbhash[hashnum];
+
+ while (scb) {
+ if (scb->hashkey == scb_phys)
+ break;
+ /* XXX Check to see if it matches the sense command block. */
+ if (scb->hashkey == (scb_phys - sizeof(struct wds_cmd)))
+ break;
+ scb = scb->nexthash;
+ }
+ return scb;
+}
+
+/*
+ * Queue a SCB to be sent to the controller, and send it if possible.
+ */
+void
+wds_queue_scb(sc, scb)
+ struct wds_softc *sc;
+ struct wds_scb *scb;
+{
+
+ TAILQ_INSERT_TAIL(&sc->sc_waiting_scb, scb, chain);
+ wds_start_scbs(sc);
+}
+
+/*
+ * Garbage collect mailboxes that are no longer in use.
+ */
+void
+wds_collect_mbo(sc)
+ struct wds_softc *sc;
+{
+ struct wds_mbx_out *wmbo; /* Mail Box Out pointer */
+ struct wds_scb *scb;
+
+ wmbo = wmbx->cmbo;
+
+ while (sc->sc_mbofull > 0) {
+ if (wmbo->cmd != WDS_MBO_FREE)
+ break;
+
+#ifdef WDSDIAG
+ scb = wds_scb_phys_kv(sc, phystol(wmbo->scb_addr));
+ scb->flags &= ~SCB_SENDING;
+#endif
+
+ --sc->sc_mbofull;
+ wds_nextmbx(wmbo, wmbx, mbo);
+ }
+
+ wmbx->cmbo = wmbo;
+}
+
+/*
+ * Send as many SCBs as we have empty mailboxes for.
+ */
+void
+wds_start_scbs(sc)
+ struct wds_softc *sc;
+{
+ int iobase = sc->sc_iobase;
+ struct wds_mbx_out *wmbo; /* Mail Box Out pointer */
+ struct wds_scb *scb;
+ int i;
+ u_char c;
+
+ wmbo = wmbx->tmbo;
+
+ while (scb = sc->sc_waiting_scb.tqh_first) {
+ if (sc->sc_mbofull >= WDS_MBX_SIZE) {
+ wds_collect_mbo(sc);
+ if (sc->sc_mbofull >= WDS_MBX_SIZE) {
+ c = WDSC_IRQMFREE;
+ wds_cmd(iobase, &c, sizeof c);
+ break;
+ }
+ }
+
+ TAILQ_REMOVE(&sc->sc_waiting_scb, scb, chain);
+#ifdef WDSDIAG
+ scb->flags |= SCB_SENDING;
+#endif
+
+ /* Link scb to mbo. */
+ if (scb->flags & SCB_SENSE)
+ ltophys(KVTOPHYS(&scb->sense), wmbo->scb_addr);
+ else
+ ltophys(KVTOPHYS(&scb->cmd), wmbo->scb_addr);
+ /* XXX What about aborts? */
+ wmbo->cmd = WDS_MBO_START;
+
+ /* Tell the card to poll immediately. */
+ c = WDSC_MSTART(wmbo - wmbx->mbo);
+ wds_cmd(sc->sc_iobase, &c, sizeof c);
+
+ if ((scb->flags & SCB_POLLED) == 0)
+ timeout(wds_timeout, scb, (scb->timeout * hz) / 1000);
+
+ next:
+ ++sc->sc_mbofull;
+ wds_nextmbx(wmbo, wmbx, mbo);
+ }
+
+ wmbx->tmbo = wmbo;
+}
+
+/*
+ * Process the result of a SCSI command.
+ */
+void
+wds_done(sc, scb, stat)
+ struct wds_softc *sc;
+ struct wds_scb *scb;
+ u_char stat;
+{
+ struct scsi_xfer *xs = scb->xs;
+ int i, x;
+
+ /* XXXXX */
+
+ /* Don't release the SCB if it was an internal command. */
+ if (xs == 0) {
+ scb->flags |= SCB_DONE;
+ return;
+ }
+
+ /* Sense handling. */
+ if (xs->error == XS_SENSE) {
+ bcopy(&scb->sense_data, &xs->sense, sizeof (struct scsi_sense_data));
+ } else {
+ if (xs->error == XS_NOERROR) {
+ /* If all went well, or an error is acceptable. */
+ if (stat == WDS_MBI_OK) {
+ /* OK, set the result */
+ xs->resid = 0;
+ } else {
+ /* Check the mailbox status. */
+ switch (stat) {
+ case WDS_MBI_OKERR:
+ /* SCSI error recorded in scb, counts as WDS_MBI_OK */
+ switch (scb->cmd.venderr) {
+ case 0x00:
+ printf("%s: Is this an error?\n", sc->sc_dev.dv_xname);
+ xs->error = XS_DRIVER_STUFFUP; /* Experiment */
+ break;
+ case 0x01:
+ /*printf("%s: OK, see SCSI error field.\n", sc->sc_dev.dv_xname);*/
+ if (scb->cmd.stat == SCSI_CHECK) {
+ /* Do sense. */
+ wds_sense (sc, scb);
+ return;
+ } else if (scb->cmd.stat == SCSI_BUSY) {
+ xs->error = XS_BUSY;
+ }
+ break;
+ case 0x40:
+ /*printf("%s: DMA underrun!\n", sc->sc_dev.dv_xname);*/
+ /* Hits this if the target returns fewer that datalen bytes (eg my CD-ROM,
+ which returns a short version string, or if DMA is turned off etc. */
+ xs->resid = 0;
+ break;
+ default:
+ printf("%s: VENDOR ERROR %02x, scsi %02x\n", sc->sc_dev.dv_xname, scb->cmd.venderr, scb->cmd.stat);
+ xs->error = XS_DRIVER_STUFFUP; /* Experiment */
+ break;
+ }
+ break;
+ case WDS_MBI_ETIME:
+ /*
+ * The documentation isn't clear on
+ * what conditions might generate this,
+ * but selection timeouts are the only
+ * one I can think of.
+ */
+ xs->error = XS_SELTIMEOUT;
+ break;
+ case WDS_MBI_ERESET:
+ case WDS_MBI_ETARCMD:
+ case WDS_MBI_ERESEL:
+ case WDS_MBI_ESEL:
+ case WDS_MBI_EABORT:
+ case WDS_MBI_ESRESET:
+ case WDS_MBI_EHRESET:
+ xs->error = XS_DRIVER_STUFFUP;
+ break;
+ }
+ }
+ } /* else sense */
+
+ if (NEEDBUFFER(sc) && xs->datalen) {
+ if (xs->flags & SCSI_DATA_IN)
+ bcopy(scb->buf->data, xs->data, xs->datalen);
+ }
+ } /* XS_NOERROR */
+
+ wds_free_scb(sc, scb);
+ xs->flags |= ITSDONE;
+ scsi_done(xs);
+}
+
+int
+wds_find(ia, sc)
+ struct isa_attach_args *ia;
+ struct wds_softc *sc;
+{
+ int iobase = ia->ia_iobase;
+ u_char c;
+ int i;
+
+ /* XXXXX */
+
+ /*
+ * Sending a command causes the CMDRDY bit to clear.
+ */
+ c = inb(iobase + WDS_STAT);
+ for (i = 0; i < 4; i++)
+ if ((inb(iobase+WDS_STAT) & WDSS_RDY) != 0) {
+ goto ready;
+ delay(10);
+ }
+ return 1;
+
+ready:
+ outb(iobase + WDS_CMD, WDSC_NOOP);
+ if (inb(iobase + WDS_STAT) & WDSS_RDY)
+ return 1;
+
+ outb(iobase + WDS_HCR, WDSH_SCSIRESET|WDSH_ASCRESET);
+ delay(10000);
+ outb(iobase + WDS_HCR, 0x00);
+ delay(500000);
+ wds_wait(iobase + WDS_STAT, WDSS_RDY, WDSS_RDY);
+ if (inb(iobase + WDS_IRQSTAT) != 1)
+ if (inb(iobase + WDS_IRQSTAT) != 7)
+ printf("%s: failed reset!!! %2x\n", sc->sc_dev.dv_xname, inb(iobase + WDS_IRQSTAT));
+
+ if ((inb(iobase + WDS_STAT) & (WDSS_RDY)) != WDSS_RDY) {
+ printf("%s: waiting for controller to become ready.", sc->sc_dev.dv_xname);
+ for (i = 0; i < 20; i++) {
+ if ((inb(iobase + WDS_STAT) & (WDSS_RDY)) == WDSS_RDY)
+ break;
+ printf(".");
+ delay(10000);
+ }
+ if ((inb(iobase + WDS_STAT) & (WDSS_RDY)) != WDSS_RDY) {
+ printf(" failed\n");
+ return 1;
+ }
+ printf("\n");
+ }
+
+ if (sc != NULL) {
+ /* XXX Can we do this better? */
+ /* who are we on the scsi bus? */
+ sc->sc_scsi_dev = 7;
+
+ sc->sc_iobase = iobase;
+ sc->sc_irq = ia->ia_irq;
+ sc->sc_drq = ia->ia_drq;
+ }
+
+ return 0;
+}
+
+/*
+ * Initialise the board and driver.
+ */
+void
+wds_init(sc)
+ struct wds_softc *sc;
+{
+ int iobase = sc->sc_iobase;
+ struct wds_setup init;
+ u_char c;
+ int i;
+
+ /*
+ * Set up initial mail box for round-robin operation.
+ */
+ for (i = 0; i < WDS_MBX_SIZE; i++) {
+ wmbx->mbo[i].cmd = WDS_MBO_FREE;
+ wmbx->mbi[i].stat = WDS_MBO_FREE;
+ }
+ wmbx->cmbo = wmbx->tmbo = &wmbx->mbo[0];
+ wmbx->tmbi = &wmbx->mbi[0];
+ sc->sc_mbofull = 0;
+
+ /* Clear the buffers. */
+ TAILQ_INIT(&wds_free_buffer);
+ for (i = 0; i < BUFCNT; i++) {
+ wds_buffer[i].busy = 0;
+ TAILQ_INSERT_HEAD(&wds_free_buffer, &wds_buffer[i], chain);
+ }
+
+ init.opcode = WDSC_INIT;
+ init.scsi_id = sc->sc_scsi_dev;
+ /* Record scsi id of controller for use in scsi_attach */
+ sc->sc_scsi_dev = init.scsi_id;
+ init.buson_t = 48;
+ init.busoff_t = 24;
+ init.xx = 0;
+ ltophys(KVTOPHYS(wmbx), init.mbaddr);
+ init.nomb = init.nimb = WDS_MBX_SIZE;
+ wds_cmd(iobase, (u_char *)&init, sizeof init);
+
+ wds_wait(iobase + WDS_STAT, WDSS_INIT, WDSS_INIT);
+
+ c = WDSC_DISUNSOL;
+ wds_cmd(iobase, &c, sizeof c);
+
+ outb(iobase + WDS_HCR, WDSH_DRQEN);
+}
+
+/*
+ * Read the board's firmware revision information.
+ */
+void
+wds_inquire_setup_information(sc)
+ struct wds_softc *sc;
+{
+ struct wds_scb *scb;
+ int iobase;
+ u_char *j;
+ int s;
+
+ iobase = sc->sc_iobase;
+
+ if ((scb = wds_get_scb(sc, SCSI_NOSLEEP, 0)) == NULL) {
+ printf("%s: no request slot available in getvers()!\n", sc->sc_dev.dv_xname);
+ return;
+ }
+ scb->xs = NULL;
+ scb->timeout = 40;
+
+ bzero(&scb->cmd, sizeof scb->cmd);
+ scb->cmd.write = 0x80;
+ scb->cmd.opcode = WDSX_GETFIRMREV;
+
+ /* Will poll card, await result. */
+ outb(iobase + WDS_HCR, WDSH_DRQEN);
+ scb->flags |= SCB_POLLED;
+
+ s = splbio();
+ wds_queue_scb(sc, scb);
+ splx(s);
+
+ if (wds_ipoll(sc, scb, scb->timeout))
+ goto out;
+
+ /* Print the version number. */
+ printf(": version %x.%02x ", scb->cmd.targ, scb->cmd.scb.opcode);
+ sc->sc_revision = (scb->cmd.targ << 8) | scb->cmd.scb.opcode;
+ /* Print out the version string. */
+ j = 2 + &(scb->cmd.targ);
+ while ((*j >= 32) && (*j < 128)) {
+ printf("%c", *j);
+ j++;
+ }
+
+out:
+ printf("\n");
+ wds_free_scb(sc, scb);
+}
+
+void
+wdsminphys(bp)
+ struct buf *bp;
+{
+
+ if (bp->b_bcount > ((WDS_NSEG - 1) << PGSHIFT))
+ bp->b_bcount = ((WDS_NSEG - 1) << PGSHIFT);
+ minphys(bp);
+}
+
+/*
+ * Send a SCSI command.
+ */
+int
+wds_scsi_cmd(xs)
+ struct scsi_xfer *xs;
+{
+ struct scsi_link *sc_link = xs->sc_link;
+ struct wds_softc *sc = sc_link->adapter_softc;
+ struct wds_scb *scb;
+ struct wds_scat_gath *sg;
+ int seg;
+ u_long thiskv, thisphys, nextphys;
+ int bytes_this_seg, bytes_this_page, datalen, flags;
+ struct iovec *iovp;
+ int s;
+
+ int iobase;
+
+ iobase = sc->sc_iobase;
+
+ if (xs->flags & SCSI_RESET) {
+ /* XXX Fix me! */
+ printf("%s: reset!\n", sc->sc_dev.dv_xname);
+ wds_init(sc);
+ return COMPLETE;
+ }
+
+ flags = xs->flags;
+ if ((scb = wds_get_scb(sc, flags, NEEDBUFFER(sc))) == NULL) {
+ xs->error = XS_DRIVER_STUFFUP;
+ return TRY_AGAIN_LATER;
+ }
+ scb->xs = xs;
+ scb->timeout = xs->timeout;
+
+ if (xs->flags & SCSI_DATA_UIO) {
+ /* XXX Fix me! */
+ /* Let's not worry about UIO. There isn't any code for the *
+ * non-SG boards anyway! */
+ printf("%s: UIO is untested and disabled!\n", sc->sc_dev.dv_xname);
+ goto bad;
+ }
+
+ /* Zero out the command structure. */
+ bzero(&scb->cmd, sizeof scb->cmd);
+ bcopy(xs->cmd, &scb->cmd.scb, xs->cmdlen < 12 ? xs->cmdlen : 12);
+
+ /* Set up some of the command fields. */
+ scb->cmd.targ = (xs->sc_link->target << 5) | xs->sc_link->lun;
+
+ /* NOTE: cmd.write may be OK as 0x40 (disable direction checking)
+ * on boards other than the WD-7000V-ASE. Need this for the ASE:
+ */
+ scb->cmd.write = (xs->flags & SCSI_DATA_IN) ? 0x80 : 0x00;
+
+ if (!NEEDBUFFER(sc) && xs->datalen) {
+ sg = scb->scat_gath;
+ seg = 0;
+#ifdef TFS
+ if (flags & SCSI_DATA_UIO) {
+ iovp = ((struct uio *)xs->data)->uio_iov;
+ datalen = ((struct uio *)xs->data)->uio_iovcnt;
+ xs->datalen = 0;
+ while (datalen && seg < WDS_NSEG) {
+ ltophys(iovp->iov_base, sg->seg_addr);
+ ltophys(iovp->iov_len, sg->seg_len);
+ xs->datalen += iovp->iov_len;
+ SC_DEBUGN(sc_link, SDEV_DB4, ("UIO(0x%x@0x%x)",
+ iovp->iov_len, iovp->iov_base));
+ sg++;
+ iovp++;
+ seg++;
+ datalen--;
+ }
+ } else
+#endif /* TFS */
+ {
+ /*
+ * Set up the scatter-gather block.
+ */
+ SC_DEBUG(sc_link, SDEV_DB4,
+ ("%d @0x%x:- ", xs->datalen, xs->data));
+
+ datalen = xs->datalen;
+ thiskv = (int)xs->data;
+ thisphys = KVTOPHYS(xs->data);
+
+ while (datalen && seg < WDS_NSEG) {
+ bytes_this_seg = 0;
+
+ /* put in the base address */
+ ltophys(thisphys, sg->seg_addr);
+
+ SC_DEBUGN(sc_link, SDEV_DB4, ("0x%x", thisphys));
+
+ /* do it at least once */
+ nextphys = thisphys;
+ while (datalen && thisphys == nextphys) {
+ /*
+ * This page is contiguous (physically)
+ * with the the last, just extend the
+ * length
+ */
+ /* check it fits on the ISA bus */
+ if (thisphys > 0xFFFFFF) {
+ printf("%s: DMA beyond"
+ " end of ISA\n",
+ sc->sc_dev.dv_xname);
+ goto bad;
+ }
+ /* how far to the end of the page */
+ nextphys = (thisphys & ~PGOFSET) + NBPG;
+ bytes_this_page = nextphys - thisphys;
+ /**** or the data ****/
+ bytes_this_page = min(bytes_this_page,
+ datalen);
+ bytes_this_seg += bytes_this_page;
+ datalen -= bytes_this_page;
+
+ /* get more ready for the next page */
+ thiskv = (thiskv & ~PGOFSET) + NBPG;
+ if (datalen)
+ thisphys = KVTOPHYS(thiskv);
+ }
+ /*
+ * next page isn't contiguous, finish the seg
+ */
+ SC_DEBUGN(sc_link, SDEV_DB4,
+ ("(0x%x)", bytes_this_seg));
+ ltophys(bytes_this_seg, sg->seg_len);
+ sg++;
+ seg++;
+ }
+ }
+ /* end of iov/kv decision */
+ SC_DEBUGN(sc_link, SDEV_DB4, ("\n"));
+ if (datalen) {
+ /*
+ * there's still data, must have run out of segs!
+ */
+ printf("%s: wds_scsi_cmd, more than %d dma segs\n",
+ sc->sc_dev.dv_xname, WDS_NSEG);
+ goto bad;
+ }
+ scb->cmd.opcode = WDSX_SCSISG;
+ ltophys(KVTOPHYS(scb->scat_gath), scb->cmd.data);
+ ltophys(seg * sizeof(struct wds_scat_gath), scb->cmd.len);
+ } else if (xs->datalen > 0) {
+ /* The board is an ASC or ASE. Do not use scatter/gather. */
+ if (xs->datalen > BUFLEN) {
+ printf("%s: wds_scsi_cmd, I/O too large for bounce buffer\n",
+ sc->sc_dev.dv_xname);
+ goto bad;
+ }
+ if (xs->flags & SCSI_DATA_OUT)
+ bcopy(xs->data, scb->buf->data, xs->datalen);
+ else
+ bzero(scb->buf->data, xs->datalen);
+ scb->cmd.opcode = WDSX_SCSICMD;
+ ltophys(KVTOPHYS(scb->buf->data), scb->cmd.data);
+ ltophys(xs->datalen, scb->cmd.len);
+ } else {
+ scb->cmd.opcode = WDSX_SCSICMD;
+ ltophys(0, scb->cmd.data);
+ ltophys(0, scb->cmd.len);
+ }
+
+ scb->cmd.stat = 0x00;
+ scb->cmd.venderr = 0x00;
+ ltophys(0, scb->cmd.link);
+
+ /* XXX Do we really want to do this? */
+ if (flags & SCSI_POLL) {
+ /* Will poll card, await result. */
+ outb(iobase + WDS_HCR, WDSH_DRQEN);
+ scb->flags |= SCB_POLLED;
+ } else {
+ /* Will send command, let interrupt routine handle result. */
+ outb(iobase + WDS_HCR, WDSH_IRQEN | WDSH_DRQEN);
+ }
+
+ s = splbio();
+ wds_queue_scb(sc, scb);
+ splx(s);
+
+ if ((flags & SCSI_POLL) == 0)
+ return SUCCESSFULLY_QUEUED;
+
+ if (wds_poll(sc, xs, scb->timeout)) {
+ wds_timeout(scb);
+ if (wds_poll(sc, xs, scb->timeout))
+ wds_timeout(scb);
+ }
+ return COMPLETE;
+
+bad:
+ xs->error = XS_DRIVER_STUFFUP;
+ wds_free_scb(sc, scb);
+ return COMPLETE;
+}
+
+/*
+ * Send a sense request.
+ */
+void
+wds_sense(sc, scb)
+ struct wds_softc *sc;
+ struct wds_scb *scb;
+{
+ struct scsi_xfer *xs = scb->xs;
+ struct scsi_sense *ss = (void *)&scb->sense.scb;
+ int s;
+ u_char c;
+ int i;
+
+ /* XXXXX */
+
+ /* Send sense request SCSI command. */
+ xs->error = XS_SENSE;
+ scb->flags |= SCB_SENSE;
+
+ /* First, save the return values */
+ if (NEEDBUFFER(sc) && xs->datalen) {
+ if (xs->flags & SCSI_DATA_IN)
+ bcopy(scb->buf->data, xs->data, xs->datalen);
+ }
+
+ /* Next, setup a request sense command block */
+ bzero(ss, sizeof(*ss));
+ ss->opcode = REQUEST_SENSE;
+ ss->byte2 = xs->sc_link->lun << 5;
+ ss->length = sizeof(struct scsi_sense_data);
+
+ /* Set up some of the command fields. */
+ scb->sense.targ = scb->cmd.targ;
+ scb->sense.write = 0x80;
+ scb->sense.opcode = WDSX_SCSICMD;
+ ltophys(KVTOPHYS(&scb->sense_data), scb->sense.data);
+ ltophys(sizeof(struct scsi_sense_data), scb->sense.len);
+
+ s = splbio();
+ wds_queue_scb(sc, scb);
+ splx(s);
+
+ /*
+ * There's no reason for us to poll here. There are two cases:
+ * 1) If it's a polling operation, then we're called from the interrupt
+ * handler, and we return and continue polling.
+ * 2) If it's an interrupt-driven operation, then it gets completed
+ * later on when the REQUEST SENSE finishes.
+ */
+}
+
+/*
+ * Poll a particular unit, looking for a particular scb
+ */
+int
+wds_poll(sc, xs, count)
+ struct wds_softc *sc;
+ struct scsi_xfer *xs;
+ int count;
+{
+ int iobase = sc->sc_iobase;
+
+ /* timeouts are in msec, so we loop in 1000 usec cycles */
+ while (count) {
+ /*
+ * If we had interrupts enabled, would we
+ * have got an interrupt?
+ */
+ if (inb(iobase + WDS_STAT) & WDSS_IRQ)
+ wdsintr(sc);
+ if (xs->flags & ITSDONE)
+ return 0;
+ delay(1000); /* only happens in boot so ok */
+ count--;
+ }
+ return 1;
+}
+
+/*
+ * Poll a particular unit, looking for a particular scb
+ */
+int
+wds_ipoll(sc, scb, count)
+ struct wds_softc *sc;
+ struct wds_scb *scb;
+ int count;
+{
+ int iobase = sc->sc_iobase;
+
+ /* timeouts are in msec, so we loop in 1000 usec cycles */
+ while (count) {
+ /*
+ * If we had interrupts enabled, would we
+ * have got an interrupt?
+ */
+ if (inb(iobase + WDS_STAT) & WDSS_IRQ)
+ wdsintr(sc);
+ if (scb->flags & SCB_DONE)
+ return 0;
+ delay(1000); /* only happens in boot so ok */
+ count--;
+ }
+ return 1;
+}
+
+void
+wds_timeout(arg)
+ void *arg;
+{
+ struct wds_scb *scb = arg;
+ struct scsi_xfer *xs = scb->xs;
+ struct scsi_link *sc_link = xs->sc_link;
+ struct wds_softc *sc = sc_link->adapter_softc;
+ int s;
+
+ sc_print_addr(sc_link);
+ printf("timed out");
+
+ s = splbio();
+
+#ifdef WDSDIAG
+ /*
+ * If The scb's mbx is not free, then the board has gone south?
+ */
+ wds_collect_mbo(sc);
+ if (scb->flags & SCB_SENDING) {
+ printf("%s: not taking commands!\n", sc->sc_dev.dv_xname);
+ Debugger();
+ }
+#endif
+
+ /*
+ * If it has been through before, then
+ * a previous abort has failed, don't
+ * try abort again
+ */
+ if (scb->flags & SCB_ABORT) {
+ /* abort timed out */
+ printf(" AGAIN\n");
+ /* XXX Must reset! */
+ } else {
+ /* abort the operation that has timed out */
+ printf("\n");
+ scb->xs->error = XS_TIMEOUT;
+ scb->timeout = WDS_ABORT_TIMEOUT;
+ scb->flags |= SCB_ABORT;
+ wds_queue_scb(sc, scb);
+ }
+
+ splx(s);
+}
diff --git a/sys/dev/isa/wdsreg.h b/sys/dev/isa/wdsreg.h
new file mode 100644
index 00000000000..e4f7bdafce7
--- /dev/null
+++ b/sys/dev/isa/wdsreg.h
@@ -0,0 +1,147 @@
+typedef u_char physaddr[3];
+typedef u_char physlen[3];
+#define ltophys _lto3b
+#define phystol _3btol
+
+/* WD7000 registers */
+#define WDS_STAT 0 /* read */
+#define WDS_IRQSTAT 1 /* read */
+
+#define WDS_CMD 0 /* write */
+#define WDS_IRQACK 1 /* write */
+#define WDS_HCR 2 /* write */
+
+/* WDS_STAT (read) defs */
+#define WDSS_IRQ 0x80
+#define WDSS_RDY 0x40
+#define WDSS_REJ 0x20
+#define WDSS_INIT 0x10
+
+/* WDS_IRQSTAT (read) defs */
+#define WDSI_MASK 0xc0
+#define WDSI_ERR 0x00
+#define WDSI_MFREE 0x80
+#define WDSI_MSVC 0xc0
+
+/* WDS_CMD (write) defs */
+#define WDSC_NOOP 0x00
+#define WDSC_INIT 0x01
+#define WDSC_DISUNSOL 0x02
+#define WDSC_ENAUNSOL 0x03
+#define WDSC_IRQMFREE 0x04
+#define WDSC_SCSIRESETSOFT 0x05
+#define WDSC_SCSIRESETHARD 0x06
+#define WDSC_MSTART(m) (0x80 + (m))
+#define WDSC_MMSTART(m) (0xc0 + (m))
+
+/* WDS_HCR (write) defs */
+#define WDSH_IRQEN 0x08
+#define WDSH_DRQEN 0x04
+#define WDSH_SCSIRESET 0x02
+#define WDSH_ASCRESET 0x01
+
+#define WDS_NSEG 17
+
+struct wds_scat_gath {
+ physlen seg_len;
+ physaddr seg_addr;
+};
+
+struct wds_cmd {
+ u_char opcode;
+ u_char targ;
+ struct scsi_generic scb;
+ u_char stat;
+ u_char venderr;
+ physlen len;
+ physaddr data;
+ physaddr link;
+ u_char write;
+ u_char xx[6];
+};
+
+struct wds_scb {
+ struct wds_cmd cmd;
+ struct wds_cmd sense;
+
+ struct wds_scat_gath scat_gath[WDS_NSEG];
+ struct scsi_sense_data sense_data;
+
+ TAILQ_ENTRY(wds_scb) chain;
+ struct wds_scb *nexthash;
+ long hashkey;
+ struct scsi_xfer *xs;
+ int flags;
+#define SCB_ALLOC 0x01
+#define SCB_ABORT 0x02
+#ifdef WDSDIAG
+#define SCB_SENDING 0x04
+#endif
+#define SCB_POLLED 0x08
+#define SCB_SENSE 0x10
+#define SCB_DONE 0x20 /* for internal commands only */
+#define SCB_BUFFER 0x40
+ int timeout;
+
+ struct wds_buf *buf;
+};
+
+#define WDSX_SCSICMD 0x00
+#define WDSX_SCSISG 0x01
+#define WDSX_OPEN_RCVBUF 0x80
+#define WDSX_RCV_CMD 0x81
+#define WDSX_RCV_DATA 0x82
+#define WDSX_RCV_DATASTAT 0x83
+#define WDSX_SND_DATA 0x84
+#define WDSX_SND_DATASTAT 0x85
+#define WDSX_SND_CMDSTAT 0x86
+#define WDSX_READINIT 0x88
+#define WDSX_READSCSIID 0x89
+#define WDSX_SETUNSOLIRQMASK 0x8a
+#define WDSX_GETUNSOLIRQMASK 0x8b
+#define WDSX_GETFIRMREV 0x8c
+#define WDSX_EXECDIAG 0x8d
+#define WDSX_SETEXECPARM 0x8e
+#define WDSX_GETEXECPARM 0x8f
+
+struct wds_mbx_out {
+ u_char cmd;
+ physaddr scb_addr;
+};
+
+struct wds_mbx_in {
+ u_char stat;
+ physaddr scb_addr;
+};
+
+/*
+ * mbo.cmd values
+ */
+#define WDS_MBO_FREE 0x0 /* MBO entry is free */
+#define WDS_MBO_START 0x1 /* MBO activate entry */
+
+/*
+ * mbi.stat values
+ */
+#define WDS_MBI_FREE 0x00 /* MBI entry is free */
+#define WDS_MBI_OK 0x01 /* completed without error */
+#define WDS_MBI_OKERR 0x02 /* completed with error */
+#define WDS_MBI_ETIME 0x04
+#define WDS_MBI_ERESET 0x05
+#define WDS_MBI_ETARCMD 0x06
+#define WDS_MBI_ERESEL 0x80
+#define WDS_MBI_ESEL 0x81
+#define WDS_MBI_EABORT 0x82
+#define WDS_MBI_ESRESET 0x83
+#define WDS_MBI_EHRESET 0x84
+
+struct wds_setup {
+ u_char opcode;
+ u_char scsi_id;
+ u_char buson_t;
+ u_char busoff_t;
+ u_char xx;
+ physaddr mbaddr;
+ u_char nomb;
+ u_char nimb;
+};
diff --git a/sys/dev/isa/wss.c b/sys/dev/isa/wss.c
index 6080334ede5..ba0b2fb7df2 100644
--- a/sys/dev/isa/wss.c
+++ b/sys/dev/isa/wss.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: wss.c,v 1.7 1996/03/20 01:01:06 mickey Exp $ */
-/* $NetBSD: wss.c,v 1.9 1996/02/16 08:18:36 mycroft Exp $ */
+/* $OpenBSD: wss.c,v 1.8 1996/04/21 22:24:49 deraadt Exp $ */
+/* $NetBSD: wss.c,v 1.11 1996/04/11 22:30:46 cgd Exp $ */
/*
* Copyright (c) 1994 John Brezak
@@ -165,8 +165,12 @@ struct audio_hw_if wss_hw_if = {
int wssprobe __P((struct device *, void *, void *));
void wssattach __P((struct device *, struct device *, void *));
-struct cfdriver wsscd = {
- NULL, "wss", wssprobe, wssattach, DV_DULL, sizeof(struct wss_softc)
+struct cfattach wss_ca = {
+ sizeof(struct wss_softc), wssprobe, wssattach
+};
+
+struct cfdriver wss_cd = {
+ NULL, "wss", DV_DULL
};
/*
@@ -250,8 +254,8 @@ wssattach(parent, self, aux)
#ifdef NEWCONFIG
isa_establish(&sc->sc_id, &sc->sc_dev);
#endif
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_AUDIO, ad1848_intr,
- &sc->sc_ad1848, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE, IPL_AUDIO,
+ ad1848_intr, &sc->sc_ad1848, sc->sc_dev.dv_xname);
ad1848_attach(&sc->sc_ad1848);
@@ -306,10 +310,10 @@ wssopen(dev, flags)
struct wss_softc *sc;
int unit = AUDIOUNIT(dev);
- if (unit >= wsscd.cd_ndevs)
+ if (unit >= wss_cd.cd_ndevs)
return ENODEV;
- sc = wsscd.cd_devs[unit];
+ sc = wss_cd.cd_devs[unit];
if (!sc)
return ENXIO;
diff --git a/sys/dev/isa/wt.c b/sys/dev/isa/wt.c
index 8fe5e81811f..70e051a7694 100644
--- a/sys/dev/isa/wt.c
+++ b/sys/dev/isa/wt.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: wt.c,v 1.7 1996/04/18 23:47:52 niklas Exp $ */
-/* $NetBSD: wt.c,v 1.29 1996/03/01 04:08:40 mycroft Exp $ */
+/* $OpenBSD: wt.c,v 1.8 1996/04/21 22:24:52 deraadt Exp $ */
+/* $NetBSD: wt.c,v 1.31 1996/04/11 22:30:49 cgd Exp $ */
/*
* Streamer tape driver.
@@ -168,8 +168,12 @@ int wtprobe __P((struct device *, void *, void *));
void wtattach __P((struct device *, struct device *, void *));
int wtintr __P((void *sc));
-struct cfdriver wtcd = {
- NULL, "wt", wtprobe, wtattach, DV_TAPE, sizeof(struct wt_softc)
+struct cfattach wt_ca = {
+ sizeof(struct wt_softc), wtprobe, wtattach
+};
+
+struct cfdriver wt_cd = {
+ NULL, "wt", DV_TAPE
};
/*
@@ -250,8 +254,8 @@ wtattach(parent, self, aux)
sc->flags = TPSTART; /* tape is rewound */
sc->dens = -1; /* unknown density */
- sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_BIO, wtintr,
- sc, sc->sc_dev.dv_xname);
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_BIO, wtintr, sc, sc->sc_dev.dv_xname);
}
int
@@ -287,9 +291,9 @@ wtopen(dev, flag)
struct wt_softc *sc;
int error;
- if (unit >= wtcd.cd_ndevs)
+ if (unit >= wt_cd.cd_ndevs)
return ENXIO;
- sc = wtcd.cd_devs[unit];
+ sc = wt_cd.cd_devs[unit];
if (!sc)
return ENXIO;
@@ -372,7 +376,7 @@ wtclose(dev)
dev_t dev;
{
int unit = minor(dev) & T_UNIT;
- struct wt_softc *sc = wtcd.cd_devs[unit];
+ struct wt_softc *sc = wt_cd.cd_devs[unit];
/* If rewind is pending, do nothing */
if (sc->flags & TPREW)
@@ -426,7 +430,7 @@ wtioctl(dev, cmd, addr, flag)
int flag;
{
int unit = minor(dev) & T_UNIT;
- struct wt_softc *sc = wtcd.cd_devs[unit];
+ struct wt_softc *sc = wt_cd.cd_devs[unit];
int error, count, op;
switch (cmd) {
@@ -526,7 +530,7 @@ wtstrategy(bp)
struct buf *bp;
{
int unit = minor(bp->b_dev) & T_UNIT;
- struct wt_softc *sc = wtcd.cd_devs[unit];
+ struct wt_softc *sc = wt_cd.cd_devs[unit];
int s;
bp->b_resid = bp->b_bcount;
diff --git a/sys/dev/pci/aic7870.c b/sys/dev/pci/aic7870.c
index b481014d4f0..0c91a4d8dcb 100644
--- a/sys/dev/pci/aic7870.c
+++ b/sys/dev/pci/aic7870.c
@@ -1,4 +1,4 @@
-/* $NetBSD: aic7870.c,v 1.7 1996/03/04 19:30:50 cgd Exp $ */
+/* $NetBSD: aic7870.c,v 1.8 1996/03/17 00:55:23 thorpej Exp $ */
/*
* Product specific probe and attach routines for:
@@ -45,9 +45,12 @@
static int aic7870_probe __P((struct device *, void *, void *));
static void aic7870_attach __P((struct device *, struct device *, void *));
-struct cfdriver ahccd = {
- NULL, "ahc", aic7870_probe, aic7870_attach, DV_DULL,
- sizeof(struct ahc_softc)
+struct cfattach ahc_ca = {
+ sizeof(struct ahc_softc), aic7870_probe, aic7870_attach
+};
+
+struct cfdriver ahc_cd = {
+ NULL, "ahc", DV_DULL
};
int ahcintr __P((void *));
@@ -106,6 +109,5 @@ aic7870_attach(parent, self, aux)
ahcattach(ahc);
- ahc->sc_ih = pci_map_int(pa->pa_tag, IPL_BIO, ahcintr, ahc,
- ahc->sc_dev.dv_xname);
+ ahc->sc_ih = pci_map_int(pa->pa_tag, IPL_BIO, ahcintr, ahc);
}
diff --git a/sys/dev/pci/files.pci b/sys/dev/pci/files.pci
index b1eaca631c6..149d0d98785 100644
--- a/sys/dev/pci/files.pci
+++ b/sys/dev/pci/files.pci
@@ -1,30 +1,36 @@
-# $OpenBSD: files.pci,v 1.3 1996/04/18 23:47:55 niklas Exp $
-# $NetBSD: files.pci,v 1.12 1996/03/04 03:29:19 cgd Exp $
+# $OpenBSD: files.pci,v 1.4 1996/04/21 22:25:06 deraadt Exp $
+# $NetBSD: files.pci,v 1.13 1996/03/17 00:55:24 thorpej Exp $
#
-# Config file and device description for machine-independent PCI code.
+# Config.new file and device description for machine-independent PCI code.
# Included by ports that need it. Requires that the SCSI files be
# defined first.
-device pci at pcibus {[dev = -1], [function = -1]}
+device pci {[dev = -1], [function = -1]}
+attach pci at pcibus
file dev/pci/pci.c pci needs-flag
file dev/pci/pci_subr.c pci
# Adaptec 7870 chips
-device ahc at pci: scsi, aic7xxx
+device ahc: scsi, aic7xxx
+attach ahc at pci
file dev/pci/aic7870.c ahc
# Ethernet driver for DC21040-based boards
-device de at pci: ether, ifnet
+device de: ether, ifnet
+attach de at pci
file dev/pci/if_de.c de
# Digital DEFPA PCI FDDI Controller
-device fpa at pci: pdq, fddi, ifnet
+device fpa: pdq, fddi, ifnet
+attach fpa at pci
file dev/pci/if_fpa.c fpa
# NCR 53c8xx SCSI chips
-device ncr at pci: scsi
+device ncr: scsi
+attach ncr at pci
file dev/pci/ncr.c ncr
# PCI-PCI bridge chips
-device ppb at pci: pcibus
+device ppb: pcibus
+attach ppb at pci
file dev/pci/ppb.c ppb
diff --git a/sys/dev/pci/if_de.c b/sys/dev/pci/if_de.c
index fbddb089889..0eaa370660a 100644
--- a/sys/dev/pci/if_de.c
+++ b/sys/dev/pci/if_de.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: if_de.c,v 1.5 1996/04/18 23:47:56 niklas Exp $ */
-/* $NetBSD: if_de.c,v 1.13 1996/03/14 03:04:17 cgd Exp $ */
+/* $OpenBSD: if_de.c,v 1.6 1996/04/21 22:25:13 deraadt Exp $ */
+/* $NetBSD: if_de.c,v 1.17 1996/04/01 19:37:54 cgd Exp $ */
/*-
* Copyright (c) 1994, 1995 Matt Thomas (matt@lkg.dec.com)
@@ -109,12 +109,12 @@
#if defined(__NetBSD__)
#include <machine/bus.h>
+#ifdef __alpha__
+#include <machine/intr.h>
+#endif
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/ic/dc21040reg.h>
-#ifdef __i386__ /* XXX -- fix later -- cgd */
-#include <i386/isa/isa_machdep.h>
-#endif
#endif /* __NetBSD__ */
/*
@@ -141,9 +141,6 @@ typedef struct {
} tulip_ringinfo_t;
#ifdef TULIP_IOMAPPED
-#ifndef __NetBSD__
-#else
-#endif
#define TULIP_EISA_CSRSIZE 16
#define TULIP_PCI_CSRSIZE 8
@@ -317,7 +314,8 @@ struct _tulip_softc_t {
struct device tulip_dev; /* base device */
void *tulip_ih; /* intrrupt vectoring */
void *tulip_ats; /* shutdown hook */
- bus_chipset_tag_t tulip_bc; /* bus chipset tag */
+ bus_chipset_tag_t tulip_bc;
+ pci_chipset_tag_t tulip_pc;
#ifdef TULIP_IOMAPPED
bus_io_handle_t tulip_ioh; /* I/O region handle */
#else
@@ -385,8 +383,9 @@ extern struct cfdriver decd;
#if defined(__NetBSD__)
typedef void ifnet_ret_t;
typedef u_long ioctl_cmd_t;
-extern struct cfdriver decd;
-#define TULIP_UNIT_TO_SOFTC(unit) ((tulip_softc_t *) decd.cd_devs[unit])
+extern struct cfattach de_ca;
+extern struct cfdriver de_cd;
+#define TULIP_UNIT_TO_SOFTC(unit) ((tulip_softc_t *) de_cd.cd_devs[unit])
#endif
#ifndef TULIP_BURSTSIZE
@@ -416,6 +415,10 @@ static ifnet_ret_t tulip_start(struct ifnet *ifp);
static void tulip_rx_intr(tulip_softc_t *sc);
static void tulip_addr_filter(tulip_softc_t *sc);
+#if defined(__NetBSD__) && defined(__alpha__)
+/* XXX XXX NEED REAL DMA MAPPING SUPPORT XXX XXX */
+#define vtophys(va) (vtophys(va) | 0x40000000)
+#endif
static int
tulip_dc21040_media_probe(
@@ -670,7 +673,7 @@ tulip_dc21140_de500_media_probe(
if ((TULIP_READ_CSR(sc, csr_gp) &
(TULIP_GP_DE500_NOTOK_100|TULIP_GP_DE500_NOTOK_10)) !=
(TULIP_GP_DE500_NOTOK_100|TULIP_GP_DE500_NOTOK_10))
- return (TULIP_READ_CSR(sc, csr_gp) & TULIP_GP_DE500_NOTOK_100) != 0;
+ return (TULIP_READ_CSR(sc, csr_gp) & TULIP_GP_DE500_NOTOK_100) == 0;
TULIP_WRITE_CSR(sc, csr_gp,
TULIP_GP_DE500_HALFDUPLEX|TULIP_GP_DE500_FORCE_100);
TULIP_WRITE_CSR(sc, csr_command,
@@ -679,7 +682,7 @@ tulip_dc21140_de500_media_probe(
TULIP_WRITE_CSR(sc, csr_command,
TULIP_READ_CSR(sc, csr_command) & ~TULIP_CMD_TXTHRSHLDCTL);
DELAY(1000000);
- return (TULIP_READ_CSR(sc, csr_gp) & TULIP_GP_DE500_NOTOK_100) != 0;
+ return (TULIP_READ_CSR(sc, csr_gp) & TULIP_GP_DE500_NOTOK_100) == 0;
}
static void
@@ -1189,10 +1192,10 @@ tulip_rx_intr(
#error BIG_PACKET is incompatible with TULIP_COPY_RXDATA
#endif
if (ms == me)
- bcopy(mtod(m, caddr_t) + sizeof(struct ether_header),
+/*XXX?*/ bcopy(mtod(ms, caddr_t) + sizeof(struct ether_header),
mtod(m0, caddr_t), total_len);
else
- m_copydata(m, 0, total_len, mtod(m0, caddr_t));
+/*XXX?*/ m_copydata(ms, 0, total_len, mtod(m0, caddr_t));
m0->m_len = m0->m_pkthdr.len = total_len;
m0->m_pkthdr.rcvif = ifp;
ether_input(ifp, &eh, m0);
@@ -2406,8 +2409,12 @@ tulip_pci_probe(
static void tulip_pci_attach(TULIP_PCI_ATTACH_ARGS);
-struct cfdriver decd = {
- 0, "de", tulip_pci_probe, tulip_pci_attach, DV_IFNET, sizeof(tulip_softc_t)
+struct cfattach de_ca = {
+ sizeof(tulip_softc_t), tulip_pci_probe, tulip_pci_attach
+};
+
+struct cfdriver de_cd = {
+ 0, "de", DV_IFNET
};
#endif /* __NetBSD__ */
@@ -2428,10 +2435,20 @@ tulip_pci_attach(
#if defined(__NetBSD__)
tulip_softc_t * const sc = (tulip_softc_t *) self;
struct pci_attach_args * const pa = (struct pci_attach_args *) aux;
+ bus_chipset_tag_t bc = pa->pa_bc;
+ pci_chipset_tag_t pc = pa->pa_pc;
+#if defined(TULIP_IOMAPPED)
+ bus_io_addr_t iobase;
+ bus_io_size_t iosize;
+#else
+ bus_mem_addr_t membase;
+ bus_mem_size_t memsize;
+#endif
int unit = sc->tulip_dev.dv_unit;
+ const char *intrstr = NULL;
#endif
int retval, idx, revinfo, id;
-#if !defined(TULIP_IOMAPPED) && !defined(__bsdi__)
+#if !defined(TULIP_IOMAPPED) && !defined(__bsdi__) && !defined(__NetBSD__)
vm_offset_t pa_csrs;
#endif
unsigned csrsize = TULIP_PCI_CSRSIZE;
@@ -2464,7 +2481,7 @@ tulip_pci_attach(
}
#endif
#if defined(__NetBSD__)
- revinfo = pci_conf_read(pa->pa_tag, PCI_CFRV) & 0xFF;
+ revinfo = pci_conf_read(pc, pa->pa_tag, PCI_CFRV) & 0xFF;
id = pa->pa_id;
#endif
@@ -2546,11 +2563,17 @@ tulip_pci_attach(
#endif /* __bsdi__ */
#if defined(__NetBSD__)
- sc->tulip_bc = pa->pa_bc;
+ sc->tulip_bc = bc;
+ sc->tulip_pc = pc;
#if defined(TULIP_IOMAPPED)
- retval = pci_map_io(pa->pa_tag, PCI_CBIO, &sc->tulip_ioh);
+ retval = pci_io_find(pc, pa->pa_tag, PCI_CBIO, &iobase, &iosize);
+ if (!retval)
+ retval = bus_io_map(bc, iobase, iosize, &sc->tulip_ioh);
#else
- retval = pci_map_mem(pa->pa_tag, PCI_CBMA, &sc->tulip_memh, &pa_csrs);
+ retval = pci_mem_find(pc, pa->pa_tag, PCI_CBMA, &membase, &memsize,
+ NULL);
+ if (!retval)
+ retval = bus_mem_map(bc, membase, memsize, 0, &sc->tulip_memh);
#endif
csr_base = 0;
if (retval) {
@@ -2587,21 +2610,27 @@ tulip_pci_attach(
bit longer anyways) */
#if defined(__NetBSD__)
if (sc->tulip_boardsw->bd_type != TULIP_DC21040_ZX314_SLAVE) {
- sc->tulip_ih = pci_map_int(pa->pa_tag, IPL_NET, tulip_intr, sc,
- sc->tulip_dev.dv_xname);
+ pci_intr_handle_t intrhandle;
+
+ if (pci_intr_map(pc, pa->pa_intrtag, pa->pa_intrpin,
+ pa->pa_intrline, &intrhandle)) {
+ printf(": couldn't map interrupt\n", self->dv_xname);
+ return;
+ }
+ intrstr = pci_intr_string(pc, intrhandle);
+ sc->tulip_ih = pci_intr_establish(pc, intrhandle, IPL_NET,
+ tulip_intr, sc, self->dv_xname);
if (sc->tulip_ih == NULL) {
- printf("%s%d: couldn't map interrupt\n",
- sc->tulip_name, sc->tulip_unit);
+ printf(": couldn't establish interrupt", self->dv_xname);
+ if (intrstr != NULL)
+ printf(" at %s", intrstr);
+ printf("\n");
return;
}
-#if defined(__i386__)
- /* gross but netbsd won't print the irq otherwise */
- printf(" irq %d", ((struct intrhand *) sc->tulip_ih)->ih_irq);
-#endif
}
sc->tulip_ats = shutdownhook_establish(tulip_pci_shutdown, sc);
if (sc->tulip_ats == NULL)
- printf("%s%d: warning: couldn't establish shutdown hook\n",
+ printf("\n%s%d: warning: couldn't establish shutdown hook",
sc->tulip_name, sc->tulip_unit);
#endif
#if defined(__FreeBSD__)
@@ -2628,6 +2657,10 @@ tulip_pci_attach(
#endif
tulip_reset(sc);
tulip_attach(sc);
+#if defined(__NetBSD__)
+ if (intrstr != NULL)
+ printf("%s: interrupting at %s\n", self->dv_xname, intrstr);
+#endif
}
}
#endif /* NDE > 0 */
diff --git a/sys/dev/pci/if_fpa.c b/sys/dev/pci/if_fpa.c
index c9451163c5c..eb6be356f02 100644
--- a/sys/dev/pci/if_fpa.c
+++ b/sys/dev/pci/if_fpa.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_fpa.c,v 1.4 1996/04/18 23:47:58 niklas Exp $ */
+/* $OpenBSD: if_fpa.c,v 1.5 1996/04/21 22:25:19 deraadt Exp $ */
/* $NetBSD: if_fpa.c,v 1.7 1996/03/17 00:55:30 thorpej Exp $ */
/*-
@@ -389,7 +389,7 @@ pdq_pci_attach(
sc->sc_ih.ih_fun = pdq_pci_ifintr;
sc->sc_ih.ih_arg = (void *)sc;
- intr_establish(ia->ia_irq, &sc->sc_ih, DV_NET);
+ intr_establish(ia->ia_irq, &sc->sc_ih, DV_NET, sc->sc_dv.dv_xname);
sc->sc_ats.func = (void (*)(void *)) pdq_hwreset;
sc->sc_ats.arg = (void *) sc->sc_pdq;
diff --git a/sys/dev/pci/ncr.c b/sys/dev/pci/ncr.c
index d96230821b1..d98f8d2b3d7 100644
--- a/sys/dev/pci/ncr.c
+++ b/sys/dev/pci/ncr.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: ncr.c,v 1.6 1996/04/18 23:47:59 niklas Exp $ */
-/* $NetBSD: ncr.c,v 1.29 1996/03/14 05:21:20 cgd Exp $ */
+/* $OpenBSD: ncr.c,v 1.7 1996/04/21 22:25:22 deraadt Exp $ */
+/* $NetBSD: ncr.c,v 1.33 1996/04/03 08:44:15 mycroft Exp $ */
/**************************************************************************
**
@@ -195,10 +195,15 @@ extern PRINT_ADDR();
#else
#include <sys/device.h>
#include <machine/bus.h>
+#ifdef __alpha__
+#include <machine/intr.h>
+#endif
#include <dev/pci/ncr_reg.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
+#ifndef __alpha__
#define DELAY(x) delay(x)
+#endif
#endif /* __NetBSD__ */
#include <scsi/scsi_all.h>
@@ -207,6 +212,10 @@ extern PRINT_ADDR();
#include <machine/clock.h>
#endif /* __NetBSD__ */
+#if defined(__NetBSD__) && defined(__alpha__)
+/* XXX XXX NEED REAL DMA MAPPING SUPPORT XXX XXX */
+#define vtophys(va) (vtophys(va) | 0x40000000)
+#endif
/*==========================================================
**
@@ -991,6 +1000,7 @@ struct ncb {
struct device sc_dev;
void *sc_ih;
bus_chipset_tag_t sc_bc;
+ pci_chipset_tag_t sc_pc;
#ifdef NCR_IOMAPPED
bus_io_handle_t sc_ioh;
#else /* !NCR_IOMAPPED */
@@ -1320,7 +1330,7 @@ static void ncr_attach (pcici_t tag, int unit);
static char ident[] =
- "\n$NetBSD: ncr.c,v 1.29 1996/03/14 05:21:20 cgd Exp $\n";
+ "\n$NetBSD: ncr.c,v 1.33 1996/04/03 08:44:15 mycroft Exp $\n";
u_long ncr_version = NCR_VERSION * 11
+ (u_long) sizeof (struct ncb) * 7
@@ -1357,8 +1367,12 @@ int ncr_cache; /* to be aligned _NOT_ static */
#ifdef __NetBSD__
-struct cfdriver ncrcd = {
- NULL, "ncr", ncr_probe, ncr_attach, DV_DULL, sizeof(struct ncb)
+struct cfattach ncr_ca = {
+ sizeof(struct ncb), ncr_probe, ncr_attach
+};
+
+struct cfdriver ncr_cd = {
+ NULL, "ncr", DV_DULL
};
#else /* !__NetBSD__ */
@@ -3326,8 +3340,14 @@ static char* ncr_probe (pcici_t tag, pcidi_t type)
#ifdef __NetBSD__
int
-ncr_print()
+ncr_print(aux, name)
+ void *aux;
+ char *name;
{
+
+ if (name != NULL)
+ printf("%s: scsibus ", name);
+ return UNCONF;
}
void
@@ -3336,7 +3356,12 @@ ncr_attach(parent, self, aux)
void *aux;
{
struct pci_attach_args *pa = aux;
- int retval;
+ bus_chipset_tag_t bc = pa->pa_bc;
+ pci_chipset_tag_t pc = pa->pa_pc;
+ bus_mem_size_t memsize;
+ int retval, cacheable;
+ pci_intr_handle_t intrhandle;
+ const char *intrstr;
ncb_p np = (void *)self;
printf(": NCR ");
@@ -3362,21 +3387,49 @@ ncr_attach(parent, self, aux)
}
printf(" SCSI\n");
+ np->sc_bc = bc;
+ np->sc_pc = pc;
+
/*
** Try to map the controller chip to
** virtual and physical memory.
*/
- retval = pci_map_mem(pa->pa_tag, 0x14, (vm_offset_t *)&np->sc_memh,
- &np->paddr);
- if (retval)
+ retval = pci_mem_find(pc, pa->pa_tag, 0x14, &np->paddr,
+ &memsize, &cacheable);
+ if (retval) {
+ printf("%s: couldn't find memory region\n", self->dv_xname);
return;
+ }
- np->sc_ih = pci_map_int(pa->pa_tag, IPL_BIO, ncr_intr, np,
- np->sc_dev.dv_xname);
- if (np->sc_ih == NULL)
+ /* Map the memory. Note that we never want it to be cacheable. */
+ retval = bus_mem_map(pa->pa_bc, np->paddr, memsize, 0, &np->sc_memh);
+ if (retval) {
+ printf("%s: couldn't map memory region\n", self->dv_xname);
return;
+ }
+ /*
+ ** Set up the controller chip's interrupt.
+ */
+ retval = pci_intr_map(pc, pa->pa_intrtag, pa->pa_intrpin,
+ pa->pa_intrline, &intrhandle);
+ if (retval) {
+ printf("%s: couldn't map interrupt\n", self->dv_xname);
+ return;
+ }
+ intrstr = pci_intr_string(pc, intrhandle);
+ np->sc_ih = pci_intr_establish(pc, intrhandle, IPL_BIO,
+ ncr_intr, np, self->dv_xname);
+ if (np->sc_ih == NULL) {
+ printf("%s: couldn't establish interrupt", self->dv_xname);
+ if (intrstr != NULL)
+ printf(" at %s", intrstr);
+ printf("\n");
+ return;
+ }
+ if (intrstr != NULL)
+ printf("%s: interrupting at %s\n", self->dv_xname, intrstr);
#else /* !__NetBSD__ */
diff --git a/sys/dev/pci/ncrstat.c b/sys/dev/pci/ncrstat.c
index 37374c88b38..6925cd42352 100644
--- a/sys/dev/pci/ncrstat.c
+++ b/sys/dev/pci/ncrstat.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ncrstat.c,v 1.6 1995/01/27 05:44:31 cgd Exp $ */
+/* $NetBSD: ncrstat.c,v 1.7 1996/03/17 00:55:36 thorpej Exp $ */
/**************************************************************************
**
@@ -92,7 +92,7 @@ struct nlist nl[] = {
{ "_ncr_version" },
#ifdef __NetBSD__
#define N_NCRCD 1
- { "_ncrcd" },
+ { "_ncr_cd" },
#else
#define N_NCRP 1
{ "_ncrp" },
@@ -114,7 +114,7 @@ u_long ccb_base;
u_long ncr_unit;
#ifdef __NetBSD__
-struct cfdriver ncrcd;
+struct cfdriver ncr_cd;
#else
u_long ncr_units;
#endif
@@ -224,20 +224,20 @@ void open_kvm(int flags)
if (!KVM_READ (
nl[N_NCRCD].n_value,
- &ncrcd,
- sizeof (ncrcd))) {
+ &ncr_cd,
+ sizeof (ncr_cd))) {
fprintf (stderr, "%s: bad kvm read.\n", prog);
exit (1);
};
- if (ncr_unit >= ncrcd.cd_ndevs){
+ if (ncr_unit >= ncr_cd.cd_ndevs){
fprintf (stderr, "%s: bad unit number (valid range: 0-%d).\n",
- prog, ncrcd.cd_ndevs-1);
+ prog, ncr_cd.cd_ndevs-1);
exit (1);
};
if (!KVM_READ (
- ncrcd.cd_devs+4*ncr_unit,
+ ncr_cd.cd_devs+4*ncr_unit,
&ncr_base,
sizeof (ncr_base))) {
fprintf (stderr, "%s: bad kvm read.\n", prog);
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index e5e770a5242..1e69d44b454 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: pci.c,v 1.1 1996/04/18 23:48:02 niklas Exp $ */
-/* $NetBSD: pci.c,v 1.15 1996/03/14 04:03:01 cgd Exp $ */
+/* $OpenBSD: pci.c,v 1.2 1996/04/21 22:25:34 deraadt Exp $ */
+/* $NetBSD: pci.c,v 1.18 1996/03/27 04:08:24 cgd Exp $ */
/*
* Copyright (c) 1995, 1996 Christopher G. Demetriou. All rights reserved.
@@ -45,8 +45,12 @@
int pcimatch __P((struct device *, void *, void *));
void pciattach __P((struct device *, struct device *, void *));
-struct cfdriver pcicd = {
- NULL, "pci", pcimatch, pciattach, DV_DULL, sizeof(struct device)
+struct cfattach pci_ca = {
+ sizeof(struct device), pcimatch, pciattach
+};
+
+struct cfdriver pci_cd = {
+ NULL, "pci", DV_DULL
};
int pciprint __P((void *, char *));
@@ -86,39 +90,70 @@ pciattach(parent, self, aux)
{
struct pcibus_attach_args *pba = aux;
bus_chipset_tag_t bc;
- int device, function, nfunctions;
+ pci_chipset_tag_t pc;
+ int bus, device, maxndevs, function, nfunctions;
- pci_md_attach_hook(parent, self, pba);
+ pci_attach_hook(parent, self, pba);
printf("\n");
- for (device = 0; device < PCI_MAX_DEVICE_NUMBER; device++) {
+ bc = pba->pba_bc;
+ pc = pba->pba_pc;
+ bus = pba->pba_bus;
+ maxndevs = pci_bus_maxdevs(pc, bus);
+
+ for (device = 0; device < maxndevs; device++) {
pcitag_t tag;
- pcireg_t id, class;
+ pcireg_t id, class, intr, bhlcr;
struct pci_attach_args pa;
struct cfdata *cf;
- int supported;
+ int supported, pin;
- tag = pci_make_tag(pba->pba_bus, device, 0);
- id = pci_conf_read(tag, PCI_ID_REG);
+ tag = pci_make_tag(pc, bus, device, 0);
+ id = pci_conf_read(pc, tag, PCI_ID_REG);
if (id == 0 || id == 0xffffffff)
continue;
- nfunctions = 1; /* XXX */
+ bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
+ nfunctions = PCI_HDRTYPE_MULTIFN(bhlcr) ? 8 : 1;
for (function = 0; function < nfunctions; function++) {
- tag = pci_make_tag(pba->pba_bus, device, function);
- id = pci_conf_read(tag, PCI_ID_REG);
+ tag = pci_make_tag(pc, bus, device, function);
+ id = pci_conf_read(pc, tag, PCI_ID_REG);
if (id == 0 || id == 0xffffffff)
continue;
- class = pci_conf_read(tag, PCI_CLASS_REG);
+ class = pci_conf_read(pc, tag, PCI_CLASS_REG);
+ intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
- pa.pa_bc = pba->pba_bc;
+ pa.pa_bc = bc;
+ pa.pa_pc = pc;
pa.pa_device = device;
pa.pa_function = function;
pa.pa_tag = tag;
pa.pa_id = id;
pa.pa_class = class;
+ if (bus == 0) {
+ pa.pa_intrswiz = 0;
+ pa.pa_intrtag = tag;
+ } else {
+ pa.pa_intrswiz = pba->pba_intrswiz + device;
+ pa.pa_intrtag = pba->pba_intrtag;
+ }
+ pin = PCI_INTERRUPT_PIN(intr);
+ if (pin == PCI_INTERRUPT_PIN_NONE) {
+ /* no interrupt */
+ pa.pa_intrpin = 0;
+ } else {
+ /*
+ * swizzle it based on the number of
+ * busses we're behind and our device
+ * number.
+ */
+ pa.pa_intrpin = /* XXX */
+ ((pin + pa.pa_intrswiz - 1) % 4) + 1;
+ }
+ pa.pa_intrline = PCI_INTERRUPT_LINE(intr);
+
config_found_sm(self, &pa, pciprint, pcisubmatch);
}
}
@@ -154,5 +189,106 @@ pcisubmatch(parent, match, aux)
if (cf->pcicf_function != PCI_UNK_FUNCTION &&
cf->pcicf_function != pa->pa_function)
return 0;
- return ((*cf->cf_driver->cd_match)(parent, match, aux));
+ return ((*cf->cf_attach->ca_match)(parent, match, aux));
+}
+
+int
+pci_io_find(pc, pcitag, reg, iobasep, iosizep)
+ pci_chipset_tag_t pc;
+ pcitag_t pcitag;
+ int reg;
+ bus_io_addr_t *iobasep;
+ bus_io_size_t *iosizep;
+{
+ pcireg_t addrdata, sizedata;
+ int s;
+
+ if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3))
+ panic("pci_io_find: bad request");
+
+ /* XXX?
+ * Section 6.2.5.1, `Address Maps', tells us that:
+ *
+ * 1) The builtin software should have already mapped the device in a
+ * reasonable way.
+ *
+ * 2) A device which wants 2^n bytes of memory will hardwire the bottom
+ * n bits of the address to 0. As recommended, we write all 1s and see
+ * what we get back.
+ */
+ addrdata = pci_conf_read(pc, pcitag, reg);
+
+ s = splhigh();
+ pci_conf_write(pc, pcitag, reg, 0xffffffff);
+ sizedata = pci_conf_read(pc, pcitag, reg);
+ pci_conf_write(pc, pcitag, reg, addrdata);
+ splx(s);
+
+ if (PCI_MAPREG_TYPE(addrdata) != PCI_MAPREG_TYPE_IO)
+ panic("pci_io_find: not an I/O region");
+
+ if (iobasep != NULL)
+ *iobasep = PCI_MAPREG_IO_ADDR(addrdata);
+ if (iosizep != NULL)
+ *iosizep = ~PCI_MAPREG_IO_ADDR(sizedata) + 1;
+
+ return (0);
+}
+
+int
+pci_mem_find(pc, pcitag, reg, membasep, memsizep, cacheablep)
+ pci_chipset_tag_t pc;
+ pcitag_t pcitag;
+ int reg;
+ bus_mem_addr_t *membasep;
+ bus_mem_size_t *memsizep;
+ int *cacheablep;
+{
+ pcireg_t addrdata, sizedata;
+ int s;
+
+ if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3))
+ panic("pci_find_mem: bad request");
+
+ /*
+ * Section 6.2.5.1, `Address Maps', tells us that:
+ *
+ * 1) The builtin software should have already mapped the device in a
+ * reasonable way.
+ *
+ * 2) A device which wants 2^n bytes of memory will hardwire the bottom
+ * n bits of the address to 0. As recommended, we write all 1s and see
+ * what we get back.
+ */
+ addrdata = pci_conf_read(pc, pcitag, reg);
+
+ s = splhigh();
+ pci_conf_write(pc, pcitag, reg, 0xffffffff);
+ sizedata = pci_conf_read(pc, pcitag, reg);
+ pci_conf_write(pc, pcitag, reg, addrdata);
+ splx(s);
+
+ if (PCI_MAPREG_TYPE(addrdata) == PCI_MAPREG_TYPE_IO)
+ panic("pci_find_mem: I/O region");
+
+ switch (PCI_MAPREG_MEM_TYPE(addrdata)) {
+ case PCI_MAPREG_MEM_TYPE_32BIT:
+ case PCI_MAPREG_MEM_TYPE_32BIT_1M:
+ break;
+ case PCI_MAPREG_MEM_TYPE_64BIT:
+/* XXX */ printf("pci_find_mem: 64-bit region\n");
+/* XXX */ return (1);
+ default:
+ printf("pci_find_mem: reserved region type\n");
+ return (1);
+ }
+
+ if (membasep != NULL)
+ *membasep = PCI_MAPREG_MEM_ADDR(addrdata); /* PCI addr */
+ if (memsizep != NULL)
+ *memsizep = ~PCI_MAPREG_MEM_ADDR(sizedata) + 1;
+ if (cacheablep != NULL)
+ *cacheablep = PCI_MAPREG_MEM_CACHEABLE(addrdata);
+
+ return 0;
}
diff --git a/sys/dev/pci/pcidevs b/sys/dev/pci/pcidevs
index 8dedc4d7b67..29c507c824b 100644
--- a/sys/dev/pci/pcidevs
+++ b/sys/dev/pci/pcidevs
@@ -1,5 +1,6 @@
-$OpenBSD: pcidevs,v 1.6 1996/04/18 23:48:04 niklas Exp $
-/* $NetBSD: pcidevs,v 1.6 1996/02/19 20:08:25 christos Exp $ */
+$OpenBSD: pcidevs,v 1.7 1996/04/21 22:25:38 deraadt Exp $
+/* $NetBSD: pcidevs,v 1.7 1996/04/04 21:46:33 mycroft Exp $ */
+
/*
* Copyright (c) 1995, 1996 Christopher G. Demetriou
@@ -468,6 +469,9 @@ product OLDNCR 810 0x0001 53c810
product OLDNCR 820 0x0002 53c820
product OLDNCR 825 0x0003 53c825
product OLDNCR 815 0x0004 53c815
+product OLDNCR 810AP 0x0005 53c810AP
+product OLDNCR 860 0x0006 53c860
+product OLDNCR 875 0x000f 53c875
/* do the NCR chips use the new ID, as well? */
/* Number Nine products */
diff --git a/sys/dev/pci/pcidevs.h b/sys/dev/pci/pcidevs.h
index f5c48baa207..0e86ed3cd96 100644
--- a/sys/dev/pci/pcidevs.h
+++ b/sys/dev/pci/pcidevs.h
@@ -473,6 +473,9 @@
#define PCI_PRODUCT_OLDNCR_820 0x0002 /* 53c820 */
#define PCI_PRODUCT_OLDNCR_825 0x0003 /* 53c825 */
#define PCI_PRODUCT_OLDNCR_815 0x0004 /* 53c815 */
+#define PCI_PRODUCT_OLDNCR_810AP 0x0005 /* 53c810AP */
+#define PCI_PRODUCT_OLDNCR_860 0x0006 /* 53c860 */
+#define PCI_PRODUCT_OLDNCR_875 0x000f /* 53c875 */
/* do the NCR chips use the new ID, as well? */
/* Number Nine products */
diff --git a/sys/dev/pci/pcidevs_data.h b/sys/dev/pci/pcidevs_data.h
index b55e1510a05..c9858b6d554 100644
--- a/sys/dev/pci/pcidevs_data.h
+++ b/sys/dev/pci/pcidevs_data.h
@@ -267,6 +267,24 @@ struct pci_knowndev pci_knowndevs[] = {
"53c815",
},
{
+ PCI_VENDOR_OLDNCR, PCI_PRODUCT_OLDNCR_810AP,
+ 0,
+ "NCR",
+ "53c810AP",
+ },
+ {
+ PCI_VENDOR_OLDNCR, PCI_PRODUCT_OLDNCR_860,
+ 0,
+ "NCR",
+ "53c860",
+ },
+ {
+ PCI_VENDOR_OLDNCR, PCI_PRODUCT_OLDNCR_875,
+ 0,
+ "NCR",
+ "53c875",
+ },
+ {
PCI_VENDOR_NUMBER9, PCI_PRODUCT_NUMBER9_IMAG128,
0,
"Number 9 Computer Company",
diff --git a/sys/dev/pci/pcireg.h b/sys/dev/pci/pcireg.h
index 1422e846559..fab00dfa6fb 100644
--- a/sys/dev/pci/pcireg.h
+++ b/sys/dev/pci/pcireg.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: pcireg.h,v 1.2 1996/04/18 23:48:07 niklas Exp $ */
-/* $NetBSD: pcireg.h,v 1.5 1996/03/04 19:30:51 cgd Exp $ */
+/* $OpenBSD: pcireg.h,v 1.3 1996/04/21 22:25:49 deraadt Exp $ */
+/* $NetBSD: pcireg.h,v 1.7 1996/03/27 04:08:27 cgd Exp $ */
/*
* Copyright (c) 1995, 1996 Christopher G. Demetriou. All rights reserved.
@@ -31,6 +31,9 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifndef _DEV_PCI_PCIREG_H_
+#define _DEV_PCI_PCIREG_H_
+
/*
* Standardized PCI configuration information
*
@@ -165,6 +168,34 @@ typedef u_int8_t pci_revision_t;
#define PCI_SUBCLASS_BRIDGE_MISC 0x80
/*
+ * PCI BIST/Header Type/Latency Timer/Cache Line Size Register.
+ */
+#define PCI_BHLC_REG 0x0c
+
+#define PCI_BIST_SHIFT 24
+#define PCI_BIST_MASK 0xff
+#define PCI_BIST(bhlcr) \
+ (((bhlcr) >> PCI_BIST_SHIFT) & PCI_BIST_MASK)
+
+#define PCI_HDRTYPE_SHIFT 24
+#define PCI_HDRTYPE_MASK 0xff
+#define PCI_HDRTYPE(bhlcr) \
+ (((bhlcr) >> PCI_HDRTYPE_SHIFT) & PCI_HDRTYPE_MASK)
+
+#define PCI_HDRTYPE_MULTIFN(bhlcr) \
+ ((PCI_HDRTYPE(bhlcr) & 0x80) != 0)
+
+#define PCI_LATTIMER_SHIFT 24
+#define PCI_LATTIMER_MASK 0xff
+#define PCI_LATTIMER(bhlcr) \
+ (((bhlcr) >> PCI_LATTIMER_SHIFT) & PCI_LATTIMER_MASK)
+
+#define PCI_CACHELINE_SHIFT 24
+#define PCI_CACHELINE_MASK 0xff
+#define PCI_CACHELINE(bhlcr) \
+ (((bhlcr) >> PCI_CACHELINE_SHIFT) & PCI_CACHELINE_MASK)
+
+/*
* Mapping registers
*/
#define PCI_MAPREG_START 0x10
@@ -220,3 +251,5 @@ typedef u_int8_t pci_intr_line_t;
#define PCI_INTERRUPT_PIN_B 0x02
#define PCI_INTERRUPT_PIN_C 0x03
#define PCI_INTERRUPT_PIN_D 0x04
+
+#endif /* _DEV_PCI_PCIREG_H_ */
diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h
index 659a87ed6db..42c170f4971 100644
--- a/sys/dev/pci/pcivar.h
+++ b/sys/dev/pci/pcivar.h
@@ -1,7 +1,8 @@
-/* $OpenBSD: pcivar.h,v 1.6 1996/04/18 23:48:08 niklas Exp $ */
-/* $NetBSD: pcivar.h,v 1.8 1995/06/18 01:26:50 cgd Exp $ */
+/* $OpenBSD: pcivar.h,v 1.7 1996/04/21 22:25:51 deraadt Exp $ */
+/* $NetBSD: pcivar.h,v 1.15 1996/03/28 02:16:23 cgd Exp $ */
/*
+ * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
* Copyright (c) 1994 Charles Hannum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -38,52 +39,73 @@
*
* This file describes types and functions which are used for PCI
* configuration. Some of this information is machine-specific, and is
- * separated into pci_machdep.h.
+ * provided by pci_machdep.h.
*/
#include <machine/bus.h>
+#include <dev/pci/pcireg.h>
+/*
+ * Structures and definitions needed by the machine-dependent header.
+ */
+typedef u_int32_t pcireg_t; /* configuration space register XXX */
+struct pcibus_attach_args;
+
+/*
+ * Machine-dependent definitions.
+ */
#if (alpha + i386 != 1)
ERROR: COMPILING FOR UNSUPPORTED MACHINE, OR MORE THAN ONE.
#endif
-
#if alpha
#include <alpha/pci/pci_machdep.h>
#endif
-
#if i386
#include <i386/pci/pci_machdep.h>
#endif
/*
- * The maximum number of devices on a PCI bus is 32. However, some
- * PCI chipsets (e.g. chipsets that implement 'Configuration Mechanism #2'
- * on the i386) can't deal with that many, so let pci_machdep.h override it.
- */
-#ifndef PCI_MAX_DEVICE_NUMBER
-#define PCI_MAX_DEVICE_NUMBER 32
-#endif
-
-/*
* PCI bus attach arguments.
*/
struct pcibus_attach_args {
char *pba_busname; /* XXX should be common */
bus_chipset_tag_t pba_bc; /* XXX should be common */
+ pci_chipset_tag_t pba_pc;
int pba_bus; /* PCI bus number */
+
+ /*
+ * Interrupt swizzling information. These fields
+ * are only used by secondary busses.
+ */
+ u_int pba_intrswiz; /* how to swizzle pins */
+ pcitag_t pba_intrtag; /* intr. appears to come from here */
};
/*
* PCI device attach arguments.
*/
struct pci_attach_args {
- bus_chipset_tag_t pa_bc; /* bus chipset tag */
+ bus_chipset_tag_t pa_bc;
+ pci_chipset_tag_t pa_pc;
- int pa_device;
- int pa_function;
+ u_int pa_device;
+ u_int pa_function;
pcitag_t pa_tag;
pcireg_t pa_id, pa_class;
+
+ /*
+ * Interrupt information.
+ *
+ * "Intrline" is used on systems whose firmware puts
+ * the right routing data into the line register in
+ * configuration space. The rest are used on systems
+ * that do not.
+ */
+ u_int pa_intrswiz; /* how to swizzle pins if ppb */
+ pcitag_t pa_intrtag; /* intr. appears to come from here */
+ pci_intr_pin_t pa_intrpin; /* intr. appears on this pin */
+ pci_intr_line_t pa_intrline; /* intr. routing information */
};
/*
@@ -101,11 +123,18 @@ struct pci_attach_args {
#define pcicf_function cf_loc[1]
#define PCI_UNK_FUNCTION -1 /* wildcarded 'function' */
-pcireg_t pci_conf_read __P((pcitag_t, int));
-void pci_conf_write __P((pcitag_t, int, pcireg_t));
-void pci_devinfo __P((pcireg_t, pcireg_t, int, char *));
-pcitag_t pci_make_tag __P((int, int, int));
-void *pci_map_int __P((pcitag_t, int, int (*)(void *), void *, char *));
-int pci_map_mem __P((pcitag_t, int, vm_offset_t *, vm_offset_t *));
+/*
+ * Configuration space access and utility functions. (Note that most,
+ * e.g. make_tag, conf_read, conf_write are declared by pci_machdep.h.)
+ */
+int pci_io_find __P((pci_chipset_tag_t, pcitag_t, int, bus_io_addr_t *,
+ bus_io_size_t *));
+int pci_mem_find __P((pci_chipset_tag_t, pcitag_t, int, bus_mem_addr_t *,
+ bus_mem_size_t *, int *));
+
+/*
+ * Helper functions for autoconfiguration.
+ */
+void pci_devinfo __P((pcireg_t, pcireg_t, int, char *));
#endif /* _DEV_PCI_PCIVAR_H_ */
diff --git a/sys/dev/pci/ppb.c b/sys/dev/pci/ppb.c
index 90d11685a20..69ad20265f2 100644
--- a/sys/dev/pci/ppb.c
+++ b/sys/dev/pci/ppb.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: ppb.c,v 1.1 1996/04/18 23:48:09 niklas Exp $ */
-/* $NetBSD: ppb.c,v 1.4 1996/03/14 04:03:03 cgd Exp $ */
+/* $OpenBSD: ppb.c,v 1.2 1996/04/21 22:25:53 deraadt Exp $ */
+/* $NetBSD: ppb.c,v 1.7 1996/03/27 04:08:34 cgd Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@@ -53,11 +53,15 @@
int ppbmatch __P((struct device *, void *, void *));
void ppbattach __P((struct device *, struct device *, void *));
-struct cfdriver ppbcd = {
- NULL, "ppb", ppbmatch, ppbattach, DV_DULL, sizeof(struct device)
+struct cfattach ppb_ca = {
+ sizeof(struct device), ppbmatch, ppbattach
};
-static int ppbprint __P((void *, char *pnp));
+struct cfdriver ppb_cd = {
+ NULL, "ppb", DV_DULL
+};
+
+int ppbprint __P((void *, char *pnp));
int
ppbmatch(parent, match, aux)
@@ -85,16 +89,17 @@ ppbattach(parent, self, aux)
void *aux;
{
struct pci_attach_args *pa = aux;
+ pci_chipset_tag_t pc = pa->pa_pc;
struct pcibus_attach_args pba;
- pcireg_t data;
+ pcireg_t busdata;
char devinfo[256];
pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo);
printf(": %s (rev. 0x%02x)\n", devinfo, PCI_REVISION(pa->pa_class));
- data = pci_conf_read(pa->pa_tag, PPB_REG_BUSINFO);
+ busdata = pci_conf_read(pc, pa->pa_tag, PPB_REG_BUSINFO);
- if (PPB_BUSINFO_SECONDARY(data) == 0) {
+ if (PPB_BUSINFO_SECONDARY(busdata) == 0) {
printf("%s: not configured by system firmware\n",
self->dv_xname);
return;
@@ -103,25 +108,29 @@ ppbattach(parent, self, aux)
#if 0
/*
* XXX can't do this, because we're not given our bus number
- * (we shouldn't need it) and we can't decompose our tag.
+ * (we shouldn't need it), and because we've no way to
+ * decompose our tag.
*/
-
/* sanity check. */
- if (pa->pa_bus != PPB_BUSINFO_PRIMARY(data))
+ if (pa->pa_bus != PPB_BUSINFO_PRIMARY(busdata))
panic("ppbattach: bus in tag (%d) != bus in reg (%d)",
- pa->pa_bus, PPB_BUSINFO_PRIMARY(data));
+ pa->pa_bus, PPB_BUSINFO_PRIMARY(busdata));
#endif
/*
* Attach the PCI bus than hangs off of it.
*/
pba.pba_busname = "pci";
- pba.pba_bus = PPB_BUSINFO_SECONDARY(data);
+ pba.pba_bc = pa->pa_bc;
+ pba.pba_pc = pc;
+ pba.pba_bus = PPB_BUSINFO_SECONDARY(busdata);
+ pba.pba_intrswiz = pa->pa_intrswiz;
+ pba.pba_intrtag = pa->pa_intrtag;
config_found(self, &pba, ppbprint);
}
-static int
+int
ppbprint(aux, pnp)
void *aux;
char *pnp;
@@ -132,5 +141,5 @@ ppbprint(aux, pnp)
if (pnp)
printf("pci at %s", pnp);
printf(" bus %d", pba->pba_bus);
- return (UNCONF);
+ return (UNCONF);
}
diff --git a/sys/dev/pcmcia/files.pcmcia b/sys/dev/pcmcia/files.pcmcia
index b20ea8bd985..3429486e007 100644
--- a/sys/dev/pcmcia/files.pcmcia
+++ b/sys/dev/pcmcia/files.pcmcia
@@ -1,4 +1,4 @@
-# $OpenBSD: files.pcmcia,v 1.2 1996/04/18 23:48:11 niklas Exp $
+# $OpenBSD: files.pcmcia,v 1.3 1996/04/21 22:25:58 deraadt Exp $
#
# Config file and device description for machine-independent PCMCIA code.
# Included by ports that need it.
@@ -7,7 +7,8 @@
# ports should define their own "device pcmcia" line (like the one below,
# but with the correct bus attachment).
-device pcmcia at pcicbus: isa
+device pcmcia: isa
+attach pcmcia at pcicbus
file dev/pcmcia/pcmcia.c pcmcia needs-count
file dev/pcmcia/pcmcia_conf.c pcmcia
diff --git a/sys/dev/ramdisk.c b/sys/dev/ramdisk.c
index 576093276d3..a3e3310efb5 100644
--- a/sys/dev/ramdisk.c
+++ b/sys/dev/ramdisk.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: ramdisk.c,v 1.4 1996/04/18 23:47:04 niklas Exp $ */
-/* $NetBSD: ramdisk.c,v 1.5 1996/03/07 10:26:29 leo Exp $ */
+/* $OpenBSD: ramdisk.c,v 1.5 1996/04/21 22:19:53 deraadt Exp $ */
+/* $NetBSD: ramdisk.c,v 1.8 1996/04/12 08:30:09 leo Exp $ */
/*
* Copyright (c) 1995 Gordon W. Ross, Leo Weppelman.
@@ -47,10 +47,14 @@
*/
#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/systm.h>
#include <sys/buf.h>
#include <sys/device.h>
#include <sys/disk.h>
+#include <sys/proc.h>
+#include <sys/conf.h>
#include <vm/vm.h>
#include <vm/vm_kern.h>
@@ -75,15 +79,10 @@ extern vm_offset_t kmem_alloc __P((vm_map_t, vm_size_t));
*
* XXX Assumption: 16 RAM-disks are enough!
*/
+#define RD_MAX_UNITS 0x10
#define RD_IS_CTRL(unit) (unit & 0x10)
#define RD_UNIT(unit) (unit & 0xF)
-/*
- * XXX - This is just for a sanity check. Only
- * applies to kernel-space RAM disk allocations.
- */
-#define RD_KMEM_MAX_SIZE 0x100000 /* 1MB */
-
/* autoconfig stuff... */
struct rd_softc {
@@ -101,32 +100,67 @@ struct rd_softc {
#define RD_ISOPEN 0x01
#define RD_SERVED 0x02
-static int rd_match (struct device *, void *self, void *);
-static void rd_attach(struct device *, struct device *self, void *);
+void rdattach __P((int));
+static void rd_attach __P((struct device *, struct device *, void *));
-struct cfdriver rdcd = {
- NULL, "rd", rd_match, rd_attach,
- DV_DULL, sizeof(struct rd_softc), NULL, 0 };
+/*
+ * Some ports (like i386) use a swapgeneric that wants to
+ * snoop around in this rd_cd structure. It is preserved
+ * (for now) to remain compatible with such practice.
+ * XXX - that practice is questionable...
+ */
+struct cfdriver rd_cd = {
+ NULL, "rd", DV_DULL, NULL, 0
+};
void rdstrategy __P((struct buf *bp));
-
struct dkdriver rddkdriver = { rdstrategy };
-static int
-rd_match(parent, self, aux)
- struct device *parent;
- void *self;
- void *aux;
+static int ramdisk_ndevs;
+static void *ramdisk_devs[RD_MAX_UNITS];
+
+/*
+ * This is called if we are configured as a pseudo-device
+ */
+void
+rdattach(n)
+ int n;
{
-#ifdef RAMDISK_HOOKS
- /*
- * This external function allows for a machine dependent
- * match function.
- */
- return (rd_match_hook(parent, self, aux));
-#else
- return(1);
+ struct rd_softc *sc;
+ int i;
+
+#ifdef DIAGNOSTIC
+ if (ramdisk_ndevs) {
+ printf("ramdisk: multiple attach calls?\n");
+ return;
+ }
#endif
+
+ /* XXX: Are we supposed to provide a default? */
+ if (n <= 1)
+ n = 1;
+ if (n > RD_MAX_UNITS)
+ n = RD_MAX_UNITS;
+ ramdisk_ndevs = n;
+
+ /* XXX: Fake-up rd_cd (see above) */
+ rd_cd.cd_ndevs = ramdisk_ndevs;
+ rd_cd.cd_devs = ramdisk_devs;
+
+ /* Attach as if by autoconfig. */
+ for (i = 0; i < n; i++) {
+
+ sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK);
+ if (!sc) {
+ printf("ramdisk: malloc for attach failed!\n");
+ return;
+ }
+ bzero((caddr_t)sc, sizeof(*sc));
+ ramdisk_devs[i] = sc;
+ sc->sc_dev.dv_unit = i;
+ sprintf(sc->sc_dev.dv_xname, "rd%d", i);
+ rd_attach(NULL, &sc->sc_dev, NULL);
+ }
}
static void
@@ -145,12 +179,10 @@ rd_attach(parent, self, aux)
*/
rd_attach_hook(sc->sc_dev.dv_unit, &sc->sc_rd);
#endif
- printf("\n");
/*
* Initialize and attach the disk structure.
*/
- bzero(&sc->sc_dkdev, sizeof(sc->sc_dkdev));
sc->sc_dkdev.dk_driver = &rddkdriver;
sc->sc_dkdev.dk_name = sc->sc_dev.dv_xname;
disk_attach(&sc->sc_dkdev);
@@ -167,6 +199,16 @@ static int rd_server_loop __P((struct rd_softc *sc));
static int rd_ioctl_server __P((struct rd_softc *sc,
struct rd_conf *urd, struct proc *proc));
#endif
+static int rd_ioctl_kalloc __P((struct rd_softc *sc,
+ struct rd_conf *urd, struct proc *proc));
+
+dev_type_open(rdopen);
+dev_type_close(rdclose);
+dev_type_read(rdread);
+dev_type_write(rdwrite);
+dev_type_ioctl(rdioctl);
+dev_type_size(rdsize);
+dev_type_dump(rddump);
int rddump(dev, blkno, va, size)
dev_t dev;
@@ -184,9 +226,9 @@ int rdsize(dev_t dev)
/* Disallow control units. */
unit = minor(dev);
- if (unit >= rdcd.cd_ndevs)
+ if (unit >= ramdisk_ndevs)
return 0;
- sc = rdcd.cd_devs[unit];
+ sc = ramdisk_devs[unit];
if (sc == NULL)
return 0;
@@ -196,7 +238,8 @@ int rdsize(dev_t dev)
return (sc->sc_size >> DEV_BSHIFT);
}
-int rdopen(dev, flag, fmt, proc)
+int
+rdopen(dev, flag, fmt, proc)
dev_t dev;
int flag, fmt;
struct proc *proc;
@@ -206,9 +249,9 @@ int rdopen(dev, flag, fmt, proc)
md = minor(dev);
unit = RD_UNIT(md);
- if (unit >= rdcd.cd_ndevs)
+ if (unit >= ramdisk_ndevs)
return ENXIO;
- sc = rdcd.cd_devs[unit];
+ sc = ramdisk_devs[unit];
if (sc == NULL)
return ENXIO;
@@ -236,7 +279,8 @@ int rdopen(dev, flag, fmt, proc)
return 0;
}
-int rdclose(dev, flag, fmt, proc)
+int
+rdclose(dev, flag, fmt, proc)
dev_t dev;
int flag, fmt;
struct proc *proc;
@@ -246,7 +290,7 @@ int rdclose(dev, flag, fmt, proc)
md = minor(dev);
unit = RD_UNIT(md);
- sc = rdcd.cd_devs[unit];
+ sc = ramdisk_devs[unit];
if (RD_IS_CTRL(md))
return 0;
@@ -258,17 +302,19 @@ int rdclose(dev, flag, fmt, proc)
}
int
-rdread(dev, uio)
+rdread(dev, uio, flags)
dev_t dev;
struct uio *uio;
+ int flags;
{
return (physio(rdstrategy, NULL, dev, B_READ, minphys, uio));
}
int
-rdwrite(dev, uio)
+rdwrite(dev, uio, flags)
dev_t dev;
struct uio *uio;
+ int flags;
{
return (physio(rdstrategy, NULL, dev, B_WRITE, minphys, uio));
}
@@ -288,7 +334,7 @@ rdstrategy(bp)
md = minor(bp->b_dev);
unit = RD_UNIT(md);
- sc = rdcd.cd_devs[unit];
+ sc = ramdisk_devs[unit];
switch (sc->sc_type) {
#if RAMDISK_SERVER
@@ -350,7 +396,7 @@ rdioctl(dev, cmd, data, flag, proc)
md = minor(dev);
unit = RD_UNIT(md);
- sc = rdcd.cd_devs[unit];
+ sc = ramdisk_devs[unit];
/* If this is not the control device, punt! */
if (RD_IS_CTRL(md) == 0)
@@ -385,7 +431,7 @@ rdioctl(dev, cmd, data, flag, proc)
* Handle ioctl RD_SETCONF for (sc_type == RD_KMEM_ALLOCATED)
* Just allocate some kernel memory and return.
*/
-int
+static int
rd_ioctl_kalloc(sc, urd, proc)
struct rd_softc *sc;
struct rd_conf *urd;
@@ -396,8 +442,6 @@ rd_ioctl_kalloc(sc, urd, proc)
/* Sanity check the size. */
size = urd->rd_size;
- if (size > RD_KMEM_MAX_SIZE)
- return EINVAL;
addr = kmem_alloc(kernel_map, size);
if (!addr)
return ENOMEM;
@@ -415,7 +459,7 @@ rd_ioctl_kalloc(sc, urd, proc)
* Handle ioctl RD_SETCONF for (sc_type == RD_UMEM_SERVER)
* Set config, then become the I/O server for this unit.
*/
-int
+static int
rd_ioctl_server(sc, urd, proc)
struct rd_softc *sc;
struct rd_conf *urd;
diff --git a/sys/dev/ramdisk.h b/sys/dev/ramdisk.h
index 687049d6582..f4ac5a70dc7 100644
--- a/sys/dev/ramdisk.h
+++ b/sys/dev/ramdisk.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: ramdisk.h,v 1.3 1996/04/18 23:47:04 niklas Exp $ */
-/* $NetBSD: ramdisk.h,v 1.3 1996/03/07 10:26:31 leo Exp $ */
+/* $OpenBSD: ramdisk.h,v 1.4 1996/04/21 22:19:56 deraadt Exp $ */
+/* $NetBSD: ramdisk.h,v 1.4 1996/03/22 23:02:04 gwr Exp $ */
/*
* Copyright (c) 1995 Gordon W. Ross
@@ -86,7 +86,6 @@ struct rd_conf {
* called by the ramdisk driver to allow machine-dependent to
* match/configure and/or load each ramdisk unit.
*/
-extern int rd_match_hook __P((struct device *, void *, void *));
extern void rd_attach_hook __P((int unit, struct rd_conf *));
extern void rd_open_hook __P((int unit, struct rd_conf *));
#endif
diff --git a/sys/dev/rcons/files.rcons b/sys/dev/rcons/files.rcons
index 571b66bf3dc..540798588bd 100644
--- a/sys/dev/rcons/files.rcons
+++ b/sys/dev/rcons/files.rcons
@@ -1,8 +1,8 @@
-# $NetBSD: files.rcons,v 1.1 1995/10/04 23:35:31 pk Exp $
+# $NetBSD: files.rcons,v 1.2 1996/04/11 21:54:38 cgd Exp $
#
# Configuration file for RASTER Console.
#
-file dev/rcons/raster_op.c rasterconsole
-file dev/rcons/raster_text.c rasterconsole
+file dev/rcons/raster_op.c rasterconsole | raster
+file dev/rcons/raster_text.c rasterconsole | raster
file dev/rcons/rcons_kern.c rasterconsole
file dev/rcons/rcons_subr.c rasterconsole
diff --git a/sys/dev/sun/kbd.c b/sys/dev/sun/kbd.c
index 524613764cb..4f5f5cbf6b4 100644
--- a/sys/dev/sun/kbd.c
+++ b/sys/dev/sun/kbd.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: kbd.c,v 1.2 1996/04/18 23:48:15 niklas Exp $ */
-/* $NetBSD: kbd.c,v 1.4 1996/02/29 19:32:14 gwr Exp $ */
+/* $OpenBSD: kbd.c,v 1.3 1996/04/21 22:26:10 deraadt Exp $ */
+/* $NetBSD: kbd.c,v 1.7 1996/04/10 21:44:58 gwr Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -191,9 +191,12 @@ struct zsops zsops_kbd;
static int kbd_match(struct device *, void *, void *);
static void kbd_attach(struct device *, struct device *, void *);
-struct cfdriver kbdcd = {
- NULL, "kbd", kbd_match, kbd_attach,
- DV_DULL, sizeof(struct kbd_softc), NULL,
+struct cfattach kbd_ca = {
+ sizeof(struct kbd_softc), kbd_match, kbd_attach
+};
+
+struct cfdriver kbd_cd = {
+ NULL, "kbd", DV_DULL
};
@@ -295,9 +298,9 @@ kbdopen(dev, flags, mode, p)
int error, s, unit;
unit = minor(dev);
- if (unit >= kbdcd.cd_ndevs)
+ if (unit >= kbd_cd.cd_ndevs)
return (ENXIO);
- k = kbdcd.cd_devs[unit];
+ k = kbd_cd.cd_devs[unit];
if (k == NULL)
return (ENXIO);
@@ -334,7 +337,7 @@ kbdclose(dev, flags, mode, p)
{
struct kbd_softc *k;
- k = kbdcd.cd_devs[minor(dev)];
+ k = kbd_cd.cd_devs[minor(dev)];
k->k_evmode = 0;
ev_fini(&k->k_events);
k->k_events.ev_io = NULL;
@@ -349,7 +352,7 @@ kbdread(dev, uio, flags)
{
struct kbd_softc *k;
- k = kbdcd.cd_devs[minor(dev)];
+ k = kbd_cd.cd_devs[minor(dev)];
return (ev_read(&k->k_events, uio, flags));
}
@@ -372,16 +375,22 @@ kbdselect(dev, rw, p)
{
struct kbd_softc *k;
- k = kbdcd.cd_devs[minor(dev)];
+ k = kbd_cd.cd_devs[minor(dev)];
return (ev_select(&k->k_events, rw, p));
}
-static int kbd_oldkeymap __P((struct kbd_state *ks,
- u_long cmd, struct okiockey *okio));
+static int kbd_ioccmd(struct kbd_softc *k, int *data);
static int kbd_iockeymap __P((struct kbd_state *ks,
u_long cmd, struct kiockeymap *kio));
+static int kbd_iocsled(struct kbd_softc *k, int *data);
+
+#ifdef KIOCGETKEY
+static int kbd_oldkeymap __P((struct kbd_state *ks,
+ u_long cmd, struct okiockey *okio));
+#endif
+
int
kbdioctl(dev, cmd, data, flag, p)
dev_t dev;
@@ -395,7 +404,7 @@ kbdioctl(dev, cmd, data, flag, p)
int *ip;
int error = 0;
- k = kbdcd.cd_devs[minor(dev)];
+ k = kbd_cd.cd_devs[minor(dev)];
ks = &k->k_state;
switch (cmd) {
@@ -429,14 +438,7 @@ kbdioctl(dev, cmd, data, flag, p)
break;
case KIOCCMD: /* Send a command to the keyboard */
- /*
- * ``unimplemented commands are ignored'' (blech)
- * so cannot check return value from kbd_docmd
- */
- error = kbd_drain_tx(k);
- if (error == 0) {
- (void) kbd_docmd(k, *(int *)data);
- }
+ error = kbd_ioccmd(k, (int *)data);
break;
case KIOCTYPE: /* Get keyboard type */
@@ -454,8 +456,7 @@ kbdioctl(dev, cmd, data, flag, p)
break;
case KIOCSLED:
- error = kbd_drain_tx(k);
- kbd_set_leds(k, *(int *)data);
+ error = kbd_iocsled(k, (int *)data);
break;
case KIOCGLED:
@@ -487,7 +488,7 @@ kbdioctl(dev, cmd, data, flag, p)
/*
* Get/Set keymap entry
*/
-int
+static int
kbd_iockeymap(ks, cmd, kio)
struct kbd_state *ks;
u_long cmd;
@@ -572,6 +573,76 @@ kbd_oldkeymap(ks, cmd, kio)
}
#endif /* KIOCGETKEY */
+
+/*
+ * keyboard command ioctl
+ * ``unimplemented commands are ignored'' (blech)
+ */
+static int
+kbd_ioccmd(k, data)
+ struct kbd_softc *k;
+ int *data;
+{
+ struct kbd_state *ks = &k->k_state;
+ int cmd, error, s;
+
+ cmd = *data;
+ switch (cmd) {
+
+ case KBD_CMD_BELL:
+ case KBD_CMD_NOBELL:
+ /* Supported by type 2, 3, and 4 keyboards */
+ break;
+
+ case KBD_CMD_CLICK:
+ case KBD_CMD_NOCLICK:
+ /* Unsupported by type 2 keyboards */
+ if (ks->kbd_id <= KB_SUN2)
+ return (0);
+ ks->kbd_click = (cmd == KBD_CMD_CLICK);
+ break;
+
+ default:
+ return (0);
+ }
+
+ s = spltty();
+
+ error = kbd_drain_tx(k);
+ if (error == 0) {
+ kbd_output(k, cmd);
+ kbd_start_tx(k);
+ }
+
+ splx(s);
+
+ return (error);
+}
+
+/*
+ * Set LEDs ioctl.
+ */
+static int
+kbd_iocsled(k, data)
+ struct kbd_softc *k;
+ int *data;
+{
+ struct kbd_state *ks = &k->k_state;
+ int leds, error, s;
+
+ leds = *data;
+
+ s = spltty();
+ error = kbd_drain_tx(k);
+ if (error == 0) {
+ kbd_set_leds(k, leds);
+ }
+ splx(s);
+
+ return (error);
+}
+
+
/****************************************************************
* middle layers:
* - keysym to ASCII sequence
@@ -686,8 +757,7 @@ kbd_input_funckey(k, keysym)
/*
* This is called by kbd_input_raw() or by kb_repeat()
- * to deliver ASCII input. Called at splsoftclock()
- * XXX: Raise to spltty before calling kd_input() ?
+ * to deliver ASCII input. Called at spltty().
*/
void
kbd_input_keysym(k, keysym)
@@ -748,23 +818,25 @@ kbd_input_keysym(k, keysym)
/*
* This is the autorepeat timeout function.
- * (called at splsoftclock)
+ * Called at splsoftclock().
*/
void
kbd_repeat(void *arg)
{
struct kbd_softc *k = (struct kbd_softc *)arg;
+ int s = spltty();
if (k->k_repeating && k->k_repeatsym >= 0) {
kbd_input_keysym(k, k->k_repeatsym);
timeout(kbd_repeat, k, k->k_repeat_step);
}
+ splx(s);
}
/*
* Called by our kbd_softint() routine on input,
* which passes the raw hardware scan codes.
- * Note: this is called at splsoftclock()
+ * Called at spltty()
*/
void
kbd_input_raw(k, c)
@@ -879,7 +951,7 @@ kbd_input_raw(k, c)
* Interface to the lower layer (zscc)
****************************************************************/
-static int
+static void
kbd_rxint(cs)
register struct zs_chanstate *cs;
{
@@ -890,11 +962,12 @@ kbd_rxint(cs)
k = cs->cs_private;
put = k->k_rbput;
- /* Read the input data ASAP. */
- c = zs_read_data(cs);
-
- /* Save the status register too. */
+ /*
+ * First read the status, because reading the received char
+ * destroys the status of this char.
+ */
rr1 = zs_read_reg(cs, 1);
+ c = zs_read_data(cs);
if (rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) {
/* Clear the receive error. */
@@ -935,29 +1008,24 @@ kbd_rxint(cs)
/* Ask for softint() call. */
cs->cs_softreq = 1;
- return(1);
}
-static int
+static void
kbd_txint(cs)
register struct zs_chanstate *cs;
{
register struct kbd_softc *k;
- register int count, rval;
k = cs->cs_private;
-
zs_write_csr(cs, ZSWR0_RESET_TXINT);
-
k->k_intr_flags |= INTR_TX_EMPTY;
/* Ask for softint() call. */
cs->cs_softreq = 1;
- return (1);
}
-static int
+static void
kbd_stint(cs)
register struct zs_chanstate *cs;
{
@@ -966,7 +1034,7 @@ kbd_stint(cs)
k = cs->cs_private;
- rr0 = zs_read_csr(cs);
+ cs->cs_rr0_new = zs_read_csr(cs);
zs_write_csr(cs, ZSWR0_RESET_STATUS);
#if 0
@@ -980,14 +1048,13 @@ kbd_stint(cs)
k->k_intr_flags |= INTR_ST_CHECK;
/* Ask for softint() call. */
cs->cs_softreq = 1;
- return (1);
}
/*
* Get input from the recieve ring and pass it on.
* Note: this is called at splsoftclock()
*/
-static int
+static void
kbd_softint(cs)
struct zs_chanstate *cs;
{
@@ -1003,7 +1070,9 @@ kbd_softint(cs)
s = splzs();
intr_flags = k->k_intr_flags;
k->k_intr_flags = 0;
- splx(s);
+
+ /* Now lower to spltty for the rest. */
+ (void) spltty();
/*
* Copy data from the receive ring to the event layer.
@@ -1057,9 +1126,10 @@ kbd_softint(cs)
*/
log(LOG_ERR, "%s: status interrupt?\n",
k->k_dev.dv_xname);
+ cs->cs_rr0 = cs->cs_rr0_new;
}
- return (1);
+ splx(s);
}
struct zsops zsops_kbd = {
@@ -1076,6 +1146,7 @@ struct zsops zsops_kbd = {
/*
* Initialization to be done at first open.
* This is called from kbdopen or kdopen (in kd.c)
+ * Called with user context.
*/
int
kbd_iopen(unit)
@@ -1085,9 +1156,9 @@ kbd_iopen(unit)
struct kbd_state *ks;
int error, s;
- if (unit >= kbdcd.cd_ndevs)
+ if (unit >= kbd_cd.cd_ndevs)
return (ENXIO);
- k = kbdcd.cd_devs[unit];
+ k = kbd_cd.cd_devs[unit];
if (k == NULL)
return (ENXIO);
ks = &k->k_state;
@@ -1144,6 +1215,9 @@ out:
return error;
}
+/*
+ * Called by kbd_input_raw, at spltty()
+ */
void
kbd_was_reset(k)
struct kbd_softc *k;
@@ -1165,14 +1239,20 @@ kbd_was_reset(k)
case KB_SUN3:
/* Type 3 keyboards come up with keyclick on */
- if (!ks->kbd_click)
- (void) kbd_docmd(k, KBD_CMD_NOCLICK);
+ if (!ks->kbd_click) {
+ /* turn off the click */
+ kbd_output(k, KBD_CMD_NOCLICK);
+ kbd_start_tx(k);
+ }
break;
case KB_SUN4:
/* Type 4 keyboards come up with keyclick off */
- if (ks->kbd_click)
- (void) kbd_docmd(k, KBD_CMD_CLICK);
+ if (ks->kbd_click) {
+ /* turn on the click */
+ kbd_output(k, KBD_CMD_CLICK);
+ kbd_start_tx(k);
+ }
break;
}
@@ -1180,6 +1260,9 @@ kbd_was_reset(k)
ks->kbd_leds = 0;
}
+/*
+ * Called by kbd_input_raw, at spltty()
+ */
void
kbd_new_layout(k)
struct kbd_softc *k;
@@ -1198,28 +1281,28 @@ kbd_new_layout(k)
/*
* Wait for output to finish.
- * Called with user context.
+ * Called at spltty(). Has user context.
*/
int
kbd_drain_tx(k)
struct kbd_softc *k;
{
- int error, s;
+ int error;
error = 0;
- s = spltty();
+
while (k->k_txflags & K_TXBUSY) {
k->k_txflags |= K_TXWANT;
error = tsleep((caddr_t)&k->k_txflags,
PZERO | PCATCH, "kbdout", 0);
}
- splx(s);
+
return (error);
}
/*
- * Send out a byte to the keyboard (i.e. reset)
- * Called with user context.
+ * Enqueue some output for the keyboard
+ * Called at spltty().
*/
void
kbd_output(k, c)
@@ -1227,9 +1310,8 @@ kbd_output(k, c)
int c; /* the data */
{
struct zs_chanstate *cs = k->k_cs;
- int put, s;
+ int put;
- s = spltty();
put = k->k_tbput;
k->k_tbuf[put] = (u_char)c;
put = (put + 1) & KBD_TX_RING_MASK;
@@ -1242,10 +1324,12 @@ kbd_output(k, c)
/* OK, really increment. */
k->k_tbput = put;
}
-
- splx(s);
}
+/*
+ * Start the sending data from the output queue
+ * Called at spltty().
+ */
void
kbd_start_tx(k)
struct kbd_softc *k;
@@ -1254,9 +1338,8 @@ kbd_start_tx(k)
int get, s;
u_char c;
- s = spltty();
if (k->k_txflags & K_TXBUSY)
- goto out;
+ return;
/* Is there anything to send? */
get = k->k_tbget;
@@ -1266,7 +1349,7 @@ kbd_start_tx(k)
k->k_txflags &= ~K_TXWANT;
wakeup((caddr_t)&k->k_txflags);
}
- goto out;
+ return;
}
/* Have something to send. */
@@ -1276,41 +1359,41 @@ kbd_start_tx(k)
k->k_txflags |= K_TXBUSY;
/* Need splzs to avoid interruption of the delay. */
- (void) splzs();
+ s = splzs();
zs_write_data(cs, c);
-
-out:
splx(s);
}
-
+/*
+ * Called at spltty by:
+ * kbd_update_leds, kbd_iocsled
+ */
void
kbd_set_leds(k, new_leds)
struct kbd_softc *k;
int new_leds;
{
struct kbd_state *ks = &k->k_state;
- int s;
-
- s = spltty();
/* Don't send unless state changes. */
if (ks->kbd_leds == new_leds)
- goto out;
+ return;
+
ks->kbd_leds = new_leds;
/* Only type 4 and later has LEDs anyway. */
if (ks->kbd_id < 4)
- goto out;
+ return;
kbd_output(k, KBD_CMD_SETLED);
kbd_output(k, new_leds);
kbd_start_tx(k);
-
-out:
- splx(s);
}
+/*
+ * Called at spltty by:
+ * kbd_input_keysym
+ */
void
kbd_update_leds(k)
struct kbd_softc *k;
@@ -1328,47 +1411,3 @@ kbd_update_leds(k)
kbd_set_leds(k, leds);
}
-
-
-/*
- * Execute a keyboard command; return 0 on success.
- */
-int
-kbd_docmd(k, cmd)
- struct kbd_softc *k;
- int cmd;
-{
- struct kbd_state *ks = &k->k_state;
- int error, s;
-
- switch (cmd) {
-
- case KBD_CMD_BELL:
- case KBD_CMD_NOBELL:
- /* Supported by type 2, 3, and 4 keyboards */
- break;
-
- case KBD_CMD_CLICK:
- /* Unsupported by type 2 keyboards */
- if (ks->kbd_id != KB_SUN2) {
- ks->kbd_click = 1;
- break;
- }
- return (EINVAL);
-
- case KBD_CMD_NOCLICK:
- /* Unsupported by type 2 keyboards */
- if (ks->kbd_id != KB_SUN2) {
- ks->kbd_click = 0;
- break;
- }
- return (EINVAL);
-
- default:
- return (EINVAL); /* ENOTTY? EOPNOTSUPP? */
- }
-
- kbd_output(k, cmd);
- kbd_start_tx(k);
- return (0);
-}
diff --git a/sys/dev/sun/ms.c b/sys/dev/sun/ms.c
index 8515ff86efc..a176c06bdcb 100644
--- a/sys/dev/sun/ms.c
+++ b/sys/dev/sun/ms.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: ms.c,v 1.2 1996/04/18 23:48:18 niklas Exp $ */
-/* $NetBSD: ms.c,v 1.3 1996/02/19 04:36:15 gwr Exp $ */
+/* $OpenBSD: ms.c,v 1.3 1996/04/21 22:26:13 deraadt Exp $ */
+/* $NetBSD: ms.c,v 1.5 1996/04/10 21:45:01 gwr Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -143,9 +143,12 @@ struct zsops zsops_ms;
static int ms_match(struct device *, void *, void *);
static void ms_attach(struct device *, struct device *, void *);
-struct cfdriver mscd = {
- NULL, "ms", ms_match, ms_attach,
- DV_DULL, sizeof(struct ms_softc), NULL,
+struct cfattach ms_ca = {
+ sizeof(struct ms_softc), ms_match, ms_attach
+};
+
+struct cfdriver ms_cd = {
+ NULL, "ms", DV_DULL
};
@@ -224,9 +227,9 @@ msopen(dev, flags, mode, p)
int error, s, unit;
unit = minor(dev);
- if (unit >= mscd.cd_ndevs)
+ if (unit >= ms_cd.cd_ndevs)
return (ENXIO);
- ms = mscd.cd_devs[unit];
+ ms = ms_cd.cd_devs[unit];
if (ms == NULL)
return (ENXIO);
@@ -248,7 +251,7 @@ msclose(dev, flags, mode, p)
{
struct ms_softc *ms;
- ms = mscd.cd_devs[minor(dev)];
+ ms = ms_cd.cd_devs[minor(dev)];
ms->ms_ready = 0; /* stop accepting events */
ev_fini(&ms->ms_events);
@@ -264,7 +267,7 @@ msread(dev, uio, flags)
{
struct ms_softc *ms;
- ms = mscd.cd_devs[minor(dev)];
+ ms = ms_cd.cd_devs[minor(dev)];
return (ev_read(&ms->ms_events, uio, flags));
}
@@ -289,7 +292,7 @@ msioctl(dev, cmd, data, flag, p)
{
struct ms_softc *ms;
- ms = mscd.cd_devs[minor(dev)];
+ ms = ms_cd.cd_devs[minor(dev)];
switch (cmd) {
@@ -326,7 +329,7 @@ msselect(dev, rw, p)
{
struct ms_softc *ms;
- ms = mscd.cd_devs[minor(dev)];
+ ms = ms_cd.cd_devs[minor(dev)];
return (ev_select(&ms->ms_events, rw, p));
}
@@ -476,7 +479,7 @@ out:
* Interface to the lower layer (zscc)
****************************************************************/
-static int
+static void
ms_rxint(cs)
register struct zs_chanstate *cs;
{
@@ -487,11 +490,12 @@ ms_rxint(cs)
ms = cs->cs_private;
put = ms->ms_rbput;
- /* Read the input data ASAP. */
- c = zs_read_data(cs);
-
- /* Save the status register too. */
+ /*
+ * First read the status, because reading the received char
+ * destroys the status of this char.
+ */
rr1 = zs_read_reg(cs, 1);
+ c = zs_read_data(cs);
if (rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) {
/* Clear the receive error. */
@@ -514,29 +518,24 @@ ms_rxint(cs)
/* Ask for softint() call. */
cs->cs_softreq = 1;
- return(1);
}
-static int
+static void
ms_txint(cs)
register struct zs_chanstate *cs;
{
register struct ms_softc *ms;
- register int count, rval;
ms = cs->cs_private;
-
zs_write_csr(cs, ZSWR0_RESET_TXINT);
-
ms->ms_intr_flags |= INTR_TX_EMPTY;
/* Ask for softint() call. */
cs->cs_softreq = 1;
- return (1);
}
-static int
+static void
ms_stint(cs)
register struct zs_chanstate *cs;
{
@@ -545,17 +544,16 @@ ms_stint(cs)
ms = cs->cs_private;
- rr0 = zs_read_csr(cs);
+ cs->cs_rr0_new = zs_read_csr(cs);
zs_write_csr(cs, ZSWR0_RESET_STATUS);
ms->ms_intr_flags |= INTR_ST_CHECK;
/* Ask for softint() call. */
cs->cs_softreq = 1;
- return (1);
}
-static int
+static void
ms_softint(cs)
struct zs_chanstate *cs;
{
@@ -571,7 +569,9 @@ ms_softint(cs)
s = splzs();
intr_flags = ms->ms_intr_flags;
ms->ms_intr_flags = 0;
- splx(s);
+
+ /* Now lower to spltty for the rest. */
+ (void) spltty();
/*
* Copy data from the receive ring to the event layer.
@@ -615,9 +615,10 @@ ms_softint(cs)
*/
log(LOG_ERR, "%s: status interrupt?\n",
ms->ms_dev.dv_xname);
+ cs->cs_rr0 = cs->cs_rr0_new;
}
- return (1);
+ splx(s);
}
struct zsops zsops_ms = {
diff --git a/sys/dev/tc/asc.c b/sys/dev/tc/asc.c
index d41fc46f32b..c61f99c5774 100644
--- a/sys/dev/tc/asc.c
+++ b/sys/dev/tc/asc.c
@@ -1,4 +1,4 @@
-/* $NetBSD: asc.c,v 1.16 1996/01/04 17:43:23 jonathan Exp $ */
+/* $NetBSD: asc.c,v 1.18 1996/03/18 01:39:47 jonathan Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -129,6 +129,8 @@
#include <sys/conf.h>
#include <sys/errno.h>
#include <sys/device.h>
+#include <dev/tc/tcvar.h>
+#include <dev/tc/ioasicvar.h>
#include <scsi/scsi_all.h>
#include <scsi/scsiconf.h>
@@ -145,7 +147,8 @@
#include <pmax/pmax/pmaxtype.h>
-#define readback(a) { register int foo; foo = (a); }
+/*#define readback(a) { register int foo; wbflush(); foo = (a); }*/
+#define readback(a) { register int foo; foo = (a); }
extern int pmax_boardtype;
/*
@@ -273,38 +276,38 @@ static int asc_disconnect(); /* process an expected disconnect */
*/
script_t asc_scripts[] = {
/* start data in */
- {SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_DATAI), /* 0 */
+ {SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, SCSI_PHASE_DATAI), /* 0 */
asc_dma_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
&asc_scripts[SCRIPT_DATA_IN + 1]},
- {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_STATUS), /* 1 */
+ {SCRIPT_MATCH(ASC_INT_BS, SCSI_PHASE_STATUS), /* 1 */
asc_last_dma_in, ASC_CMD_I_COMPLETE,
&asc_scripts[SCRIPT_GET_STATUS]},
/* continue data in after a chunk is finished */
- {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAI), /* 2 */
+ {SCRIPT_MATCH(ASC_INT_BS, SCSI_PHASE_DATAI), /* 2 */
asc_dma_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
&asc_scripts[SCRIPT_DATA_IN + 1]},
/* start data out */
- {SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_DATAO), /* 3 */
+ {SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, SCSI_PHASE_DATAO), /* 3 */
asc_dma_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
&asc_scripts[SCRIPT_DATA_OUT + 1]},
- {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_STATUS), /* 4 */
+ {SCRIPT_MATCH(ASC_INT_BS, SCSI_PHASE_STATUS), /* 4 */
asc_last_dma_out, ASC_CMD_I_COMPLETE,
&asc_scripts[SCRIPT_GET_STATUS]},
/* continue data out after a chunk is finished */
- {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAO), /* 5 */
+ {SCRIPT_MATCH(ASC_INT_BS, SCSI_PHASE_DATAO), /* 5 */
asc_dma_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
&asc_scripts[SCRIPT_DATA_OUT + 1]},
/* simple command with no data transfer */
- {SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_STATUS), /* 6 */
+ {SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, SCSI_PHASE_STATUS), /* 6 */
script_nop, ASC_CMD_I_COMPLETE,
&asc_scripts[SCRIPT_GET_STATUS]},
/* get status and finish command */
- {SCRIPT_MATCH(ASC_INT_FC, ASC_PHASE_MSG_IN), /* 7 */
+ {SCRIPT_MATCH(ASC_INT_FC, SCSI_PHASE_MSG_IN), /* 7 */
asc_get_status, ASC_CMD_MSG_ACPT,
&asc_scripts[SCRIPT_DONE]},
{SCRIPT_MATCH(ASC_INT_DISC, 0), /* 8 */
@@ -312,61 +315,61 @@ script_t asc_scripts[] = {
&asc_scripts[SCRIPT_DONE]},
/* message in */
- {SCRIPT_MATCH(ASC_INT_FC, ASC_PHASE_MSG_IN), /* 9 */
+ {SCRIPT_MATCH(ASC_INT_FC, SCSI_PHASE_MSG_IN), /* 9 */
asc_msg_in, ASC_CMD_MSG_ACPT,
&asc_scripts[SCRIPT_MSG_IN + 1]},
- {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_MSG_IN), /* 10 */
+ {SCRIPT_MATCH(ASC_INT_BS, SCSI_PHASE_MSG_IN), /* 10 */
script_nop, ASC_CMD_XFER_INFO,
&asc_scripts[SCRIPT_MSG_IN]},
/* send synchonous negotiation reply */
- {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_MSG_OUT), /* 11 */
+ {SCRIPT_MATCH(ASC_INT_BS, SCSI_PHASE_MSG_OUT), /* 11 */
asc_replysync, ASC_CMD_XFER_INFO,
&asc_scripts[SCRIPT_REPLY_SYNC]},
/* try to negotiate synchonous transfer parameters */
- {SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_MSG_OUT), /* 12 */
+ {SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, SCSI_PHASE_MSG_OUT), /* 12 */
asc_sendsync, ASC_CMD_XFER_INFO,
&asc_scripts[SCRIPT_TRY_SYNC + 1]},
- {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_MSG_IN), /* 13 */
+ {SCRIPT_MATCH(ASC_INT_BS, SCSI_PHASE_MSG_IN), /* 13 */
script_nop, ASC_CMD_XFER_INFO,
&asc_scripts[SCRIPT_MSG_IN]},
- {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_COMMAND), /* 14 */
+ {SCRIPT_MATCH(ASC_INT_BS, SCSI_PHASE_COMMAND), /* 14 */
script_nop, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
&asc_scripts[SCRIPT_RESUME_NO_DATA]},
/* handle a disconnect */
- {SCRIPT_MATCH(ASC_INT_DISC, ASC_PHASE_DATAO), /* 15 */
+ {SCRIPT_MATCH(ASC_INT_DISC, SCSI_PHASE_DATAO), /* 15 */
asc_disconnect, ASC_CMD_ENABLE_SEL,
&asc_scripts[SCRIPT_RESEL]},
/* reselect sequence: this is just a placeholder so match fails */
- {SCRIPT_MATCH(0, ASC_PHASE_MSG_IN), /* 16 */
+ {SCRIPT_MATCH(0, SCSI_PHASE_MSG_IN), /* 16 */
script_nop, ASC_CMD_MSG_ACPT,
&asc_scripts[SCRIPT_RESEL]},
/* resume data in after a message */
- {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAI), /* 17 */
+ {SCRIPT_MATCH(ASC_INT_BS, SCSI_PHASE_DATAI), /* 17 */
asc_resume_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
&asc_scripts[SCRIPT_DATA_IN + 1]},
/* resume partial DMA data in after a message */
- {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAI), /* 18 */
+ {SCRIPT_MATCH(ASC_INT_BS, SCSI_PHASE_DATAI), /* 18 */
asc_resume_dma_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
&asc_scripts[SCRIPT_DATA_IN + 1]},
/* resume data out after a message */
- {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAO), /* 19 */
+ {SCRIPT_MATCH(ASC_INT_BS, SCSI_PHASE_DATAO), /* 19 */
asc_resume_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
&asc_scripts[SCRIPT_DATA_OUT + 1]},
/* resume partial DMA data out after a message */
- {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAO), /* 20 */
+ {SCRIPT_MATCH(ASC_INT_BS, SCSI_PHASE_DATAO), /* 20 */
asc_resume_dma_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
&asc_scripts[SCRIPT_DATA_OUT + 1]},
/* resume after a message when there is no more data */
- {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_STATUS), /* 21 */
+ {SCRIPT_MATCH(ASC_INT_BS, SCSI_PHASE_STATUS), /* 21 */
script_nop, ASC_CMD_I_COMPLETE,
&asc_scripts[SCRIPT_GET_STATUS]},
};
@@ -446,7 +449,7 @@ typedef struct asc_softc *asc_softc_t;
#define ASCDMA_WRITE 2
static void tb_dma_start(), tb_dma_end(), asic_dma_start(), asic_dma_end();
extern u_long asc_iomem;
-extern u_long asic_base;
+
/*
* Autoconfiguration data for config.
@@ -455,11 +458,16 @@ int ascmatch __P((struct device * parent, void *cfdata, void *aux));
void ascattach __P((struct device *parent, struct device *self, void *aux));
int ascprint(void*, char*);
-extern struct cfdriver asccd;
-struct cfdriver asccd = {
- NULL, "asc", ascmatch, ascattach, DV_DULL, sizeof(struct asc_softc)
+struct cfattach asc_ca = {
+ sizeof(struct asc_softc), ascmatch, ascattach
+};
+
+extern struct cfdriver asc_cd;
+struct cfdriver asc_cd = {
+ NULL, "as", DV_DULL
};
+
#ifdef USE_NEW_SCSI
/* Glue to the machine-independent scsi */
struct scsi_adapter asc_switch = {
@@ -498,19 +506,22 @@ ascmatch(parent, match, aux)
{
struct cfdata *cf = match;
struct confargs *ca = aux;
- void *sccaddr;
+ void *ascaddr;
- if (!BUS_MATCHNAME(ca, "asc") && !BUS_MATCHNAME(ca, "PMAZ-AA "))
+ /*if (parent->dv_cfdata->cf_driver == &ioasic_cd) */
+ if (!TC_BUS_MATCHNAME(ca, "asc") && !TC_BUS_MATCHNAME(ca, "PMAZ-AA "))
return (0);
- sccaddr = BUS_CVTADDR(ca);
+ ascaddr = (void*)ca->ca_addr;
- if (badaddr(sccaddr + ASC_OFFSET_53C94, 4))
+ if (badaddr(ascaddr + ASC_OFFSET_53C94, 4))
return (0);
return (1);
}
+extern struct cfdriver ioasic_cd; /* XXX */
+
void
ascattach(parent, self, aux)
struct device *parent;
@@ -526,7 +537,7 @@ ascattach(parent, self, aux)
void *ascaddr;
int unit;
- ascaddr = (void *)MACH_PHYS_TO_UNCACHED(BUS_CVTADDR(ca));
+ ascaddr = (void*)MACH_PHYS_TO_UNCACHED(ca->ca_addr);
unit = asc->sc_dev.dv_unit;
/*
@@ -539,25 +550,20 @@ ascattach(parent, self, aux)
* (1) how to do dma
* (2) timing based on turbochannel frequency
*/
- switch (pmax_boardtype) {
- case DS_3MIN:
- case DS_MAXINE:
- case DS_3MAXPLUS:
- if (unit == 0) {
+
+ if (asc->sc_dev.dv_parent->dv_cfdata->cf_driver == &ioasic_cd) {
asc->buff = (u_char *)MACH_PHYS_TO_UNCACHED(asc_iomem);
bufsiz = 8192;
- *((volatile int *)ASIC_REG_SCSI_DMAPTR(asic_base)) = -1;
- *((volatile int *)ASIC_REG_SCSI_DMANPTR(asic_base)) = -1;
- *((volatile int *)ASIC_REG_SCSI_SCR(asic_base)) = 0;
+ *((volatile int *)IOASIC_REG_SCSI_DMAPTR(ioasic_base)) = -1;
+ *((volatile int *)IOASIC_REG_SCSI_DMANPTR(ioasic_base)) = -1;
+ *((volatile int *)IOASIC_REG_SCSI_SCR(ioasic_base)) = 0;
asc->dma_start = asic_dma_start;
asc->dma_end = asic_dma_end;
- break;
- }
+ } else
+ {
/*
* Fall through for turbochannel option.
*/
- case DS_3MAX:
- default:
asc->dmar = (volatile int *)(ascaddr + ASC_OFFSET_DMAR);
asc->buff = (u_char *)(ascaddr + ASC_OFFSET_RAM);
bufsiz = PER_TGT_DMA_SIZE;
@@ -639,6 +645,7 @@ ascattach(parent, self, aux)
/* tie pseudo-slot to device */
BUS_INTR_ESTABLISH(ca, asc_intr, asc);
+
printf(": target %d\n", id);
@@ -690,7 +697,7 @@ asc_start(scsicmd)
register ScsiCmd *scsicmd; /* command to start */
{
register struct pmax_scsi_device *sdp = scsicmd->sd;
- register asc_softc_t asc = asccd.cd_devs[sdp->sd_ctlr];
+ register asc_softc_t asc = asc_cd.cd_devs[sdp->sd_ctlr];
int s;
s = splbio();
@@ -979,18 +986,18 @@ again:
state = &asc->st[asc->target];
switch (ASC_PHASE(status)) {
- case ASC_PHASE_DATAI:
- case ASC_PHASE_DATAO:
+ case SCSI_PHASE_DATAI:
+ case SCSI_PHASE_DATAO:
ASC_TC_GET(regs, len);
fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
printf("asc_intr: data overrun: buflen %d dmalen %d tc %d fifo %d\n",
state->buflen, state->dmalen, len, fifo);
goto abort;
- case ASC_PHASE_MSG_IN:
+ case SCSI_PHASE_MSG_IN:
break;
- case ASC_PHASE_MSG_OUT:
+ case SCSI_PHASE_MSG_OUT:
/*
* Check for parity error.
* Hardware will automatically set ATN
@@ -1008,7 +1015,7 @@ again:
readback(regs->asc_cmd);
goto done;
- case ASC_PHASE_STATUS:
+ case SCSI_PHASE_STATUS:
/* probably an error in the SCSI command */
asc->script = &asc_scripts[SCRIPT_GET_STATUS];
regs->asc_cmd = ASC_CMD_I_COMPLETE;
@@ -1176,7 +1183,7 @@ again:
/*
* Disconnects can happen normally when the
* command is complete with the phase being
- * either ASC_PHASE_DATAO or ASC_PHASE_MSG_IN.
+ * either SCSI_PHASE_DATAO or SCSI_PHASE_MSG_IN.
* The SCRIPT_MATCH() only checks for one phase
* so we can wind up here.
* Perform the appropriate operation, then proceed.
@@ -1955,7 +1962,7 @@ asc_msg_in(asc, status, ss, ir)
status = asc_wait(regs, ASC_CSR_INT);
ir = regs->asc_intr;
/* some just break out here, some dont */
- if (ASC_PHASE(status) == ASC_PHASE_MSG_OUT) {
+ if (ASC_PHASE(status) == SCSI_PHASE_MSG_OUT) {
regs->asc_fifo = SCSI_ABORT;
regs->asc_cmd = ASC_CMD_XFER_INFO;
readback(regs->asc_cmd);
@@ -2079,12 +2086,12 @@ asic_dma_start(asc, state, cp, flag)
int flag;
{
register volatile u_int *ssr = (volatile u_int *)
- ASIC_REG_CSR(asic_base);
+ IOASIC_REG_CSR(ioasic_base);
u_int phys, nphys;
/* stop DMA engine first */
- *ssr &= ~ASIC_CSR_DMAEN_SCSI;
- *((volatile int *)ASIC_REG_SCSI_SCR(asic_base)) = 0;
+ *ssr &= ~IOASIC_CSR_DMAEN_SCSI;
+ *((volatile int *)IOASIC_REG_SCSI_SCR(ioasic_base)) = 0;
phys = MACH_CACHED_TO_PHYS(cp);
cp = (caddr_t)pmax_trunc_page(cp + NBPG);
@@ -2093,14 +2100,14 @@ asic_dma_start(asc, state, cp, flag)
asc->dma_next = cp;
asc->dma_xfer = state->dmalen - (nphys - phys);
- *(volatile int *)ASIC_REG_SCSI_DMAPTR(asic_base) =
- ASIC_DMA_ADDR(phys);
- *(volatile int *)ASIC_REG_SCSI_DMANPTR(asic_base) =
- ASIC_DMA_ADDR(nphys);
+ *(volatile int *)IOASIC_REG_SCSI_DMAPTR(ioasic_base) =
+ IOASIC_DMA_ADDR(phys);
+ *(volatile int *)IOASIC_REG_SCSI_DMANPTR(ioasic_base) =
+ IOASIC_DMA_ADDR(nphys);
if (flag == ASCDMA_READ)
- *ssr |= ASIC_CSR_SCSI_DIR | ASIC_CSR_DMAEN_SCSI;
+ *ssr |= IOASIC_CSR_SCSI_DIR | IOASIC_CSR_DMAEN_SCSI;
else
- *ssr = (*ssr & ~ASIC_CSR_SCSI_DIR) | ASIC_CSR_DMAEN_SCSI;
+ *ssr = (*ssr & ~IOASIC_CSR_SCSI_DIR) | IOASIC_CSR_DMAEN_SCSI;
MachEmptyWriteBuffer();
}
@@ -2111,34 +2118,34 @@ asic_dma_end(asc, state, flag)
int flag;
{
register volatile u_int *ssr = (volatile u_int *)
- ASIC_REG_CSR(asic_base);
+ IOASIC_REG_CSR(ioasic_base);
register volatile u_int *dmap = (volatile u_int *)
- ASIC_REG_SCSI_DMAPTR(asic_base);
+ IOASIC_REG_SCSI_DMAPTR(ioasic_base);
register u_short *to;
register int w;
int nb;
- *ssr &= ~ASIC_CSR_DMAEN_SCSI;
+ *ssr &= ~IOASIC_CSR_DMAEN_SCSI;
to = (u_short *)MACH_PHYS_TO_CACHED(*dmap >> 3);
*dmap = -1;
- *((volatile int *)ASIC_REG_SCSI_DMANPTR(asic_base)) = -1;
+ *((volatile int *)IOASIC_REG_SCSI_DMANPTR(ioasic_base)) = -1;
MachEmptyWriteBuffer();
if (flag == ASCDMA_READ) {
MachFlushDCache(MACH_PHYS_TO_CACHED(
MACH_UNCACHED_TO_PHYS(state->dmaBufAddr)), state->dmalen);
- if (nb = *((int *)ASIC_REG_SCSI_SCR(asic_base))) {
+ if (nb = *((int *)IOASIC_REG_SCSI_SCR(ioasic_base))) {
/* pick up last upto6 bytes, sigh. */
/* Last byte really xferred is.. */
- w = *(int *)ASIC_REG_SCSI_SDR0(asic_base);
+ w = *(int *)IOASIC_REG_SCSI_SDR0(ioasic_base);
*to++ = w;
if (--nb > 0) {
w >>= 16;
*to++ = w;
}
if (--nb > 0) {
- w = *(int *)ASIC_REG_SCSI_SDR1(asic_base);
+ w = *(int *)IOASIC_REG_SCSI_SDR1(ioasic_base);
*to++ = w;
}
}
@@ -2152,20 +2159,20 @@ asic_dma_end(asc, state, flag)
void
asc_dma_intr()
{
- asc_softc_t asc = &asccd.cd_devs[0]; /*XXX*/
+ asc_softc_t asc = &asc_cd.cd_devs[0]; /*XXX*/
u_int next_phys;
asc->dma_xfer -= NBPG;
if (asc->dma_xfer <= -NBPG) {
volatile u_int *ssr = (volatile u_int *)
- ASIC_REG_CSR(asic_base);
- *ssr &= ~ASIC_CSR_DMAEN_SCSI;
+ IOASIC_REG_CSR(ioasic_base);
+ *ssr &= ~IOASIC_CSR_DMAEN_SCSI;
} else {
asc->dma_next += NBPG;
next_phys = MACH_CACHED_TO_PHYS(asc->dma_next);
}
- *(volatile int *)ASIC_REG_SCSI_DMANPTR(asic_base) =
- ASIC_DMA_ADDR(next_phys);
+ *(volatile int *)IOASIC_REG_SCSI_DMANPTR(ioasic_base) =
+ IOASIC_DMA_ADDR(next_phys);
MachEmptyWriteBuffer();
}
#endif /*notdef*/
diff --git a/sys/dev/tc/files.tc b/sys/dev/tc/files.tc
index e0e77a12141..053a8463a77 100644
--- a/sys/dev/tc/files.tc
+++ b/sys/dev/tc/files.tc
@@ -1,12 +1,14 @@
-# $OpenBSD: files.tc,v 1.2 1996/04/18 23:48:21 niklas Exp $
-# $NetBSD: files.tc,v 1.2 1996/02/27 22:00:04 cgd Exp $
+# $OpenBSD: files.tc,v 1.3 1996/04/21 22:26:22 deraadt Exp $
+# $NetBSD: files.tc,v 1.3 1996/03/17 00:58:33 thorpej Exp $
#
# Config.new file and device description for machine-independent
# TurboChannel code. Included by ports that need it.
-device tc at tcbus {[slot = -1], [offset = -1]}
+device tc {[slot = -1], [offset = -1]}
+attach tc at tcbus
file dev/tc/tc.c tc needs-flag
# XXX conflicts with ISA if_le.c
-#device le at ioasic, tc: ether, ifnet # XXX PMAX BASEBOARD OPTIONS
+#device le: ether, ifnet # XXX PMAX BASEBOARD OPTIONS
+#attach le at ioasic, tc with le_tc
#file dev/tc/if_le.c le needs-flag # for le_iomem
diff --git a/sys/dev/tc/if_le.c b/sys/dev/tc/if_le.c
index b7909dfabbb..b528f8c831e 100644
--- a/sys/dev/tc/if_le.c
+++ b/sys/dev/tc/if_le.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: if_le.c,v 1.2 1996/04/18 23:48:21 niklas Exp $ */
-/* $NetBSD: if_le.c,v 1.3 1996/02/26 23:38:38 cgd Exp $ */
+/* $OpenBSD: if_le.c,v 1.3 1996/04/21 22:26:24 deraadt Exp $ */
+/* $NetBSD: if_le.c,v 1.6 1996/04/08 20:09:56 jonathan Exp $ */
/*-
* Copyright (c) 1995 Charles M. Hannum. All rights reserved.
@@ -40,6 +40,11 @@
* @(#)if_le.c 8.2 (Berkeley) 11/16/93
*/
+
+/*
+ * Supported busses: DEC IOCTL asic baseboard device, TurboChannel option,
+ * plus baseboard device on "busless" DECstations.
+ */
#ifdef alpha
#define CAN_HAVE_IOASIC 1
#define CAN_HAVE_TC 1
@@ -48,9 +53,14 @@
#define CAN_HAVE_IOASIC 1
#define CAN_HAVE_TC 1
#define CAN_HAVE_MAINBUS 1
-#endif
+#endif /* pmax */
+
+
+/*
+ * For each bus on which a LANCE device might appear, determine
+ * if that bus was configured into the current kernel.
+ */
-#include "bpfilter.h"
#ifdef CAN_HAVE_MAINBUS
/*XXX TEST FOR KN01 OR MIPSFAIR? */
#endif
@@ -61,6 +71,8 @@
#include "ioasic.h"
#endif
+#include "bpfilter.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
@@ -85,7 +97,8 @@
#endif
#if CAN_HAVE_MAINBUS
#include <pmax/pmax/kn01.h>
-extern struct cfdriver mainbuscd; /* XXX */
+#include <pmax/pmax/kn01var.h>
+extern struct cfdriver mainbus_cd; /* XXX */
#endif
#include <dev/tc/if_levar.h>
@@ -96,7 +109,7 @@ extern struct cfdriver mainbuscd; /* XXX */
#include <dev/ic/am7990var.h>
/* access LANCE registers */
-void lewritereg();
+void lewritereg __P((volatile u_short *regptr, u_short val));
#define LERDWR(cntl, src, dst) { (dst) = (src); tc_mb(); }
#define LEWREG(src, dst) lewritereg(&(dst), (src))
@@ -106,15 +119,19 @@ void lewritereg();
extern caddr_t le_iomem;
-#define LE_SOFTC(unit) lecd.cd_devs[unit]
+#define LE_SOFTC(unit) le_cd.cd_devs[unit]
#define LE_DELAY(x) DELAY(x)
-int lematch __P((struct device *, void *, void *));
-void leattach __P((struct device *, struct device *, void *));
+int le_tc_match __P((struct device *, void *, void *));
+void le_tc_attach __P((struct device *, struct device *, void *));
int leintr __P((void *));
-struct cfdriver lecd = {
- NULL, "le", lematch, leattach, DV_IFNET, sizeof (struct le_softc)
+struct cfattach le_tc_ca = {
+ sizeof(struct le_softc), le_tc_match, le_tc_attach
+};
+
+struct cfdriver le_cd = {
+ NULL, "le", DV_IFNET
};
integrate void
@@ -142,33 +159,39 @@ lerdcsr(sc, port)
}
int
-lematch(parent, match, aux)
+le_tc_match(parent, match, aux)
struct device *parent;
void *match, *aux;
{
#if CAN_HAVE_IOASIC && (NIOASIC > 0)
- if (parent->dv_cfdata->cf_driver == &ioasiccd) {
+ if (parent->dv_cfdata->cf_driver == &ioasic_cd) {
struct ioasicdev_attach_args *d = aux;
- if (!ioasic_submatch(match, aux))
+ if (!ioasic_submatch(match, aux)) {
return (0);
- if (strncmp("lance ", d->iada_modname, TC_ROM_LLEN))
+ }
+ if (strncmp("lance", d->iada_modname, TC_ROM_LLEN)) {
return (0);
+ }
} else
#endif /* IOASIC */
+
#if CAN_HAVE_TC && (NTC > 0)
- if (parent->dv_cfdata->cf_driver == &tccd) {
- struct tcdev_attach_args *d = aux;
+ if (parent->dv_cfdata->cf_driver == &tc_cd) {
+ struct tc_attach_args *d = aux;
- if (strncmp("PMAD-AA ", d->tcda_modname, TC_ROM_LLEN) &&
- strncmp("PMAD-BA ", d->tcda_modname, TC_ROM_LLEN))
+ if (strncmp("PMAD-AA ", d->ta_modname, TC_ROM_LLEN) &&
+ strncmp("PMAD-BA ", d->ta_modname, TC_ROM_LLEN))
return (0);
} else
#endif /* TC */
-#if CAN_HAVE_MAINBUS /* XXX TEST FOR KN01 OR MIPSFAIR? */
- if (parent->dv_cfdata->cf_driver == &mainbuscd) {
- /* XXX VARIOUS PMAX BASEBOARD CASES? */
+
+#if CAN_HAVE_MAINBUS && defined(DS3100)
+ if (parent->dv_cfdata->cf_driver == &mainbus_cd) {
+ struct confargs *d = aux;
+ if (strcmp("lance", d->ca_name) != 0)
+ return (0);
} else
#endif /* MAINBUS */
return (0);
@@ -176,19 +199,21 @@ lematch(parent, match, aux)
return (1);
}
+typedef void (*ie_fn_t) __P((struct device *, void *,
+ tc_intrlevel_t, int (*)(void *), void *));
+
void
-leattach(parent, self, aux)
+le_tc_attach(parent, self, aux)
struct device *parent, *self;
void *aux;
{
register struct le_softc *sc = (void *)self;
- void (*ie_fn) __P((struct device *, void *, tc_intrlevel_t,
- int (*)(void *), void *));
+ ie_fn_t ie_fn;
u_char *cp; /* pointer to MAC address */
int i;
#if CAN_HAVE_IOASIC && (NIOASIC > 0)
- if (parent->dv_cfdata->cf_driver == &ioasiccd) {
+ if (parent->dv_cfdata->cf_driver == &ioasic_cd) {
struct ioasicdev_attach_args *d = aux;
/* It's on the system IOCTL ASIC */
@@ -209,16 +234,16 @@ leattach(parent, self, aux)
} else
#endif /* IOASIC */
#if CAN_HAVE_TC && (NTC > 0)
- if (parent->dv_cfdata->cf_driver == &tccd) {
- struct tcdev_attach_args *d = aux;
+ if (parent->dv_cfdata->cf_driver == &tc_cd) {
+ struct tc_attach_args *d = aux;
/*
* It's on the turbochannel proper, or a kn02
* baseboard implementation of a TC option card.
*/
- sc->sc_r1 = (struct lereg1 *)(d->tcda_addr + LE_OFFSET_LANCE);
- sc->sc_mem = (void *)(d->tcda_addr + LE_OFFSET_RAM);
- cp = (u_char *)(d->tcda_addr + LE_OFFSET_ROM + 2);
+ sc->sc_r1 = (struct lereg1 *)(d->ta_addr + LE_OFFSET_LANCE);
+ sc->sc_mem = (void *)(d->ta_addr + LE_OFFSET_RAM);
+ cp = (u_char *)(d->ta_addr + LE_OFFSET_ROM + 2);
sc->sc_copytodesc = copytobuf_contig;
sc->sc_copyfromdesc = copyfrombuf_contig;
@@ -226,7 +251,7 @@ leattach(parent, self, aux)
sc->sc_copyfrombuf = copyfrombuf_contig;
sc->sc_zerobuf = zerobuf_contig;
- sc->sc_cookie = d->tcda_cookie;
+ sc->sc_cookie = d->ta_cookie;
/*
* TC lance boards have onboard SRAM buffers. DMA
* between the onbard RAM and main memory is not possible,
@@ -235,8 +260,8 @@ leattach(parent, self, aux)
ie_fn = tc_intr_establish;
} else
#endif /* TC */
-#if CAN_HAVE_MAINBUS /* XXX TEST FOR KN01 OR MIPSFAIR? */
- if (parent->dv_cfdata->cf_driver == &mainbuscd) {
+#if CAN_HAVE_MAINBUS && defined(DS3100)
+ if (parent->dv_cfdata->cf_driver == &mainbus_cd) {
struct confargs *ca = aux;
/*
@@ -253,11 +278,11 @@ leattach(parent, self, aux)
sc->sc_zerobuf = zerobuf_gap2;
sc->sc_cookie = (void *)ca->ca_slotpri; /*XXX more thought */
- /* XXX BASEBOARD INTERRUPT ESTABLISH FUNCTION? */
+ ie_fn = (ie_fn_t) kn01_intr_establish;
} else
#endif /* MAINBUS */
- panic("leattach: can't be here");
+ panic("le_tc_attach: can't be here");
sc->sc_conf3 = 0;
sc->sc_addr = 0;
@@ -271,7 +296,7 @@ leattach(parent, self, aux)
cp += 4;
}
- sc->sc_arpcom.ac_if.if_name = lecd.cd_name;
+ sc->sc_arpcom.ac_if.if_name = le_cd.cd_name;
leconfig(sc);
(*ie_fn)(parent, sc->sc_cookie, TC_IPL_NET, leintr, sc);
diff --git a/sys/dev/tc/ioasicvar.h b/sys/dev/tc/ioasicvar.h
index f060c1b3209..ed312acd9df 100644
--- a/sys/dev/tc/ioasicvar.h
+++ b/sys/dev/tc/ioasicvar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: ioasicvar.h,v 1.1 1995/12/20 00:50:42 cgd Exp $ */
+/* $NetBSD: ioasicvar.h,v 1.2 1996/03/17 21:37:45 jonathan Exp $ */
/*
* Copyright (c) 1995 Carnegie-Mellon University.
@@ -48,7 +48,7 @@ struct ioasicdev_attach_args {
* The IOASIC (bus) cfdriver, so that subdevices can more
* easily tell what bus they're on.
*/
-extern struct cfdriver ioasiccd;
+extern struct cfdriver ioasic_cd;
/*
diff --git a/sys/dev/tc/tc.c b/sys/dev/tc/tc.c
index ba5d3b5b8ed..1b861c032be 100644
--- a/sys/dev/tc/tc.c
+++ b/sys/dev/tc/tc.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: tc.c,v 1.2 1996/04/18 23:48:22 niklas Exp $ */
-/* $NetBSD: tc.c,v 1.10 1996/03/05 23:15:07 cgd Exp $ */
+/* $OpenBSD: tc.c,v 1.3 1996/04/21 22:26:28 deraadt Exp $ */
+/* $NetBSD: tc.c,v 1.13 1996/04/09 20:50:06 jonathan Exp $ */
/*
* Copyright (c) 1994, 1995 Carnegie-Mellon University.
@@ -29,12 +29,15 @@
*/
#include <sys/param.h>
+#include <sys/systm.h>
#include <sys/device.h>
#include <dev/tc/tcreg.h>
#include <dev/tc/tcvar.h>
#include <dev/tc/tcdevs.h>
+#include <machine/autoconf.h>
+
struct tc_softc {
struct device sc_dv;
@@ -50,8 +53,14 @@ struct tc_softc {
/* Definition of the driver for autoconfig. */
int tcmatch __P((struct device *, void *, void *));
void tcattach __P((struct device *, struct device *, void *));
-struct cfdriver tccd =
- { NULL, "tc", tcmatch, tcattach, DV_DULL, sizeof (struct tc_softc) };
+
+struct cfattach tc_ca = {
+ sizeof(struct tc_softc), tcmatch, tcattach
+};
+
+struct cfdriver tc_cd = {
+ NULL, "tc", DV_DULL
+};
int tcprint __P((void *, char *));
int tcsubmatch __P((struct device *, void *, void *));
@@ -87,7 +96,6 @@ tcattach(parent, self, aux)
const struct tc_builtin *builtin;
struct tc_slotdesc *slot;
tc_addr_t tcaddr;
- void *match;
int i;
printf("%s MHz clock\n",
@@ -214,7 +222,7 @@ tcsubmatch(parent, match, aux)
(cf->tccf_offset != d->ta_offset))
return 0;
- return ((*cf->cf_driver->cd_match)(parent, match, aux));
+ return ((*cf->cf_attach->ca_match)(parent, match, aux));
}
diff --git a/sys/dev/tc/tcvar.h b/sys/dev/tc/tcvar.h
index e8473dcb5b5..970d5334635 100644
--- a/sys/dev/tc/tcvar.h
+++ b/sys/dev/tc/tcvar.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: tcvar.h,v 1.2 1996/04/18 23:48:24 niklas Exp $ */
-/* $NetBSD: tcvar.h,v 1.3 1996/02/27 01:37:33 cgd Exp $ */
+/* $OpenBSD: tcvar.h,v 1.3 1996/04/21 22:26:30 deraadt Exp $ */
+/* $NetBSD: tcvar.h,v 1.4 1996/03/17 21:37:47 jonathan Exp $ */
/*
* Copyright (c) 1995 Carnegie-Mellon University.
@@ -128,6 +128,6 @@ void tc_intr_disestablish __P((struct device *, void *));
* The TurboChannel bus cfdriver, so that subdevices can more
* easily tell what bus they're on.
*/
-extern struct cfdriver tccd;
+extern struct cfdriver tc_cd;
#endif /* __DEV_TC_TCVAR_H__ */
diff --git a/sys/dev/vnd.c b/sys/dev/vnd.c
index 0eb6a69fc01..066af83becd 100644
--- a/sys/dev/vnd.c
+++ b/sys/dev/vnd.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: vnd.c,v 1.5 1996/03/02 00:29:25 niklas Exp $ */
-/* $NetBSD: vnd.c,v 1.24 1996/02/10 00:11:44 christos Exp $ */
+/* $OpenBSD: vnd.c,v 1.6 1996/04/21 22:19:59 deraadt Exp $ */
+/* $NetBSD: vnd.c,v 1.26 1996/03/30 23:06:11 christos Exp $ */
/*
* Copyright (c) 1988 University of Utah.
@@ -74,11 +74,11 @@
#include <sys/device.h>
#include <sys/disk.h>
#include <sys/stat.h>
-#include <sys/conf.h>
#include <sys/mount.h>
#include <sys/vnode.h>
#include <sys/file.h>
#include <sys/uio.h>
+#include <sys/conf.h>
#include <miscfs/specfs/specdev.h>
@@ -126,10 +126,6 @@ struct vnd_softc {
struct vnd_softc *vnd_softc;
int numvnd = 0;
-/* {b,c}devsw[] function prototypes XXX: move them to dev_conf.h */
-bdev_decl(vnd);
-cdev_decl(vnd);
-
/* called by main() at boot time */
void vndattach __P((int));
@@ -394,7 +390,7 @@ vndstart(vnd)
vnd->sc_tab.b_actf = bp->b_actf;
#ifdef DEBUG
if (vnddebug & VDB_IO)
- printf("vndstart(%d): bp %p vp %p blkno %x addr %p cnt %x\n",
+ printf("vndstart(%d): bp %p vp %p blkno %x addr %p cnt %lx\n",
vnd-vnd_softc, bp, bp->b_vp, bp->b_blkno, bp->b_data,
bp->b_bcount);
#endif
@@ -419,7 +415,7 @@ vndiodone(bp)
s = splbio();
#ifdef DEBUG
if (vnddebug & VDB_IO)
- printf("vndiodone(%d): vbp %p vp %p blkno %x addr %p cnt %x\n",
+ printf("vndiodone(%d): vbp %p vp %p blkno %x addr %p cnt %lx\n",
vnd-vnd_softc, vbp, vbp->vb_buf.b_vp, vbp->vb_buf.b_blkno,
vbp->vb_buf.b_data, vbp->vb_buf.b_bcount);
#endif