📄 psi240i.c
字号:
}irqerror:; DEB(printk ("\npsi240i error Device Status: %X\n", status)); SCpnt->result = DecodeError (shost, status); SCpnt->scsi_done (SCpnt); }static void do_Irq_Handler (int irq, void *dev_id, struct pt_regs *regs) { unsigned long flags; spin_lock_irqsave(&io_request_lock, flags); Irq_Handler(irq, dev_id, regs); spin_unlock_irqrestore(&io_request_lock, flags); }/**************************************************************** * Name: Psi240i_QueueCommand * * Description: Process a queued command from the SCSI manager. * * Parameters: SCpnt - Pointer to SCSI command structure. * done - Pointer to done function to call. * * Returns: Status code. * ****************************************************************/int Psi240i_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { UCHAR *cdb = (UCHAR *)SCpnt->cmnd; // Pointer to SCSI CDB PADAPTER240I padapter = HOSTDATA(SCpnt->host); // Pointer to adapter control structure POUR_DEVICE pdev = &padapter->device[SCpnt->target];// Pointer to device information UCHAR rc; // command return code SCpnt->scsi_done = done; padapter->ide.ide.ides.spigot = pdev->spigot; padapter->buffer = SCpnt->request_buffer; if (done) { if ( !pdev->device ) { SCpnt->result = DID_BAD_TARGET << 16; done (SCpnt); return 0; } } else { printk("psi240i_queuecommand: %02X: done can't be NULL\n", *cdb); return 0; } switch ( *cdb ) { case SCSIOP_INQUIRY: // inquiry CDB { padapter->ide.ide.ide[6] = pdev->byte6; padapter->ide.ide.ides.cmd = IDE_COMMAND_IDENTIFY; break; } case SCSIOP_TEST_UNIT_READY: // test unit ready CDB SCpnt->result = DID_OK << 16; done (SCpnt); return 0; case SCSIOP_READ_CAPACITY: // read capctiy CDB { PREAD_CAPACITY_DATA pdata = (PREAD_CAPACITY_DATA)SCpnt->request_buffer; pdata->blksiz = 0x20000; XANY2SCSI ((UCHAR *)&pdata->blks, pdev->blocks); SCpnt->result = DID_OK << 16; done (SCpnt); return 0; } case SCSIOP_VERIFY: // verify CDB *(ULONG *)padapter->ide.ide.ides.lba = XSCSI2LONG (&cdb[2]); padapter->ide.ide.ide[6] |= pdev->byte6; padapter->ide.ide.ide[2] = (UCHAR)((USHORT)cdb[8] | ((USHORT)cdb[7] << 8)); padapter->ide.ide.ides.cmd = IDE_COMMAND_VERIFY; break; case SCSIOP_READ: // read10 CDB padapter->startSector = XSCSI2LONG (&cdb[2]); padapter->sectorCount = (USHORT)cdb[8] | ((USHORT)cdb[7] << 8); SetupTransfer (padapter, pdev->byte6); padapter->ide.ide.ides.cmd = IDE_CMD_READ_MULTIPLE; break; case SCSIOP_READ6: // read6 CDB padapter->startSector = SCSI2LONG (&cdb[1]); padapter->sectorCount = cdb[4]; SetupTransfer (padapter, pdev->byte6); padapter->ide.ide.ides.cmd = IDE_CMD_READ_MULTIPLE; break; case SCSIOP_WRITE: // write10 CDB padapter->startSector = XSCSI2LONG (&cdb[2]); padapter->sectorCount = (USHORT)cdb[8] | ((USHORT)cdb[7] << 8); SetupTransfer (padapter, pdev->byte6); padapter->ide.ide.ides.cmd = IDE_CMD_WRITE_MULTIPLE; break; case SCSIOP_WRITE6: // write6 CDB padapter->startSector = SCSI2LONG (&cdb[1]); padapter->sectorCount = cdb[4]; SetupTransfer (padapter, pdev->byte6); padapter->ide.ide.ides.cmd = IDE_CMD_WRITE_MULTIPLE; break; default: DEB (printk ("psi240i_queuecommand: Unsupported command %02X\n", *cdb)); SCpnt->result = DID_ERROR << 16; done (SCpnt); return 0; } padapter->SCpnt = SCpnt; // Save this command data rc = IdeCmd (padapter); if ( rc ) { padapter->expectingIRQ = 0; DEB (printk ("psi240i_queuecommand: %02X, %02X: Device failed to respond for command\n", *cdb, padapter->ide.ide.ides.cmd)); SCpnt->result = DID_ERROR << 16; done (SCpnt); return 0; } DEB (printk("psi240i_queuecommand: %02X, %02X now waiting for interrupt ", *cdb, padapter->ide.ide.ides.cmd)); return 0; }static void internal_done(Scsi_Cmnd * SCpnt) { SCpnt->SCp.Status++; }/**************************************************************** * Name: Psi240i_Command * * Description: Process a command from the SCSI manager. * * Parameters: SCpnt - Pointer to SCSI command structure. * * Returns: Status code. * ****************************************************************/int Psi240i_Command (Scsi_Cmnd *SCpnt) { DEB(printk("psi240i_command: ..calling psi240i_queuecommand\n")); Psi240i_QueueCommand (SCpnt, internal_done); SCpnt->SCp.Status = 0; while (!SCpnt->SCp.Status) barrier (); return SCpnt->result; }/*************************************************************************** * Name: ReadChipMemory * * Description: Read information from controller memory. * * Parameters: psetup - Pointer to memory image of setup information. * base - base address of memory. * length - lenght of data space in bytes. * port - I/O address of data port. * * Returns: Nothing. * **************************************************************************/void ReadChipMemory (void *pdata, USHORT base, USHORT length, USHORT port) { USHORT z, zz; UCHAR *pd = (UCHAR *)pdata; outb_p (SEL_NONE, port + REG_SEL_FAIL); // setup data port zz = 0; while ( zz < length ) { outw_p (base, port + REG_ADDRESS); // setup address for ( z = 0; z < 8; z++ ) { if ( (zz + z) < length ) *pd++ = inb_p (port + z); // read data byte } zz += 8; base += 8; } }/**************************************************************** * Name: Psi240i_Detect * * Description: Detect and initialize our boards. * * Parameters: tpnt - Pointer to SCSI host template structure. * * Returns: Number of adapters found. * ****************************************************************/int Psi240i_Detect (Scsi_Host_Template *tpnt) { int board; int count = 0; int unit; int z; USHORT port; CHIP_CONFIG_N chipConfig; CHIP_DEVICE_N chipDevice[8]; struct Scsi_Host *pshost; ULONG flags; for ( board = 0; board < 6; board++ ) // scan for I/O ports { port = portAddr[board]; // get base address to test if ( check_region (port, 16) ) // test for I/O addresses available continue; // nope if ( inb_p (port + REG_FAIL) != CHIP_ID ) // do the first test for likley hood that it is us continue; outb_p (SEL_NONE, port + REG_SEL_FAIL); // setup EEPROM/RAM access outw (0, port + REG_ADDRESS); // setup EEPROM address zero if ( inb_p (port) != 0x55 ) // test 1st byte continue; // nope if ( inb_p (port + 1) != 0xAA ) // test 2nd byte continue; // nope // at this point our board is found and can be accessed. Now we need to initialize // our informatation and register with the kernel. ReadChipMemory (&chipConfig, CHIP_CONFIG, sizeof (chipConfig), port); ReadChipMemory (&chipDevice, CHIP_DEVICE, sizeof (chipDevice), port); ReadChipMemory (&ChipSetup, CHIP_EEPROM_DATA, sizeof (ChipSetup), port); if ( !chipConfig.numDrives ) // if no devices on this board continue; pshost = scsi_register (tpnt, sizeof(ADAPTER240I)); if(pshost == NULL) continue; save_flags (flags); cli (); if ( request_irq (chipConfig.irq, do_Irq_Handler, 0, "psi240i", NULL) ) { printk ("Unable to allocate IRQ for PSI-240I controller.\n"); restore_flags (flags); goto unregister; } PsiHost[chipConfig.irq - 10] = pshost; pshost->unique_id = port; pshost->io_port = port; pshost->n_io_port = 16; /* Number of bytes of I/O space used */ pshost->irq = chipConfig.irq; for ( z = 0; z < 11; z++ ) // build regester address array HOSTDATA(pshost)->ports[z] = port + z; HOSTDATA(pshost)->ports[11] = port + REG_FAIL; HOSTDATA(pshost)->ports[12] = port + REG_ALT_STAT; DEB (printk ("\nPorts =")); DEB (for (z=0;z<13;z++) printk(" %#04X",HOSTDATA(pshost)->ports[z]);); for ( z = 0; z < chipConfig.numDrives; ++z ) { unit = chipDevice[z].channel & 0x0F; HOSTDATA(pshost)->device[unit].device = ChipSetup.setupDevice[unit].device; HOSTDATA(pshost)->device[unit].byte6 = (UCHAR)(((unit & 1) << 4) | 0xE0); HOSTDATA(pshost)->device[unit].spigot = (UCHAR)(1 << (unit >> 1)); HOSTDATA(pshost)->device[unit].sectors = ChipSetup.setupDevice[unit].sectors; HOSTDATA(pshost)->device[unit].heads = ChipSetup.setupDevice[unit].heads; HOSTDATA(pshost)->device[unit].cylinders = ChipSetup.setupDevice[unit].cylinders; HOSTDATA(pshost)->device[unit].blocks = ChipSetup.setupDevice[unit].blocks; DEB (printk ("\nHOSTDATA->device = %X", HOSTDATA(pshost)->device[unit].device)); DEB (printk ("\n byte6 = %X", HOSTDATA(pshost)->device[unit].byte6)); DEB (printk ("\n spigot = %X", HOSTDATA(pshost)->device[unit].spigot)); DEB (printk ("\n sectors = %X", HOSTDATA(pshost)->device[unit].sectors)); DEB (printk ("\n heads = %X", HOSTDATA(pshost)->device[unit].heads)); DEB (printk ("\n cylinders = %X", HOSTDATA(pshost)->device[unit].cylinders)); DEB (printk ("\n blocks = %lX", HOSTDATA(pshost)->device[unit].blocks)); } restore_flags (flags); printk("\nPSI-240I EIDE CONTROLLER: at I/O = %x IRQ = %d\n", port, chipConfig.irq); printk("(C) 1997 Perceptive Solutions, Inc. All rights reserved\n\n"); count++; continue;unregister:; scsi_unregister (pshost); } return count; }/**************************************************************** * Name: Psi240i_Abort * * Description: Process the Abort command from the SCSI manager. * * Parameters: SCpnt - Pointer to SCSI command structure. * * Returns: Allways snooze. * ****************************************************************/int Psi240i_Abort (Scsi_Cmnd *SCpnt) { DEB (printk ("psi240i_abort\n")); return SCSI_ABORT_SNOOZE; }/**************************************************************** * Name: Psi240i_Reset * * Description: Process the Reset command from the SCSI manager. * * Parameters: SCpnt - Pointer to SCSI command structure. * flags - Flags about the reset command * * Returns: No active command at this time, so this means * that each time we got some kind of response the * last time through. Tell the mid-level code to * request sense information in order to decide what * to do next. * ****************************************************************/int Psi240i_Reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags) { return SCSI_RESET_PUNT; }#include "sd.h"/**************************************************************** * Name: Psi240i_BiosParam * * Description: Process the biosparam request from the SCSI manager to * return C/H/S data. * * Parameters: disk - Pointer to SCSI disk structure. * dev - Major/minor number from kernel. * geom - Pointer to integer array to place geometry data. * * Returns: zero. * ****************************************************************/int Psi240i_BiosParam (Scsi_Disk *disk, kdev_t dev, int geom[]) { POUR_DEVICE pdev; pdev = &(HOSTDATA(disk->device->host)->device[disk->device->id]); geom[0] = pdev->heads; geom[1] = pdev->sectors; geom[2] = pdev->cylinders; return 0; }/* Eventually this will go into an include file, but this will be later */static Scsi_Host_Template driver_template = PSI240I;#include "scsi_module.c"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -