Annotation of linux/kernel/blk_drv/scsi/ultrastor.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *     ultrastor.c     (C) 1991 David B. Gentzel
                      3:  *     Low-level scsi driver for UltraStor 14F
                      4:  *     by David B. Gentzel, Whitfield Software Services, Carnegie, PA
                      5:  *         ([email protected])
                      6:  *     Thanks to UltraStor for providing the necessary documentation
                      7:  */
                      8: 
                      9: /* ??? Caveats:
                     10:    This driver is VERY stupid.  It takes no advantage of much of the power of
                     11:    the UltraStor controller.  We just sit-and-spin while waiting for commands
                     12:    to complete.  I hope to go back and beat it into shape, but PLEASE, anyone
                     13:    else who would like to, please make improvements! */
                     14: 
                     15: #include <linux/config.h>
                     16: 
                     17: #ifdef CONFIG_SCSI_ULTRASTOR
                     18: 
                     19: #include <stddef.h>
                     20: 
                     21: #include <linux/string.h>
                     22: #include <linux/config.h>
                     23: #include <linux/sched.h>
                     24: #include <linux/fs.h>
                     25: #include <linux/kernel.h>
                     26: #include <linux/hdreg.h>
                     27: #include <asm/system.h>
                     28: #include <asm/io.h>
                     29: #include <asm/segment.h>
                     30: 
                     31: #include "ultrastor.h"
                     32: #include "scsi.h"
                     33: #include "hosts.h"
                     34: 
                     35: #define VERSION "1.0 alpha"
                     36: 
                     37: #define ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr)[0])
                     38: #define BYTE(num, n) ((unsigned char)((unsigned int)(num) >> ((n) * 8)))
                     39: 
                     40: /* Simply using "unsigned long" in these structures won't work as it causes
                     41:    alignment.  Perhaps the "aligned" attribute may be used in GCC 2.0 to get
                     42:    around this, but for now I use this hack. */
                     43: typedef struct {
                     44:     unsigned char bytes[4];
                     45: } Longword;
                     46: 
                     47: /* Used to store configuration info read from config i/o registers.  Most of
                     48:    this is not used yet, but might as well save it. */
                     49: struct config {
                     50:     struct {
                     51:        unsigned char bios_segment: 3;
                     52:        unsigned char reserved: 1;
                     53:        unsigned char interrupt: 2;
                     54:        unsigned char dma_channel: 2;
                     55:     } config_1;
                     56:     struct {
                     57:        unsigned char ha_scsi_id: 3;
                     58:        unsigned char mapping_mode: 2;
                     59:        unsigned char bios_drive_number: 1;
                     60:        unsigned char tfr_port: 2;
                     61:     } config_2;
                     62: };
                     63: 
                     64: /* MailBox SCSI Command Packet.  Basic command structure for communicating
                     65:    with controller. */
                     66: struct mscp {
                     67:     unsigned char opcode: 3;           /* type of command */
                     68:     unsigned char xdir: 2;             /* data transfer direction */
                     69:     unsigned char dcn: 1;              /* disable disconnect */
                     70:     unsigned char ca: 1;               /* use cache (if available) */
                     71:     unsigned char sg: 1;               /* scatter/gather operation */
                     72:     unsigned char target_id: 3;                /* target SCSI id */
                     73:     unsigned char ch_no: 2;            /* SCSI channel (always 0 for 14f) */
                     74:     unsigned char lun: 3;              /* logical unit number */
                     75:     Longword transfer_data;            /* transfer data pointer */
                     76:     Longword transfer_data_length;     /* length in bytes */
                     77:     Longword command_link;             /* for linking command chains */
                     78:     unsigned char scsi_command_link_id;        /* identifies command in chain */
                     79:     unsigned char number_of_sg_list;   /* (if sg is set) 8 bytes per list */
                     80:     unsigned char length_of_sense_byte;
                     81:     unsigned char length_of_scsi_cdbs; /* 6, 10, or 12 */
                     82:     unsigned char scsi_cdbs[12];       /* SCSI commands */
                     83:     unsigned char adapter_status;      /* non-zero indicates HA error */
                     84:     unsigned char target_status;       /* non-zero indicates target error */
                     85:     Longword sense_data;
                     86: };
                     87: 
                     88: /* Allowed BIOS base addresses for 14f (NULL indicates reserved) */
                     89: static const void *const bios_segment_table[8] = {
                     90:     NULL,           (void *)0xC4000, (void *)0xC8000, (void *)0xCC000,
                     91:     (void *)0xD0000, (void *)0xD4000, (void *)0xD8000, (void *)0xDC000,
                     92: };
                     93: 
                     94: /* Allowed IRQs for 14f */
                     95: static const unsigned char interrupt_table[4] = { 15, 14, 11, 10 };
                     96: 
                     97: /* Allowed DMA channels for 14f (0 indicates reserved) */
                     98: static const unsigned char dma_channel_table[4] = { 5, 6, 7, 0 };
                     99: 
                    100: #if 0  /* Not currently used, head/sector mappings allowed by 14f */
                    101: static const struct {
                    102:     unsigned char heads;
                    103:     unsigned char sectors;
                    104: } mapping_table[4] = { { 16, 63 }, { 64, 32 }, { 64, 63 }, { 0, 0 } };
                    105: #endif
                    106: 
                    107: /* Config info */
                    108: static struct config config;
                    109: 
                    110: /* Our index in the host adapter array maintained by higher-level driver */
                    111: static int host_number;
                    112: 
                    113: /* PORT_ADDRESS is first port address used for i/o of messages. */
                    114: #ifdef PORT_OVERRIDE
                    115: # define PORT_ADDRESS PORT_OVERRIDE
                    116: #else
                    117: static unsigned short port_address = 0;
                    118: # define PORT_ADDRESS port_address
                    119: #endif
                    120: 
                    121: static volatile int aborted = 0;
                    122: 
                    123: #ifndef PORT_OVERRIDE
                    124: static const unsigned short ultrastor_ports[] = {
                    125:     0x330, 0x340, 0x310, 0x230, 0x240, 0x210, 0x130, 0x140,
                    126: };
                    127: #endif
                    128: 
                    129: static const struct {
                    130:     const char *signature;
                    131:     size_t offset;
                    132:     size_t length;
                    133: } signatures[] = {
                    134:     { "SBIOS 1.01 COPYRIGHT (C) UltraStor Corporation,1990-1992.", 0x10, 57 },
                    135: };
                    136: 
                    137: int ultrastor_14f_detect(int hostnum)
                    138: {
                    139:     size_t i;
                    140:     unsigned char in_byte;
                    141:     const void *base_address;
                    142: 
                    143: #ifdef DEBUG
                    144:     printk("ultrastor_14f_detect: called\n");
                    145: #endif
                    146: 
                    147: #ifndef PORT_OVERRIDE
                    148: /* ??? This is easy to implement, but I'm not sure how "friendly" it is to
                    149:    go off and read random i/o ports. */
                    150: # error Not implemented!
                    151: #endif
                    152: 
                    153:     if (!PORT_ADDRESS) {
                    154: #ifdef DEBUG
                    155:        printk("ultrastor_14f_detect: no port address found!\n");
                    156: #endif
                    157:        return FALSE;
                    158:     }
                    159: 
                    160: #ifdef DEBUG
                    161:     printk("ultrastor_14f_detect: port address = %X\n", PORT_ADDRESS);
                    162: #endif
                    163: 
                    164:     in_byte = inb(PRODUCT_ID(PORT_ADDRESS + 0));
                    165:     if (in_byte != US14F_PRODUCT_ID_0) {
                    166: #ifdef DEBUG
                    167:        printk("ultrastor_14f_detect: unknown product ID 0 - %02X\n", in_byte);
                    168: #endif
                    169:        return FALSE;
                    170:     }
                    171:     in_byte = inb(PRODUCT_ID(PORT_ADDRESS + 1));
                    172:     /* Only upper nibble is defined for Product ID 1 */
                    173:     if ((in_byte & 0xF0) != US14F_PRODUCT_ID_1) {
                    174: #ifdef DEBUG
                    175:        printk("ultrastor_14f_detect: unknown product ID 1 - %02X\n", in_byte);
                    176: #endif
                    177:        return FALSE;
                    178:     }
                    179: 
                    180:     /* All above tests passed, must be the right thing.  Get some useful
                    181:        info. */
                    182:     *(char *)&config.config_1 = inb(CONFIG(PORT_ADDRESS + 0));
                    183:     *(char *)&config.config_2 = inb(CONFIG(PORT_ADDRESS + 1));
                    184: 
                    185:     /* To verify this card, we simply look for the UltraStor SCSI from the
                    186:        BIOS version notice. */
                    187:     base_address = bios_segment_table[config.config_1.bios_segment];
                    188:     if (base_address != NULL) {
                    189:        int found = 0;
                    190: 
                    191:        for (i = 0; !found && i < ARRAY_SIZE(signatures); i++)
                    192:            if (memcmp((char *)base_address + signatures[i].offset,
                    193:                       signatures[i].signature, signatures[i].length))
                    194:                found = 1;
                    195:        if (!found)
                    196:            base_address = NULL;
                    197:     }
                    198:     if (!base_address) {
                    199: #ifdef DEBUG
                    200:        printk("ultrastor_14f_detect: not detected.\n");
                    201: #endif
                    202:        return FALSE;
                    203:     }
                    204: 
                    205:     /* Final consistancy check, verify previous info. */
                    206:     if (!dma_channel_table[config.config_1.dma_channel]
                    207:        || !(config.config_2.tfr_port & 0x2)) {
                    208: #ifdef DEBUG
                    209:        printk("ultrastor_14f_detect: consistancy check failed\n");
                    210: #endif
                    211:        return FALSE;
                    212:     }
                    213: 
                    214:     /* If we were TRULY paranoid, we could issue a host adapter inquiry
                    215:        command here and verify the data returned.  But frankly, I'm
                    216:        exhausted! */
                    217: 
                    218:     /* Finally!  Now I'm satisfied... */
                    219: #ifdef DEBUG
                    220:     printk("ultrastor_14f_detect: detect succeeded\n"
                    221:           "  BIOS segment: %05X\n"
                    222:           "  Interrupt: %d\n"
                    223:           "  DMA channel: %d\n"
                    224:           "  H/A SCSI ID: %d\n",
                    225:           base_address, interrupt_table[config.config_1.interrupt],
                    226:           dma_channel_table[config.config_1.dma_channel],
                    227:           config.config_2.ha_scsi_id);
                    228: #endif
                    229:     host_number = hostnum;
                    230:     scsi_hosts[hostnum].this_id = config.config_2.ha_scsi_id;
                    231:     return TRUE;
                    232: }
                    233: 
                    234: const char *ultrastor_14f_info(void)
                    235: {
                    236:     return "UltraStor 14F SCSI driver version "
                    237:           VERSION
                    238:           " by David B. Gentzel\n";
                    239: }
                    240: 
                    241: #if 0
                    242: int ultrastor_14f_queuecommand(unsigned char target, const void *cmnd,
                    243:                               void *buff, int bufflen, void (*done)(int, int))
                    244: #else
                    245: int ultrastor_14f_command(unsigned char target, const void *cmnd,
                    246:                          void *buff, int bufflen)
                    247: #endif
                    248: {
                    249:     struct mscp mscp = {
                    250:        OP_SCSI, DTD_SCSI, FALSE, TRUE, FALSE,
                    251:        target, 0, 0 /* LUN??? */,
                    252:        *(Longword *)&buff,
                    253:        *(Longword *)&bufflen,
                    254:        { 0, 0, 0, 0 },
                    255:        0,
                    256:        0,
                    257:        0,
                    258:        ((*(char *)cmnd <= 0x1F) ? 6 : 10),
                    259:        { 0 },  /* Filled in via memcpy below */
                    260:        0,
                    261:        0,
                    262:        { 0, 0, 0, 0 }
                    263:     };
                    264:     unsigned char in_byte;
                    265: 
                    266:     memcpy(mscp.scsi_cdbs, cmnd, mscp.length_of_scsi_cdbs);
                    267: 
                    268:     /* Find free OGM slot (OGMINT bit is 0) */
                    269:     do
                    270:        in_byte = inb(LCL_DOORBELL_INTR(PORT_ADDRESS));
                    271:     while (!aborted && (in_byte & 1));
                    272:     if (aborted)
                    273:        /* ??? is this right? */
                    274:        return (aborted << 16);
                    275: 
                    276:     /* Store pointer in OGM address bytes */
                    277:     outb(BYTE(&mscp, 0), OGM_DATA_PTR(PORT_ADDRESS + 0));
                    278:     outb(BYTE(&mscp, 1), OGM_DATA_PTR(PORT_ADDRESS + 1));
                    279:     outb(BYTE(&mscp, 2), OGM_DATA_PTR(PORT_ADDRESS + 2));
                    280:     outb(BYTE(&mscp, 3), OGM_DATA_PTR(PORT_ADDRESS + 3));
                    281: 
                    282:     /* Issue OGM interrupt */
                    283:     outb(0x1, LCL_DOORBELL_INTR(PORT_ADDRESS));
                    284: 
                    285:     /* Wait for ICM interrupt */
                    286:     do
                    287:        in_byte = inb(SYS_DOORBELL_INTR(PORT_ADDRESS));
                    288:     while (!aborted && !(in_byte & 1));
                    289:     if (aborted)
                    290:        /* ??? is this right? */
                    291:        return (aborted << 16);
                    292: 
                    293:     /* Clean ICM slot (set ICMINT bit to 0) */
                    294:     outb(0x1, SYS_DOORBELL_INTR(PORT_ADDRESS));
                    295: 
                    296:     /* ??? not right, but okay for now? */
                    297:     return (mscp.adapter_status << 16) | mscp.target_status;
                    298: }
                    299: 
                    300: int ultrastor_14f_abort(int code)
                    301: {
                    302:     aborted = (code ? code : DID_ABORT);
                    303:     return 0;
                    304: }
                    305: 
                    306: int ultrastor_14f_reset(void)
                    307: {
                    308:     unsigned char in_byte;
                    309: 
                    310: #ifdef DEBUG
                    311:     printk("ultrastor_14f_reset: called\n");
                    312: #endif
                    313: 
                    314:     /* Issue SCSI BUS reset */
                    315:     outb(0x20, LCL_DOORBELL_INTR(PORT_ADDRESS));
                    316:     /* Wait for completion... */
                    317:     do
                    318:        in_byte = inb(LCL_DOORBELL_INTR(PORT_ADDRESS));
                    319:     while (in_byte & 0x20);
                    320: 
                    321:     aborted = DID_RESET;
                    322: 
                    323: #ifdef DEBUG
                    324:     printk("ultrastor_14f_reset: returning\n");
                    325: #endif
                    326:     return 0;
                    327: }
                    328: 
                    329: #endif

unix.superglobalmegacorp.com

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