diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1996-04-21 22:33:19 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1996-04-21 22:33:19 +0000 |
commit | 67d88b0a9910a68bb666b448d2dac29cb4d3d8c2 (patch) | |
tree | 967b89f6e07398a22bd8c76d30179b648776542d /sys/dev | |
parent | ba95d3c1d69cdb251d15a12ebf70f50b0ea2019b (diff) |
partial sync with netbsd 960418, more to come
Diffstat (limited to 'sys/dev')
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 |