Annotation of researchv9/sys/boot/stand/sc.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * @(#)sc.c 1.1 86/02/03 Copyright (c) 1985 by Sun Microsystems, Inc.
        !             3:  */
        !             4: 
        !             5: #include <sys/param.h>
        !             6: #include <sys/inode.h>
        !             7: #include <sun/dklabel.h>
        !             8: #include <sun/dkio.h>
        !             9: #include <sys/buf.h>
        !            10: #include <sundev/screg.h>
        !            11: #include <sundev/sireg.h>
        !            12: #include <sundev/scsi.h>
        !            13: #include <machine/sunromvec.h>
        !            14: #include <machine/idprom.h>
        !            15: #include "saio.h"
        !            16: 
        !            17: /*
        !            18:  * Low-level routines common to all devices on the SCSI bus
        !            19:  */
        !            20: 
        !            21: /*
        !            22:  * Interface to the routines in this module is via a second "sip"
        !            23:  * structure contained in the caller's local variables.
        !            24:  *
        !            25:  * This "sip" must be initialized with sip->si_boottab = scdriver
        !            26:  * and must then be devopen()ed before any I/O can be done.
        !            27:  *
        !            28:  * The device must be closed with devclose().
        !            29:  */
        !            30: 
        !            31: /* How our addrs look to the SCSI DMA hardware */
        !            32: #define        SCSI_DMA_ADDR(x)        (((int)x)&0x000FFFFF)
        !            33: 
        !            34: /*
        !            35:  * The interfaces we export
        !            36:  */
        !            37: extern int nullsys();
        !            38: int scopen();
        !            39: 
        !            40: struct boottab scdriver =
        !            41:        {"sd",  nullsys,        nullsys,        scopen,         nullsys,
        !            42:                nullsys,        "",     0};
        !            43: 
        !            44: char seqerr_msg[] = "sequence error";  /* Saves dup copy of string */
        !            45: 
        !            46: /*
        !            47:  * Record an error message from scsi
        !            48:  */
        !            49: sc_error(msg)
        !            50:        char *msg;
        !            51: {
        !            52:        printf("scsi: %s\n", msg);
        !            53: }
        !            54: 
        !            55: #define        SCSI_MULTI_BASE 0x80000
        !            56: #define        SCSI_VME_BASE   0x200000
        !            57: #define        SCSI_SIZE       0x4000          /* incr to next board - OK for VME ? */
        !            58: #define        SCSI_NSTD       2               /* # of standard address boards */
        !            59: 
        !            60: /*
        !            61:  * Open the SCSI host adapter.
        !            62:  * Note that the Multibus address and the VME address
        !            63:  * are totally different, although both are controller '0'.
        !            64:  * More fon goes here for the model 25.
        !            65:  */
        !            66: int
        !            67: scopen(sip)
        !            68:        register struct saioreq *sip;
        !            69: {
        !            70:        register struct scsi_ha_reg *har;
        !            71:        struct idprom id;
        !            72:        register int base;
        !            73:        enum MAPTYPES space;
        !            74:        char *devalloc();
        !            75: 
        !            76:        if (idprom(IDFORM_1, &id) == IDFORM_1 &&
        !            77:            id.id_machine == IDM_SUN2_MULTI) {
        !            78:                base = SCSI_MULTI_BASE;
        !            79:                space = MAP_MBMEM;
        !            80:        } else {
        !            81:                base = SCSI_VME_BASE;
        !            82:                space = MAP_VME24A16D;
        !            83:        }
        !            84:        if (sip->si_ctlr < SCSI_NSTD)
        !            85:                sip->si_ctlr = base + sip->si_ctlr * SCSI_SIZE;
        !            86:        /* now map it in */
        !            87:        sip->si_devaddr = devalloc(space, sip->si_ctlr,
        !            88:            sizeof (struct scsi_ha_reg));
        !            89:        if (sip->si_devaddr == 0)
        !            90:                return (-1);
        !            91: 
        !            92:        har = (struct scsi_ha_reg *) sip->si_devaddr;
        !            93:        har->icr = 0;
        !            94:        return 0;
        !            95: }
        !            96: 
        !            97: 
        !            98: /*
        !            99:  * Write a command to the SCSI bus.
        !           100:  *
        !           101:  * The supplied sip is the one opened by scopen().
        !           102:  * DMA is done based on sip->si_ma and sip->si_cc.
        !           103:  *
        !           104:  * Returns -1 for error, otherwise returns the residual count not DMAed
        !           105:  * (zero for success).
        !           106:  *
        !           107:  * FIXME, this must be accessed via a boottab vector,
        !           108:  * to allow host adap to switch.
        !           109:  * Must pass cdb, scb in sip somewhere...
        !           110:  */
        !           111: int
        !           112: scdoit(cdb, scb, sip)
        !           113:        register struct scsi_cdb *cdb;
        !           114:        register struct scsi_scb *scb;
        !           115:        register struct saioreq *sip;
        !           116: {
        !           117:        register char *cp;
        !           118:        register int i, b;
        !           119:        register struct scsi_ha_reg *har;
        !           120: 
        !           121:        har = (struct scsi_ha_reg *) sip->si_devaddr;
        !           122: 
        !           123:        /* select controller */
        !           124:        har->data = 1 << sip->si_unit;          /* Set target on SCSI bus */
        !           125: 
        !           126:        i = 100000;
        !           127:        for(;;) {
        !           128:                if ((har->icr & ICR_BUSY) == 0) {
        !           129:                        break;
        !           130:                }
        !           131:                if (i-- <= 0) {
        !           132:                        sc_error("bus continuously busy");
        !           133:                        har->icr = ICR_RESET;
        !           134:                        DELAY(50);
        !           135:                        har->icr = 0;
        !           136:                        return (-1);
        !           137:                }
        !           138:        }
        !           139:        har->icr = ICR_SELECT;
        !           140:        if (sc_wait(har, ICR_BUSY) == 0) {
        !           141:                /*
        !           142:                 * No response to select.  Reset bus and get out.
        !           143:                 */
        !           144:                sc_error("no such controller on SCSI bus");
        !           145:                har->icr = ICR_RESET;
        !           146:                DELAY(50);
        !           147:                har->icr = 0;
        !           148:                return (-1);
        !           149:        }
        !           150:        /* pass command */
        !           151:        har->icr = ICR_WORD_MODE | ICR_DMA_ENABLE;
        !           152:        har->dma_addr = SCSI_DMA_ADDR(sip->si_ma);
        !           153:        har->dma_count = ~sip->si_cc;
        !           154:        cp = (char *) cdb;
        !           155:        for (i = 0; i < sizeof (struct scsi_cdb); i++) {
        !           156:                if (sc_putbyte(har, ICR_COMMAND, *cp++) == 0) {
        !           157:                        return (-1);
        !           158:                }
        !           159:        }
        !           160:        /* wait for command completion */
        !           161:        if (sc_wait(har, ICR_INTERRUPT_REQUEST) == 0) {
        !           162:                return (-1);
        !           163:        }
        !           164:        /* handle odd length dma transfer, adjust dma count */
        !           165:        if (har->icr & ICR_ODD_LENGTH) {
        !           166:                if ((cdb->cmd == SC_REQUEST_SENSE) || (cdb->cmd == SC_READ)) {
        !           167:                        cp = (char *)sip->si_ma + sip->si_cc - 1;
        !           168:                        *cp = (char)har->data;
        !           169:                        har->dma_count = ~(~har->dma_count - 1);
        !           170:                } else {
        !           171:                        har->dma_count = ~(~har->dma_count + 1);
        !           172:                }
        !           173:        }
        !           174:        /* get status */
        !           175:        cp = (char *) scb;
        !           176:        i = 0;
        !           177:        for (;;) {
        !           178:                b = sc_getbyte(har, ICR_STATUS);
        !           179:                if (b == -1) {
        !           180:                        break;
        !           181:                }
        !           182:                if (i < STATUS_LEN) {
        !           183:                        cp[i++] = b;
        !           184:                }
        !           185:        }
        !           186:        b = sc_getbyte(har, ICR_MESSAGE_IN);
        !           187:        if (b != SC_COMMAND_COMPLETE) {
        !           188:                if (b >= 0) {   /* if not, sc_getbyte already printed msg */
        !           189:                        sc_error("invalid message");
        !           190:                }
        !           191:                return (-1);
        !           192:        }
        !           193:        return (sip->si_cc - ~har->dma_count);
        !           194: }
        !           195: 
        !           196: 
        !           197: /*
        !           198:  * Wait for a condition on the scsi bus.
        !           199:  */
        !           200: int
        !           201: sc_wait(har, cond)
        !           202:        register struct scsi_ha_reg *har;
        !           203: {
        !           204:        register int icr, count;
        !           205: 
        !           206:        if (cond == ICR_INTERRUPT_REQUEST) {
        !           207:                count = 1000000;
        !           208:        } else {
        !           209:                count = 10000;
        !           210:        }
        !           211:        while (((icr = har->icr) & cond) != cond) {
        !           212:                if (--count <= 0) {
        !           213:                        sc_error("timeout");
        !           214:                        return (0);
        !           215:                }
        !           216:                if (icr & ICR_BUS_ERROR) {
        !           217:                        sc_error("bus error");
        !           218:                        return (0);
        !           219:                }
        !           220:                DELAY(5000);
        !           221:        }
        !           222:        return (1);
        !           223: }
        !           224: 
        !           225: 
        !           226: /*
        !           227:  * Put a byte into the scsi command register.
        !           228:  */
        !           229: int
        !           230: sc_putbyte(har, bits, c)
        !           231:        register struct scsi_ha_reg *har;
        !           232: {
        !           233:        if (sc_wait(har, ICR_REQUEST) == 0) {
        !           234:                return (0);
        !           235:        }
        !           236:        if ((har->icr & ICR_BITS) != bits) {
        !           237:                sc_error(seqerr_msg);
        !           238:                return (0);
        !           239:        }
        !           240:        har->cmd_stat = c;
        !           241:        return (1);
        !           242: }
        !           243: 
        !           244: 
        !           245: /*
        !           246:  * Get a byte from the scsi command/status register.
        !           247:  * <bits> defines the bits we want to see on in the ICR.
        !           248:  * If <bits> is wrong, we print a message -- unless <bits> is ICR_STATUS.
        !           249:  * This hack is because scdoit keeps calling getbyte until it sees a non-
        !           250:  * status byte; this is not an error in sequence as long as the next byte
        !           251:  * has MESSAGE_IN tags.  FIXME.
        !           252:  */
        !           253: int
        !           254: sc_getbyte(har, bits)
        !           255:        register struct scsi_ha_reg *har;
        !           256: {
        !           257:        if (sc_wait(har, ICR_REQUEST) == 0) {
        !           258:                return (-1);
        !           259:        }
        !           260:        if ((har->icr & ICR_BITS) != bits) {
        !           261:                if (bits != ICR_STATUS) sc_error(seqerr_msg);   /* Hack hack */
        !           262:                return (-1);
        !           263:        }
        !           264:        return (har->cmd_stat);
        !           265: }

unix.superglobalmegacorp.com

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