⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wd7000.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
    }    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 + -