Annotation of researchv9/sys/boot/stand/sc.c, revision 1.1.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.