📄 fdomain.c
字号:
iobase) This function gets the Interrupt Level and I/O base address from the PCI configuration registers. */#ifdef CONFIG_PCIstatic int fdomain_pci_bios_detect( int *irq, int *iobase, struct pci_dev **ret_pdev ){ unsigned int pci_irq; /* PCI interrupt line */ unsigned long pci_base; /* PCI I/O base address */ struct pci_dev *pdev = NULL; if (!pci_present()) return 0;#if DEBUG_DETECT /* Tell how to print a list of the known PCI devices from bios32 and list vendor and device IDs being used if in debug mode. */ printk( "scsi: <fdomain> INFO: use lspci -v to see list of PCI devices\n" ); printk( "scsi: <fdomain> TMC-3260 detect:" " Using Vendor ID: 0x%x and Device ID: 0x%x\n", PCI_VENDOR_ID_FD, PCI_DEVICE_ID_FD_36C70 );#endif if ((pdev = pci_find_device(PCI_VENDOR_ID_FD, PCI_DEVICE_ID_FD_36C70, pdev)) == NULL) return 0; if (pci_enable_device(pdev)) return 0; #if DEBUG_DETECT printk( "scsi: <fdomain> TMC-3260 detect:" " PCI bus %u, device %u, function %u\n", pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));#endif /* We now have the appropriate device function for the FD board so we just read the PCI config info from the registers. */ pci_base = pci_resource_start(pdev, 0); pci_irq = pdev->irq; /* Now we have the I/O base address and interrupt from the PCI configuration registers. */ *irq = pci_irq; *iobase = pci_base; *ret_pdev = pdev;#if DEBUG_DETECT printk( "scsi: <fdomain> TMC-3260 detect:" " IRQ = %d, I/O base = 0x%x [0x%lx]\n", *irq, *iobase, pci_base );#endif if (!fdomain_is_valid_port( *iobase )) { printk( "scsi: <fdomain>" " PCI card detected, but driver not loaded (invalid port)\n" ); return 0; } /* Fill in a few global variables. Ugh. */ bios_major = bios_minor = -1; PCI_bus = 1; Quantum = 0; bios_base = 0; return 1;}#endifint fdomain_16x0_detect( Scsi_Host_Template *tpnt ){ int retcode; struct Scsi_Host *shpnt; struct pci_dev *pdev = NULL;#if DO_DETECT int i = 0; int j = 0; const int buflen = 255; Scsi_Cmnd SCinit; unsigned char do_inquiry[] = { INQUIRY, 0, 0, 0, buflen, 0 }; unsigned char do_request_sense[] = { REQUEST_SENSE, 0, 0, 0, buflen, 0 }; unsigned char do_read_capacity[] = { READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; unsigned char buf[buflen];#endif tpnt->proc_name = "fdomain";#ifdef MODULE if (fdomain) fdomain_setup(fdomain);#endif if (setup_called) {#if DEBUG_DETECT printk( "scsi: <fdomain> No BIOS, using port_base = 0x%x, irq = %d\n", port_base, interrupt_level );#endif if (!fdomain_is_valid_port( port_base )) { printk( "scsi: <fdomain> Cannot locate chip at port base 0x%x\n", port_base ); printk( "scsi: <fdomain> Bad LILO/INSMOD parameters?\n" ); return 0; } } else { int flag = 0;#ifdef CONFIG_PCI /* Try PCI detection first */ flag = fdomain_pci_bios_detect( &interrupt_level, &port_base, &pdev );#endif if (!flag) { /* Then try ISA bus detection */ flag = fdomain_isa_detect( &interrupt_level, &port_base ); if (!flag) { printk( "scsi: <fdomain> Detection failed (no card)\n" ); return 0; } } } SCSI_Mode_Cntl_port = port_base + SCSI_Mode_Cntl; FIFO_Data_Count_port = port_base + FIFO_Data_Count; Interrupt_Cntl_port = port_base + Interrupt_Cntl; Interrupt_Status_port = port_base + Interrupt_Status; Read_FIFO_port = port_base + Read_FIFO; Read_SCSI_Data_port = port_base + Read_SCSI_Data; SCSI_Cntl_port = port_base + SCSI_Cntl; SCSI_Data_NoACK_port = port_base + SCSI_Data_NoACK; SCSI_Status_port = port_base + SCSI_Status; TMC_Cntl_port = port_base + TMC_Cntl; TMC_Status_port = port_base + TMC_Status; Write_FIFO_port = port_base + Write_FIFO; Write_SCSI_Data_port = port_base + Write_SCSI_Data; fdomain_16x0_reset( NULL, 0 ); if (fdomain_test_loopback()) { printk( "scsi: <fdomain> Detection failed" " (loopback test failed at port base 0x%x)\n", port_base ); if (setup_called) { printk( "scsi: <fdomain> Bad LILO/INSMOD parameters?\n" ); } return 0; } if (this_id) { tpnt->this_id = (this_id & 0x07); adapter_mask = (1 << tpnt->this_id); } else { if (PCI_bus || (bios_major == 3 && bios_minor >= 2) || bios_major < 0) { tpnt->this_id = 7; adapter_mask = 0x80; } else { tpnt->this_id = 6; adapter_mask = 0x40; } } /* Print out a banner here in case we can't get resources. */ shpnt = scsi_register( tpnt, 0 ); if(shpnt == NULL) return 0; shpnt->irq = interrupt_level; shpnt->io_port = port_base; scsi_set_pci_device(shpnt, pdev); shpnt->n_io_port = 0x10; print_banner( shpnt ); /* Log IRQ with kernel */ if (!interrupt_level) { printk( "scsi: <fdomain>" " Card Detected, but driver not loaded (no IRQ)\n" ); return 0; } else { /* Register the IRQ with the kernel */ retcode = request_irq( interrupt_level, do_fdomain_16x0_intr, pdev?SA_SHIRQ:0, "fdomain", shpnt); if (retcode < 0) { if (retcode == -EINVAL) { printk( "scsi: <fdomain> IRQ %d is bad!\n", interrupt_level ); printk( " This shouldn't happen!\n" ); printk( " Send mail to faith@acm.org\n" ); } else if (retcode == -EBUSY) { printk( "scsi: <fdomain> IRQ %d is already in use!\n", interrupt_level ); printk( " Please use another IRQ!\n" ); } else { printk( "scsi: <fdomain> Error getting IRQ %d\n", interrupt_level ); printk( " This shouldn't happen!\n" ); printk( " Send mail to faith@acm.org\n" ); } printk( "scsi: <fdomain> Detected, but driver not loaded (IRQ)\n" ); return 0; } } /* Log I/O ports with kernel */ request_region( port_base, 0x10, "fdomain" );#if DO_DETECT /* These routines are here because of the way the SCSI bus behaves after a reset. This appropriate behavior was not handled correctly by the higher level SCSI routines when I first wrote this driver. Now, however, correct scan routines are part of scsi.c and these routines are no longer needed. However, this code is still good for debugging. */ SCinit.request_buffer = SCinit.buffer = buf; SCinit.request_bufflen = SCinit.bufflen = sizeof(buf)-1; SCinit.use_sg = 0; SCinit.lun = 0; printk( "scsi: <fdomain> detection routine scanning for devices:\n" ); for (i = 0; i < 8; i++) { SCinit.target = i; if (i == tpnt->this_id) /* Skip host adapter */ continue; memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense)); retcode = fdomain_16x0_command(&SCinit); if (!retcode) { memcpy(SCinit.cmnd, do_inquiry, sizeof(do_inquiry)); retcode = fdomain_16x0_command(&SCinit); if (!retcode) { printk( " SCSI ID %d: ", i ); for (j = 8; j < (buf[4] < 32 ? buf[4] : 32); j++) printk( "%c", buf[j] >= 20 ? buf[j] : ' ' ); memcpy(SCinit.cmnd, do_read_capacity, sizeof(do_read_capacity)); retcode = fdomain_16x0_command(&SCinit); if (!retcode) { unsigned long blocks, size, capacity; blocks = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; size = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7]; capacity = +( +(blocks / 1024L) * +(size * 10L)) / 1024L; printk( "%lu MB (%lu byte blocks)", ((capacity + 5L) / 10L), size ); } else { memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense)); retcode = fdomain_16x0_command(&SCinit); } printk ("\n" ); } else { memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense)); retcode = fdomain_16x0_command(&SCinit); } } }#endif return 1; /* Maximum of one adapter will be detected. */}const char *fdomain_16x0_info( struct Scsi_Host *ignore ){ static char buffer[128]; char *pt; strcpy( buffer, "Future Domain 16-bit SCSI Driver Version" ); if (strchr( VERSION, ':')) { /* Assume VERSION is an RCS Revision string */ strcat( buffer, strchr( VERSION, ':' ) + 1 ); pt = strrchr( buffer, '$') - 1; if (!pt) /* Stripped RCS Revision string? */ pt = buffer + strlen( buffer ) - 1; if (*pt != ' ') ++pt; *pt = '\0'; } else { /* Assume VERSION is a number */ strcat( buffer, " " VERSION ); } return buffer;} /* First pass at /proc information routine. *//* * inout : decides on the direction of the dataflow and the meaning of the * variables * buffer: If inout==FALSE data is being written to it else read from it * *start: If inout==FALSE start of the valid data in the buffer * offset: If inout==FALSE offset from the beginning of the imaginary file * from which we start writing into the buffer * length: If inout==FALSE max number of bytes to be written into the buffer * else number of bytes in the buffer */int fdomain_16x0_proc_info( char *buffer, char **start, off_t offset, int length, int hostno, int inout ){ const char *info = fdomain_16x0_info( NULL ); int len; int pos; int begin; if (inout) return(-ENOSYS); begin = 0; strcpy( buffer, info ); strcat( buffer, "\n" ); pos = len = strlen( buffer ); if(pos < offset) { len = 0; begin = pos; } *start = buffer + (offset - begin); /* Start of wanted data */ len -= (offset - begin); if(len > length) len = length; return(len);} #if 0static int fdomain_arbitrate( void ){ int status = 0; unsigned long timeout;#if EVERY_ACCESS printk( "fdomain_arbitrate()\n" );#endif outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */ outb( adapter_mask, port_base + SCSI_Data_NoACK ); /* Set our id bit */ outb( 0x04 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */ timeout = 500; do { status = inb( TMC_Status_port ); /* Read adapter status */ if (status & 0x02) /* Arbitration complete */ return 0; mdelay(1); /* Wait one millisecond */ } while (--timeout); /* Make bus idle */ fdomain_make_bus_idle();#if EVERY_ACCESS printk( "Arbitration failed, status = %x\n", status );#endif#if ERRORS_ONLY printk( "scsi: <fdomain> Arbitration failed, status = %x\n", status );#endif return 1;}#endifstatic int fdomain_select( int target ){ int status; unsigned long timeout; static int flag = 0; outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */ outb( adapter_mask | (1 << target), SCSI_Data_NoACK_port ); /* Stop arbitration and enable parity */ outb( PARITY_MASK, TMC_Cntl_port ); timeout = 350; /* 350 msec */ do { status = inb( SCSI_Status_port ); /* Read adapter status */ if (status & 1) { /* Busy asserted */ /* Enable SCSI Bus (on error, should make bus idle with 0) */ outb( 0x80, SCSI_Cntl_port ); return 0; } mdelay(1); /* wait one msec */ } while (--timeout); /* Make bus idle */ fdomain_make_bus_idle();#if EVERY_ACCESS if (!target) printk( "Selection failed\n" );#endif#if ERRORS_ONLY if (!target) { if (!flag) /* Skip first failure for all chips. */ ++flag; else printk( "scsi: <fdomain> Selection failed\n" ); }#endif return 1;}void my_done( int error ){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -