Annotation of linux/kernel/blk_drv/scsi/ultrastor.c, revision 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.