Annotation of 43BSDReno/sys/hpstand/scsi.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1988 University of Utah.
        !             3:  * Copyright (c) 1990 The Regents of the University of California.
        !             4:  * All rights reserved.
        !             5:  *
        !             6:  * This code is derived from software contributed to Berkeley by
        !             7:  * Van Jacobson of Lawrence Berkeley Laboratory and the Systems
        !             8:  * Programming Group of the University of Utah Computer Science Department.
        !             9:  *
        !            10:  * Redistribution is only permitted until one year after the first shipment
        !            11:  * of 4.4BSD by the Regents.  Otherwise, redistribution and use in source and
        !            12:  * binary forms are permitted provided that: (1) source distributions retain
        !            13:  * this entire copyright notice and comment, and (2) distributions including
        !            14:  * binaries display the following acknowledgement:  This product includes
        !            15:  * software developed by the University of California, Berkeley and its
        !            16:  * contributors'' in the documentation or other materials provided with the
        !            17:  * distribution and in all advertising materials mentioning features or use
        !            18:  * of this software.  Neither the name of the University nor the names of
        !            19:  * its contributors may be used to endorse or promote products derived from
        !            20:  * this software without specific prior written permission.
        !            21:  * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
        !            22:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
        !            23:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            24:  *
        !            25:  * from: Utah $Hdr: scsi.c 1.3 90/01/27$
        !            26:  *
        !            27:  *     @(#)scsi.c      7.1 (Berkeley) 5/8/90
        !            28:  */
        !            29: 
        !            30: /*
        !            31:  * SCSI bus driver for standalone programs.
        !            32:  */
        !            33: 
        !            34: #include "../sys/types.h"
        !            35: #include "../sys/reboot.h"
        !            36: #include "../hpdev/device.h"
        !            37: #include "../hpdev/scsireg.h"
        !            38: #include "scsivar.h"
        !            39: 
        !            40: #include "saio.h"
        !            41: #include "samachdep.h"
        !            42: 
        !            43: struct scsi_softc scsi_softc[NSCSI];
        !            44: 
        !            45: #define        scsiunit(x)     ((x) >> 3)
        !            46: #define        scsislave(x)    ((x) & 7)
        !            47: 
        !            48: void scsireset();
        !            49: int scsi_cmd_wait = 500;
        !            50: int scsi_data_wait = 300000;
        !            51: 
        !            52: scsiinit()
        !            53: {
        !            54:        extern struct hp_hw sc_table[];
        !            55:        register struct hp_hw *hw;
        !            56:        register struct scsi_softc *hs;
        !            57:        register int i, addr;
        !            58:        static int first = 1;
        !            59:        
        !            60:        i = 0;
        !            61:        for (hw = sc_table; i < NSCSI && hw < &sc_table[MAX_CTLR]; hw++) {
        !            62:                if (hw->hw_type != SCSI)
        !            63:                        continue;
        !            64:                hs = &scsi_softc[i];
        !            65:                hs->sc_addr = hw->hw_addr;
        !            66:                scsireset(i);
        !            67:                if (howto & RB_ASKNAME)
        !            68:                        printf("scsi%d at sc%d\n", i, hw->hw_sc);
        !            69:                /*
        !            70:                 * Adjust devtype on first call.  This routine assumes that
        !            71:                 * adaptor is in the high byte of devtype.
        !            72:                 */
        !            73:                if (first && ((devtype >> 24) & 0xff) == hw->hw_sc) {
        !            74:                        devtype = (devtype & 0x00ffffff) | (i << 24);
        !            75:                        first = 0;
        !            76:                }
        !            77:                hs->sc_alive = 1;
        !            78:                i++;
        !            79:        }
        !            80: }
        !            81: 
        !            82: scsialive(unit)
        !            83:        register int unit;
        !            84: {
        !            85:        unit = scsiunit(unit);
        !            86:        if (unit >= NSCSI || scsi_softc[unit].sc_alive == 0)
        !            87:                return (0);
        !            88:        return (1);
        !            89: }
        !            90: 
        !            91: void
        !            92: scsireset(unit)
        !            93:        register int unit;
        !            94: {
        !            95:        volatile register struct scsidevice *hd;
        !            96:        register struct scsi_softc *hs;
        !            97:        u_int i;
        !            98: 
        !            99:        unit = scsiunit(unit);
        !           100:        hs = &scsi_softc[unit];
        !           101:        hd = (struct scsidevice *)hs->sc_addr;
        !           102:        hd->scsi_id = 0xFF;
        !           103:        DELAY(100);
        !           104:        /*
        !           105:         * Disable interrupts then reset the FUJI chip.
        !           106:         */
        !           107:        hd->scsi_csr  = 0;
        !           108:        hd->scsi_sctl = SCTL_DISABLE | SCTL_CTRLRST;
        !           109:        hd->scsi_scmd = 0;
        !           110:        hd->scsi_tmod = 0;
        !           111:        hd->scsi_pctl = 0;
        !           112:        hd->scsi_temp = 0;
        !           113:        hd->scsi_tch  = 0;
        !           114:        hd->scsi_tcm  = 0;
        !           115:        hd->scsi_tcl  = 0;
        !           116:        hd->scsi_ints = 0;
        !           117: 
        !           118:        /*
        !           119:         * Configure the FUJI chip with its SCSI address, all
        !           120:         * interrupts enabled & appropriate parity.
        !           121:         */
        !           122:        i = (~hd->scsi_hconf) & 0x7;
        !           123:        hs->sc_scsi_addr = 1 << i;
        !           124:        hd->scsi_bdid = i;
        !           125:        if (hd->scsi_hconf & HCONF_PARITY)
        !           126:                hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB |
        !           127:                                SCTL_SEL_ENAB | SCTL_RESEL_ENAB |
        !           128:                                SCTL_INTR_ENAB | SCTL_PARITY_ENAB;
        !           129:        else
        !           130:                hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB |
        !           131:                                SCTL_SEL_ENAB | SCTL_RESEL_ENAB |
        !           132:                                SCTL_INTR_ENAB;
        !           133:        hd->scsi_sctl &=~ SCTL_DISABLE;
        !           134: }
        !           135: 
        !           136: 
        !           137: int
        !           138: scsiabort(hs, hd)
        !           139:        register struct scsi_softc *hs;
        !           140:        volatile register struct scsidevice *hd;
        !           141: {
        !           142:        printf("scsi error: scsiabort\n");
        !           143:        return (0);
        !           144: }
        !           145: 
        !           146: static int
        !           147: issue_select(hd, target, our_addr)
        !           148:        volatile register struct scsidevice *hd;
        !           149:        u_char target, our_addr;
        !           150: {
        !           151:        if (hd->scsi_ssts & (SSTS_INITIATOR|SSTS_TARGET|SSTS_BUSY))
        !           152:                return (1);
        !           153: 
        !           154:        if (hd->scsi_ints & INTS_DISCON)
        !           155:                hd->scsi_ints = INTS_DISCON;
        !           156: 
        !           157:        hd->scsi_pctl = 0;
        !           158:        hd->scsi_temp = (1 << target) | our_addr;
        !           159:        /* select timeout is hardcoded to 2ms */
        !           160:        hd->scsi_tch = 0;
        !           161:        hd->scsi_tcm = 32;
        !           162:        hd->scsi_tcl = 4;
        !           163: 
        !           164:        hd->scsi_scmd = SCMD_SELECT;
        !           165:        return (0);
        !           166: }
        !           167: 
        !           168: static int
        !           169: wait_for_select(hd)
        !           170:        volatile register struct scsidevice *hd;
        !           171: {
        !           172:        u_char ints;
        !           173: 
        !           174:        while ((ints = hd->scsi_ints) == 0)
        !           175:                DELAY(1);
        !           176:        hd->scsi_ints = ints;
        !           177:        return (!(hd->scsi_ssts & SSTS_INITIATOR));
        !           178: }
        !           179: 
        !           180: static int
        !           181: ixfer_start(hd, len, phase, wait)
        !           182:        volatile register struct scsidevice *hd;
        !           183:        int len;
        !           184:        u_char phase;
        !           185:        register int wait;
        !           186: {
        !           187: 
        !           188:        hd->scsi_tch = len >> 16;
        !           189:        hd->scsi_tcm = len >> 8;
        !           190:        hd->scsi_tcl = len;
        !           191:        hd->scsi_pctl = phase;
        !           192:        hd->scsi_tmod = 0; /*XXX*/
        !           193:        hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR;
        !           194: 
        !           195:        /* wait for xfer to start or svc_req interrupt */
        !           196:        while ((hd->scsi_ssts & SSTS_BUSY) == 0) {
        !           197:                if (hd->scsi_ints || --wait < 0)
        !           198:                        return (0);
        !           199:                DELAY(1);
        !           200:        }
        !           201:        return (1);
        !           202: }
        !           203: 
        !           204: static int
        !           205: ixfer_out(hd, len, buf)
        !           206:        volatile register struct scsidevice *hd;
        !           207:        int len;
        !           208:        register u_char *buf;
        !           209: {
        !           210:        register int wait = scsi_data_wait;
        !           211: 
        !           212:        for (; len > 0; --len) {
        !           213:                while (hd->scsi_ssts & SSTS_DREG_FULL) {
        !           214:                        if (hd->scsi_ints || --wait < 0)
        !           215:                                return (len);
        !           216:                        DELAY(1);
        !           217:                }
        !           218:                hd->scsi_dreg = *buf++;
        !           219:        }
        !           220:        return (0);
        !           221: }
        !           222: 
        !           223: static int
        !           224: ixfer_in(hd, len, buf)
        !           225:        volatile register struct scsidevice *hd;
        !           226:        int len;
        !           227:        register u_char *buf;
        !           228: {
        !           229:        register int wait = scsi_data_wait;
        !           230: 
        !           231:        for (; len > 0; --len) {
        !           232:                while (hd->scsi_ssts & SSTS_DREG_EMPTY) {
        !           233:                        if (hd->scsi_ints || --wait < 0) {
        !           234:                                while (! (hd->scsi_ssts & SSTS_DREG_EMPTY)) {
        !           235:                                        *buf++ = hd->scsi_dreg;
        !           236:                                        --len;
        !           237:                                }
        !           238:                                return (len);
        !           239:                        }
        !           240:                        DELAY(1);
        !           241:                }
        !           242:                *buf++ = hd->scsi_dreg;
        !           243:        }
        !           244:        return (len);
        !           245: }
        !           246: 
        !           247: static int
        !           248: scsiicmd(hs, target, cbuf, clen, buf, len, xferphase)
        !           249:        struct scsi_softc *hs;
        !           250:        int target;
        !           251:        u_char *cbuf;
        !           252:        int clen;
        !           253:        u_char *buf;
        !           254:        int len;
        !           255:        u_char xferphase;
        !           256: {
        !           257:        volatile register struct scsidevice *hd =
        !           258:                                (struct scsidevice *)hs->sc_addr;
        !           259:        int i;
        !           260:        u_char phase, ints;
        !           261:        register int wait;
        !           262: 
        !           263:        /* select the SCSI bus (it's an error if bus isn't free) */
        !           264:        if (issue_select(hd, target, hs->sc_scsi_addr))
        !           265:                return (0);
        !           266:        if (wait_for_select(hd))
        !           267:                return (0);
        !           268:        /*
        !           269:         * Wait for a phase change (or error) then let the device
        !           270:         * sequence us through the various SCSI phases.
        !           271:         */
        !           272:        phase = CMD_PHASE;
        !           273:        while (1) {
        !           274:                wait = scsi_cmd_wait;
        !           275:                switch (phase) {
        !           276: 
        !           277:                case CMD_PHASE:
        !           278:                        if (ixfer_start(hd, clen, phase, wait))
        !           279:                                if (ixfer_out(hd, clen, cbuf))
        !           280:                                        goto abort;
        !           281:                        phase = xferphase;
        !           282:                        break;
        !           283: 
        !           284:                case DATA_IN_PHASE:
        !           285:                        if (len <= 0)
        !           286:                                goto abort;
        !           287:                        wait = scsi_data_wait;
        !           288:                        if (ixfer_start(hd, len, phase, wait) ||
        !           289:                            !(hd->scsi_ssts & SSTS_DREG_EMPTY))
        !           290:                                ixfer_in(hd, len, buf);
        !           291:                        phase = STATUS_PHASE;
        !           292:                        break;
        !           293: 
        !           294:                case DATA_OUT_PHASE:
        !           295:                        if (len <= 0)
        !           296:                                goto abort;
        !           297:                        wait = scsi_data_wait;
        !           298:                        if (ixfer_start(hd, len, phase, wait))
        !           299:                                if (ixfer_out(hd, len, buf))
        !           300:                                        goto abort;
        !           301:                        phase = STATUS_PHASE;
        !           302:                        break;
        !           303: 
        !           304:                case STATUS_PHASE:
        !           305:                        wait = scsi_data_wait;
        !           306:                        if (ixfer_start(hd, sizeof(hs->sc_stat), phase, wait) ||
        !           307:                            !(hd->scsi_ssts & SSTS_DREG_EMPTY))
        !           308:                                ixfer_in(hd, sizeof(hs->sc_stat), &hs->sc_stat);
        !           309:                        phase = MESG_IN_PHASE;
        !           310:                        break;
        !           311: 
        !           312:                case MESG_IN_PHASE:
        !           313:                        if (ixfer_start(hd, sizeof(hs->sc_msg), phase, wait) ||
        !           314:                            !(hd->scsi_ssts & SSTS_DREG_EMPTY)) {
        !           315:                                ixfer_in(hd, sizeof(hs->sc_msg), &hs->sc_msg);
        !           316:                                hd->scsi_scmd = SCMD_RST_ACK;
        !           317:                        }
        !           318:                        phase = BUS_FREE_PHASE;
        !           319:                        break;
        !           320: 
        !           321:                case BUS_FREE_PHASE:
        !           322:                        return (1);
        !           323: 
        !           324:                default:
        !           325:                        printf("unexpected scsi phase %d\n", phase);
        !           326:                        goto abort;
        !           327:                }
        !           328:                /* wait for last command to complete */
        !           329:                while ((ints = hd->scsi_ints) == 0) {
        !           330:                        if (--wait < 0)
        !           331:                                goto abort;
        !           332:                        DELAY(1);
        !           333:                }
        !           334:                hd->scsi_ints = ints;
        !           335:                if (ints & INTS_SRV_REQ)
        !           336:                        phase = hd->scsi_psns & PHASE;
        !           337:                else if (ints & INTS_DISCON)
        !           338:                        return (1);
        !           339:                else if ((ints & INTS_CMD_DONE) == 0) {
        !           340:                        goto abort;
        !           341:                }
        !           342:        }
        !           343: abort:
        !           344:        scsiabort(hs, hd);
        !           345:        return (0);
        !           346: }
        !           347: 
        !           348: int
        !           349: scsi_test_unit_rdy(unit)
        !           350: {
        !           351:        int ctlr = scsiunit(unit);
        !           352:        int slave = scsislave(unit);
        !           353:        register struct scsi_softc *hs = &scsi_softc[ctlr];
        !           354:        static struct scsi_cdb6 cdb = { CMD_TEST_UNIT_READY };
        !           355: 
        !           356:        if (scsiicmd(hs, slave, &cdb, sizeof(cdb), (u_char *)0, 0,
        !           357:                     STATUS_PHASE) == 0)
        !           358:                return (0);
        !           359:                
        !           360:        return (hs->sc_stat == 0);
        !           361: }
        !           362: 
        !           363: int
        !           364: scsi_request_sense(unit, buf, len)
        !           365:        int unit;
        !           366:        u_char *buf;
        !           367:        unsigned len;
        !           368: {
        !           369:        int ctlr = scsiunit(unit);
        !           370:        int slave = scsislave(unit);
        !           371:        register struct scsi_softc *hs = &scsi_softc[ctlr];
        !           372:        static struct scsi_cdb6 cdb = { CMD_REQUEST_SENSE };
        !           373: 
        !           374:        cdb.len = len;
        !           375:        return (scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE));
        !           376: }
        !           377: 
        !           378: int
        !           379: scsi_read_capacity(unit, buf, len)
        !           380:        int unit;
        !           381:        u_char *buf;
        !           382:        unsigned len;
        !           383: {
        !           384:        int ctlr = scsiunit(unit);
        !           385:        int slave = scsislave(unit);
        !           386:        register struct scsi_softc *hs = &scsi_softc[ctlr];
        !           387:        static struct scsi_cdb10 cdb = { CMD_READ_CAPACITY };
        !           388: 
        !           389:        return (scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE));
        !           390: }
        !           391: 
        !           392: int
        !           393: scsi_tt_read(unit, buf, len, blk, nblk)
        !           394:        int unit;
        !           395:        u_char *buf;
        !           396:        u_int len;
        !           397:        daddr_t blk;
        !           398:        u_int nblk;
        !           399: {
        !           400:        int ctlr = scsiunit(unit);
        !           401:        int slave = scsislave(unit);
        !           402:        register struct scsi_softc *hs = &scsi_softc[ctlr];
        !           403:        struct scsi_cdb10 cdb;
        !           404:        int stat;
        !           405: 
        !           406:        bzero(&cdb, sizeof(cdb));
        !           407:        cdb.cmd = CMD_READ_EXT;
        !           408:        cdb.lbah = blk >> 24;
        !           409:        cdb.lbahm = blk >> 16;
        !           410:        cdb.lbalm = blk >> 8;
        !           411:        cdb.lbal = blk;
        !           412:        cdb.lenh = nblk >> (8 + DEV_BSHIFT);
        !           413:        cdb.lenl = nblk >> DEV_BSHIFT;
        !           414:        stat = scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE);
        !           415:        if (stat == 0)
        !           416:                return (1);
        !           417:        return (hs->sc_stat);
        !           418: }
        !           419: 
        !           420: int
        !           421: scsi_tt_write(unit, buf, len, blk, nblk)
        !           422:        int unit;
        !           423:        u_char *buf;
        !           424:        u_int len;
        !           425:        daddr_t blk;
        !           426:        u_int nblk;
        !           427: {
        !           428:        int ctlr = scsiunit(unit);
        !           429:        int slave = scsislave(unit);
        !           430:        register struct scsi_softc *hs = &scsi_softc[ctlr];
        !           431:        struct scsi_cdb10 cdb;
        !           432:        int stat;
        !           433: 
        !           434:        bzero(&cdb, sizeof(cdb));
        !           435:        cdb.cmd = CMD_WRITE_EXT;
        !           436:        cdb.lbah = blk >> 24;
        !           437:        cdb.lbahm = blk >> 16;
        !           438:        cdb.lbalm = blk >> 8;
        !           439:        cdb.lbal = blk;
        !           440:        cdb.lenh = nblk >> (8 + DEV_BSHIFT);
        !           441:        cdb.lenl = nblk >> DEV_BSHIFT;
        !           442:        stat = scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_OUT_PHASE);
        !           443:        if (stat == 0)
        !           444:                return (1);
        !           445:        return (hs->sc_stat);
        !           446: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.