Annotation of sys/dev/eisa/uha_eisa.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: uha_eisa.c,v 1.6 2007/04/10 17:47:55 miod Exp $ */
! 2: /* $NetBSD: uha_eisa.c,v 1.5 1996/10/21 22:31:07 thorpej Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1994, 1996 Charles M. Hannum. All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: * 3. All advertising materials mentioning features or use of this software
! 16: * must display the following acknowledgement:
! 17: * This product includes software developed by Charles M. Hannum.
! 18: * 4. The name of the author may not be used to endorse or promote products
! 19: * derived from this software without specific prior written permission.
! 20: *
! 21: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 22: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 23: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 24: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 25: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 26: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 27: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 28: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 29: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 30: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 31: */
! 32:
! 33: #include <sys/types.h>
! 34: #include <sys/param.h>
! 35: #include <sys/systm.h>
! 36: #include <sys/device.h>
! 37: #include <sys/kernel.h>
! 38: #include <sys/proc.h>
! 39: #include <sys/user.h>
! 40:
! 41: #include <machine/bus.h>
! 42: #include <machine/intr.h>
! 43:
! 44: #include <scsi/scsi_all.h>
! 45: #include <scsi/scsiconf.h>
! 46:
! 47: #include <dev/eisa/eisavar.h>
! 48: #include <dev/eisa/eisadevs.h>
! 49:
! 50: #include <dev/ic/uhareg.h>
! 51: #include <dev/ic/uhavar.h>
! 52:
! 53: #define UHA_EISA_SLOT_OFFSET 0xc80
! 54: #define UHA_EISA_IOSIZE 0x020
! 55:
! 56: #ifndef DDB
! 57: #define Debugger() panic("should call debugger here (uha_eisa.c)")
! 58: #endif
! 59:
! 60: int uha_eisa_match(struct device *, void *, void *);
! 61: void uha_eisa_attach(struct device *, struct device *, void *);
! 62:
! 63: struct cfattach uha_eisa_ca = {
! 64: sizeof(struct uha_softc), uha_eisa_match, uha_eisa_attach
! 65: };
! 66:
! 67: #define KVTOPHYS(x) vtophys((vaddr_t)(x))
! 68:
! 69: int u24_find(bus_space_tag_t, bus_space_handle_t, struct uha_softc *);
! 70: void u24_start_mbox(struct uha_softc *, struct uha_mscp *);
! 71: int u24_poll(struct uha_softc *, struct scsi_xfer *, int);
! 72: int u24_intr(void *);
! 73: void u24_init(struct uha_softc *);
! 74:
! 75: /*
! 76: * Check the slots looking for a board we recognise
! 77: * If we find one, note its address (slot) and call
! 78: * the actual probe routine to check it out.
! 79: */
! 80: int
! 81: uha_eisa_match(parent, match, aux)
! 82: struct device *parent;
! 83: void *match, *aux;
! 84: {
! 85: struct eisa_attach_args *ea = aux;
! 86: bus_space_tag_t iot = ea->ea_iot;
! 87: bus_space_handle_t ioh;
! 88: int rv;
! 89:
! 90: /* must match one of our known ID strings */
! 91: if (strncmp(ea->ea_idstring, "USC024", 6))
! 92: return (0);
! 93:
! 94: if (bus_space_map(iot, EISA_SLOT_ADDR(ea->ea_slot) +
! 95: UHA_EISA_SLOT_OFFSET, UHA_EISA_IOSIZE, 0, &ioh))
! 96: return (0);
! 97:
! 98: rv = u24_find(iot, ioh, NULL);
! 99:
! 100: bus_space_unmap(iot, ioh, UHA_EISA_IOSIZE);
! 101:
! 102: return (rv);
! 103: }
! 104:
! 105: /*
! 106: * Attach all the sub-devices we can find
! 107: */
! 108: void
! 109: uha_eisa_attach(parent, self, aux)
! 110: struct device *parent, *self;
! 111: void *aux;
! 112: {
! 113: struct eisa_attach_args *ea = aux;
! 114: struct uha_softc *sc = (void *)self;
! 115: bus_space_tag_t iot = ea->ea_iot;
! 116: bus_space_handle_t ioh;
! 117: eisa_chipset_tag_t ec = ea->ea_ec;
! 118: eisa_intr_handle_t ih;
! 119: const char *model, *intrstr;
! 120:
! 121: if (!strncmp(ea->ea_idstring, "USC024", 6))
! 122: model = EISA_PRODUCT_USC0240;
! 123: else
! 124: model = "unknown model!";
! 125: printf(": %s\n", model);
! 126:
! 127: if (bus_space_map(iot, EISA_SLOT_ADDR(ea->ea_slot) +
! 128: UHA_EISA_SLOT_OFFSET, UHA_EISA_IOSIZE, 0, &ioh))
! 129: panic("uha_attach: could not map I/O addresses");
! 130:
! 131: sc->sc_iot = iot;
! 132: sc->sc_ioh = ioh;
! 133: if (!u24_find(iot, ioh, sc))
! 134: panic("uha_attach: u24_find failed!");
! 135:
! 136: if (eisa_intr_map(ec, sc->sc_irq, &ih)) {
! 137: printf("%s: couldn't map interrupt (%d)\n",
! 138: sc->sc_dev.dv_xname, sc->sc_irq);
! 139: return;
! 140: }
! 141: intrstr = eisa_intr_string(ec, ih);
! 142: sc->sc_ih = eisa_intr_establish(ec, ih, IST_LEVEL, IPL_BIO,
! 143: u24_intr, sc, sc->sc_dev.dv_xname);
! 144: if (sc->sc_ih == NULL) {
! 145: printf("%s: couldn't establish interrupt",
! 146: sc->sc_dev.dv_xname);
! 147: if (intrstr != NULL)
! 148: printf(" at %s", intrstr);
! 149: printf("\n");
! 150: return;
! 151: }
! 152: printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
! 153:
! 154: /* Save function pointers for later use. */
! 155: sc->start_mbox = u24_start_mbox;
! 156: sc->poll = u24_poll;
! 157: sc->init = u24_init;
! 158:
! 159: uha_attach(sc);
! 160: }
! 161:
! 162: int
! 163: u24_find(iot, ioh, sc)
! 164: bus_space_tag_t iot;
! 165: bus_space_handle_t ioh;
! 166: struct uha_softc *sc;
! 167: {
! 168: u_int8_t config0, config1, config2;
! 169: int irq, drq;
! 170: int resetcount = 4000; /* 4 secs? */
! 171:
! 172: config0 = bus_space_read_1(iot, ioh, U24_CONFIG + 0);
! 173: config1 = bus_space_read_1(iot, ioh, U24_CONFIG + 1);
! 174: config2 = bus_space_read_1(iot, ioh, U24_CONFIG + 2);
! 175: if ((config0 & U24_MAGIC1) == 0 ||
! 176: (config1 & U24_MAGIC2) == 0)
! 177: return (0);
! 178:
! 179: drq = -1;
! 180:
! 181: switch (config0 & U24_IRQ_MASK) {
! 182: case U24_IRQ10:
! 183: irq = 10;
! 184: break;
! 185: case U24_IRQ11:
! 186: irq = 11;
! 187: break;
! 188: case U24_IRQ14:
! 189: irq = 14;
! 190: break;
! 191: case U24_IRQ15:
! 192: irq = 15;
! 193: break;
! 194: default:
! 195: printf("u24_find: illegal irq setting %x\n",
! 196: config0 & U24_IRQ_MASK);
! 197: return (0);
! 198: }
! 199:
! 200: bus_space_write_1(iot, ioh, U24_LINT, UHA_ASRST);
! 201:
! 202: while (--resetcount) {
! 203: if (bus_space_read_1(iot, ioh, U24_LINT))
! 204: break;
! 205: delay(1000); /* 1 mSec per loop */
! 206: }
! 207: if (!resetcount) {
! 208: printf("u24_find: board timed out during reset\n");
! 209: return (0);
! 210: }
! 211:
! 212: /* if we want to fill in softc, do so now */
! 213: if (sc != NULL) {
! 214: sc->sc_irq = irq;
! 215: sc->sc_drq = drq;
! 216: sc->sc_scsi_dev = config2 & U24_HOSTID_MASK;
! 217: }
! 218:
! 219: return (1);
! 220: }
! 221:
! 222: void
! 223: u24_start_mbox(sc, mscp)
! 224: struct uha_softc *sc;
! 225: struct uha_mscp *mscp;
! 226: {
! 227: bus_space_tag_t iot = sc->sc_iot;
! 228: bus_space_handle_t ioh = sc->sc_ioh;
! 229: int spincount = 100000; /* 1s should be enough */
! 230:
! 231: while (--spincount) {
! 232: if ((bus_space_read_1(iot, ioh, U24_LINT) & U24_LDIP) == 0)
! 233: break;
! 234: delay(100);
! 235: }
! 236: if (!spincount) {
! 237: printf("%s: uha_start_mbox, board not responding\n",
! 238: sc->sc_dev.dv_xname);
! 239: Debugger();
! 240: }
! 241:
! 242: bus_space_write_4(iot, ioh, U24_OGMPTR, KVTOPHYS(mscp));
! 243: if (mscp->flags & MSCP_ABORT)
! 244: bus_space_write_1(iot, ioh, U24_OGMCMD, 0x80);
! 245: else
! 246: bus_space_write_1(iot, ioh, U24_OGMCMD, 0x01);
! 247: bus_space_write_1(iot, ioh, U24_LINT, U24_OGMFULL);
! 248:
! 249: if ((mscp->xs->flags & SCSI_POLL) == 0)
! 250: timeout_add(&mscp->xs->stimeout, (mscp->timeout * hz) / 1000);
! 251: }
! 252:
! 253: int
! 254: u24_poll(sc, xs, count)
! 255: struct uha_softc *sc;
! 256: struct scsi_xfer *xs;
! 257: int count;
! 258: {
! 259: bus_space_tag_t iot = sc->sc_iot;
! 260: bus_space_handle_t ioh = sc->sc_ioh;
! 261:
! 262: while (count) {
! 263: /*
! 264: * If we had interrupts enabled, would we
! 265: * have got an interrupt?
! 266: */
! 267: if (bus_space_read_1(iot, ioh, U24_SINT) & U24_SDIP)
! 268: u24_intr(sc);
! 269: if (xs->flags & ITSDONE)
! 270: return (0);
! 271: delay(1000);
! 272: count--;
! 273: }
! 274: return (1);
! 275: }
! 276:
! 277: int
! 278: u24_intr(arg)
! 279: void *arg;
! 280: {
! 281: struct uha_softc *sc = arg;
! 282: bus_space_tag_t iot = sc->sc_iot;
! 283: bus_space_handle_t ioh = sc->sc_ioh;
! 284: struct uha_mscp *mscp;
! 285: u_char uhastat;
! 286: u_long mboxval;
! 287:
! 288: #ifdef UHADEBUG
! 289: printf("%s: uhaintr ", sc->sc_dev.dv_xname);
! 290: #endif /*UHADEBUG */
! 291:
! 292: if ((bus_space_read_1(iot, ioh, U24_SINT) & U24_SDIP) == 0)
! 293: return (0);
! 294:
! 295: for (;;) {
! 296: /*
! 297: * First get all the information and then
! 298: * acknowledge the interrupt
! 299: */
! 300: uhastat = bus_space_read_1(iot, ioh, U24_SINT);
! 301: mboxval = bus_space_read_4(iot, ioh, U24_ICMPTR);
! 302: bus_space_write_1(iot, ioh, U24_SINT, U24_ICM_ACK);
! 303: bus_space_write_1(iot, ioh, U24_ICMCMD, 0);
! 304:
! 305: #ifdef UHADEBUG
! 306: printf("status = 0x%x ", uhastat);
! 307: #endif /*UHADEBUG*/
! 308:
! 309: /*
! 310: * Process the completed operation
! 311: */
! 312: mscp = uha_mscp_phys_kv(sc, mboxval);
! 313: if (!mscp) {
! 314: printf("%s: BAD MSCP RETURNED!\n",
! 315: sc->sc_dev.dv_xname);
! 316: continue; /* whatever it was, it'll timeout */
! 317: }
! 318: timeout_del(&mscp->xs->stimeout);
! 319: uha_done(sc, mscp);
! 320:
! 321: if ((bus_space_read_1(iot, ioh, U24_SINT) & U24_SDIP) == 0)
! 322: return (1);
! 323: }
! 324: }
! 325:
! 326: void
! 327: u24_init(sc)
! 328: struct uha_softc *sc;
! 329: {
! 330: bus_space_tag_t iot = sc->sc_iot;
! 331: bus_space_handle_t ioh = sc->sc_ioh;
! 332:
! 333: /* free OGM and ICM */
! 334: bus_space_write_1(iot, ioh, U24_OGMCMD, 0);
! 335: bus_space_write_1(iot, ioh, U24_ICMCMD, 0);
! 336: /* make sure interrupts are enabled */
! 337: #ifdef UHADEBUG
! 338: printf("u24_init: lmask=%02x, smask=%02x\n",
! 339: bus_space_read_1(iot, ioh, U24_LMASK),
! 340: bus_space_read_1(iot, ioh, U24_SMASK));
! 341: #endif
! 342: bus_space_write_1(iot, ioh, U24_LMASK, 0xd2); /* XXX */
! 343: bus_space_write_1(iot, ioh, U24_SMASK, 0x92); /* XXX */
! 344: }
CVSweb