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

unix.superglobalmegacorp.com

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