📄 wd7000.c
字号:
} return (1);}void wd7000_revision (Adapter *host){ static IcbRevLvl icb = {ICB_OP_GET_REVISION}; icb.phase = 1; /* * Like diagnostics, this is only done at init time, in fact, from * wd7000_detect, so there should be OGMBs available. If it fails, * the only damage will be that the revision will show up as 0.0, * which in turn means that scatter/gather will be disabled. */ mail_out (host, (struct scb *) &icb); while (icb.phase) barrier (); /* wait for completion */ host->rev1 = icb.primary; host->rev2 = icb.secondary;}#undef SPRINTF#define SPRINTF(args...) { if (pos < (buffer + length)) pos += sprintf (pos, ## args); }int wd7000_set_info (char *buffer, int length, struct Scsi_Host *host){ unsigned long flags; save_flags (flags); cli ();#ifdef WD7000_DEBUG printk ("Buffer = <%.*s>, length = %d\n", length, buffer, length);#endif /* * Currently this is a no-op */ printk ("Sorry, this function is currently out of order...\n"); restore_flags (flags); return (length);}int wd7000_proc_info (char *buffer, char **start, off_t offset, int length, int hostno, int inout){ struct Scsi_Host *host = NULL; Scsi_Device *scd; Adapter *adapter; unsigned long flags; char *pos = buffer; short i;#ifdef WD7000_DEBUG Mailbox *ogmbs, *icmbs; short count;#endif /* * Find the specified host board. */ for (i = 0; i < IRQS; i++) if (wd7000_host[i] && (wd7000_host[i]->host_no == hostno)) { host = wd7000_host[i]; break; } /* * Host not found! */ if (! host) return (-ESRCH); /* * Has data been written to the file ? */ if (inout) return (wd7000_set_info (buffer, length, host)); adapter = (Adapter *) host->hostdata; save_flags (flags); cli (); SPRINTF ("Host scsi%d: Western Digital WD-7000 (rev %d.%d)\n", hostno, adapter->rev1, adapter->rev2); SPRINTF (" IO base: 0x%x\n", adapter->iobase); SPRINTF (" IRQ: %d\n", adapter->irq); SPRINTF (" DMA channel: %d\n", adapter->dma); SPRINTF (" Interrupts: %d\n", adapter->int_counter); SPRINTF (" BUS_ON time: %d nanoseconds\n", adapter->bus_on * 125); SPRINTF (" BUS_OFF time: %d nanoseconds\n", adapter->bus_off * 125);#ifdef WD7000_DEBUG ogmbs = adapter->mb.ogmb; icmbs = adapter->mb.icmb; SPRINTF ("\nControl port value: 0x%x\n", adapter->control); SPRINTF ("Incoming mailbox:\n"); SPRINTF (" size: %d\n", ICMB_CNT); SPRINTF (" queued messages: "); for (i = count = 0; i < ICMB_CNT; i++) if (icmbs[i].status) { count++; SPRINTF ("0x%x ", i); } SPRINTF (count ? "\n" : "none\n"); SPRINTF ("Outgoing mailbox:\n"); SPRINTF (" size: %d\n", OGMB_CNT); SPRINTF (" next message: 0x%x\n", adapter->next_ogmb); SPRINTF (" queued messages: "); for (i = count = 0; i < OGMB_CNT; i++) if (ogmbs[i].status) { count++; SPRINTF ("0x%x ", i); } SPRINTF (count ? "\n" : "none\n");#endif /* * Display driver information for each device attached to the board. */ scd = host->host_queue; SPRINTF ("\nAttached devices: %s\n", scd ? "" : "none"); for ( ; scd; scd = scd->next) if (scd->host->host_no == hostno) { SPRINTF (" [Channel: %02d, Id: %02d, Lun: %02d] ", scd->channel, scd->id, scd->lun); SPRINTF ("%s ", (scd->type < MAX_SCSI_DEVICE_CODE) ? scsi_device_types[(short) scd->type] : "Unknown device"); for (i = 0; (i < 8) && (scd->vendor[i] >= 0x20); i++) SPRINTF ("%c", scd->vendor[i]); SPRINTF (" "); for (i = 0; (i < 16) && (scd->model[i] >= 0x20); i++) SPRINTF ("%c", scd->model[i]); SPRINTF ("\n"); } SPRINTF ("\n"); restore_flags (flags); /* * Calculate start of next buffer, and return value. */ *start = buffer + offset; if ((pos - buffer) < offset) return (0); else if ((pos - buffer - offset) < length) return (pos - buffer - offset); else return (length);}/* * Returns the number of adapters this driver is supporting. * * The source for hosts.c says to wait to call scsi_register until 100% * sure about an adapter. We need to do it a little sooner here; we * need the storage set up by scsi_register before wd7000_init, and * changing the location of an Adapter structure is more trouble than * calling scsi_unregister. * */int wd7000_detect (Scsi_Host_Template *tpnt){ short present = 0, biosaddr_ptr, sig_ptr, i, pass; short biosptr[NUM_CONFIGS]; unsigned iobase; Adapter *host = NULL; struct Scsi_Host *sh;#ifdef WD7000_DEBUG printk ("wd7000_detect: started\n");#endif for (i = 0; i < IRQS; wd7000_host[i++] = NULL) ; for (i = 0; i < NUM_CONFIGS; biosptr[i++] = -1) ; tpnt->proc_dir = &proc_scsi_wd7000; tpnt->proc_info = &wd7000_proc_info; /* * Set up SCB free list, which is shared by all adapters */ init_scbs (); for (pass = 0; pass < NUM_CONFIGS; pass++) { /* * First, search for BIOS SIGNATURE... */ for (biosaddr_ptr = 0; biosaddr_ptr < NUM_ADDRS; biosaddr_ptr++) for (sig_ptr = 0; sig_ptr < NUM_SIGNATURES; sig_ptr++) { for (i = 0; i < pass; i++) if (biosptr[i] == biosaddr_ptr) break; if (i == pass) { void *biosaddr = ioremap (wd7000_biosaddr[biosaddr_ptr] + signatures[sig_ptr].ofs, signatures[sig_ptr].len); short bios_match=0; if(biosaddr) bios_match = memcmp ((char *) biosaddr, signatures[sig_ptr].sig, signatures[sig_ptr].len); iounmap (biosaddr); if (! bios_match) goto bios_matched; } } bios_matched: /* * BIOS SIGNATURE has been found. */#ifdef WD7000_DEBUG printk ("wd7000_detect: pass %d\n", pass + 1); if (biosaddr_ptr == NUM_ADDRS) printk ("WD-7000 SST BIOS not detected...\n"); else printk ("WD-7000 SST BIOS detected at 0x%lx: checking...\n", wd7000_biosaddr[biosaddr_ptr]);#endif if (configs[pass].irq < 0) continue; iobase = configs[pass].iobase;#ifdef WD7000_DEBUG printk ("wd7000_detect: check IO 0x%x region...\n", iobase);#endif if (!check_region (iobase, 4)) {#ifdef WD7000_DEBUG printk ("wd7000_detect: ASC reset (IO 0x%x) ...", iobase);#endif /* * ASC reset... */ outb (ASC_RES, iobase + ASC_CONTROL); delay (1); outb (0, iobase + ASC_CONTROL); if (WAIT (iobase + ASC_STAT, ASC_STATMASK, CMD_RDY, 0))#ifdef WD7000_DEBUG { printk ("failed!\n"); continue; } else printk ("ok!\n");#else continue;#endif if (inb (iobase + ASC_INTR_STAT) == 1) { /* * We register here, to get a pointer to the extra space, * which we'll use as the Adapter structure (host) for * this adapter. It is located just after the registered * Scsi_Host structure (sh), and is located by the empty * array hostdata. */ sh = scsi_register (tpnt, sizeof (Adapter)); host = (Adapter *) sh->hostdata;#ifdef WD7000_DEBUG printk ("wd7000_detect: adapter allocated at 0x%x\n", (int) host);#endif memset (host, 0, sizeof (Adapter)); host->irq = configs[pass].irq; host->dma = configs[pass].dma; host->iobase = iobase; host->int_counter = 0; host->bus_on = configs[pass].bus_on; host->bus_off = configs[pass].bus_off; host->sh = wd7000_host[host->irq - IRQ_MIN] = sh;#ifdef WD7000_DEBUG printk ("wd7000_detect: Trying init WD-7000 card at IO " "0x%x, IRQ %d, DMA %d...\n", host->iobase, host->irq, host->dma);#endif if (!wd7000_init (host)) { /* Initialization failed */ scsi_unregister (sh); continue; } /* * OK from here - we'll use this adapter/configuration. */ wd7000_revision (host); /* important for scatter/gather */ /* * Register our ports. */ request_region (host->iobase, 4, "wd7000"); /* * For boards before rev 6.0, scatter/gather isn't supported. */ if (host->rev1 < 6) sh->sg_tablesize = SG_NONE; present++; /* count it */ if (biosaddr_ptr != NUM_ADDRS) biosptr[pass] = biosaddr_ptr; printk ("Western Digital WD-7000 (rev %d.%d) ", host->rev1, host->rev2); printk ("using IO 0x%x, IRQ %d, DMA %d.\n", host->iobase, host->irq, host->dma); printk (" BUS_ON time: %dns, BUS_OFF time: %dns\n", host->bus_on * 125, host->bus_off * 125); } }#ifdef WD7000_DEBUG else printk ("wd7000_detect: IO 0x%x region already allocated!\n", iobase);#endif } if (!present) printk ("Failed initialization of WD-7000 SCSI card!\n"); return (present);}/* * I have absolutely NO idea how to do an abort with the WD7000... */int wd7000_abort (Scsi_Cmnd *SCpnt){ Adapter *host = (Adapter *) SCpnt->host->hostdata; if (inb (host->iobase + ASC_STAT) & INT_IM) { printk ("wd7000_abort: lost interrupt\n"); wd7000_intr_handle (host->irq, NULL, NULL); return (SCSI_ABORT_SUCCESS); } return (SCSI_ABORT_SNOOZE);}/* * I also have no idea how to do a reset... */int wd7000_reset (Scsi_Cmnd *SCpnt, unsigned int unused){ return (SCSI_RESET_PUNT);}/* * This was borrowed directly from aha1542.c. (Zaga) */int wd7000_biosparam (Disk *disk, kdev_t dev, int *ip){#ifdef WD7000_DEBUG printk ("wd7000_biosparam: dev=%s, size=%d, ", kdevname (dev), disk->capacity);#endif /* * try default translation */ ip[0] = 64; ip[1] = 32; ip[2] = disk->capacity / (64 * 32); /* * for disks >1GB do some guessing */ if (ip[2] >= 1024) { int info[3]; /* * try to figure out the geometry from the partition table */ if ((scsicam_bios_param (disk, dev, info) < 0) || !(((info[0] == 64) && (info[1] == 32)) || ((info[0] == 255) && (info[1] == 63)))) { printk ("wd7000_biosparam: unable to verify geometry for disk with >1GB.\n" " using extended translation.\n"); ip[0] = 255; ip[1] = 63; ip[2] = disk->capacity / (255 * 63); } else { ip[0] = info[0]; ip[1] = info[1]; ip[2] = info[2]; if (info[0] == 255) printk ("wd7000_biosparam: current partition table is using extended translation.\n"); } }#ifdef WD7000_DEBUG printk ("bios geometry: head=%d, sec=%d, cyl=%d\n", ip[0], ip[1], ip[2]); printk ("WARNING: check, if the bios geometry is correct.\n");#endif return (0);}#ifdef MODULE/* Eventually this will go into an include file, but this will be later */Scsi_Host_Template driver_template = WD7000;#include "scsi_module.c"#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -