diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
commit | d6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch) | |
tree | ece253b876159b39c620e62b6c9b1174642e070e /sys/arch/sparc/dev/si.c |
initial import of NetBSD tree
Diffstat (limited to 'sys/arch/sparc/dev/si.c')
-rw-r--r-- | sys/arch/sparc/dev/si.c | 348 |
1 files changed, 348 insertions, 0 deletions
diff --git a/sys/arch/sparc/dev/si.c b/sys/arch/sparc/dev/si.c new file mode 100644 index 00000000000..8deb965ec19 --- /dev/null +++ b/sys/arch/sparc/dev/si.c @@ -0,0 +1,348 @@ +/* $NetBSD: si.c,v 1.6 1995/09/14 20:38:56 pk Exp $ */ + +/* + * Copyright (C) 1994 Adam Glass, Gordon W. Ross + * Copyright (C) 1993 Allen K. Briggs, Chris P. Caputo, + * Michael L. Finch, Bradley A. Grantham, and + * Lawrence A. Kesteloot + * 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 the Alice Group. + * 4. The names of the Alice Group or any of its members may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE ALICE GROUP ``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 ALICE GROUP 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. + */ + +#define DEBUG 1 + +/* XXX - Need to add support for real DMA. -gwr */ +/* #define PSEUDO_DMA 1 (broken) */ + +#include <sys/types.h> +#include <sys/malloc.h> +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/errno.h> +#include <sys/buf.h> +#include <sys/proc.h> +#include <sys/user.h> +#include <sys/device.h> + +#include <machine/autoconf.h> +#include <machine/cpu.h> +#include <machine/pmap.h> + +#include <scsi/scsi_all.h> +#include <scsi/scsi_debug.h> +#include <scsi/scsiconf.h> + +#include <dev/ic/ncr5380reg.h> +#include <dev/ic/ncr5380var.h> +#include <sparc/dev/sireg.h> + +#ifdef DEBUG +static int ncr5380_debug = 0; +static int si_flags = 0 /* | SDEV_DB2 */ ; +#endif + +static int si_match __P((struct device *, void *, void *)); +static void si_attach __P((struct device *, struct device *, void *)); +static int si_print __P((void *, char *)); +static int si_intr __P((void *)); +static void si_dma_intr __P((struct ncr5380_softc *)); +static int reset_adapter __P((struct ncr5380_softc *)); + + +static char scsi_name[] = "si"; + +struct scsi_adapter ncr5380_switch = { + ncr5380_scsi_cmd, /* scsi_cmd() */ + minphys, /* scsi_minphys() */ + NULL, /* open_target_lu() */ + NULL, /* close_target_lu() */ +}; + +/* This is copied from julian's bt driver */ +/* "so we have a default dev struct for our link struct." */ +struct scsi_device si_dev = { + NULL, /* Use default error handler. */ + NULL, /* Use default start handler. */ + NULL, /* Use default async handler. */ + NULL, /* Use default "done" routine.*/ +}; + +struct cfdriver sicd = { + NULL, "si", si_match, si_attach, DV_DULL, + sizeof(struct ncr5380_softc), NULL, 0, +}; + +/* + * An `sw' is just an `si' behind a different DMA engine. + * This driver doesn't currently do DMA, so we can more or less + * handle it here. (It's really not much different than the + * Sun 3/50 SCSI controller, if I understand it right.) + */ +struct cfdriver swcd = { + NULL, "sw", si_match, si_attach, DV_DULL, + sizeof(struct ncr5380_softc), NULL, 0, +}; + +static int +si_print(aux, name) + void *aux; + char *name; +{ + if (name != NULL) + printf("%s: scsibus ", name); + return UNCONF; +} + +static int +si_match(parent, vcf, aux) + struct device *parent; + void *vcf; + void *aux; +{ + struct cfdata *cf = vcf; + struct confargs *ca = aux; + struct romaux *ra = &ca->ca_ra; + + /* Are we looking for the right thing? */ + if (strcmp(cf->cf_driver->cd_name, ra->ra_name)) + return (0); + + /* Nothing but a Sun 4 is going to have these devices. */ + if (cputyp != CPU_SUN4) + return (0); + + /* Figure out the bus type and look for the appropriate adapter. */ + switch (ca->ca_bustype) { + case BUS_VME16: + /* AFAIK, the `si' can only exist on the vmes. */ + if (strcmp(ra->ra_name, "si") || cpumod == SUN4_100) + return (0); + break; + + case BUS_OBIO: + /* AFAIK, an `sw' can only exist on the obio. */ + if (strcmp(ra->ra_name, "sw") || cpumod != SUN4_100) + return (0); + break; + + default: + /* Don't know what we ended up with ... */ + return (0); + } + + /* Default interrupt priority always splbio == 2 */ + if (ra->ra_intr[0].int_pri == -1) + ra->ra_intr[0].int_pri == 2; + + /* Make sure there is something there... */ + if (probeget(ra->ra_vaddr + 1, 1) == -1) + return (0); + + /* + * If we're looking for an `si', we have to determine whether + * it is an `sc' (Sun2) or `si' (Sun3) SCSI board. This can be + * determined using the fact that the `sc' board occupies 4K bytes + * in VME space but the `si' board occupies 2K bytes. + * Note that the `si' board should NOT respond to this. + */ + if (strcmp(cf->cf_driver->cd_name, "si") == 0) + if (probeget(ra->ra_vaddr + 0x801, 1) != -1) + return(0); + + return (1); +} + +static void +si_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct ncr5380_softc *ncr5380 = (struct ncr5380_softc *) self; + volatile struct si_regs *regs; + struct confargs *ca = aux; + struct romaux *ra = &ca->ca_ra; + struct bootpath *bp; + + /* Map the controller registers. */ + regs = (struct si_regs *)mapiodev(ra->ra_paddr, + sizeof(struct si_regs), ca->ca_bustype); + + /* Establish the interrupt. */ + ncr5380->sc_ih.ih_fun = si_intr; + ncr5380->sc_ih.ih_arg = ncr5380; + + switch (ca->ca_bustype) { + case BUS_VME16: + /* + * This will be an `si'. + */ + vmeintr_establish(ra->ra_intr[0].int_vec, + ra->ra_intr[0].int_pri, &ncr5380->sc_ih); + ncr5380->sc_adapter_iv_am = + VME_SUPV_DATA_24 | (ra->ra_intr[0].int_vec & 0xFF); + break; + + case BUS_OBIO: + /* + * This will be an `sw'. + */ + intr_establish(ra->ra_intr[0].int_pri, &ncr5380->sc_ih); + break; + + default: + printf("\n"); + panic("si_attach: unknown bus type 0x%x", ca->ca_bustype); + } + + ncr5380->sc_adapter_type = ca->ca_bustype; + ncr5380->sc_regs = regs; + + /* + * fill in the prototype scsi_link. + */ + ncr5380->sc_link.adapter_softc = ncr5380; + ncr5380->sc_link.adapter_target = 7; + ncr5380->sc_link.adapter = &ncr5380_switch; + ncr5380->sc_link.device = &si_dev; + ncr5380->sc_link.openings = 2; +#ifdef DEBUG + ncr5380->sc_link.flags |= si_flags; +#endif + + printf(" pri %d\n", ra->ra_intr[0].int_pri); + reset_adapter(ncr5380); + ncr5380_reset_scsibus(ncr5380); + + /* + * If the boot path is "sw" or "si" at the moment and it's me, then + * walk out pointer to the sub-device, ready for the config + * below. + */ + bp = ra->ra_bp; + if (bp != NULL && strcmp(bp->name, ra->ra_name) == 0 && + bp->val[0] == -1 && bp->val[1] == ncr5380->sc_dev.dv_unit) + bootpath_store(1, bp + 1); + + /* Configure sub-devices */ + config_found(self, &(ncr5380->sc_link), si_print); + + bootpath_store(1, NULL); +} + +static void +si_dma_intr(ncr5380) + struct ncr5380_softc *ncr5380; +{ + volatile struct si_regs *regs = ncr5380->sc_regs; + +#ifdef DEBUG + printf (" si_dma_intr\n"); +#endif +} + +static int +si_intr(arg) + void *arg; +{ + struct ncr5380_softc *ncr5380 = arg; + volatile struct si_regs *si = ncr5380->sc_regs; + int rv = 0; + + switch (ncr5380->sc_adapter_type) { + case BUS_VME16: + /* Interrupts not enabled? Can not be for us. */ + if ((si->si_csr & SI_CSR_INTR_EN) == 0) + return rv; + + if (si->si_csr & SI_CSR_DMA_IP) { + si_dma_intr(ncr5380); + rv++; + } + if (si->si_csr & SI_CSR_SBC_IP) { + ncr5380_sbc_intr(ncr5380); + rv++; + } + break; + + case BUS_OBIO: + /* Interrupts not enabled? Can not be for us. */ + if ((si->sw_csr & SI_CSR_INTR_EN) == 0) + return rv; + + if (si->sw_csr & SI_CSR_DMA_IP) { + si_dma_intr(ncr5380); + rv++; + } + if (si->sw_csr & SI_CSR_SBC_IP) { + ncr5380_sbc_intr(ncr5380); + rv++; + } + break; + } + + return rv; +} + +static int +reset_adapter(sc) + struct ncr5380_softc *sc; +{ + volatile struct si_regs *si = sc->sc_regs; + +#ifdef DEBUG + if (ncr5380_debug) { + printf("reset_adapter\n"); + } +#endif + + switch(sc->sc_adapter_type) { + case BUS_VME16: + /* The reset bits in the CSR are active low. */ + si->si_csr = 0; + delay(20); + si->si_csr = SI_CSR_FIFO_RES | SI_CSR_SCSI_RES; + si->fifo_count = 0; + si->dma_addrh = 0; + si->dma_addrl = 0; + si->dma_counth = 0; + si->dma_countl = 0; + si->iv_am = sc->sc_adapter_iv_am; + break; + + case BUS_OBIO: + si->sw_csr = 0; + delay(20); + si->sw_csr = SI_CSR_FIFO_RES | SI_CSR_SCSI_RES; + si->dma_addr = 0; + si->dma_count = 0; + break; + } +} + +#include <dev/ic/ncr5380.c> + |