Annotation of sys/dev/eisa/cac_eisa.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: cac_eisa.c,v 1.2 2001/11/05 17:25:58 art Exp $ */
! 2: /* $NetBSD: cac_eisa.c,v 1.1 2000/09/01 12:15:20 ad Exp $ */
! 3:
! 4: /*-
! 5: * Copyright (c) 2000 The NetBSD Foundation, Inc.
! 6: * All rights reserved.
! 7: *
! 8: * This code is derived from software contributed to The NetBSD Foundation
! 9: * by Andrew Doran.
! 10: *
! 11: * Redistribution and use in source and binary forms, with or without
! 12: * modification, are permitted provided that the following conditions
! 13: * are met:
! 14: * 1. Redistributions of source code must retain the above copyright
! 15: * notice, this list of conditions and the following disclaimer.
! 16: * 2. Redistributions in binary form must reproduce the above copyright
! 17: * notice, this list of conditions and the following disclaimer in the
! 18: * documentation and/or other materials provided with the distribution.
! 19: * 3. All advertising materials mentioning features or use of this software
! 20: * must display the following acknowledgement:
! 21: * This product includes software developed by the NetBSD
! 22: * Foundation, Inc. and its contributors.
! 23: * 4. Neither the name of The NetBSD Foundation nor the names of its
! 24: * contributors may be used to endorse or promote products derived
! 25: * from this software without specific prior written permission.
! 26: *
! 27: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
! 28: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
! 29: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 30: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
! 31: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 32: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 33: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 34: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 35: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 36: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 37: * POSSIBILITY OF SUCH DAMAGE.
! 38: */
! 39:
! 40: /*
! 41: * Copyright (c) 2000 Jonathan Lemon
! 42: * Copyright (c) 1999 by Matthew N. Dodd <winter@jurai.net>
! 43: * All Rights Reserved.
! 44: *
! 45: * Redistribution and use in source and binary forms, with or without
! 46: * modification, are permitted provided that the following conditions
! 47: * are met:
! 48: * 1. Redistributions of source code must retain the above copyright
! 49: * notice, this list of conditions, and the following disclaimer,
! 50: * without modification, immediately at the beginning of the file.
! 51: * 2. The name of the author may not be used to endorse or promote products
! 52: * derived from this software without specific prior written permission.
! 53: *
! 54: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
! 55: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 56: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 57: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
! 58: * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 59: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 60: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 61: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 62: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 63: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 64: * SUCH DAMAGE.
! 65: */
! 66:
! 67: /*
! 68: * EISA front-end for cac(4) driver.
! 69: */
! 70:
! 71: #include <sys/types.h>
! 72: #include <sys/param.h>
! 73: #include <sys/systm.h>
! 74: #include <sys/device.h>
! 75:
! 76: #include <machine/bus.h>
! 77: #include <machine/intr.h>
! 78:
! 79: #include <dev/eisa/eisavar.h>
! 80: #include <dev/eisa/eisadevs.h>
! 81:
! 82: #include <scsi/scsi_all.h>
! 83: #include <scsi/scsi_disk.h>
! 84: #include <scsi/scsiconf.h>
! 85:
! 86: #include <dev/ic/cacreg.h>
! 87: #include <dev/ic/cacvar.h>
! 88:
! 89: #define CAC_EISA_SLOT_OFFSET 0x0c88
! 90: #define CAC_EISA_IOSIZE 0x0017
! 91: #define CAC_EISA_IOCONF 0x38
! 92:
! 93: int cac_eisa_match(struct device *, void *, void *);
! 94: void cac_eisa_attach(struct device *, struct device *, void *);
! 95:
! 96: struct cac_ccb *cac_eisa_l0_completed(struct cac_softc *);
! 97: int cac_eisa_l0_fifo_full(struct cac_softc *);
! 98: void cac_eisa_l0_intr_enable(struct cac_softc *, int);
! 99: int cac_eisa_l0_intr_pending(struct cac_softc *);
! 100: void cac_eisa_l0_submit(struct cac_softc *, struct cac_ccb *);
! 101:
! 102: struct cfattach cac_eisa_ca = {
! 103: sizeof(struct cac_softc), cac_eisa_match, cac_eisa_attach
! 104: };
! 105:
! 106: static const
! 107: struct cac_linkage cac_eisa_l0 = {
! 108: cac_eisa_l0_completed,
! 109: cac_eisa_l0_fifo_full,
! 110: cac_eisa_l0_intr_enable,
! 111: cac_eisa_l0_intr_pending,
! 112: cac_eisa_l0_submit
! 113: };
! 114:
! 115: static const
! 116: struct cac_eisa_type {
! 117: const char *ct_prodstr;
! 118: const char *ct_typestr;
! 119: const struct cac_linkage *ct_linkage;
! 120: } cac_eisa_type[] = {
! 121: { "CPQ4001", "IDA", &cac_eisa_l0 },
! 122: { "CPQ4002", "IDA-2", &cac_eisa_l0 },
! 123: { "CPQ4010", "IEAS", &cac_eisa_l0 },
! 124: { "CPQ4020", "SMART", &cac_eisa_l0 },
! 125: { "CPQ4030", "SMART-2/E", &cac_l0 },
! 126: };
! 127:
! 128: int
! 129: cac_eisa_match(parent, match, aux)
! 130: struct device *parent;
! 131: void *match, *aux;
! 132: {
! 133: struct eisa_attach_args *ea;
! 134: int i;
! 135:
! 136: ea = aux;
! 137:
! 138: for (i = 0; i < sizeof(cac_eisa_type) / sizeof(cac_eisa_type[0]); i++)
! 139: if (strcmp(ea->ea_idstring, cac_eisa_type[i].ct_prodstr) == 0)
! 140: return (1);
! 141:
! 142: return (0);
! 143: }
! 144:
! 145: void
! 146: cac_eisa_attach(parent, self, aux)
! 147: struct device *parent;
! 148: struct device *self;
! 149: void *aux;
! 150: {
! 151: struct eisa_attach_args *ea;
! 152: bus_space_handle_t ioh;
! 153: eisa_chipset_tag_t ec;
! 154: eisa_intr_handle_t ih;
! 155: struct cac_softc *sc;
! 156: bus_space_tag_t iot;
! 157: const char *intrstr;
! 158: int irq, i;
! 159:
! 160: ea = aux;
! 161: sc = (struct cac_softc *)self;
! 162: iot = ea->ea_iot;
! 163: ec = ea->ea_ec;
! 164:
! 165: if (bus_space_map(iot, EISA_SLOT_ADDR(ea->ea_slot) +
! 166: CAC_EISA_SLOT_OFFSET, CAC_EISA_IOSIZE, 0, &ioh)) {
! 167: printf(": can't map i/o space\n");
! 168: return;
! 169: }
! 170:
! 171: sc->sc_iot = iot;
! 172: sc->sc_ioh = ioh;
! 173: sc->sc_dmat = ea->ea_dmat;
! 174:
! 175: /*
! 176: * Map and establish the interrupt.
! 177: */
! 178: switch (bus_space_read_1(iot, ioh, CAC_EISA_IOCONF) & 0xf0) {
! 179: case 0x20:
! 180: irq = 10;
! 181: break;
! 182: case 0x10:
! 183: irq = 11;
! 184: break;
! 185: case 0x40:
! 186: irq = 14;
! 187: break;
! 188: case 0x80:
! 189: irq = 15;
! 190: break;
! 191: default:
! 192: printf(": controller on invalid IRQ\n");
! 193: return;
! 194: }
! 195:
! 196: if (eisa_intr_map(ec, irq, &ih)) {
! 197: printf(": can't map interrupt (%d)\n", irq);
! 198: return;
! 199: }
! 200:
! 201: intrstr = eisa_intr_string(ec, ih);
! 202: if ((sc->sc_ih = eisa_intr_establish(ec, ih, IST_LEVEL, IPL_BIO,
! 203: cac_intr, sc, sc->sc_dv.dv_xname)) == NULL) {
! 204: printf(": can't establish interrupt");
! 205: if (intrstr != NULL)
! 206: printf(" at %s", intrstr);
! 207: printf("\n");
! 208: return;
! 209: }
! 210:
! 211: /*
! 212: * Print board type and attach to the bus-independent code.
! 213: */
! 214: for (i = 0; i < sizeof(cac_eisa_type) / sizeof(cac_eisa_type[0]); i++)
! 215: if (strcmp(ea->ea_idstring, cac_eisa_type[i].ct_prodstr) == 0)
! 216: break;
! 217:
! 218: printf(" %s: Compaq %s\n", intrstr, cac_eisa_type[i].ct_typestr);
! 219: sc->sc_cl = cac_eisa_type[i].ct_linkage;
! 220: cac_init(sc, 0);
! 221: }
! 222:
! 223: /*
! 224: * Linkage specific to EISA boards.
! 225: */
! 226:
! 227: int
! 228: cac_eisa_l0_fifo_full(struct cac_softc *sc)
! 229: {
! 230:
! 231: return ((cac_inb(sc, CAC_EISAREG_SYSTEM_DOORBELL) &
! 232: CAC_EISA_CHANNEL_CLEAR) == 0);
! 233: }
! 234:
! 235: void
! 236: cac_eisa_l0_submit(struct cac_softc *sc, struct cac_ccb *ccb)
! 237: {
! 238: u_int16_t size;
! 239:
! 240: /*
! 241: * On these boards, `ccb_hdr.size' is actually for control flags.
! 242: * Set it to zero and pass the value by means of an I/O port.
! 243: */
! 244: size = letoh16(ccb->ccb_hdr.size) << 2;
! 245: ccb->ccb_hdr.size = 0;
! 246:
! 247: bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, (caddr_t)ccb - sc->sc_ccbs,
! 248: sizeof(struct cac_ccb), BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
! 249:
! 250: cac_outb(sc, CAC_EISAREG_SYSTEM_DOORBELL, CAC_EISA_CHANNEL_CLEAR);
! 251: cac_outl(sc, CAC_EISAREG_LIST_ADDR, ccb->ccb_paddr);
! 252: cac_outw(sc, CAC_EISAREG_LIST_LEN, size);
! 253: cac_outb(sc, CAC_EISAREG_LOCAL_DOORBELL, CAC_EISA_CHANNEL_BUSY);
! 254: }
! 255:
! 256: struct cac_ccb *
! 257: cac_eisa_l0_completed(struct cac_softc *sc)
! 258: {
! 259: struct cac_ccb *ccb;
! 260: u_int32_t off;
! 261: u_int8_t status;
! 262:
! 263: if ((cac_inb(sc, CAC_EISAREG_SYSTEM_DOORBELL) &
! 264: CAC_EISA_CHANNEL_BUSY) == 0)
! 265: return (NULL);
! 266:
! 267: cac_outb(sc, CAC_EISAREG_SYSTEM_DOORBELL, CAC_EISA_CHANNEL_BUSY);
! 268: off = cac_inl(sc, CAC_EISAREG_COMPLETE_ADDR);
! 269: status = cac_inb(sc, CAC_EISAREG_LIST_STATUS);
! 270: cac_outb(sc, CAC_EISAREG_LOCAL_DOORBELL, CAC_EISA_CHANNEL_CLEAR);
! 271:
! 272: if (off == 0)
! 273: return (NULL);
! 274:
! 275: off = (off & ~3) - sc->sc_ccbs_paddr;
! 276: ccb = (struct cac_ccb *)(sc->sc_ccbs + off);
! 277:
! 278: bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, off, sizeof(struct cac_ccb),
! 279: BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
! 280:
! 281: ccb->ccb_req.error = status;
! 282: return (ccb);
! 283: }
! 284:
! 285: int
! 286: cac_eisa_l0_intr_pending(struct cac_softc *sc)
! 287: {
! 288:
! 289: return (cac_inb(sc, CAC_EISAREG_SYSTEM_DOORBELL) &
! 290: CAC_EISA_CHANNEL_BUSY);
! 291: }
! 292:
! 293: void
! 294: cac_eisa_l0_intr_enable(struct cac_softc *sc, int state)
! 295: {
! 296:
! 297: if (state) {
! 298: cac_outb(sc, CAC_EISAREG_SYSTEM_DOORBELL,
! 299: ~CAC_EISA_CHANNEL_CLEAR);
! 300: cac_outb(sc, CAC_EISAREG_LOCAL_DOORBELL,
! 301: CAC_EISA_CHANNEL_BUSY);
! 302: cac_outb(sc, CAC_EISAREG_INTR_MASK, CAC_INTR_ENABLE);
! 303: cac_outb(sc, CAC_EISAREG_SYSTEM_MASK, CAC_INTR_ENABLE);
! 304: } else
! 305: cac_outb(sc, CAC_EISAREG_SYSTEM_MASK, CAC_INTR_DISABLE);
! 306: }
CVSweb