📄 pci2220i.c
字号:
udelay (125); if ( AtapiWaitReady (padapter, 1000) ) return TRUE; if ( inb_p (padapter->regStatCmd) || (inb_p (padapter->regLba8) != 0x14) || (inb_p (padapter->regLba16) != 0xEB) ) return TRUE; return FALSE; }/**************************************************************** * Name: WalkScatGath :LOCAL * * Description: Transfer data to/from scatter/gather buffers. * * Parameters: padapter - Pointer adapter data structure. * datain - TRUE if data read. * length - Number of bytes to transfer. * * Returns: Nothing. * ****************************************************************/static void WalkScatGath (PADAPTER2220I padapter, UCHAR datain, ULONG length) { ULONG count; UCHAR *buffer = padapter->kBuffer; while ( length ) { count = ( length > padapter->currentSgCount ) ? padapter->currentSgCount : length; if ( datain ) memcpy (padapter->currentSgBuffer, buffer, count); else memcpy (buffer, padapter->currentSgBuffer, count); padapter->currentSgCount -= count; if ( !padapter->currentSgCount ) { if ( padapter->nextSg < padapter->SCpnt->use_sg ) { padapter->currentSgBuffer = ((struct scatterlist *)padapter->SCpnt->request_buffer)[padapter->nextSg].address; padapter->currentSgCount = ((struct scatterlist *)padapter->SCpnt->request_buffer)[padapter->nextSg].length; padapter->nextSg++; } } else padapter->currentSgBuffer += count; length -= count; buffer += count; } }/**************************************************************** * Name: BusMaster :LOCAL * * Description: Do a bus master I/O. * * Parameters: padapter - Pointer adapter data structure. * datain - TRUE if data read. * irq - TRUE if bus master interrupt expected. * * Returns: Nothing. * ****************************************************************/static void BusMaster (PADAPTER2220I padapter, UCHAR datain, UCHAR irq) { ULONG zl; zl = ( padapter->sectorCount > MAX_BUS_MASTER_BLOCKS ) ? MAX_BUS_MASTER_BLOCKS : padapter->sectorCount; padapter->sectorCount -= zl; zl *= (ULONG)BYTES_PER_SECTOR; if ( datain ) { padapter->readCount = zl; outb_p (8, padapter->regDmaDesc); // read operation if ( padapter->bigD ) { if ( irq && !padapter->sectorCount ) outb_p (0x0C, padapter->regDmaMode); // interrupt on else outb_p (0x08, padapter->regDmaMode); // no interrupt } else { if ( irq && !padapter->sectorCount ) outb_p (0x05, padapter->regDmaMode); // interrupt on else outb_p (0x01, padapter->regDmaMode); // no interrupt } } else { outb_p (0x00, padapter->regDmaDesc); // write operation if ( padapter->bigD ) outb_p (0x08, padapter->regDmaMode); // no interrupt else outb_p (0x01, padapter->regDmaMode); // no interrupt WalkScatGath (padapter, FALSE, zl); } outl (padapter->timingAddress, padapter->regDmaAddrLoc); outl (padapter->kBufferDma, padapter->regDmaAddrPci); outl (zl, padapter->regDmaCount); outb_p (0x03, padapter->regDmaCmdStat); // kick the DMA engine in gear }/**************************************************************** * Name: AtapiBusMaster :LOCAL * * Description: Do a bus master I/O. * * Parameters: padapter - Pointer adapter data structure. * datain - TRUE if data read. * length - Number of bytes to transfer. * * Returns: Nothing. * ****************************************************************/static void AtapiBusMaster (PADAPTER2220I padapter, UCHAR datain, ULONG length) { outl (padapter->timingAddress, padapter->regDmaAddrLoc); outl (padapter->kBufferDma, padapter->regDmaAddrPci); outl (length, padapter->regDmaCount); if ( datain ) { if ( padapter->readCount ) WalkScatGath (padapter, TRUE, padapter->readCount); outb_p (0x08, padapter->regDmaDesc); // read operation outb_p (0x08, padapter->regDmaMode); // no interrupt padapter->readCount = length; } else { outb_p (0x00, padapter->regDmaDesc); // write operation outb_p (0x08, padapter->regDmaMode); // no interrupt if ( !padapter->atapiSpecial ) WalkScatGath (padapter, FALSE, length); } outb_p (0x03, padapter->regDmaCmdStat); // kick the DMA engine in gear }/**************************************************************** * Name: WriteData :LOCAL * * Description: Write data to device. * * Parameters: padapter - Pointer adapter data structure. * * Returns: TRUE if drive does not assert DRQ in time. * ****************************************************************/static int WriteData (PADAPTER2220I padapter) { ULONG zl; if ( !WaitDrq (padapter) ) { if ( padapter->timingPIO ) { zl = (padapter->sectorCount > MAX_BUS_MASTER_BLOCKS) ? MAX_BUS_MASTER_BLOCKS : padapter->sectorCount; WalkScatGath (padapter, FALSE, zl * BYTES_PER_SECTOR); outsw (padapter->regData, padapter->kBuffer, zl * (BYTES_PER_SECTOR / 2)); padapter->sectorCount -= zl; } else BusMaster (padapter, 0, 0); return 0; } padapter->cmd = 0; // null out the command byte return 1; }/**************************************************************** * Name: WriteDataBoth :LOCAL * * Description: Write data to device. * * Parameters: padapter - Pointer to adapter structure. * pdev - Pointer to device structure * * Returns: Index + 1 of drive not failed or zero for OK. * ****************************************************************/static int WriteDataBoth (PADAPTER2220I padapter, POUR_DEVICE pdev) { ULONG zl; UCHAR status0, status1; SelectSpigot (padapter, pdev->spigots[0]); status0 = WaitDrq (padapter); if ( !status0 ) { SelectSpigot (padapter, pdev->spigots[1]); status1 = WaitDrq (padapter); if ( !status1 ) { SelectSpigot (padapter, pdev->spigots[0] | pdev->spigots[1] | padapter->bigD); if ( padapter->timingPIO ) { zl = (padapter->sectorCount > MAX_BUS_MASTER_BLOCKS) ? MAX_BUS_MASTER_BLOCKS : padapter->sectorCount; WalkScatGath (padapter, FALSE, zl * BYTES_PER_SECTOR); outsw (padapter->regData, padapter->kBuffer, zl * (BYTES_PER_SECTOR / 2)); padapter->sectorCount -= zl; } else BusMaster (padapter, 0, 0); return 0; } } padapter->cmd = 0; // null out the command byte if ( status0 ) return 2; return 1; }/**************************************************************** * Name: IdeCmd :LOCAL * * Description: Process an IDE command. * * Parameters: padapter - Pointer adapter data structure. * pdev - Pointer to device. * * Returns: Zero if no error or status register contents on error. * ****************************************************************/static UCHAR IdeCmd (PADAPTER2220I padapter, POUR_DEVICE pdev) { UCHAR status; SelectSpigot (padapter, pdev->spigot | padapter->bigD); // select the spigot outb_p (pdev->byte6 | ((UCHAR *)(&padapter->startSector))[3], padapter->regLba24); // select the drive status = WaitReady (padapter); if ( !status ) { outb_p (padapter->sectorCount, padapter->regSectCount); outb_p (((UCHAR *)(&padapter->startSector))[0], padapter->regLba0); outb_p (((UCHAR *)(&padapter->startSector))[1], padapter->regLba8); outb_p (((UCHAR *)(&padapter->startSector))[2], padapter->regLba16); padapter->expectingIRQ = TRUE; WriteCommand (padapter, padapter->cmd); return 0; } padapter->cmd = 0; // null out the command byte return status; }/**************************************************************** * Name: IdeCmdBoth :LOCAL * * Description: Process an IDE command to both drivers. * * Parameters: padapter - Pointer adapter data structure. * pdev - Pointer to device structure * * Returns: Index + 1 of drive not failed or zero for OK. * ****************************************************************/static UCHAR IdeCmdBoth (PADAPTER2220I padapter, POUR_DEVICE pdev) { UCHAR status0; UCHAR status1; SelectSpigot (padapter, pdev->spigots[0] | pdev->spigots[1]); // select the spigots outb_p (padapter->pdev->byte6 | ((UCHAR *)(&padapter->startSector))[3], padapter->regLba24);// select the drive SelectSpigot (padapter, pdev->spigots[0]); status0 = WaitReady (padapter); if ( !status0 ) { SelectSpigot (padapter, pdev->spigots[1]); status1 = WaitReady (padapter); if ( !status1 ) { SelectSpigot (padapter, pdev->spigots[0] | pdev->spigots[1] | padapter->bigD); outb_p (padapter->sectorCount, padapter->regSectCount); outb_p (((UCHAR *)(&padapter->startSector))[0], padapter->regLba0); outb_p (((UCHAR *)(&padapter->startSector))[1], padapter->regLba8); outb_p (((UCHAR *)(&padapter->startSector))[2], padapter->regLba16); padapter->expectingIRQ = TRUE; WriteCommand (padapter, padapter->cmd); return 0; } } padapter->cmd = 0; // null out the command byte if ( status0 ) return 2; return 1; }/**************************************************************** * Name: OpDone :LOCAL * * Description: Complete an operatoin done sequence. * * Parameters: padapter - Pointer to host data block. * spigot - Spigot select code. * device - Device byte code. * * Returns: Nothing. * ****************************************************************/static void OpDone (PADAPTER2220I padapter, ULONG result) { Scsi_Cmnd *SCpnt = padapter->SCpnt; if ( padapter->reconPhase ) { padapter->reconPhase = 0; if ( padapter->SCpnt ) { Pci2220i_QueueCommand (SCpnt, SCpnt->scsi_done); } else { if ( padapter->reconOn ) { ReconTimerExpiry ((unsigned long)padapter); } } } else { padapter->cmd = 0; padapter->SCpnt = NULL; padapter->pdev = NULL; SCpnt->result = result; SCpnt->scsi_done (SCpnt); if ( padapter->reconOn && !padapter->reconTimer.data ) { padapter->reconTimer.expires = jiffies + (HZ / 4); // start in 1/4 second padapter->reconTimer.data = (unsigned long)padapter; add_timer (&padapter->reconTimer); } } }/**************************************************************** * Name: InlineIdentify :LOCAL * * Description: Do an intline inquiry on a drive. * * Parameters: padapter - Pointer to host data block. * spigot - Spigot select code. * device - Device byte code. * * Returns: Last addressable sector or zero if none. * ****************************************************************/static ULONG InlineIdentify (PADAPTER2220I padapter, UCHAR spigot, UCHAR device) { PIDENTIFY_DATA pid = (PIDENTIFY_DATA)padapter->kBuffer; SelectSpigot (padapter, spigot | SEL_IRQ_OFF); // select the spigot outb_p ((device << 4) | 0xA0, padapter->regLba24); // select the drive if ( WaitReady (padapter) ) return 0; WriteCommand (padapter, IDE_COMMAND_IDENTIFY); if ( WaitDrq (padapter) ) return 0; insw (padapter->regData, padapter->kBuffer, sizeof (IDENTIFY_DATA) >> 1); return (pid->LBATotalSectors - 1); }/**************************************************************** * Name: AtapiIdentify :LOCAL * * Description: Do an intline inquiry on a drive. * * Parameters: padapter - Pointer to host data block. * pdev - Pointer to device table. * * Returns: TRUE on error. * ****************************************************************/static ULONG AtapiIdentify (PADAPTER2220I padapter, POUR_DEVICE pdev) { ATAPI_GENERAL_0 ag0; USHORT zs; int z; AtapiDevice (padapter, pdev->byte6); WriteCommand (padapter, IDE_COMMAND_ATAPI_IDENTIFY); if ( AtapiWaitDrq (padapter, 3000) ) return TRUE; *(USHORT *)&ag0 = inw_p (padapter->regData); for ( z = 0; z < 255; z++ ) zs = inw_p (padapter->regData); if ( ag0.ProtocolType == 2 ) { if ( ag0.CmdDrqType == 1 ) pdev->cmdDrqInt = TRUE; switch ( ag0.CmdPacketSize ) { case 0: pdev->packet = 6; break; case 1: pdev->packet = 8; break; default: pdev->packet = 6; break; } return FALSE; } return TRUE; }/**************************************************************** * Name: Atapi2Scsi * * Description: Convert ATAPI data to SCSI data. * * Parameters: padapter - Pointer adapter data structure. * SCpnt - Pointer to SCSI command structure. * * Returns: Nothing. * ****************************************************************/void Atapi2Scsi (PADAPTER2220I padapter, Scsi_Cmnd *SCpnt) { UCHAR *buff = padapter->currentSgBuffer; switch ( SCpnt->cmnd[0] ) { case SCSIOP_MODE_SENSE: buff[0] = padapter->kBuffer[1]; buff[1] = padapter->kBuffer[2]; buff[2] = padapter->kBuffer[3]; buff[3] = padapter->kBuffer[7]; memcpy (&buff[4], &padapter->kBuffer[8], padapter->atapiCdb[8] - 8); break; case SCSIOP_INQUIRY: padapter->kBuffer[2] = 2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -