📄 wd7000.c
字号:
return (0); } if (WAIT (host->iobase + ASC_STAT, ASC_STATMASK, ASC_INIT, 0)) { printk ("%s: WAIT timed out.\n", __FUNCTION__); return (0); } if (request_irq (host->irq, do_wd7000_intr_handle, SA_INTERRUPT, "wd7000", NULL)) { printk ("%s: can't get IRQ %d.\n", __FUNCTION__, host->irq); return (0); } if (request_dma (host->dma, "wd7000")) { printk ("%s: can't get DMA channel %d.\n", __FUNCTION__, host->dma); free_irq (host->irq, NULL); return (0); } wd7000_enable_dma (host); wd7000_enable_intr (host); if (! wd7000_diagnostics (host, ICB_DIAG_FULL)) { free_dma (host->dma); free_irq (host->irq, NULL); return (0); } return (1);}void wd7000_revision (Adapter *host){ static IcbRevLvl icb = { ICB_OP_GET_REVISION }; /* * 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. */ icb.phase = 1; mail_out (host, (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){ ulong 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; ulong 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. */#if (LINUX_VERSION_CODE >= 0x020100) scd = host->host_queue;#else scd = scsi_devices;#endif 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]; uint iobase; Adapter *host = NULL; struct Scsi_Host *sh;#ifdef WD7000_DEBUG printk ("%s: started\n", __FUNCTION__);#endif /* * Set up SCB free list, which is shared by all adapters */ scbs_init (); 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; for (pass = 0; pass < NUM_CONFIGS; pass++) { short bios_match = 1;#ifdef WD7000_DEBUG printk ("%s: pass %d\n", __FUNCTION__, pass + 1);#endif /* * First, search for BIOS SIGNATURE... */ for (biosaddr_ptr = 0; bios_match && (biosaddr_ptr < NUM_ADDRS); biosaddr_ptr++) for (sig_ptr = 0; bios_match && (sig_ptr < NUM_SIGNATURES); sig_ptr++) { for (i = 0; i < pass; i++) if (biosptr[i] == biosaddr_ptr) break; if (i == pass) {#if (LINUX_VERSION_CODE >= 0x020100) char *biosaddr = (char *) ioremap (wd7000_biosaddr[biosaddr_ptr] + signatures[sig_ptr].ofs, signatures[sig_ptr].len);#else char *biosaddr = (char *) (wd7000_biosaddr[biosaddr_ptr] + signatures[sig_ptr].ofs);#endif bios_match = memcmp (biosaddr, signatures[sig_ptr].sig, signatures[sig_ptr].len);#if (LINUX_VERSION_CODE >= 0x020100) iounmap (biosaddr);#else#endif if (! bios_match) { /* * BIOS SIGNATURE has been found. */ biosptr[pass] = biosaddr_ptr;#ifdef WD7000_DEBUG printk ("WD-7000 SST BIOS detected at 0x%lx: checking...\n", wd7000_biosaddr[biosaddr_ptr]);#endif } } }#ifdef WD7000_DEBUG if (bios_match) printk ("WD-7000 SST BIOS not detected...\n");#endif if (configs[pass].irq < 0) continue; iobase = configs[pass].iobase;#ifdef WD7000_DEBUG printk ("%s: check IO 0x%x region...\n", __FUNCTION__, iobase);#endif if (! check_region (iobase, 4)) {#ifdef WD7000_DEBUG printk ("%s: ASC reset (IO 0x%x) ...", __FUNCTION__, 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 ("%s: adapter allocated at 0x%x\n", __FUNCTION__, (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 ("%s: Trying to init WD-7000 card at IO 0x%x, IRQ %d, DMA %d...\n", __FUNCTION__, 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 */ 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 ("%s: IO 0x%x region is already allocated!\n", __FUNCTION__, 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 ("%s: lost interrupt\n", __FUNCTION__); 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, uint flags){ 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 ("%s: dev=%s, size=%d, ", __FUNCTION__, 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 ("%s: unable to verify geometry for disk with >1GB.\n" " using extended translation.\n", __FUNCTION__); 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 ("%s: current partition table is using extended translation.\n", __FUNCTION__); } }#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 + -