/*====================================================================== A driver for the PCI NinjaSCSI32bi SCSI Host Adapter nins32.c 0.2 2000/06/16 The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. ======================================================================*/ // #define NINJA32UDE 1 // for 32BI-UDE // #define LOGITEC_ONLY 1 // for LOGITEC board #define USE_SELECTSAVEFLAG #include #include #include #include #include #include #include #include #include #include #include #include #include #include "scsi.h" #include "hosts.h" #include #include "sd.h" #include #include #if defined(MODULE) || defined(PCMCIA) #include #endif #if defined(PCMCIA) # undef MODULE #endif #ifndef KERNEL_VERSION # define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) #endif #include // #if (LINUX_VERSION_CODE > KERNEL_VERSION(1,2,13)) #include /* to get disk capacity */ #endif // ---------------------------------------------------------------- #include "nins32.h" // ---------------------------------------------------------------- #ifdef MODULE static Scsi_Host_Template driver_template = (Scsi_Host_Template)NINJA32BI; #include "scsi_module.c" #endif #include #include #include #if (LINUX_VERSION_CODE >= KERNEL_VERSION(1,3,98)) #include #else #include "drivers/scsi/scsi_ioctl.h" #endif static PSPECIFIC_LU_EXTENSION table[7][10]; struct tq_struct ns3_tq; static ULONG FifoAlign; UCHAR srbStatus= SRB_STATUS_SUCCESS; struct proc_dir_entry proc_scsi_nins32 = { PROC_SCSI_NINS32, 6, "nins32", S_IFDIR | S_IRUGO | S_IXUGO, 2 }; // 起動オプション用 typedef struct _nins32_driver_option_ { char isConfig; char useDisconnect; char transferMode; }nins32_driver_option; static nins32_driver_option drvOption = {1,0,0}; #define SYNC_TABLE_MAX20 8 static SYNC_TABLE SyncTable20[] = {{0x0c,0x0c,0x1,0}, // 20MB 50ns {0x0d,0x18,0x2,0}, // 13.3MB 75ns {0x19,0x19,0x3,1}, // 10MB 100ns {0x1a,0x1f,0x4,1}, // 8.0MB 125ns {0x20,0x25,0x5,2}, // 6.7MB 150ns {0x26,0x32,0x7,3}, // 5MB 200ns {0x33,0x38,0x8,3}, // 4.4MB 225ns {0x39,0x3e,0x9,3}}; // 4MB 250ns #define SYNC_TABLE_MAX10 3 static SYNC_TABLE SyncTable10[] = {{0x19,0x19,0x1,0}, // 10MB 100ns {0x1a,0x25,0x2,0}, // 6.7MB 150ns {0x26,0x32,0x3,1}}; // 5MB 200ns #define SYNC_TABLE_MAXPCI 5 static SYNC_TABLE SyncTablePci[] = {{0x0c,0x0f,0x1,0}, // 20MB 50ns -> 16.6MB 60ns {0x10,0x16,0x2,0}, // 13.3MB 75ns -> 11.1MB 90ns {0x17,0x1e,0x3,1}, // 10MB 100ns -> 8.3MB 120ns {0x1f,0x25,0x5,1}, // 6.7MB 150ns -> 6.7MB 150ns {0x26,0x32,0x6,2}}; // 5MB 200ns -> 4.8MB 210ns VOID pio32_datain (IN pnins32_host DeviceExtension , ULONG Buffer, ULONG Length ); static VOID Ns3StartExecution( IN PSPECIFIC_DEVICE_EXTENSION DeviceExtension, IN PSPECIFIC_LU_EXTENSION LuExtension, IN Scsi_Cmnd *Srb ); static int is_dir_out(Scsi_Cmnd *cmd) { // not implemented return 0; if (cmd->request.cmd == WRITE) { return TRUE; } return FALSE; } #ifdef USE_IRQ_POLL VOID Ns3IrqPolling ( IN PSPECIFIC_DEVICE_EXTENSION DeviceExtension ) { LONG i; Ns3DebugPrint(0x20, (__FUNCTION__ " Ns3IrqPolling in \n")); i = INT_POLL_SEL; while (i > 0 ) { *((PUSHORT) &DevIntIrqStatus) = SCSI_READW(DeviceExtension->BaseAddress, irq.pIrqStatus); if ( (*(PUSHORT)&DevIntIrqStatus) & 0xff0 ) { // Timerは無視 Ns3Interrupt( DeviceExtension ); break; } i--; //ループ間隔 530CS-133MHz : 4.5us if ( i != 0) ScsiPortStallExecution(5); } ((PIRQ_CONTROLP)&DeviceExtension->IrqMaskData)->ScsiIrqMask = 0; // SCSI IRQ Enable ((PIRQ_CONTROLP)&DeviceExtension->IrqMaskData)->FifoIrqMask = 0; ((PIRQ_CONTROLP)&DeviceExtension->IrqMaskData)->CardBusIrqMask = 0; SCSI_WRITEW(DeviceExtension, irq.pIrqControl,DeviceExtension->IrqMaskData); } #endif // USE_IRQ_POLL // 待ち処理 void ScsiPortStallExecution(ULONG delayTime){ if( delayTime > 1000 ) { int i; ULONG cnt = delayTime; cnt /= 1000; cnt++; for(i = 0; i < cnt;i++) { udelay(1000); // Ns3DebugPrint(0x20, (".")); } } else { udelay(delayTime); } } BOOLEAN Ns3TimerRequest(pnin_softc devExt) { Ns3DebugPrint(0x20, (__FUNCTION__ " : in\n")); if( devExt->dev_timer.expires ) { Ns3DebugPrint(0x20, (__FUNCTION__ " : runnnig now end\n")); return FALSE; } init_timer(&devExt->dev_timer); devExt->dev_timer.expires = jiffies + 500; devExt->dev_timer.data = (unsigned long)devExt; devExt->dev_timer.function = Ns3Timer; /* timer handler */ #ifndef NOUSE_ADDTIMER add_timer(&devExt->dev_timer); #endif Ns3DebugPrint(0x20, (__FUNCTION__ ": add_timer and end\n")); return TRUE; } /* //----------------------------------------------------------------------- // Routine Name: // // Ns3Select // // Routine Description: // // Perform selection process on SCSI bus. // // Arguments: // // DevExt - Device adapter context pointer. // // Return Value: // // TRUE : Select Success /// //----------------------------------------------------------------------- */ static boolean Ns3Select(IN pnin_softc DeviceExtension ,Scsi_Cmnd *srb) { PSPECIFIC_TARGET_EXTENSION targetState; PSCSI_REGISTER baseAddress = DeviceExtension->BaseAddress; UCHAR cdbLength; PUCHAR cdb; UCHAR dataByte; USHORT dataWord, AtnWord; ULONG dataDword; PSPECIFIC_LU_EXTENSION luExtension = DeviceExtension->ActiveLogicalUnit; Ns3DebugPrint(0x01,(__FUNCTION__ ": TargetId = %x ",DeviceExtension->TargetId)); cdbLength = srb->cmd_len; cdb = srb->cmnd; //srb->Cdb; AtnWord = 0; ((PCOMMAND_CONTROL)&AtnWord)->AutoATN = 1; if ( DeviceExtension->AdapterOption & OPT_NO_ATN ) { Ns3DebugPrint(0x20,("OPT_NO_ATN\n")); ((PCOMMAND_CONTROL)&AtnWord)->AutoATN = 0; DeviceExtension->MsgOutCount = 0; } luExtension->AckCounter = 0; // //--- Disable INTERRUPT // dataWord = 0; ((PIRQ_CONTROLP)&dataWord)->FifoIrqMask = 1; ((PIRQ_CONTROLP)&dataWord)->CardBusIrqMask = 1; if (DeviceExtension->PollingMode != 0xff) { ((PIRQ_CONTROLP)&dataWord)->TimerIrqMask = 1; } ((PIRQ_CONTROLP)&dataWord)->ScsiIrqMask = 1; // dataWord = 0; SCSI_WRITEW(DeviceExtension, irq.pIrqControl, dataWord); DeviceExtension->IrqMaskData = dataWord; Ns3DebugPrint(0x1001,(": IrqMaskData[%x] ",dataWord)); targetState = &DeviceExtension->TargetState[srb->target]; SCSI_WRITED(DeviceExtension , pSelTimeOut, 10000); // SELECTION TIMEOUT = 250ms // INITIATOR + TARGET ID SET dataByte = (1 << SCSI_INITIATOR_ID) | (1 << (srb->target)); SCSI_WRITE(DeviceExtension, _22.pTargetId, dataByte); #ifdef NINJA32UDE SCSI_WRITE(DeviceExtension, pSreqSmplRate, 0); //+[ude] Ns3DebugPrint(0x02, (" : SreqSmplRate = 0")); #else // NINJA32UDE dataWord = 0; ((PTRANSFER_CONTROL)&dataWord)->AllCountClr = 1; ((PTRANSFER_CONTROL)&dataWord)->FifoTest = 1; SCSI_WRITEW(DeviceExtension, trans.pTransferStatus, dataWord); dataDword = dataByte | (dataByte <<8) | (dataByte <<16) | (dataByte<<24); SCSI_WRITED(DeviceExtension, _30.pwFifoData, dataDword); dataWord = 0; ((PTRANSFER_CONTROL)&dataWord)->AllCountClr = 1; SCSI_WRITEW(DeviceExtension, trans.pTransferStatus, dataWord); #endif // NINJA32UDE dataByte = 0; ((PSYNC_REG)&dataByte)->SyncPeriod = targetState->SynchronousPeriod; ((PSYNC_REG)&dataByte)->SyncOffset = targetState->SynchronousOffset; SCSI_WRITE(DeviceExtension, pSyncReg,dataByte); SCSI_WRITE(DeviceExtension, pAckWidth, targetState->AckWidth); //[test] #ifdef UDEEnable if ( targetState->TargetFlags & PD_DUALEDGE_ENABLE) { if (!((ULONG)srb->DataBuffer & 3)){ srb->Cdb[8] /=2; } } #endif // //--- CDBをCOMMAND FIFOに積む --- // dataWord = 0; ((PCOMMAND_CONTROL)&dataWord)->ClrCdbFifoPointer = 1; SCSI_WRITEW(DeviceExtension,_18.pCommandControl, dataWord); // CDB FIFO COUNTER CLEAR Ns3DebugPrint(0x02, (__FUNCTION__ "COMMAND FIFO : ")); while (cdbLength > 0) { Ns3DebugPrint(0x02, ("[%x]", *cdb)); SCSI_WRITE(DeviceExtension, pCommandData, *cdb++); cdbLength--; } Ns3DebugPrint(0x02, ("\n")); if (DeviceExtension->MsgOutCount == 1 ) { dataDword = DeviceExtension->MsgOutBuffer[0] << 24; dataDword |= 0x81; // MV & 1BYTEMESSAGE SCSI_WRITED(DeviceExtension,pScsiMsgOut,dataDword); // Ns3DebugPrint(0x20, (" : pScsiMsgOut[%x]",dataDword)); } else { SCSI_WRITED(DeviceExtension,pScsiMsgOut, 0 ); Ns3DebugPrint(0x20, (" : MsgOutCount != 1\n")); } #ifdef NINJA32UDE // Set MiscReg +[ude] dataWord = SCSI_SREADW(baseAddress,pMiscReg); dataWord &= 0x1f9; if ( luExtension->XferMode == XMODE_DMA ) { ((PMISC_REG)&dataWord)->BmStop_NDataPhase = 1; } else { ((PMISC_REG)&dataWord)->BmStop_NDataPhase = 0; Ns3DebugPrint(0x20, (" : BmStop_NDataPhase = 0 ")); } SCSI_SWRITEW(baseAddress,pMiscReg,dataWord); #endif // NINJA32UDE // TRANSFERMODE dataWord = 0; if ( srb->request_bufflen && (luExtension->XferMode == XMODE_DMA) ) { ((PTRANSFER_CONTROL)&dataWord)->BmStart = 1; if(is_dir_out(srb)) ((PTRANSFER_CONTROL)&dataWord)->AdvancedBmWrite = 1; // data out } if ( luExtension->XferMode == XMODE_PIO32 ) { Ns3DebugPrint(0x20, (" : XMODE_PIO32:")); ((PTRANSFER_CONTROL)&dataWord)->CB_PIO_Mode = 1; // ((PTRANSFER_CONTROL)&dataWord)->BlindMode = 1; luExtension->pXferRead = DeviceExtension->pXferRead; luExtension->pXferWrite = DeviceExtension->pXferWrite; } else if (luExtension->XferMode == XMODE_MMIO) { Ns3DebugPrint(0x20, (" : CB_MMIO_Mode:")); ((PTRANSFER_CONTROL)&dataWord)->CB_MMIO_Mode = 1; // ((PTRANSFER_CONTROL)&dataWord)->BlindMode = 1; luExtension->pXferRead = DeviceExtension->pXferRead; luExtension->pXferWrite = DeviceExtension->pXferWrite; } ((PTRANSFER_CONTROL)&dataWord)->TransferGo = 1; ((PTRANSFER_CONTROL)&dataWord)->AllCountClr = 1; //[test] #ifdef UDEEnable if ( targetState->TargetFlags & PD_DUALEDGE_ENABLE) { if (!((ULONG)srb->DataBuffer & 3)){ ((PTRANSFER_CONTROL)&dataWord)->DualAgeEnable = 1; } } #endif SCSI_WRITEW(DeviceExtension, trans.pTransferStatus, dataWord); // YAMAHA dataByte = SCSI_READ(DeviceExtension, sc.pScsiBusMonitor); if ( dataByte != 0 ) { // BUS Free ? Ns3DebugPrint(0x20, (" : ScsiBusMonitor[%x]:",dataByte)); SCSI_WRITEW(DeviceExtension, trans.pTransferControl, 0); SCSI_WRITED(DeviceExtension, pBmCnt, 0); // SCSI IRQ Enable ((PIRQ_CONTROLP)&DeviceExtension->IrqMaskData)->ScsiIrqMask = 0; if ( (luExtension->XferMode == XMODE_PIO32) || (luExtension->XferMode == XMODE_MMIO ) ) { ((PIRQ_CONTROLP)&DeviceExtension->IrqMaskData)->FifoIrqMask = 0; } ((PIRQ_CONTROLP)&DeviceExtension->IrqMaskData)->CardBusIrqMask = 0; SCSI_WRITEW(DeviceExtension, irq.pIrqControl, DeviceExtension->IrqMaskData); Ns3DebugPrint(0x20, (" YAMAHA FALSE tareget[%x]\n",srb->target)); return FALSE; } // Start AUTO-SCSI if ( luExtension->XferMode == XMODE_DMA ) { ((PCOMMAND_CONTROL)&AtnWord)->AutoMsgin00_04 = 1; ((PCOMMAND_CONTROL)&AtnWord)->AutoMsgin02 = 1; Ns3DebugPrint(0x20, (__FUNCTION__ " :Start AUTO-SCSI ")); } ((PCOMMAND_CONTROL)&AtnWord)->ClrCdbFifoPointer = 1; ((PCOMMAND_CONTROL)&AtnWord)->AutoScsiStart = 1; SCSI_WRITEW(DeviceExtension, _18.pCommandControl, AtnWord); // dataByte2 = SCSI_READW(DeviceExtension, irq.pIrqStatus); // Ns3DebugPrint(0x20, (" SCSI IRQ jj[%x] ",dataByte2)); // //--- ARBITRATION START --- // dataByte = 0; Ns3DebugPrint(0x02, ("ArbitStatus ")); while (!( ((PARBIT_STATUS)&dataByte)->ArbitWin || ((PARBIT_STATUS)&dataByte)->ArbitFail ) ) { dataByte = SCSI_READ(DeviceExtension, _1a.pArbitStatus); // Get BUS Ns3DebugPrint(0x02, ("[%x] ", dataByte)); } if ( ((PARBIT_STATUS)&dataByte)->ArbitFail ) { Ns3DebugPrint(0x20, (__FUNCTION__" ArbitFail\n\n")); dataByte = 0; ((PSET_ARBIT)&dataByte)->ArbitFlagClear = 1; SCSI_WRITE(DeviceExtension, _1a.pSetArbit, dataByte); // ARBITRATION FLAG CLEAR SCSI_WRITEW(DeviceExtension, trans.pTransferStatus, 0); SCSI_WRITED(DeviceExtension, pBmCnt, 0); // SCSI IRQ Enable ((PIRQ_CONTROLP)&DeviceExtension->IrqMaskData)->ScsiIrqMask = 0; if( (luExtension->XferMode == XMODE_PIO32) || (luExtension->XferMode == XMODE_MMIO) ){ ((PIRQ_CONTROLP)&DeviceExtension->IrqMaskData)->FifoIrqMask = 0; } ((PIRQ_CONTROLP)&DeviceExtension->IrqMaskData)->CardBusIrqMask = 0; SCSI_WRITEW(DeviceExtension, irq.pIrqControl, DeviceExtension->IrqMaskData); return(FALSE); } dataByte = 0; ((PSET_ARBIT)&dataByte)->ArbitFlagClear = 1; SCSI_WRITE(DeviceExtension, _1a.pSetArbit, dataByte); // ARBITRATION FLAG CLEAR DeviceExtension->ScsiState = SC_SELECT; //+[v1.10] // win ! DeviceExtension->ActiveLogicalUnit->TransferedLength = 0; #ifdef PCI // +[kamii] vvv '99.09.06 LED対応 SCSI_SWRITE(baseAddress, pExtPort, 0x00); // LED点灯 #endif // +[kamii] ^^^ '99.09.06 // //--- ARBITRATION SUCCESS --- // DeviceExtension->AdapterFlags &= ~PD_PENDING_START_IO; DeviceExtension->NextSrbRequest = NULL; DeviceExtension->IntWait = TRUE; // SCSI IRQ Enable ((PIRQ_CONTROLP)&DeviceExtension->IrqMaskData)->ScsiIrqMask = 0; if( (luExtension->XferMode == XMODE_PIO32) || (luExtension->XferMode == XMODE_MMIO) ) { ((PIRQ_CONTROLP)&DeviceExtension->IrqMaskData)->FifoIrqMask = 0; } ((PIRQ_CONTROLP)&DeviceExtension->IrqMaskData)->CardBusIrqMask = 0; SCSI_WRITEW(DeviceExtension, irq.pIrqControl,DeviceExtension->IrqMaskData); SCSI_WRITEW(DeviceExtension, irq.pIrqControl,DeviceExtension->IrqMaskData); if (!DeviceExtension->wIrqSelect.ScsiResetIrqSel) { DeviceExtension->wIrqSelect.ScsiResetIrqSel = 1; SCSI_SWRITEW(baseAddress, pIrqSelect, *(PUSHORT)&DeviceExtension->wIrqSelect); } if (DeviceExtension->PollingMode == 0x7f) { Ns3DebugPrint(0x20, (__FUNCTION__ " : Call Ns3TimerRequest ***\n")); Ns3TimerRequest(DeviceExtension); } Ns3DebugPrint(0x20, (__FUNCTION__" end ...\n\n")); return(TRUE); } // end Ns3Select() //----------------------------------------------------------------------- // Routine Name: // // Ns3AutoSelect // // Routine Description: // // Perform selection process on SCSI bus. // // Arguments: // // DeviceExtension - Device adapter context pointer. // // Return Value: // // TRUE : Select Success /// // ARBITRATIONとIDENTIFYの追加 //----------------------------------------------------------------------- BOOLEAN Ns3AutoSelect( IN pnins32_host DeviceExtension ) { Scsi_Cmnd *srb; PSPECIFIC_TARGET_EXTENSION targetState; PSCSI_REGISTER baseAddress = DeviceExtension->BaseAddress; UCHAR cdbLength; PUCHAR cdb, autoCdb; UCHAR /*BusyByte, */dataByte; USHORT dataWord, AtnWord; ULONG dataDword; PAUTO_PARA AutoPara; PSPECIFIC_LU_EXTENSION luExtension = DeviceExtension->ActiveLogicalUnit; Ns3DebugPrint(0x01,( "__FUNCTION__: Dev= %lx, TID = %x \n",DeviceExtension,DeviceExtension->TargetId)); srb = DeviceExtension->NextSrbRequest; Ns3DebugPrint(0x20, (__FUNCTION__ " : srb = DeviceExtension->NextSrbRequest\n")); cdbLength = COMMAND_SIZE(srb->cmnd[0]); cdb = srb->cmnd; dataByte = SCSI_READ(DeviceExtension, sc.pScsiBusMonitor); if ( dataByte != 0 ) // BUS Free ? return FALSE; AutoPara = luExtension->SrbExtension; AtnWord = 0; ((PCOMMAND_CONTROL)&AtnWord)->AutoATN = 1; if ( DeviceExtension->AdapterOption & OPT_NO_ATN ) { ((PCOMMAND_CONTROL)&AtnWord)->AutoATN = 0; DeviceExtension->MsgOutCount = 0; } luExtension->AckCounter = 0; // //--- Disable INTERRUPT // dataWord = 0; ((PIRQ_CONTROLP)&dataWord)->FifoIrqMask = 1; ((PIRQ_CONTROLP)&dataWord)->CardBusIrqMask = 1; if (DeviceExtension->PollingMode != 0xff) { ((PIRQ_CONTROLP)&dataWord)->TimerIrqMask = 1; } ((PIRQ_CONTROLP)&dataWord)->ScsiIrqMask = 1; SCSI_WRITEW(DeviceExtension, irq.pIrqControl, dataWord); DeviceExtension->IrqMaskData = dataWord; targetState = &DeviceExtension->TargetState[srb->target]; SCSI_WRITED(DeviceExtension , pSelTimeOut, 10000); //SELECTION TIMEOUT = 250ms // INITIATOR + TARGET ID SET dataByte = (1 << SCSI_INITIATOR_ID) | (1 << (srb->target)); AutoPara->TargetId = dataByte; SCSI_WRITE(DeviceExtension, _22.pTargetId, dataByte); //+[ap] // 同期パラメータの設定 dataByte = 0; ((PSYNC_REG)&dataByte)->SyncPeriod = targetState->SynchronousPeriod; ((PSYNC_REG)&dataByte)->SyncOffset = targetState->SynchronousOffset; AutoPara->SyncReg = dataByte; AutoPara->AckWidth = targetState->AckWidth; #ifdef NINJA32UDE SCSI_WRITE(DeviceExtension, pSyncReg,dataByte); //+[ap] SCSI_WRITE(DeviceExtension, pAckWidth, targetState->AckWidth); //+[ap] #else AutoPara->SmplRate = 0; //+[ude] #endif // Ns3SetTransferMode( DeviceExtension ); // //--- CDBをCOMMAND FIFOに積む --- // dataWord = 0; ((PCOMMAND_CONTROL)&dataWord)->ClrCdbFifoPointer = 1; SCSI_WRITEW(DeviceExtension,_18.pCommandControl, dataWord); // CDB FIFO COUNTER CLEAR autoCdb = (PUCHAR)&AutoPara->Cdb[0]; while (cdbLength > 0) { Ns3DebugPrint(0x02, ( "%x ", *cdb)); *autoCdb = *cdb++; autoCdb +=4; cdbLength--; } Ns3DebugPrint(0x02, ( "\n")); if (DeviceExtension->MsgOutCount == 1 ) { dataDword = DeviceExtension->MsgOutBuffer[0] << 24; dataDword |= 0x81; // MV & 1BYTEMESSAGE AutoPara->ScsiMsgOut = dataDword; } else AutoPara->ScsiMsgOut = 0; #ifdef NINJA32UDE // [ude] SCSI_WRITE(DeviceExtension, sc.pClearCounter , 0x3f); // All Pointer Clear #endif // SET TRANSFERMODE dataWord = 0; if ( srb->request_bufflen && (luExtension->XferMode == XMODE_DMA) ) { ((PTRANSFER_CONTROL)&dataWord)->BmStart = 1; if(is_dir_out(srb)) ((PTRANSFER_CONTROL)&dataWord)->AdvancedBmWrite = 1; // data out } if ( luExtension->XferMode == XMODE_PIO32 ) { ((PTRANSFER_CONTROL)&dataWord)->CB_PIO_Mode = 1; // ((PTRANSFER_CONTROL)&dataWord)->BlindMode = 1; luExtension->pXferRead = DeviceExtension->pXferRead; luExtension->pXferWrite = DeviceExtension->pXferWrite; } else if (luExtension->XferMode == XMODE_MMIO) { ((PTRANSFER_CONTROL)&dataWord)->CB_MMIO_Mode = 1; // ((PTRANSFER_CONTROL)&dataWord)->BlindMode = 1; luExtension->pXferRead = DeviceExtension->pXferRead; luExtension->pXferWrite = DeviceExtension->pXferWrite; } ((PTRANSFER_CONTROL)&dataWord)->TransferGo = 1; #ifndef NINJA32UDE ((PTRANSFER_CONTROL)&dataWord)->AllCountClr = 1; #endif AutoPara->TransferControl = dataWord; // START AUTO SCSI if ( luExtension->XferMode == XMODE_DMA ) { ((PCOMMAND_CONTROL)&AtnWord)->AutoMsgin00_04 = 1; ((PCOMMAND_CONTROL)&AtnWord)->AutoMsgin02 = 1; } ((PCOMMAND_CONTROL)&AtnWord)->ClrCdbFifoPointer = 1; ((PCOMMAND_CONTROL)&AtnWord)->AutoScsiStart = 1; // AutoPara->CommandControl = AtnWord; AutoPara->SgAdr = luExtension->PhySGlist; SCSI_WRITED(DeviceExtension, pSgAdr,luExtension->PhySrbExtension); dataWord = 0; ((PCOMMAND_CONTROL)&dataWord)->ClrCdbFifoPointer = 1; ((PCOMMAND_CONTROL)&dataWord)->AutoParameter = 1; SCSI_WRITEW(DeviceExtension,_18.pCommandControl, dataWord); // //--- ARBITRATION START --- // dataByte = 0; while (!( ((PARBIT_STATUS)&dataByte)->ArbitWin || ((PARBIT_STATUS)&dataByte)->ArbitFail ) ) { dataByte = SCSI_READ(DeviceExtension, _1a.pArbitStatus); // BUS? } if ( ((PARBIT_STATUS)&dataByte)->ArbitFail ) { // ARBITRATION FAILED dataByte = 0; ((PSET_ARBIT)&dataByte)->ArbitFlagClear = 1; SCSI_WRITE(DeviceExtension, _1a.pSetArbit, dataByte); // ARBITRATION FLAG CLEAR SCSI_WRITEW(DeviceExtension, trans.pTransferControl, 0); SCSI_WRITED(DeviceExtension, pBmCnt, 0); // SCSI IRQ Enable ((PIRQ_CONTROLP)&DeviceExtension->IrqMaskData)->ScsiIrqMask = 0; if ( (luExtension->XferMode == XMODE_PIO32) || (luExtension->XferMode == XMODE_MMIO) ) { ((PIRQ_CONTROLP)&DeviceExtension->IrqMaskData)->FifoIrqMask = 0; } ((PIRQ_CONTROLP)&DeviceExtension->IrqMaskData)->CardBusIrqMask = 0; SCSI_WRITEW(DeviceExtension, irq.pIrqControl, DeviceExtension->IrqMaskData); return(FALSE); } dataByte = 0; ((PSET_ARBIT)&dataByte)->ArbitFlagClear = 1; SCSI_WRITE(DeviceExtension, _1a.pSetArbit, dataByte); // ARBITRATION FLAG CLEAR Ns3DebugPrint(0x20, (" ARBITRATION FLAG CLEAR" )); DeviceExtension->ScsiState = SC_SELECT; DeviceExtension->ActiveLogicalUnit->TransferedLength = 0; // //--- ARBITRATION SUCCESS --- // DeviceExtension->AdapterFlags &= ~PD_PENDING_START_IO; DeviceExtension->NextSrbRequest = NULL; DeviceExtension->IntWait = TRUE; // SCSI IRQ Enable ((PIRQ_CONTROLP)&DeviceExtension->IrqMaskData)->ScsiIrqMask = 0; if ( (luExtension->XferMode == XMODE_PIO32) || (luExtension->XferMode == XMODE_MMIO) ) { ((PIRQ_CONTROLP)&DeviceExtension->IrqMaskData)->FifoIrqMask = 0; } ((PIRQ_CONTROLP)&DeviceExtension->IrqMaskData)->CardBusIrqMask = 0; SCSI_WRITEW(DeviceExtension, irq.pIrqControl,DeviceExtension->IrqMaskData); if (!DeviceExtension->wIrqSelect.ScsiResetIrqSel) { DeviceExtension->wIrqSelect.ScsiResetIrqSel = 1; Ns3DebugPrint(0x20, (__FUNCTION__ "------- ScsiResetIrqSel [%x]\n" ,DeviceExtension->wIrqSelect.ScsiResetIrqSel)); SCSI_SWRITEW(baseAddress, pIrqSelect, *(PUSHORT)&DeviceExtension->wIrqSelect); } if (DeviceExtension->PollingMode == 0x7f) { Ns3DebugPrint(0x20, (__FUNCTION__ " : Call Ns3TimerRequest\n")); Ns3TimerRequest(DeviceExtension); } return(TRUE); } // end Ns3AutoSelect() //----------------------------------------------------------------------- VOID Ns3BurstRead( IN pnins32_host DeviceExtension ) { ULONG Length; // TRANSFER_STATUS FifoStatus; // PSCSI_REGISTER baseAddress = DeviceExtension->BaseAddress; PSPECIFIC_LU_EXTENSION LuExtension = DeviceExtension->ActiveLogicalUnit; Ns3DebugPrint(0x04, ( __FUNCTION__ " : in ------------- \n")); while( DeviceExtension->CurDataLength > 0 ) { *((PUSHORT) &DevIntIrqStatus) = SCSI_READW(DeviceExtension, irq.pIrqStatus); if ( DevIntIrqStatus.AutoScsiIrq ) break; // Phase Change ? // *((PUSHORT) &FifoStatus) = SCSI_READW(DeviceExtension, pTransferStatus); // if ( FifoStatus.FifoTrueFull ) { Length = DeviceExtension->CurDataLength; // 1回の最大TRANSFER数の変更 if ( Length > READ_XFER_CNT) Length = READ_XFER_CNT; // TRANSFER ROUTINE (*LuExtension->pXferRead)( DeviceExtension, DeviceExtension->CurDataPointer, Length ); DeviceExtension->CurDataPointer += Length; DeviceExtension->CurDataLength -= Length; DeviceExtension->ActiveLogicalUnit->TransferedLength += Length; // } } if ( !DevIntIrqStatus.AutoScsiIrq) { *((PUSHORT) &DevIntIrqStatus) = SCSI_READW(DeviceExtension, irq.pIrqStatus); } // Phase Changeで途中で終わってしまったとき if ( DevIntIrqStatus.AutoScsiIrq ) { // Phase Change ? if ( DeviceExtension->CurDataLength > 0) { Length = SCSI_READW(DeviceExtension, pFifoRestCnt) & 0x1ff; if ( Length != 0 ) { (*LuExtension->pXferRead)(DeviceExtension, DeviceExtension->CurDataPointer, Length ); DeviceExtension->CurDataPointer += Length; DeviceExtension->CurDataLength -= Length; DeviceExtension->ActiveLogicalUnit->TransferedLength += Length; } } } DeviceExtension->ScsiState = SC_DATA; } //----------------------------------------------------------------------- //----------------------------------------------------------------------- VOID Ns3BurstWrite( IN pnins32_host DeviceExtension ) { ULONG Length; // TRANSFER_STATUS FifoStatus; // PSCSI_REGISTER baseAddress = DeviceExtension->BaseAddress; PSPECIFIC_LU_EXTENSION LuExtension = DeviceExtension->ActiveLogicalUnit; Ns3DebugPrint(0x04, ( __FUNCTION__ " : in ------------- \n")); while( DeviceExtension->CurDataLength > 0 ) { *((PUSHORT) &DevIntIrqStatus) = SCSI_READW(DeviceExtension, irq.pIrqStatus); if ( DevIntIrqStatus.AutoScsiIrq ) break; // Phase Change ? // *((PUSHORT) &FifoStatus) = SCSI_READW(DeviceExtension, pTransferStatus); // if ( FifoStatus.FifoTrueEmpty) { Length = DeviceExtension->CurDataLength; // 1回の最大TRANSFER数の変更 if ( Length > WRITE_BURST_CNT) Length = WRITE_BURST_CNT; // TRANSFER ROUTINE (*LuExtension->pXferWrite)( DeviceExtension, DeviceExtension->CurDataPointer, Length ); DeviceExtension->CurDataPointer += Length; DeviceExtension->CurDataLength -= Length; DeviceExtension->ActiveLogicalUnit->TransferedLength += Length ; // } if ( !DevIntIrqStatus.AutoScsiIrq ) { //ここでも見ないと送ったあとでPhase Changeになることがある *((PUSHORT) &DevIntIrqStatus) = SCSI_READW(DeviceExtension, irq.pIrqStatus); } // Phase ChangeでFIFOにデータが残ってしまったとき if ( DevIntIrqStatus.AutoScsiIrq ) { // Phase Change ? Length = (SCSI_READW(DeviceExtension, pFifoRestCnt) & 0x1ff); if ( Length ) { DeviceExtension->CurDataPointer -= Length; DeviceExtension->CurDataLength += Length; // POINTERを戻す DeviceExtension->ActiveLogicalUnit->TransferedLength -= Length ; } } DeviceExtension->ScsiState = SC_DATA; } } //----------------------------------------------------------------------- // スポットリード // //----------------------------------------------------------------------- VOID Ns3SpotRead ( IN pnins32_host DeviceExtension ) { // UCHAR dataByte; // PSCSI_REGISTER baseAddress = DeviceExtension->BaseAddress; // TRANSFER_STATUS FifoStatus; WORD FifoCount; LONG LoopCount = 0; UCHAR ScsiPhase; LONG i; PSPECIFIC_LU_EXTENSION LuExtension = DeviceExtension->ActiveLogicalUnit; Ns3DebugPrint(0x4000, ( __FUNCTION__ " : in ------ ")); ScsiPhase = SCSI_READ(DeviceExtension, sc.pScsiBusMonitor) & 0x7; Ns3DebugPrint(0x4000, (" : ScsiPhase [%x] ",ScsiPhase)); if (( ScsiPhase == BP_DATA_IN )/*||( ScsiPhase == BP_MESSAGE_IN )*/) { Ns3DebugPrint(0x4000, (__FUNCTION__ " : BP_DATA_IN(%x)bytes ",DeviceExtension->CurDataLength)); while (LoopCount == 0) { *((PUSHORT) &DevIntIrqStatus) = SCSI_READW(DeviceExtension, irq.pIrqStatus); if ( DevIntIrqStatus.AutoScsiIrq ) { break; // Phase Change ? } // FIFO残数を読む FifoCount = SCSI_READW(DeviceExtension, pFifoRestCnt) & 0x1ff; Ns3DebugPrint(0x4000,( ": xFifoCount [%x] ",FifoCount)); if ( FifoCount > 0x40 ) FifoCount = 0x40; //+[v1.03.00] if ( FifoCount & 3 ) FifoCount &= 0x7c; if ( FifoCount == 0) { break; } // TRANSFER ROUTINE (*LuExtension->pXferRead)(DeviceExtension, DeviceExtension->CurDataPointer, FifoCount ); DeviceExtension->CurDataLength -= FifoCount ; DeviceExtension->CurDataPointer += FifoCount; DeviceExtension->ActiveLogicalUnit->TransferedLength += FifoCount ; LoopCount++; DeviceExtension->IntWait = FALSE; for ( i = 0; i< INT_POLL_IRQ ; i++) { *((PUSHORT)&DevIntIrqStatus) = SCSI_READW(DeviceExtension, irq.pIrqStatus); if ( DevIntIrqStatus.AutoScsiIrq ) { Ns3DebugPrint(0x4000,(": AutoScsiIrq = TRUE break\n")); break; // Phase Change ? } if ( DevIntIrqStatus.FifoShldIrq ) { DevIntIrqStatus.FifoShldIrq = 0; LoopCount = 0; // もう一度 break; } ScsiPortStallExecution(2); } } } else { // データフェーズ以外 になってしまった時 FifoCount = SCSI_READW(DeviceExtension, pFifoRestCnt) & 0x1ff; if ( FifoCount ) { // FIFO残数を読む if ( FifoCount > 0x40 ) FifoCount = 0x40; (*LuExtension->pXferRead)(DeviceExtension, DeviceExtension->CurDataPointer, FifoCount ); DeviceExtension->CurDataLength -= FifoCount ; DeviceExtension->CurDataPointer += FifoCount; DeviceExtension->ActiveLogicalUnit->TransferedLength += FifoCount ; DeviceExtension->IntWait = TRUE; return; } } // Phase Changeで途中で終わってしまったとき if(DevIntIrqStatus.AutoScsiIrq){ if( (FifoCount = SCSI_READW(DeviceExtension, pFifoRestCnt) & 0x1ff) && (FifoCount != 0) ) { Ns3DebugPrint(0x4000, (__FUNCTION__ " : Phase ChangeAAA DE read ")); (*LuExtension->pXferRead)(DeviceExtension, DeviceExtension->CurDataPointer, FifoCount ); DeviceExtension->CurDataPointer += FifoCount; DeviceExtension->CurDataLength -= FifoCount; DeviceExtension->ActiveLogicalUnit->TransferedLength += FifoCount; } } DeviceExtension->ScsiState = SC_DATA; // 次の FifoFull を待つ } //----------------------------------------------------------------------- // スポットライト // //----------------------------------------------------------------------- VOID Ns3SpotWrite ( IN pnins32_host DeviceExtension ) { // UCHAR dataByte; // PSCSI_REGISTER baseAddress = DeviceExtension->BaseAddress; // TRANSFER_STATUS FifoStatus; ULONG FifoCount; LONG LoopCount = 0; LONG i; PSPECIFIC_LU_EXTENSION LuExtension = DeviceExtension->ActiveLogicalUnit; Ns3DebugPrint(0x2000, ( __FUNCTION__ " : in ----------")); while (LoopCount == 0) { *((PUSHORT) &DevIntIrqStatus) = SCSI_READW(DeviceExtension, irq.pIrqStatus); if ( DevIntIrqStatus.AutoScsiIrq ) { Ns3DebugPrint(0x2000, ( " : AutoScsiIrq")); break; // Phase Change ? } FifoCount = WRITE_SPOT_CNT; if ( DeviceExtension->CurDataLength < WRITE_SPOT_CNT ) { Ns3DebugPrint(0x2000, ( " CurDataLength < WRITE_SPOT_CNT")); FifoCount = DeviceExtension->CurDataLength; } // TRANSFER ROUTINE Ns3DebugPrint(0x2000, ( " pXferWrite ")); (*LuExtension->pXferWrite)( /*(PULONG)*/DeviceExtension, DeviceExtension->CurDataPointer, FifoCount ); DeviceExtension->CurDataLength -= FifoCount ; DeviceExtension->CurDataPointer += FifoCount; DeviceExtension->ActiveLogicalUnit->TransferedLength += FifoCount ; Ns3DebugPrint(0x2000, ( "Ns3SpotWrite: DataPointer=%lx ,Length=%lx\n", DeviceExtension->CurDataPointer, DeviceExtension->CurDataLength)); if ( DeviceExtension->CurDataLength == 0 ) { Ns3DebugPrint(0x2000, ( __FUNCTION__ " : CurDataLength == 0 ")); DeviceExtension->IntWait = TRUE; break; } LoopCount++; DeviceExtension->IntWait = FALSE; for ( i = 0; i< INT_POLL_IRQ ; i++) { *((PUSHORT) &DevIntIrqStatus) = SCSI_READW(DeviceExtension, irq.pIrqStatus); if ( DevIntIrqStatus.AutoScsiIrq ) { Ns3DebugPrint(0x2000, ( __FUNCTION__ " : AutoScsiIrq ")); break; // Phase Change ? } if ( DevIntIrqStatus.FifoShldIrq ) { Ns3DebugPrint(0x2000, ( __FUNCTION__ " : FifoShldIrq ")); DevIntIrqStatus.FifoShldIrq = 0; LoopCount = 0; break; } ScsiPortStallExecution(2); } } if ( DevIntIrqStatus.PhaseChgIrq ) { // Phase Change ? Ns3DebugPrint(0x2000, ( __FUNCTION__ " : PhaseChgIrq")); DeviceExtension->IntWait = TRUE; } Ns3DebugPrint(0x2000, ( __FUNCTION__ " : out ")); DeviceExtension->ScsiState = SC_DATA; // 次の FifoEmpty を待つ } //----------------------------------------------------------------------- ///----------------------------------------------------------------------- VOID Ns3SlowRead ( IN pnins32_host DeviceExtension ) { ULONG Buffer = DeviceExtension->CurDataPointer; // UCHAR dataByte; // PSCSI_REGISTER baseAddress = DeviceExtension->BaseAddress; // TRANSFER_STATUS FifoStatus; ULONG FifoCount; LONG LoopCount = 0; UCHAR ScsiPhase; USHORT dataWord; ULONG FifoByte; Ns3DebugPrint(0x4000, ( __FUNCTION__ " : in ---- ")); // Off Blind MODE dataWord = SCSI_READW(DeviceExtension, trans.pTransferControl); ((PTRANSFER_CONTROL)&dataWord)->BlindMode = 0; SCSI_WRITEW(DeviceExtension, trans.pTransferControl, dataWord); Ns3DebugPrint(0x4000, ( " : BlindMode off ")); ScsiPhase = SCSI_READ(DeviceExtension, sc.pScsiBusMonitor) & 0x7; if ( ScsiPhase == BP_DATA_IN ) { Ns3DebugPrint(0x4000, ( " : ScsiPhase[BP_DATA_IN] ")); // if ( ((PIRQ_CONTROLP)&DeviceExtension->IrqMaskData)->FifoIrqMask) { // dataWord = SCSI_SREADW(baseAddress, pIrqSelect); // ((PIRQ_SELECT)&dataWord)->FifoShldIrqSel = 1; // FIFO IRQ Enable // SCSI_SWRITEW(baseAddress, pIrqSelect, dataWord); // ((PIRQ_CONTROLP)&DeviceExtension->IrqMaskData)->FifoIrqMask = 0; // FIFO IRQ MASK Disable // } while (LoopCount == 0) { // *((PUSHORT) &DevIntIrqStatus) = SCSI_READW(DeviceExtension, irq.pIrqStatus); // *((PUSHORT) &FifoStatus) = SCSI_READW(DeviceExtension, pTransferStatus); // if ( FifoStatus.FifoTrueFull || DevIntIrqStatus.AutoScsiIrq ) { FifoCount = SCSI_READW(DeviceExtension, pFifoRestCnt) & 0x7c; Ns3DebugPrint(0x4000, ( " : FifoCount[%x] ",FifoCount)); if (FifoCount) { SCSI_READ_FIFOD(DeviceExtension, Buffer, FifoCount); Buffer += FifoCount; DeviceExtension->CurDataLength -= FifoCount ; DeviceExtension->CurDataPointer = Buffer; DeviceExtension->ActiveLogicalUnit->TransferedLength += FifoCount ; } LoopCount++; // } } } else { Ns3DebugPrint(0x4000, ( __FUNCTION__ " : ScsiPhase --[NOT]-- BP_DATA_IN \n")); FifoCount = SCSI_READW(DeviceExtension, pFifoRestCnt) & 0x1ff; Ns3DebugPrint(0x4000, ( __FUNCTION__ " : FifoCount (%x)\n",FifoCount)); FifoByte = FifoCount & 3; if ( (FifoCount & 0x7c) ) { SCSI_READ_FIFOD( DeviceExtension, Buffer, (FifoCount & 0x7c) ); } if ( FifoByte ) { SCSI_READ_FIFOD( DeviceExtension, &FifoAlign, 4); memcpy((PUCHAR)&FifoAlign,(PUCHAR)(Buffer+(FifoCount & 0x7c)), FifoByte); } Buffer += FifoCount; DeviceExtension->CurDataLength -= FifoCount ; DeviceExtension->CurDataPointer = Buffer; DeviceExtension->ActiveLogicalUnit->TransferedLength += FifoCount ; return; } DeviceExtension->ScsiState = SC_DATA; } //----------------------------------------------------------------------- //----------------------------------------------------------------------- VOID Ns3SlowWrite ( IN pnins32_host DeviceExtension ) { ULONG Buffer = DeviceExtension->CurDataPointer; ULONG FifoCount; USHORT dataWord; ULONG FifoByte; Ns3DebugPrint(0x2000, ( __FUNCTION__ " : in -----")); // BLIND MODE OFF dataWord = SCSI_READW(DeviceExtension, trans.pTransferControl); ((PTRANSFER_CONTROL)&dataWord)->BlindMode = 0; SCSI_WRITEW(DeviceExtension, trans.pTransferControl, dataWord); // if ( ((PIRQ_CONTROLP)&DeviceExtension->IrqMaskData)->FifoIrqMask) { //既に解除済み? // dataWord = SCSI_SREADW(baseAddress, pIrqSelect); // ((PIRQ_SELECT)&dataWord)->FifoShldIrqSel = 1; // FIFO IRQ Enable // SCSI_SWRITEW(baseAddress, pIrqSelect, dataWord); // ((PIRQ_CONTROLP)&DeviceExtension->IrqMaskData)->FifoIrqMask = 0; // FIFO IRQ MASKを解除させる // } // *((PUSHORT) &DevIntIrqStatus) = SCSI_READW(DeviceExtension, irq.pIrqStatus); // *((PUSHORT) &FifoStatus) = SCSI_READW(DeviceExtension, pTransferStatus); // if ( FifoStatus.FifoTrueEmpty) { FifoCount = 32; if ( DeviceExtension->CurDataLength < 32 ) { Ns3DebugPrint(0x2000, ( " : Length[%x] < 32 ",DeviceExtension->CurDataLength)); FifoCount = DeviceExtension->CurDataLength; FifoByte = FifoCount & 3; if ( (FifoCount & 0x7c) ) { Ns3DebugPrint(0x2000, ( " : SCSI_WRITE_FIFOD(%x) ",(FifoCount & 0x7c))); SCSI_WRITE_FIFOD( DeviceExtension, Buffer, (FifoCount & 0x7c) ); } if ( FifoByte ) { // ScsiPortWriteRegisterBufferUchar((PUCHAR)&FifoAlign,(PUCHAR)Buffer, FifoByte); Ns3DebugPrint(0x2000, ( " : SCSI_WRITE_FIFOD( 4) ")); memcpy((PUCHAR)&FifoAlign,(PUCHAR)Buffer, FifoByte); SCSI_WRITE_FIFOD( DeviceExtension, &FifoAlign, 4); Buffer += FifoByte; } } else { Ns3DebugPrint(0x2000, ( " : CurDataLength[%x] >= 32... ",DeviceExtension->CurDataLength)); SCSI_WRITE_FIFOD( DeviceExtension, Buffer, (FifoCount & 0x7c)); } Buffer += FifoCount; DeviceExtension->CurDataLength -= FifoCount ; DeviceExtension->CurDataPointer = Buffer; DeviceExtension->ActiveLogicalUnit->TransferedLength += FifoCount ; // } DeviceExtension->ScsiState = SC_DATA; // 次の FifoEmpty を待つ Ns3DebugPrint(0x2000, ( __FUNCTION__ " : out \n")); } //----------------------------------------------------------------------- // Routine Name: // // Ns3DataInPhase // // Routine Description: // // This routine sets the DmaPending flag in the device extension, // calls the OS-specific driver to set up the system DMA chip, // and returns. Control is received again in DmaStarted when the DMA // setup is complete. // // Arguments: // // DeviceExtension - Device adapter context pointer. // // Return Value: // // TRUE if DMA started // FALSE if missed request // //----------------------------------------------------------------------- VOID Ns3DataInPhase( IN pnins32_host DeviceExtension ) { UCHAR targetId = DeviceExtension->TargetId; UCHAR devType; // ULONG TransferLength = DeviceExtension->CurDataLength; DeviceExtension->InterruptPending = FALSE; // flag clear Ns3DebugPrint(0x4000, ( __FUNCTION__ " : CurDataPointer=%lx ,CurDataLength=%lx\n", DeviceExtension->CurDataPointer, DeviceExtension->CurDataLength)); DeviceExtension->DmaPending = TRUE; devType = DeviceExtension->DeviceType[targetId]; Ns3DebugPrint(0x4000, ( __FUNCTION__ " : devType = %x ", devType)); if ( (DeviceExtension->ActiveLogicalUnit->ActiveLuRequest->request_bufflen < 0x100) || (DeviceExtension->ActiveLogicalUnit->ActiveLuRequest->request_bufflen & 3)|| (DeviceExtension->CurDataLength < 0x100) || (DeviceExtension->CurDataLength & 3) ) { Ns3DebugPrint(0x4000, (" : Ns3SlowReadA \n")); Ns3SlowRead ( DeviceExtension ); // 256以下or4で割れない? return; } //+[v1.00.02] for WinCDR+Sony CDR if ( DeviceExtension->ActiveLogicalUnit->ActiveLuRequest->cmnd/*Cdb*/[0] == 0x43) { Ns3DebugPrint(0x4000, (" : Ns3SlowReadB \n")); Ns3SlowRead ( DeviceExtension ); return; } switch ( devType ) { case 0: case 5: Ns3SpotRead ( DeviceExtension ); // Ns3BurstRead( DeviceExtension ); break; case 6: Ns3SlowRead (DeviceExtension ); break; default: Ns3SpotRead ( DeviceExtension ); break; } Ns3DebugPrint(0x4000, ( __FUNCTION__ " : end")); } // end Ns3DataInPhase() //----------------------------------------------------------------------- // Routine Name: // // Ns3DataOutPhase // // Routine Description: // // This routine sets the DmaPending flag in the device extension, // calls the OS-specific driver to set up the system DMA chip, // and returns. Control is received again in DmaStarted when the DMA // setup is complete. // // Arguments: // // DeviceExtension - Device adapter context pointer. // // Return Value: // // TRUE if DMA started // FALSE if missed request // //----------------------------------------------------------------------- VOID Ns3DataOutPhase( IN pnins32_host DeviceExtension ) { UCHAR targetId = DeviceExtension->TargetId; UCHAR devType; UCHAR dataByte; DeviceExtension->InterruptPending = FALSE; // flag clear Ns3DebugPrint(0x2000, (__FUNCTION__ "ID[%x]: Len=%lx\n",targetId,DeviceExtension->CurDataLength)); DeviceExtension->DmaPending = TRUE; devType = DeviceExtension->DeviceType[targetId]; if ( (DeviceExtension->ActiveLogicalUnit->ActiveLuRequest->request_bufflen < 0x100) || (DeviceExtension->ActiveLogicalUnit->ActiveLuRequest->request_bufflen & 3)) { Ns3DebugPrint(0x2000, (__FUNCTION__ ": bufflen[%x] ",DeviceExtension->ActiveLogicalUnit->ActiveLuRequest->request_bufflen)); Ns3SlowWrite ( DeviceExtension ); return; } dataByte = DeviceExtension->TransferMode; switch ( devType ) { case 0: Ns3SpotWrite ( DeviceExtension ); break; case 6: Ns3SlowWrite ( DeviceExtension ); break; default: Ns3SpotWrite ( DeviceExtension ); break; } } // end Ns3DataOutPhase() //----------------------------------------------------------------------- // TRANSFER // //----------------------------------------------------------------------- // //--- MMIO 32bit DATA INTRANSFER ---- // VOID mmio32_datain (IN pnins32_host DeviceExtension, ULONG Buffer, ULONG xferLength ) { // ULONG SmitBuffer = DeviceExtension->SmitBuffer; ULONG TransferBuffer, TransferLength; PSPECIFIC_LU_EXTENSION LuExtension = DeviceExtension->ActiveLogicalUnit; Scsi_Cmnd *Srb = LuExtension->ActiveLuRequest; ULONG BufferPos,ByteOffset,i; Ns3DebugPrint (0x100,(__FUNCTION__ "in\n")); Ns3DebugPrint (0x100,("IOP_SG_LIST Top = %lx\n",&LuExtension->IOP_SG_LIST[0])); // SG LISTにおける現在地を求める BufferPos = (ULONG)DeviceExtension->CurDataPointer - (ULONG)Srb->request_buffer; // 現在のBufferPosがListの何番めにいるか調べる // またそのListまでのBYTEOFFSETを算出する i = 0; ByteOffset = 0; do { ByteOffset += LuExtension->IOP_SG_LIST[i].BlockCount; if ( BufferPos >= ByteOffset ) i++; else break; } while ( i < LuExtension->SG_Count ); ByteOffset -= LuExtension->IOP_SG_LIST[i].BlockCount; TransferBuffer = LuExtension->IOP_SG_LIST[i].BufferAddress + BufferPos - ByteOffset ; TransferLength = xferLength; if ( LuExtension->IOP_SG_LIST[i].BlockCount < TransferLength ) TransferLength = LuExtension->IOP_SG_LIST[i].BlockCount; // List間にまたがるか? if ( (TransferBuffer + TransferLength) > (LuExtension->IOP_SG_LIST[i].BufferAddress+LuExtension->IOP_SG_LIST[i].BlockCount) ) TransferLength = LuExtension->IOP_SG_LIST[i].BufferAddress + LuExtension->IOP_SG_LIST[i].BlockCount- TransferBuffer; Ns3DebugPrint(0x04, ( "Ns3MMioIn: DataPointer=%lx ,Length=%lx\n", TransferBuffer,TransferLength)); if ( TransferLength !=xferLength ) { i++; TransferBuffer = LuExtension->IOP_SG_LIST[i].BufferAddress; TransferLength = xferLength - TransferLength; } } // //--- MMIO 32bit DATA OUTTRANSFER ---- // VOID mmio32_dataout (IN pnins32_host DeviceExtension , ULONG Buffer, ULONG xferLength ) { ULONG TransferBuffer, TransferLength; PSPECIFIC_LU_EXTENSION LuExtension = DeviceExtension->ActiveLogicalUnit; Scsi_Cmnd *Srb = DeviceExtension->ActiveLogicalUnit->ActiveLuRequest; ULONG BufferPos,ByteOffset,i; Ns3DebugPrint (0x100,(__FUNCTION__ "in\n")); Ns3DebugPrint (0x100,("IOP_SG_LIST Top = %lx\n",&LuExtension->IOP_SG_LIST[0])); // SG LISTにおける現在地を求める BufferPos = (ULONG)DeviceExtension->CurDataPointer - (ULONG)Srb->request_buffer; // 現在のBufferPosがListの何番めにいるか調べる // またそのListまでのBYTEOFFSETを算出する i = 0; ByteOffset = 0; do { ByteOffset += LuExtension->IOP_SG_LIST[i].BlockCount; if ( BufferPos >= ByteOffset ) i++; else break; } while ( i < LuExtension->SG_Count ); ByteOffset -= LuExtension->IOP_SG_LIST[i].BlockCount; TransferBuffer = LuExtension->IOP_SG_LIST[i].BufferAddress + BufferPos - ByteOffset ; TransferLength = xferLength; if ( LuExtension->IOP_SG_LIST[i].BlockCount < TransferLength ) TransferLength = LuExtension->IOP_SG_LIST[i].BlockCount; // List間にまたがるか? if ( (TransferBuffer + TransferLength) > (LuExtension->IOP_SG_LIST[i].BufferAddress+LuExtension->IOP_SG_LIST[i].BlockCount) ) TransferLength = LuExtension->IOP_SG_LIST[i].BufferAddress + LuExtension->IOP_SG_LIST[i].BlockCount- TransferBuffer; Ns3DebugPrint(0x04, ( "Ns3MMioOut: DataPointer=%lx ,Length=%lx\n", TransferBuffer,TransferLength)); if ( TransferLength !=xferLength ) { i++; TransferBuffer = LuExtension->IOP_SG_LIST[i].BufferAddress; TransferLength = xferLength - TransferLength; } // TI PCIC // ScsiPortWritePortUchar((PUCHAR)&((DeviceExtension->BaseAddress)->pIndexReg),0x10); (DeviceExtension->BaseAddress)->pIndexReg = 0x10; } // //--- MMIO 8bit DATA INTRANSFER ---- // VOID mmio8_datain (IN pnins32_host DeviceExtension , ULONG Buffer, ULONG Length ) { Ns3DebugPrint (0x100,(__FUNCTION__ "in\n")); // ScsiPortReadRegisterBufferUchar( (PUCHAR)DeviceExtension->SmitBuffer, (PUCHAR)&Buffer, 64); memcpy((PUCHAR)&Buffer, (PUCHAR)DeviceExtension->SmitBuffer, 64); // TI PCIC // ScsiPortWritePortUchar( // (PUCHAR)&((DeviceExtension->BaseAddress)->pIndexReg),0x10); (DeviceExtension->BaseAddress)->pIndexReg = 0x10; } // //--- MMIO 8bit DATA OUTTRANSFER ---- // VOID mmio8_dataout (IN pnins32_host DeviceExtension , ULONG Buffer, ULONG Length ) { Ns3DebugPrint (0x100,(__FUNCTION__ "in\n")); // ScsiPortWriteRegisterBufferUchar( (PUCHAR)DeviceExtension->SmitBuffer, (PUCHAR)&Buffer, 64); memcpy( (PUCHAR)DeviceExtension->SmitBuffer, (PUCHAR)&Buffer, 64); // TI PCIC // ScsiPortWritePortUchar( (PUCHAR)&((DeviceExtension->BaseAddress)->pIndexReg),0x10); (DeviceExtension->BaseAddress)->pIndexReg = 0x10; } // //--- PIO 32bit DATA INTRANSFER ---- // VOID pio32_datain (IN pnins32_host DeviceExtension , ULONG Buffer, ULONG Length ) { Ns3DebugPrint (0x100,(__FUNCTION__ "in\n")); SCSI_READ_FIFOD(DeviceExtension, Buffer , Length); return; } // //--- PIO 32bit DATA OUTTRANSFER ---- // VOID pio32_dataout (IN pnins32_host DeviceExtension , ULONG Buffer, ULONG Length ) { Ns3DebugPrint (0x100,(__FUNCTION__ "in\n")); SCSI_WRITE_FIFOD(DeviceExtension, Buffer , Length); } // //--- PIO 8bit DATA INTRANSFER ---- // VOID pio8_datain (IN pnins32_host DeviceExtension , void * Buffer, ULONG Length ) { Ns3DebugPrint (0x100,(__FUNCTION__ "in\n")); SCSI_READ_FIFO(DeviceExtension, (void *)Buffer , Length); } // //--- PIO 8bit DATA OUTTRANSFER ---- // VOID pio8_dataout (IN pnins32_host DeviceExtension , void * Buffer, ULONG Length ) { Ns3DebugPrint (0x100,(__FUNCTION__ "in\n")); // SCSI_WRITE_FIFO(DeviceExtension->BaseAddress, Buffer , Length); SCSI_WRITE_FIFO(DeviceExtension, (void *)Buffer , Length); } //----------------------------------------------------------------------- // Routine Name: // // Ns3SendCDB // // Routine Description: // // Send the SCSI Command Descriptor Block (CDB) to the indicated target/lun. // // Arguments: // // DeviceExtension - Device adapter context pointer. // // Return Value: // // None // //----------------------------------------------------------------------- VOID Ns3SendCDB( IN pnins32_host DeviceExtension ) { // PSCSI_REGISTER baseAddress = DeviceExtension->BaseAddress; UCHAR dataByte; USHORT dataWord; Ns3DebugPrint(0x02, ( "Ns3SendCDB: \n")); dataByte = SCSI_READ(DeviceExtension, sc.pScsiBusMonitor); if ( ((PSCSI_BUS_MONITOR)&dataByte)->Scsi_ATN ) { // まだATN ? // SCSI-1デバイスの場合 dataByte = 0; ((PSCSI_BUS_CONTROL)&dataByte)->AutoDirection = 1; ((PSCSI_BUS_CONTROL)&dataByte)->AckEnb = 1; SCSI_WRITE(DeviceExtension, pScsiBusCtrl, dataByte); // ATN off } // TRANSFERCOUNTER CLEAR dataWord = 0; ((PTRANSFER_CONTROL)&dataWord)->TransferGo = 1; ((PTRANSFER_CONTROL)&dataWord)->AllCountClr = 1; SCSI_WRITEW(DeviceExtension, trans.pTransferControl, dataWord); // CDB send dataWord = 0; ((PCOMMAND_CONTROL)&dataWord)->AutoCommandPhase = 1; ((PCOMMAND_CONTROL)&dataWord)->ClrCdbFifoPointer = 1; SCSI_WRITEW(DeviceExtension, _18.pCommandControl, dataWord); DeviceExtension->ScsiState = SC_UNDETERMINED; // // Set up the running data pointer info for a possible data transfer. // DeviceExtension->CurDataPointer = DeviceExtension->ActiveLogicalUnit->SavedDataPointer; DeviceExtension->CurDataLength = DeviceExtension->ActiveLogicalUnit->SavedDataLength; DeviceExtension->ActiveLogicalUnit->TransferedLength = 0; // INTERRUPT許可 DeviceExtension->InterruptPending = TRUE; } // end Ns3SendCDB() //----------------------------------------------------------------------- // Routine Name: // // Ns3AutoStatus // // Routine Description: // // This routine will obtain the status from the target. // // Arguments: // // DeviceExtension - Device adapter context pointer. // // Return Value: // // None // //----------------------------------------------------------------------- VOID Ns3AutoStatus( IN pnins32_host DeviceExtension ) { UCHAR status; // UCHAR dataByte; Scsi_Cmnd *srb; // PSCSI_REGISTER baseAddress = DeviceExtension->BaseAddress; PSPECIFIC_LU_EXTENSION luExtension; PSPECIFIC_TARGET_EXTENSION targetState; luExtension = DeviceExtension->ActiveLogicalUnit; srb = luExtension->ActiveLuRequest; status = SCSI_READ(DeviceExtension, pScsiCsbIn); // Status byte in switch (status) { case SCSISTAT_GOOD: Ns3DebugPrint(0x02, ( ": SCSISTAT_GOOD ")); case SCSISTAT_CONDITION_MET: case SCSISTAT_INTERMEDIATE: case SCSISTAT_INTERMEDIATE_COND_MET: Ns3DebugPrint(0x02, ( ": SCSISTAT_INTERMEDIATE_COND_MET ")); targetState = &DeviceExtension->TargetState[srb->target]; if (srb->cmnd/*Cdb*/[0] == 0x12 && srb->lun == 0 && DeviceExtension->DeviceType[srb->target] == 0xff) { PINQUIRYDATA inquiryData = (PINQUIRYDATA)srb->request_buffer/*DataBuffer*/; Ns3DebugPrint(0x02, ( ": Cdb == 0x12 ")); DeviceExtension->DeviceType[srb->target] = inquiryData->DeviceType; if ( DeviceExtension->DeviceType[srb->target] == 6 || //+[v1.02] DeviceExtension->DeviceType[srb->target] == 3) { targetState->TargetFlags |= PD_SYNCHRONOUS_NEGOTIATION_DONE; targetState->TargetFlags |= PD_DO_NOT_NEGOTIATE; } // EPSON製品だったら非同期 if (!strncmp( inquiryData->VendorId,"EPSO",4 ) ) { targetState->TargetFlags |= PD_SYNCHRONOUS_NEGOTIATION_DONE; targetState->TargetFlags |= PD_DO_NOT_NEGOTIATE; } //+[v0.94] 九松のドライブだったら同期しない { char VUCID[] = {"KME CD-ROM09 "}; PINQUIRYDATA inquiryData = srb->request_buffer; ULONG i; for ( i=0; i<16; i++) if (inquiryData->ProductId[i] != VUCID[i] ) break; if ( i == 16) { targetState->TargetFlags |= PD_SYNCHRONOUS_NEGOTIATION_DONE; targetState->TargetFlags |= PD_DO_NOT_NEGOTIATE; } } if ( !DeviceExtension->ConCheckDone ) { DeviceExtension->NumConnect += 1; if ( srb->target == 7 ) DeviceExtension->ConCheckDone = TRUE; } } if (srb->cmnd/*Cdb*/[0] == 0x25) { Ns3DebugPrint(0x02, ( ": Cdb == 0x25 ")); if ( DeviceExtension->DeviceType[srb->target] == 0x7 && *((PULONG)(srb->request_buffer/*DataBuffer*/)+1) == 0x080000) { PSPECIFIC_TARGET_EXTENSION targetState; targetState = &DeviceExtension->TargetState[srb->target]; targetState->TargetFlags |= PD_NONCACHE; } } //*[v1.01] for Caravelle 8x CD-R if (srb->request_bufflen > DeviceExtension->ActiveLogicalUnit->TransferedLength) { Ns3DebugPrint(0x02, ( ": request_bufflen > TransferedLength ")); srbStatus = SRB_STATUS_DATA_OVERRUN; srb->result = DID_ERROR << 16; } else srbStatus = SRB_STATUS_SUCCESS; Ns3DebugPrint(0x02, ( "Ns3Status: DataLen =%lx\n",srb->request_bufflen )); break; case SCSISTAT_CHECK_CONDITION: Ns3DebugPrint(0x02, (" : SCSISTAT_CHECK_CONDITION ")); case SCSISTAT_COMMAND_TERMINATED: Ns3DebugPrint(0x02, (" : SCSISTAT_COMMAND_TERMINATED ")); srbStatus = SRB_STATUS_ERROR; Ns3DebugPrint(0x02, (" : SRB_STATUS_ERROR\n")); srb->result = DID_SOFT_ERROR << 16; break; case SCSISTAT_BUSY: case SCSISTAT_RESERVATION_CONFLICT: case SCSISTAT_QUEUE_FULL: default: srbStatus = SRB_STATUS_BUSY; srb->result = DID_BUS_BUSY << 16; Ns3DebugPrint(0x002, (__FUNCTION__ " : SRB_STATUS_BUSY\n")); break; } } // end Ns3AutoStatus() //----------------------------------------------------------------------- // Routine Name: // // Ns3AutoMsgIn // // Routine Description: // // This routine will receive the message from the target. // // Arguments: // // DeviceExtension - Device adapter context pointer. // // Return Value: // // None // //----------------------------------------------------------------------- VOID Ns3AutoMsgIn( IN pnins32_host DeviceExtension) { PSPECIFIC_LU_EXTENSION luExtension; Scsi_Cmnd *srb; PUCHAR msg; UCHAR dataByte; PSPECIFIC_TARGET_EXTENSION targetState = 0; USHORT dataWord; luExtension = DeviceExtension->ActiveLogicalUnit; Ns3DebugPrint(0x08, (__FUNCTION__ "in : ")); if ( luExtension ) { // RESELECTIONの時は NULL なので... srb = luExtension->ActiveLuRequest; targetState = &( DeviceExtension->TargetState[srb->target] ); Ns3DebugPrint(0x08, ("luExtension != NULL ")); } msg = &(DeviceExtension->MessageBuffer[DeviceExtension->MessageCount]); // //--- MESSAGE first byte --- dataByte = SCSI_READ(DeviceExtension, sc.pScsiBusMonitor) & S_PHASE_MASK; Ns3DebugPrint(0x08, (__FUNCTION__ ": pScsiBusMonitor = %x ", dataByte)); if ( (dataByte == BM_MESSAGE_IN) && (luExtension) ){ // msg in phase? &request? Ns3DebugPrint(0x08, (": BM_MESSAGE_IN & luExtension ")); *msg = SCSI_READ(DeviceExtension, _22.pScsiDataIn); // msg byte in Ns3DebugPrint(0x08, (": message = [%x]\n", *msg)); dataByte = SCSI_READ(DeviceExtension, pScsiBusCtrl); ((PSCSI_BUS_CONTROL)&dataByte)->AutoDirection = 1; ((PSCSI_BUS_CONTROL)&dataByte)->AckEnb = 1; ((PSCSI_BUS_CONTROL)&dataByte)->ScsiACK = 1; SCSI_WRITE(DeviceExtension , pScsiBusCtrl, dataByte); Ns3WaitForReqOff(DeviceExtension); // REQ off ? // //--- Identify Message ? ---- if ( (*msg & 0x80) && (DeviceExtension->MessageCount == 0)) { Ns3DebugPrint(0x08, (__FUNCTION__ ": Identify Message ?\n")); DeviceExtension->TargetLun = *msg & 0xf; if ( DevIntIrqStatus.ReselectIrq ) { // RESELEC ? Ns3DebugPrint(0x08, (__FUNCTION__ ": ReselectIrq\n")); if ( DeviceExtension->AdapterOption & OPT_AUTOPARA ) Ns3ProcessAutoResel(DeviceExtension); else Ns3ProcessReselection(DeviceExtension); DevIntIrqStatus.ReselectIrq = 0; DevIntIrqStatus.PhaseChgIrq = 0; return; } } else if (DeviceExtension->MessageBuffer[0] != MSG_EXTENDED) { Ns3DebugPrint(0x08, (__FUNCTION__ ": MessageBuffer[0] != MSG_EXTENDED\n")); DeviceExtension->ScsiState = SC_UNDETERMINED; switch ( *msg ) { case MSG_CMDCOMPLETE : DeviceExtension->ScsiState = SC_COMPLETE; Ns3DebugPrint(0x08, (__FUNCTION__ ": MSG_CMDCOMPLETE ")); break; case MSG_DISCONNECT : Ns3DebugPrint(0x08, (__FUNCTION__ ": MSG_DISCONNECT\n")); DeviceExtension->ScsiState = SC_DISCONNECT; break; case MSG_SAVEDATAPOINTER : Ns3DebugPrint(0x08, (__FUNCTION__ ": MSG_SAVEDATAPOINTER\n")); DeviceExtension->ScsiState = SC_DISCONNECT; luExtension->SavedDataPointer = DeviceExtension->CurDataPointer; luExtension->SavedDataLength = DeviceExtension->CurDataLength; break; case MSG_RESTOREPOINTERS: Ns3DebugPrint(0x08, (__FUNCTION__ ": MSG_RESTOREPOINTERS\n")); DeviceExtension->CurDataPointer = luExtension->SavedDataPointer; DeviceExtension->CurDataLength = luExtension->SavedDataLength; break; case MSG_EXTENDED : Ns3DebugPrint(0x08, (__FUNCTION__ ": MSG_EXTENDED\n")); break; case MSG_MESSAGE_REJECT: Ns3DebugPrint(0x08, (__FUNCTION__ ": MSG_MESSAGE_REJECT\n")); if ( luExtension ) { // RESELECTIONの時は NULL なので... if (targetState->TargetFlags & PD_SYNCHRONOUS_TRANSFER_SENT) { targetState->TargetFlags &= ~PD_SYNCHRONOUS_TRANSFER_SENT; targetState->TargetFlags |= PD_DO_NOT_NEGOTIATE; } } break; #ifdef UDEEnable case SCSIMESS_NO_OPERATION: if ( (targetState->TargetFlags & PD_WIDEDATA_TRANSFER_SENT) && ( DeviceExtension->MsgOutBuffer[4] == 0xde)) { targetState->TargetFlags |= PD_DUALEDGE_ENABLE; } break; #endif } // switch } // if msg msg++; DeviceExtension->MessageCount ++; } // if BP dataWord =0; if (DeviceExtension->MessageBuffer[0] == MSG_EXTENDED && DeviceExtension->MessageCount > 1 && (DeviceExtension->MessageBuffer[1]+2) == DeviceExtension->MessageCount ) { Ns3DebugPrint(0x08, (__FUNCTION__ ": before Ns3MessageDecode\n")); if (Ns3MessageDecode( DeviceExtension )) // DECODE 後送るMESSAGEがあれば ((PCOMMAND_CONTROL)&dataWord)->AutoATN = 1; // 次のMESSAGEに備える DeviceExtension->MessageCount = 0; DeviceExtension->MessageBuffer[0] = 0; } // AutoMsgDisable if (DeviceExtension->MessageBuffer[0] != MSG_EXTENDED) { if ( luExtension->XferMode == XMODE_DMA ) { Ns3DebugPrint(0x08, (__FUNCTION__ ": XferMode == XMODE_DMA Sync\n")); ((PCOMMAND_CONTROL)&dataWord)->AutoMsgin00_04 = 1; ((PCOMMAND_CONTROL)&dataWord)->AutoMsgin02 = 1; } } ((PCOMMAND_CONTROL)&dataWord)->AutoCommandPhase = 1; ((PCOMMAND_CONTROL)&dataWord)->ClrCdbFifoPointer = 1; ((PCOMMAND_CONTROL)&dataWord)->AutoScsiRestart = 1; SCSI_WRITEW(DeviceExtension, _18.pCommandControl, dataWord); dataByte = SCSI_READ(DeviceExtension, pScsiBusCtrl); ((PSCSI_BUS_CONTROL)&dataByte)->ScsiACK = 0; SCSI_WRITE(DeviceExtension , pScsiBusCtrl, dataByte); // ACK Off ! Ns3DebugPrint(0x08, (__FUNCTION__ ": pScsiBusCtrl[%x] out\n",dataByte)); } // end Ns3AutoMsgIn() //----------------------------------------------------------------------- // Routine Name: // // Ns3AutoMsgOut // // Routine Description: // // This routine will sent the message to the target. // // Arguments: // // DeviceExtension - Device adapter context pointer. // // Return Value: // // None // //----------------------------------------------------------------------- VOID Ns3AutoMsgOut( IN pnins32_host DeviceExtension ) { // PSCSI_REGISTER baseAddress = DeviceExtension->BaseAddress; UCHAR /*i = 0, */dataByte; // IRQ_STATUS IrqStatus; USHORT dataWord; PSPECIFIC_LU_EXTENSION luExtension; luExtension = DeviceExtension->ActiveLogicalUnit; if ( DeviceExtension->MsgOutCount == 0 ) { DeviceExtension->MsgOutBuffer[0] = MSG_NOOP; //SCSIMESS_NO_OPERATION; DeviceExtension->MessageSent = 0; DeviceExtension->MsgOutCount = 1; } dataByte = SCSI_READ(DeviceExtension, sc.pScsiBusMonitor) & S_PHASE_MASK; if ( dataByte == BM_MESSAGE_OUT ) { // MESSAGE OUT PHASE? dataWord = 0; ((PCOMMAND_CONTROL)&dataWord)->AutoATN = 1; // ATN ON ! -> MESSAGE send MODEへ if ( DeviceExtension->MsgOutCount == 1) { // Last Byte ? SCSI_WRITEW(DeviceExtension ,_18.pCommandControl , 0 ); // ATN Off ! ((PCOMMAND_CONTROL)&dataWord)->AutoATN = 0; } Ns3DebugPrint(0x08, ( "Ns3MessageOut: message = %x\n", DeviceExtension->MsgOutBuffer[DeviceExtension->MessageSent])); SCSI_WRITE(DeviceExtension ,_22.pScsiOutLatch, // MESSAGE out DeviceExtension->MsgOutBuffer[DeviceExtension->MessageSent]); dataByte = SCSI_READ(DeviceExtension, pScsiBusCtrl); ((PSCSI_BUS_CONTROL)&dataByte)->AutoDirection = 1; ((PSCSI_BUS_CONTROL)&dataByte)->AckEnb = 1; ((PSCSI_BUS_CONTROL)&dataByte)->ScsiACK = 1; SCSI_WRITE(DeviceExtension , pScsiBusCtrl, dataByte); Ns3WaitForReqOff(DeviceExtension); // REQ Off ? if ( luExtension->XferMode == XMODE_DMA ) { ((PCOMMAND_CONTROL)&dataWord)->AutoMsgin00_04 = 1; ((PCOMMAND_CONTROL)&dataWord)->AutoMsgin02 = 1; } ((PCOMMAND_CONTROL)&dataWord)->AutoCommandPhase = 1; ((PCOMMAND_CONTROL)&dataWord)->ClrCdbFifoPointer = 1; ((PCOMMAND_CONTROL)&dataWord)->AutoScsiRestart = 1; SCSI_WRITEW(DeviceExtension, _18.pCommandControl, dataWord); ((PSCSI_BUS_CONTROL)&dataByte)->ScsiACK = 0; // ACK Off ! SCSI_WRITE(DeviceExtension , pScsiBusCtrl, dataByte); DeviceExtension->MessageSent++; DeviceExtension->MsgOutCount--; } DeviceExtension->ScsiState = SC_UNDETERMINED; } // end Ns3AutoMsgOut() //----------------------------------------------------------------------- // Routine Name: // // Ns3WaitForAckOff // // Routine Description: // // Spin checking the status of the Ns3 adapter until it indicates that // the SCSI ACK line is Low // // Arguments: // // DeviceExtension - Device adapter context pointer. // // Return Value: // // TRUE - indicates that the SCSI REQUEST line was Negated in time. // FALSE - indicates timeout occurred while waiting for the SCSI REQUEST // line. //----------------------------------------------------------------------- BOOLEAN Ns3WaitForAckOff( pnins32_host DeviceExtension ) { // PSCSI_REGISTER baseAddress = DeviceExtension->BaseAddress; ULONG spinCount = REQUEST_SPIN_WAIT; UCHAR dataByte; Ns3DebugPrint(0x04, (__FUNCTION__ ": in ")); do { dataByte = SCSI_READ(DeviceExtension, sc.pScsiBusMonitor); if ( !((PSCSI_BUS_MONITOR)&dataByte)-> Scsi_ACK ) // ACK Off ? return TRUE; } while (spinCount--); Ns3DebugPrint(0x04, ("TIMEOUT\n")); if (DeviceExtension->ActiveLogicalUnit) { Ns3DebugPrint(0x100, (__FUNCTION__ " : TIME OUT ERROR")); DeviceExtension->ActiveLogicalUnit->ActiveLuRequest->result = DID_TIME_OUT<<16; Ns3NotifyCompletion(DeviceExtension, TRUE); // SP_REQUEST_TIMEOUT, } return FALSE; } // end Ns3WaitForAckOff() //----------------------------------------------------------------------- // Routine Name: // // Ns3WaitForReqOff // // Routine Description: // // Spin checking the status of the Ns3 adapter until it indicates that // the SCSI REQUEST line is high. // // Arguments: // // DeviceExtension - Device adapter context pointer. // // Return Value: // // TRUE - indicates that the SCSI REQUEST line was asserted in time. // FALSE - indicates timeout occurred while waiting for the SCSI REQUEST // line. //----------------------------------------------------------------------- BOOLEAN Ns3WaitForReqOff( pnins32_host DeviceExtension ) { // PSCSI_REGISTER baseAddress = DeviceExtension->BaseAddress; ULONG spinCount = REQUEST_SPIN_WAIT; UCHAR dataByte; Ns3DebugPrint(0x04, (__FUNCTION__ ": in ")); do { dataByte = SCSI_READ(DeviceExtension, sc.pScsiBusMonitor); if ( !((PSCSI_BUS_MONITOR)&dataByte)-> Scsi_REQ ) // REQ Off ? return TRUE; } while (spinCount--); Ns3DebugPrint(0x04, ("TIMEOUT\n")); if (DeviceExtension->ActiveLogicalUnit) { Ns3DebugPrint(0x100, (__FUNCTION__ " : TIME OUT ERROR")); DeviceExtension->ActiveLogicalUnit->ActiveLuRequest->result = DID_TIME_OUT<<16; Ns3NotifyCompletion(DeviceExtension, TRUE); // SP_REQUEST_TIMEOUT } return FALSE; } // end Ns3WaitForReqOff() //----------------------------------------------------------------------- // Routine Name: // // Ns3Status // // Routine Description: // // This routine will obtain the status from the target. // // Arguments: // // DeviceExtension - Device adapter context pointer. // // Return Value: // // None // //----------------------------------------------------------------------- VOID Ns3Status( IN pnins32_host DeviceExtension ) { UCHAR status; UCHAR dataByte; Scsi_Cmnd *srb = DeviceExtension->ActiveLogicalUnit->ActiveLuRequest; PSPECIFIC_TARGET_EXTENSION targetState; dataByte = SCSI_READ(DeviceExtension, sc.pScsiBusMonitor) & S_PHASE_MASK; if ( dataByte == BM_STATUS ) { // Status PHASE? status = SCSI_READ(DeviceExtension, pScsiDataWithAck); // Status byte in Ns3DebugPrint(0x02, ( "Ns3Status: Returned status byte=[%x] ", status)); switch (status) { case SCSISTAT_GOOD: case SCSISTAT_CONDITION_MET: case SCSISTAT_INTERMEDIATE: case SCSISTAT_INTERMEDIATE_COND_MET: targetState = &DeviceExtension->TargetState[srb->target]; if (srb->cmnd/*Cdb*/[0] == 0x12 && srb->lun == 0 && DeviceExtension->DeviceType[srb->target] == 0xff) { PINQUIRYDATA inquiryData = (PINQUIRYDATA)srb->request_buffer/*DataBuffer*/; DeviceExtension->DeviceType[srb->target] = inquiryData->DeviceType; if ( DeviceExtension->DeviceType[srb->target] == 6 || //+[v1.02] DeviceExtension->DeviceType[srb->target] == 3) { targetState->TargetFlags |= PD_SYNCHRONOUS_NEGOTIATION_DONE; targetState->TargetFlags |= PD_DO_NOT_NEGOTIATE; } // EPSON製品だったら非同期 if (!strncmp( inquiryData->VendorId,"EPSO",4 ) ) { targetState->TargetFlags |= PD_SYNCHRONOUS_NEGOTIATION_DONE; targetState->TargetFlags |= PD_DO_NOT_NEGOTIATE; } } //*[v1.01] for Caravelle 8x CD-R if (srb->request_bufflen > DeviceExtension->ActiveLogicalUnit->TransferedLength) { // srbStatus = SRB_STATUS_DATA_OVERRUN; } else // srbStatus = SRB_STATUS_SUCCESS; Ns3DebugPrint(0x02, ( "Ns3Status: DataLen =%ulx\n",srb->request_bufflen )); break; case SCSI_CHECK: case SCSI_COMMAND_TERMINATED: // ? srbStatus = SRB_STATUS_ERROR; break; case SCSI_BUSY: case SCSI_RESERVATION_CONFLICT: case SCSI_QUEUE_FULL: default: // ? srbStatus = SRB_STATUS_BUSY; break; } Ns3WaitForAckOff(DeviceExtension); } // if BM_STATUS DeviceExtension->ScsiState = SC_UNDETERMINED; } // end Ns3Status() //----------------------------------------------------------------------- // Routine Name: // // Ns3MessageIn // // Routine Description: // // This routine will receive the message from the target. // // Arguments: // // DeviceExtension - Device adapter context pointer. // // Return Value: // // None // //----------------------------------------------------------------------- VOID Ns3MessageIn( IN pnins32_host DeviceExtension) { PSPECIFIC_LU_EXTENSION luExtension; Scsi_Cmnd *srb; PSCSI_REGISTER baseAddress; PUCHAR msg; UCHAR dataByte; ULONG MessageCount = 0; BOOLEAN NegAck = TRUE; PSPECIFIC_TARGET_EXTENSION targetState = 0; Ns3DebugPrint(0x08,(__FUNCTION__" in :")); baseAddress = DeviceExtension->BaseAddress; msg = &(DeviceExtension->MessageBuffer[0]); DeviceExtension->MessageCount = 0; luExtension = DeviceExtension->ActiveLogicalUnit; Ns3DebugPrint(0x08,(__FUNCTION__" luExtension[%p] :",luExtension)); if ( luExtension ) { srb = luExtension->ActiveLuRequest; Ns3DebugPrint(0x08,(__FUNCTION__" ActiveLuRequest[%p] target[%x]:",luExtension->ActiveLuRequest,srb->target)); targetState = &(DeviceExtension->TargetState[srb->target]); } Ns3DebugPrint(0x08,(__FUNCTION__" : IrqMask = %x\n",DeviceExtension->IrqMaskData)); // //--- MESSAGE FirstByte --- // dataByte = SCSI_READ(DeviceExtension, sc.pScsiBusMonitor) & S_PHASE_MASK; Ns3DebugPrint(0x08,(__FUNCTION__" : ScsiBusMonitor = %x\n",dataByte)); if ( dataByte == BM_MESSAGE_IN ) { // MESSAGE IN PHASE? *msg = SCSI_READ(DeviceExtension, _22.pScsiDataIn); // msg byte in Ns3DebugPrint(0x08, ( __FUNCTION__": message = %x ", *msg)); dataByte = SCSI_READ(DeviceExtension, pScsiBusCtrl); ((PSCSI_BUS_CONTROL)&dataByte)->AutoDirection = 1; ((PSCSI_BUS_CONTROL)&dataByte)->AckEnb = 1; //+[32bit] ((PSCSI_BUS_CONTROL)&dataByte)->ScsiACK = 1; //+[32bit] SCSI_WRITE(DeviceExtension , pScsiBusCtrl, dataByte); Ns3WaitForReqOff(DeviceExtension); // REQ Off ? // //--- Identify Message ? ---- // if ( *msg & 0x80 ) { Ns3DebugPrint(0x08, ( ": Identify Message ")); DeviceExtension->TargetLun = *msg & 0xf; // if ( DeviceExtension->ScsiState == SC_RESELECT ) // RESELECT? if ( DevIntIrqStatus.ReselectIrq ) { Ns3DebugPrint(0x08, ( ": ReSelect ")); if ( DeviceExtension->AdapterOption & OPT_AUTOPARA ) Ns3ProcessAutoResel(DeviceExtension); else Ns3ProcessReselection(DeviceExtension); DevIntIrqStatus.ReselectIrq = 0; DevIntIrqStatus.PhaseChgIrq = 0; return; } } else { DeviceExtension->ScsiState = SC_UNDETERMINED; switch ( *msg ) { case MSG_CMDCOMPLETE : Ns3DebugPrint(0x08, ( ": MSG_CMDCOMPLETE ")); DeviceExtension->ScsiState = SC_COMPLETE; break; case MSG_DISCONNECT : Ns3DebugPrint(0x08, (__FUNCTION__ ": MSG_DISCONNECT\n" )); DeviceExtension->ScsiState = SC_DISCONNECT; //+[32bit] luExtension->SavedDataPointer = DeviceExtension->CurDataPointer; luExtension->SavedDataLength = DeviceExtension->CurDataLength; break; case MSG_SAVEDATAPOINTER : MessageCount = 1; // Wait DISCONNECT MESSAGE Ns3DebugPrint(0x08, (__FUNCTION__ ": MSG_SAVEDATAPOINTER\n" )); DeviceExtension->ScsiState = SC_DISCONNECT; luExtension->SavedDataPointer = DeviceExtension->CurDataPointer; luExtension->SavedDataLength = DeviceExtension->CurDataLength; break; case MSG_RESTOREPOINTERS: Ns3DebugPrint(0x08, ( ": MSG_RESTOREPOINTERS ")); DeviceExtension->CurDataPointer = luExtension->SavedDataPointer; DeviceExtension->CurDataLength = luExtension->SavedDataLength; break; case MSG_EXTENDED : Ns3DebugPrint(0x08, ( ": MSG_EXTENDED ")); MessageCount = 6; if (targetState->TargetFlags & PD_SYNCHRONOUS_TRANSFER_SENT) MessageCount = 4; NegAck = FALSE; break; case MSG_MESSAGE_REJECT: Ns3DebugPrint(0x08, ( ": MSG_MESSAGE_REJECT ")); if (targetState->TargetFlags & PD_SYNCHRONOUS_TRANSFER_SENT) { targetState->TargetFlags &= ~PD_SYNCHRONOUS_TRANSFER_SENT; targetState->TargetFlags |= PD_DO_NOT_NEGOTIATE; } break; default: Ns3DebugPrint(0x08, ( ": MSG_??? ")); break; } } dataByte = SCSI_READ(DeviceExtension, pScsiBusCtrl); ((PSCSI_BUS_CONTROL)&dataByte)->ScsiACK = 0; SCSI_WRITE(DeviceExtension , pScsiBusCtrl, dataByte); // ACK Off ! msg++; DeviceExtension->MessageCount ++; } Ns3DebugPrint(0x08, (": MessageCount[%x],[%x]", MessageCount,NegAck)); *((PUSHORT) &DevIntIrqStatus) = SCSI_READW(DeviceExtension,irq.pIrqStatus); Ns3DebugPrint(0x08, (__FUNCTION__ ": IrqStatus = %x\n", *((PUSHORT) &DevIntIrqStatus))); while ( !(DevIntIrqStatus.PhaseChgIrq)) { // Phase Change dataByte = SCSI_READ(DeviceExtension, sc.pScsiBusMonitor) & S_PHASE_MASK; //-[v0.50] for OLMPUS MO // if ((MessageCount == 0) && ((dataByte & 0x7) != BP_MESSAGE_IN) ) // break; if ( dataByte == BM_MESSAGE_IN ) { // MESSAGE IN PHASE? *((PUSHORT) &DevIntIrqStatus) = SCSI_READW(DeviceExtension,irq.pIrqStatus); if ( DevIntIrqStatus.PhaseChgIrq ) break; *msg = SCSI_READ(DeviceExtension, _22.pScsiDataIn); // msg byte in if ( *msg == MSG_DISCONNECT ) { Ns3DebugPrint(0x08, (": MSG_DISCONNECT " )); DeviceExtension->ScsiState = SC_DISCONNECT; } Ns3DebugPrint(0x08, (__FUNCTION__ ": message = %x\n", *msg)); dataByte = SCSI_READ(DeviceExtension, pScsiBusCtrl); ((PSCSI_BUS_CONTROL)&dataByte)->ScsiACK = 1; SCSI_WRITE(DeviceExtension , pScsiBusCtrl, dataByte); // ACK On ! Ns3WaitForReqOff(DeviceExtension); // REQ off ? if ( ( MessageCount != 1) || ( MessageCount == 1 && NegAck )) { dataByte = SCSI_READ(DeviceExtension, pScsiBusCtrl); ((PSCSI_BUS_CONTROL)&dataByte)->ScsiACK = 0; SCSI_WRITE(DeviceExtension , pScsiBusCtrl, dataByte); // ACK Off ! } msg++; DeviceExtension->MessageCount ++; if ( MessageCount != 0 ) MessageCount--; if ( MessageCount == 0 && !NegAck ) break; } *((PUSHORT) &DevIntIrqStatus) = SCSI_READW(DeviceExtension,irq.pIrqStatus); } // while ( !(DevIntIrqStatus.PhaseChgIrq)); // still Phase Change if (DeviceExtension->MessageBuffer[0] == MSG_EXTENDED ) { dataByte = SCSI_READ(DeviceExtension, pScsiBusCtrl); ((PSCSI_BUS_CONTROL)&dataByte)->ScsiACK = 0; // ACK Off ! if (Ns3MessageDecode( DeviceExtension )) // DECODE ((PSCSI_BUS_CONTROL)&dataByte)->ScsiATN = 1; // ATN On ! SCSI_WRITE(DeviceExtension , pScsiBusCtrl, dataByte); } Ns3DebugPrint(0x08, (__FUNCTION__ ": out\n")); } // end Ns3MessageIn() //----------------------------------------------------------------------- // Routine Name: // // Ns3MessageOut // // Routine Description: // // This routine will sent the message to the target. // // Arguments: // // DeviceExtension - Device adapter context pointer. // // Return Value: // // None // //----------------------------------------------------------------------- VOID Ns3MessageOut( IN pnins32_host DeviceExtension ) { // PSCSI_REGISTER baseAddress = DeviceExtension->BaseAddress; UCHAR dataByte; PUCHAR msg = &DeviceExtension->MsgOutBuffer[0]; if ( DeviceExtension->MsgOutCount == 0 ) { DeviceExtension->MsgOutBuffer[0] = MSG_NOOP; // SCSIMESS_NO_OPERATION; DeviceExtension->MsgOutCount = 1; } do { *((PUSHORT) &DevIntIrqStatus) = SCSI_READW(DeviceExtension, irq.pIrqStatus); if (DevIntIrqStatus.PhaseChgIrq) break; //+[32bit] dataByte = SCSI_READ(DeviceExtension , pScsiBusCtrl); ((PSCSI_BUS_CONTROL)&dataByte)->AutoDirection = 1; SCSI_WRITE(DeviceExtension , pScsiBusCtrl, dataByte); dataByte = SCSI_READ(DeviceExtension, sc.pScsiBusMonitor) & S_PHASE_MASK; if ( dataByte == BM_MESSAGE_OUT ) { // MESSAGE OUT PHASE? if ( DeviceExtension->MsgOutCount == 1) // Last Byte ? SCSI_WRITEW(DeviceExtension ,_18.pCommandControl , 0 ); // ATN Off ! Ns3DebugPrint(0x08, ( "Ns3MessageOut: message = %x\n", *msg)); SCSI_WRITE(DeviceExtension ,pScsiDataWithAck, *msg); // MESSAGE out Ns3WaitForAckOff(DeviceExtension); msg++; DeviceExtension->MsgOutCount--; } } while ( DeviceExtension->MsgOutCount != 0 ); Ns3DebugPrint(0x08, ( "\n")); if ( DevIntIrqStatus.PhaseChgIrq && DeviceExtension->MsgOutCount != 0) SCSI_WRITEW(DeviceExtension ,_18.pCommandControl , 0 ); // ATN Off ! DeviceExtension->ScsiState = SC_UNDETERMINED; } // end Ns3MessageOut() //----------------------------------------------------------------------- // Routine Name: // // Ns3RunPhase // // Routine Description: // // This routine runs through the bus phases until some type of completion // indication is received. // // Arguments: // // DeviceExtension - Device adapter context pointer. // // Return Value: // // None. // //----------------------------------------------------------------------- VOID Ns3RunPhase( IN pnins32_host DeviceExtension ) { PSCSI_REGISTER baseAddress = DeviceExtension->BaseAddress; ULONG Count; PSPECIFIC_TARGET_EXTENSION targetState; PSPECIFIC_LU_EXTENSION luExtension; luExtension = DeviceExtension->ActiveLogicalUnit; Ns3DebugPrint(0x10, ( __FUNCTION__ " in\n")); // //--- BUS FREE ( DISCONNETCT ) ? ---- // if ( DevIntIrqStatus.LatchBusFree ) { Ns3DebugPrint(0x10, ( __FUNCTION__ " LatchBusFree\n")); SCSI_WRITEW(DeviceExtension, trans.pTransferControl, 0); SCSI_WRITED(DeviceExtension, pBmCnt, 0); // dataByte = DeviceExtension->TransferMode; // mode FIFOtest/option // ((PTRANSFER_MODE)&dataByte)->TransferGo = 0; // ((PTRANSFER_MODE)&dataByte)->FifoTest_Braind = 0; // SCSI_WRITE(DeviceExtension, pTransferMode, dataByte); // TRANSFERMODESET Count = 0; if (luExtension->XferMode == XMODE_DMA) { Count = luExtension->pSGlist->TransferDataBuffer[luExtension->Current_SG_Entry].Address & 3; } luExtension->TransferedLength += SCSI_READD(DeviceExtension, pSackCnt) - Count; if ( DeviceExtension->ScsiState == SC_COMPLETE ) { Ns3DebugPrint(0x10, ( __FUNCTION__ " SC_COMPLETE\n")); DeviceExtension->ActiveLogicalUnit->ActiveLuRequest->result = DID_OK<< 16; Ns3NotifyCompletion(DeviceExtension, (BOOLEAN)(!luExtension->NextReq)); DeviceExtension->ScsiState = SC_BUSFREE; DeviceExtension->IntWait = FALSE; if (DeviceExtension->AdapterFlags & PD_PENDING_START_IO) { //+[v1.10] // tor Ns3StartIo(DeviceExtension,DeviceExtension->NextSrbRequest ); Ns3DebugPrint(0x10, (__FUNCTION__ ":Ns3StartIo(->NextSrbRequest \n")); } DevIntIrqStatus.LatchBusFree = 0; DevIntIrqStatus.PhaseChgIrq = 0; return; } else if (DeviceExtension->ScsiState == SC_DISCONNECT ) { DeviceExtension->ScsiState = SC_BUSFREE; Ns3DebugPrint(0x10,( __FUNCTION__": SCSI bus disconnect\n")); if (DeviceExtension->AdapterFlags & PD_PENDING_START_IO) { //+[v1.10] Ns3DebugPrint(0x10, (__FUNCTION__ ":Ns3StartIo(NextSrbRequest2 \n")); } DevIntIrqStatus.LatchBusFree = 0; DevIntIrqStatus.PhaseChgIrq = 0; return; } DevIntIrqStatus.LatchBusFree = 0; Ns3DebugPrint(0x10,( __FUNCTION__": Unexpected bus disconnect.\n")); targetState = &DeviceExtension->TargetState[DeviceExtension ->TargetId]; if (targetState->TargetFlags & PD_SYNCHRONOUS_TRANSFER_SENT) { Ns3DebugPrint(0x10, ( __FUNCTION__ " PD_SYNCHRONOUS_TRANSFER_SENT\n")); targetState->TargetFlags &= ~PD_SYNCHRONOUS_TRANSFER_SENT; targetState->TargetFlags |= PD_DO_NOT_NEGOTIATE; } DeviceExtension->ScsiState = SC_BUSFREE; if ( luExtension ) { Ns3DebugPrint(0x100, ( " : GO DID_NO_CONNECT")); DeviceExtension->ActiveLogicalUnit->ActiveLuRequest->result = DID_NO_CONNECT<<16; Ns3NotifyCompletion(DeviceExtension, TRUE); } if (DeviceExtension->AdapterFlags & PD_PENDING_START_IO) { //+[v1.10] // tor Ns3StartIo(DeviceExtension,DeviceExtension->NextSrbRequest ); Ns3DebugPrint(0x10, (__FUNCTION__ ":Ns3StartIo(NextSrbRequest 3 \n")); } return; } // //--- PHASE CHANGE ? --- // DeviceExtension->ScsiPrePhase = SCSI_SREAD(baseAddress,pOldScsiPhase); Ns3DebugPrint(0x10, ( __FUNCTION__ " Phase[%x]\n",( (*(PUSHORT)&DevIntIrqStatus) & 7 ))); switch ( (*(PUSHORT)&DevIntIrqStatus) & 7 ) { case BP_COMMAND: Ns3SendCDB(DeviceExtension);//COMMANDPHASE START DevIntIrqStatus.PhaseChgIrq = 0; break; case BP_DATA_IN: Ns3DataInPhase(DeviceExtension); //DATA PHASE START break; case BP_DATA_OUT: Ns3DataOutPhase(DeviceExtension); //DATA PHASE START break; case BP_STATUS: Ns3Status(DeviceExtension); DevIntIrqStatus.PhaseChgIrq = 0; break; case BP_MESSAGE_IN: Ns3MessageIn(DeviceExtension); break; case BP_MESSAGE_OUT: Ns3MessageOut(DeviceExtension); break; default: Ns3DebugPrint(0x10, ( __FUNCTION__ " Phase default\n")); DeviceExtension->ScsiState = SC_COMPLETE; // tor luExtension->ActiveLuRequest->SrbStatus = // tor SRB_STATUS_PHASE_SEQUENCE_FAILURE; DevIntIrqStatus.PhaseChgIrq = 0; break; } } // end Ns3RunPhase() //----------------------------------------------------------------------------- // RESELECTION // //Routine Description: Ns3ProcessReselection // // This function updates the device extension and the logical unit extension // when target reselects. If necessary, the DMA is set up. This routine // should be called before the identify message has been accepted. The SCSI // protocol chip will be restarted with either a select-and-transfer command // or a message accept. // //Arguments: // // DeviceExtension - Supplies a pointer to the specific device extension. // // TargetId - Supplies the target id of the reselecting target. // // LogicalUnitNumber - Supplies the logical unit number of the reselecting // target. // //Return Value: // // TRUE - Returned if the reselection is valid. // // FALSE - Returned if the reselection is invalid and ATN should be set. // //----------------------------------------------------------------------------- BOOLEAN Ns3ProcessReselection( IN pnins32_host DeviceExtension ) { PSPECIFIC_LU_EXTENSION luExtension; Scsi_Cmnd *srb; PSPECIFIC_TARGET_EXTENSION targetState; UCHAR dataByte; CHAR TargetId; LONG i; USHORT dataWord, dataXmode; Ns3DebugPrint(0x10,(__FUNCTION__ ": in\n")); TargetId = (UCHAR)(SCSI_READ(DeviceExtension, _18.reselect.pReselectId) & 0x7f); i = 0xffffffff; while ( TargetId > 0 ) { i++; TargetId = TargetId >> 1; } DeviceExtension->TargetId = (UCHAR)i; Ns3DebugPrint(0x10,(__FUNCTION__ ": Id/Lun(%d,%d)\n",DeviceExtension->TargetId,DeviceExtension->TargetLun)); // // Get the specific logical unit extension. // luExtension = ScsiPortGetLogicalUnit(DeviceExtension,/*pathId,*/ DeviceExtension->TargetId, DeviceExtension->TargetLun ); DeviceExtension->ActiveLogicalUnit = luExtension; if(!luExtension) { DeviceExtension->ActiveLogicalUnit->ActiveLuRequest->result = DID_ABORT <<16; Ns3NotifyCompletion(DeviceExtension, TRUE); return FALSE; } if (!luExtension || !luExtension->ActiveLuRequest) { Ns3DebugPrint(0x10,( ": Reselection Failed.\n")); // // Send an abort message. Put the message-in the buffer, set the // state, indicate that a disconnect is expected after this, and // set the attention signal. // DeviceExtension->MsgOutBuffer[0] = MSG_ABORT; // SCSIMESS_ABORT; DeviceExtension->MsgOutCount = 1; DeviceExtension->MessageSent = 0; // DeviceExtension->AdapterState = MessageOut; // DeviceExtension->AdapterFlags &= ~PD_ADAPTER_DISCONNECT_MASK; // DeviceExtension->AdapterFlags |= PD_MESSAGE_OUT_VALID | // PD_DISCONNECT_EXPECTED; // // The target and logical unit specified are not valid. A // MESSAGE REJECT message has been set up. Set ATN and accept the // message. // // TRANSFERMODEの設定 dataWord = 0; // ((PTRANSFER_CONTROL)&dataWord)->BmStart = 1; ((PTRANSFER_CONTROL)&dataWord)->TransferGo = 1; ((PTRANSFER_CONTROL)&dataWord)->AllCountClr = 1; SCSI_WRITEW(DeviceExtension, trans.pTransferControl, dataWord); // Restart AUTO SCSI dataWord = 0; ((PCOMMAND_CONTROL)&dataWord)->AutoMsgin00_04 = 1; ((PCOMMAND_CONTROL)&dataWord)->AutoMsgin02 = 1; ((PCOMMAND_CONTROL)&dataWord)->AutoScsiRestart = 1; ((PCOMMAND_CONTROL)&dataWord)->AutoATN = 1; // ATN ON ! SCSI_WRITEW(DeviceExtension, _18.pCommandControl, dataWord); dataByte = SCSI_READ(DeviceExtension, pScsiBusCtrl); ((PSCSI_BUS_CONTROL)&dataByte)->ScsiACK = 0; // ACK Off ! SCSI_WRITE(DeviceExtension , pScsiBusCtrl, dataByte); Ns3DebugPrint(0x10,(__FUNCTION__ ": FALSE\n\n\n")); return(FALSE); } srb = luExtension->ActiveLuRequest; targetState = &DeviceExtension->TargetState[i]; again_bm:; DeviceExtension->CurDataPointer = luExtension->SavedDataPointer; DeviceExtension->CurDataLength = luExtension->SavedDataLength; if ( luExtension->XferMode == XMODE_DMA && #ifdef NINJA32UDE luExtension->TargetFlags & PD_NONCACHE && #else targetState->TargetFlags & PD_NONCACHE && #endif DeviceExtension->CurDataLength > 0 ) { if (is_dir_out(srb)) { PSG_LIST SGlist = luExtension->pSGlist ; SGlist->TransferDataBuffer[0].Address = DeviceExtension->NonCachedPhysical; SGlist->TransferDataBuffer[0].Length = DeviceExtension->CurDataLength | BM_LAST; memcpy(DeviceExtension->NonCachedExtension->Address, (PVOID)DeviceExtension->CurDataPointer, DeviceExtension->CurDataLength); } } // Set sync parameter #if 0 // Writeだったら10MB --> G/AではOK if ( (targetState->TargetSrbFlags & SRB_FLAGS_DATA_OUT) && (targetState->SynchronousPeriod == 1)) { dataByte = 0; ((PSYNC_REG)&dataByte)->SyncPeriod = 3; ((PSYNC_REG)&dataByte)->SyncOffset = targetState->SynchronousOffset; SCSI_WRITE(DeviceExtension, pSyncReg, dataByte); SCSI_WRITE(DeviceExtension, pAckWidth, 1); } else { #endif dataByte = 0; ((PSYNC_REG)&dataByte)->SyncPeriod = targetState->SynchronousPeriod; ((PSYNC_REG)&dataByte)->SyncOffset = targetState->SynchronousOffset; SCSI_WRITE(DeviceExtension, pSyncReg,dataByte); SCSI_WRITE(DeviceExtension, pAckWidth, targetState->AckWidth); // } //Scatter/Gather TABLE ADDRESS の設定 Ns3DebugPrint(0x10,(__FUNCTION__ ": Set Scatter/Gather table address\n")); #ifndef NINJA32UDE SCSI_WRITED(DeviceExtension, pBmCnt, 0); #endif if ( DeviceExtension->CurDataLength ) { Ns3DebugPrint(0x10,(__FUNCTION__": address is [%x]\n",(luExtension->PhySGlist + (luExtension->Current_SG_Entry*8)) )); SCSI_WRITED(DeviceExtension, pSgAdr, luExtension->PhySGlist + (luExtension->Current_SG_Entry*8) ); } #ifdef NINJA32UDE SCSI_WRITED(DeviceExtension, pBmCnt, 0); // clear counter +[ude] SCSI_WRITE(DeviceExtension, sc.pClearCounter , 0x2f); // All Pointer Clear #endif // NINJA32UDE // Restart AUTO SCSI dataWord = 0; if ( luExtension->XferMode == XMODE_DMA){ ((PCOMMAND_CONTROL)&dataWord)->AutoMsgin00_04 = 1; ((PCOMMAND_CONTROL)&dataWord)->AutoMsgin02 = 1; } Ns3DebugPrint(0x10,(":AutoScsiRestart\n" )); ((PCOMMAND_CONTROL)&dataWord)->AutoScsiRestart = 1; SCSI_WRITEW(DeviceExtension, _18.pCommandControl, dataWord); // Set TRANSFERMODE dataXmode = 0; ((PTRANSFER_CONTROL)&dataXmode)->TransferGo = 1; if ( DeviceExtension->CurDataLength && (luExtension->XferMode == XMODE_DMA) ) ((PTRANSFER_CONTROL)&dataXmode)->BmStart = 1; if ( luExtension->XferMode == XMODE_PIO32 ) { ((PTRANSFER_CONTROL)&dataXmode)->CB_PIO_Mode = 1; // ((PTRANSFER_CONTROL)&dataXmode)->BlindMode = 1; luExtension->pXferRead = DeviceExtension->pXferRead; luExtension->pXferWrite = DeviceExtension->pXferWrite; } else if ( luExtension->XferMode == XMODE_MMIO){ ((PTRANSFER_CONTROL)&dataXmode)->CB_MMIO_Mode = 1; // ((PTRANSFER_CONTROL)&dataXmode)->BlindMode = 1; luExtension->pXferRead = DeviceExtension->pXferRead; luExtension->pXferWrite = DeviceExtension->pXferWrite; } #ifndef NINJA32UDE ((PTRANSFER_CONTROL)&dataXmode)->AllCountClr = 1; #endif SCSI_WRITEW(DeviceExtension, trans.pTransferControl, dataXmode); DeviceExtension->ScsiState = SC_RESELECT; Ns3DebugPrint(0x10,( ": Reselect Start ID=%d\n",DeviceExtension->TargetId)); // Ns3SetTransferMode( DeviceExtension ); // TRANSFERMODE SET // // A reselection has been completed. Set the active logical unit, // restore the active data pointer, set the state. // In addition, any adapter flags set by a pending select must be // cleared using the disconnect mask. // DeviceExtension->MessageCount = 0; // Set INTERRUPT MASK if ( luExtension->XferMode == XMODE_PIO32 || luExtension->XferMode == XMODE_MMIO) ((PIRQ_CONTROLP)&DeviceExtension->IrqMaskData)->FifoIrqMask = 0; else ((PIRQ_CONTROLP)&DeviceExtension->IrqMaskData)->FifoIrqMask = 1; #if 0 // Sg table TRANSFERed? if ( ((PTRANSFER_CONTROL)&dataXmode)->BmStart ) { bmcnt = 0; while ( bmcnt == 0) { bmcnt = SCSI_READD(DeviceExtension,pBmCnt); } } #endif if ( ((PTRANSFER_CONTROL)&dataXmode)->BmStart ) { Ns3DebugPrint(0x10,(__FUNCTION__ ": dataXmode->BmStart\n")); dataByte = 0; while (!((PARBIT_STATUS)&dataByte)->SgTableValid ) { dataByte = SCSI_READ(DeviceExtension, _1a.pArbitStatus); // Parameter TRANSFERされた? //+[v0.98] vvv dataWord = SCSI_READW(DeviceExtension, trans.pTransferControl); if(! ((PTRANSFER_CONTROL)&dataWord)->BmStart) { // BM START? // SCSI_WRITE(DeviceExtension,pScsiCsbIn,0); // for DEBUG // __asm__ int 3; goto again_bm; // もう一度設定 -> } } } dataByte = SCSI_READ(DeviceExtension, pScsiBusCtrl); ((PSCSI_BUS_CONTROL)&dataByte)->ScsiACK = 0; // ACK Off ! SCSI_WRITE(DeviceExtension , pScsiBusCtrl, dataByte); Ns3DebugPrint(0x10,(__FUNCTION__ ": end\n")); return(TRUE); } // Ns3ProcessReselection //----------------------------------------------------------------------------- // AUTO PARAMETER RESELECTION // //Routine Description: Ns3ProcessAutoResel // // This function updates the device extension and the logical unit extension // when target reselects. If necessary, the DMA is set up. This routine // should be called before the identify message has been accepted. The SCSI // protocol chip will be restarted with either a select-and-transfer command // or a message accept. // //Arguments: // // DeviceExtension - Supplies a pointer to the specific device extension. // // TargetId - Supplies the target id of the reselecting target. // // LogicalUnitNumber - Supplies the logical unit number of the reselecting // target. // //Return Value: // // TRUE - Returned if the reselection is valid. // // FALSE - Returned if the reselection is invalid and ATN should be set. // //----------------------------------------------------------------------------- BOOLEAN Ns3ProcessAutoResel( IN pnins32_host DeviceExtension ) { PSPECIFIC_LU_EXTENSION luExtension; Scsi_Cmnd *srb; PSPECIFIC_TARGET_EXTENSION targetState; UCHAR dataByte; CHAR TargetId; LONG i; USHORT dataWord, dataXmode; PAUTO_PARA AutoPara; TargetId = (UCHAR)(SCSI_READ(DeviceExtension, _18.reselect.pReselectId) & 0x7f); i = 0xffffffff; while ( TargetId > 0 ) { i++; TargetId = TargetId >> 1; } DeviceExtension->TargetId = (UCHAR)i; // // Get the specific logical unit extension. // luExtension = ScsiPortGetLogicalUnit(DeviceExtension, DeviceExtension->TargetId, DeviceExtension->TargetLun ); DeviceExtension->ActiveLogicalUnit = luExtension; if (!luExtension || !luExtension->ActiveLuRequest) { Ns3DebugPrint(0x10,(__FUNCTION__ ": Reselection Failed.\n")); // // Send an abort message. Put the message-in the buffer, set the // state, indicate that a disconnect is expected after this, and // set the attention signal. // DeviceExtension->MsgOutBuffer[0] = MSG_ABORT; // SCSIMESS_ABORT; DeviceExtension->MsgOutCount = 1; DeviceExtension->MessageSent = 0; // DeviceExtension->AdapterState = MessageOut; // DeviceExtension->AdapterFlags &= ~PD_ADAPTER_DISCONNECT_MASK; // DeviceExtension->AdapterFlags |= PD_MESSAGE_OUT_VALID | // PD_DISCONNECT_EXPECTED; // // The target and logical unit specified are not valid. A // MESSAGE REJECT message has been set up. Set ATN and accept the // message. // // Set TRANSFERMODE dataWord = 0; // ((PTRANSFER_CONTROL)&dataWord)->BmStart = 1; ((PTRANSFER_CONTROL)&dataWord)->TransferGo = 1; ((PTRANSFER_CONTROL)&dataWord)->AllCountClr = 1; SCSI_WRITEW(DeviceExtension, trans.pTransferControl, dataWord); // Restart AUTO SCSI dataWord = 0; ((PCOMMAND_CONTROL)&dataWord)->AutoMsgin00_04 = 1; ((PCOMMAND_CONTROL)&dataWord)->AutoMsgin02 = 1; ((PCOMMAND_CONTROL)&dataWord)->AutoScsiRestart = 1; ((PCOMMAND_CONTROL)&dataWord)->AutoATN = 1; // ATN ON ! SCSI_WRITEW(DeviceExtension, _18.pCommandControl, dataWord); dataByte = SCSI_READ(DeviceExtension, pScsiBusCtrl); ((PSCSI_BUS_CONTROL)&dataByte)->ScsiACK = 0; // ACK Off ! SCSI_WRITE(DeviceExtension , pScsiBusCtrl, dataByte); return(FALSE); } srb = luExtension->ActiveLuRequest; targetState = &DeviceExtension->TargetState[i]; DeviceExtension->CurDataPointer = luExtension->SavedDataPointer; DeviceExtension->CurDataLength = luExtension->SavedDataLength; if (luExtension->XferMode == XMODE_DMA && #ifdef NINJA32UDE luExtension->TargetFlags & PD_NONCACHE && #else targetState->TargetFlags & PD_NONCACHE && #endif DeviceExtension->CurDataLength > 0 ){ if (is_dir_out(srb)) { PSG_LIST SGlist = luExtension->pSGlist ; SGlist->TransferDataBuffer[0].Address = DeviceExtension->NonCachedPhysical; SGlist->TransferDataBuffer[0].Length = DeviceExtension->CurDataLength | BM_LAST; memcpy(DeviceExtension->NonCachedExtension->Address, (PVOID)DeviceExtension->CurDataPointer, DeviceExtension->CurDataLength); } } AutoPara = luExtension->SrbExtension; #ifdef NINJA32UDE // Counter Clear+[ude] SCSI_WRITE(DeviceExtension, sc.pClearCounter , 0x3f); // All Pointer Clear AutoPara->TargetId = i; //+[ude] AutoPara->SmplRate = 0; //+[ude] #endif // Set sync parameter #if 0 // Writeだったら10MB --> G/AではOK if ( (targetState->TargetSrbFlags & SRB_FLAGS_DATA_OUT) && (targetState->SynchronousPeriod == 1)) { dataByte = 0; ((PSYNC_REG)&dataByte)->SyncPeriod = 3; ((PSYNC_REG)&dataByte)->SyncOffset = targetState->SynchronousOffset; AutoPara->SyncReg = dataByte; AutoPara->AckWidth = 1; } else { #endif dataByte = 0; ((PSYNC_REG)&dataByte)->SyncPeriod = targetState->SynchronousPeriod; ((PSYNC_REG)&dataByte)->SyncOffset = targetState->SynchronousOffset; AutoPara->SyncReg = dataByte; AutoPara->AckWidth = targetState->AckWidth; // } //Scatter/Gather TABLE ADDRESS SCSI_WRITED(DeviceExtension, pBmCnt, 0); if ( DeviceExtension->CurDataLength ) { AutoPara->SgAdr = luExtension->PhySGlist + (luExtension->Current_SG_Entry*8) ; } // Set TRANSFERMODE dataXmode = 0; ((PTRANSFER_CONTROL)&dataXmode)->TransferGo = 1; if ( DeviceExtension->CurDataLength && (luExtension->XferMode == XMODE_DMA) ) ((PTRANSFER_CONTROL)&dataXmode)->BmStart = 1; if ( luExtension->XferMode == XMODE_PIO32 ) { ((PTRANSFER_CONTROL)&dataXmode)->CB_PIO_Mode = 1; // ((PTRANSFER_CONTROL)&dataXmode)->BlindMode = 1; luExtension->pXferRead = DeviceExtension->pXferRead; luExtension->pXferWrite = DeviceExtension->pXferWrite; } else if (luExtension->XferMode == XMODE_MMIO){ ((PTRANSFER_CONTROL)&dataXmode)->CB_MMIO_Mode = 1; // ((PTRANSFER_CONTROL)&dataXmode)->BlindMode = 1; luExtension->pXferRead = DeviceExtension->pXferRead; luExtension->pXferWrite = DeviceExtension->pXferWrite; } #ifndef NINJA32UDE ((PTRANSFER_CONTROL)&dataXmode)->AllCountClr = 1; #endif AutoPara->TransferControl = dataXmode; DeviceExtension->ScsiState = SC_RESELECT; // Restart AUTO SCSI dataWord = 0; if ( luExtension->XferMode == XMODE_DMA ) { ((PCOMMAND_CONTROL)&dataWord)->AutoMsgin00_04 = 1; ((PCOMMAND_CONTROL)&dataWord)->AutoMsgin02 = 1; } ((PCOMMAND_CONTROL)&dataWord)->AutoScsiRestart = 1; AutoPara->CommandControl = dataWord; SCSI_WRITED(DeviceExtension, pSgAdr,luExtension->PhySrbExtension); dataWord = 0; ((PCOMMAND_CONTROL)&dataWord)->ClrCdbFifoPointer = 1; ((PCOMMAND_CONTROL)&dataWord)->AutoParameter = 1; SCSI_WRITEW(DeviceExtension,_18.pCommandControl, dataWord); Ns3DebugPrint(0x10,( "Ns3AutoResel: Resel Start ID=%d\n",DeviceExtension->TargetId)); // Ns3SetTransferMode( DeviceExtension ); // TRANSFERMODE SET DeviceExtension->MessageCount = 0; dataByte = 0; while (! ((PARBIT_STATUS)&dataByte)->AutoParameterValid) { dataByte = SCSI_READ(DeviceExtension, _1a.pArbitStatus); } // Set INTERRUPT MASK if ( luExtension->XferMode == XMODE_PIO32 || luExtension->XferMode == XMODE_MMIO) ((PIRQ_CONTROLP)&DeviceExtension->IrqMaskData)->FifoIrqMask = 0; else ((PIRQ_CONTROLP)&DeviceExtension->IrqMaskData)->FifoIrqMask = 1; #if 0 if ( ((PTRANSFER_CONTROL)&dataXmode)->BmStart ) { bmcnt = 0; while ( bmcnt == 0) { bmcnt = SCSI_READD(DeviceExtension,pBmCnt); } } #endif if (((PTRANSFER_CONTROL)&dataXmode)->BmStart) { dataByte = 0; while (! ((PARBIT_STATUS)&dataByte)->SgTableValid ) { dataByte = SCSI_READ(DeviceExtension, _1a.pArbitStatus); // TRANSFER? } } dataByte = SCSI_READ(DeviceExtension, pScsiBusCtrl); ((PSCSI_BUS_CONTROL)&dataByte)->ScsiACK = 0; // ACK Off ! SCSI_WRITE(DeviceExtension , pScsiBusCtrl, dataByte); return(TRUE); } // Ns3ProcessAutoResel //----------------------------------------------------------------------------- // SYNCHRONOUS_DATA_REQ // //Routine Description: Ns3DecodeSynchronousRequest // // This function should be called before the final byte of the message is // accepted from the SCSI bus. // //Return Value: // // TRUE - Returned if the request is acceptable. // // FALSE - Returned if the request should be rejected and a synchronous // transfer should be used. // //----------------------------------------------------------------------------- BOOLEAN Ns3DecodeSynchronousRequest( IN pnins32_host DeviceExtension, PSPECIFIC_TARGET_EXTENSION TargetState, IN UCHAR TargetID, IN BOOLEAN ResponseExpected ) { PSCSI_EXTENDED_MESSAGE extendedMessage; LONG period; LONG i; UCHAR dataByte; PSYNC_TABLE pSyncTable; ULONG SyncMax; if ( DeviceExtension->MCLK == 40 ) { pSyncTable = SyncTable20; SyncMax = SYNC_TABLE_MAX20; } else if ( DeviceExtension->MCLK == 20 ) { pSyncTable = SyncTable10; SyncMax = SYNC_TABLE_MAX10; } else if ( DeviceExtension->MCLK == 33 ) { pSyncTable = SyncTablePci; SyncMax = SYNC_TABLE_MAXPCI; } else { pSyncTable = SyncTable20; SyncMax = SYNC_TABLE_MAX20; } extendedMessage = (PSCSI_EXTENDED_MESSAGE) DeviceExtension->MessageBuffer; // // Determine the transfer offset. It is the minimum of the SCSI protocol // chip's maximum offset and the requested offset. // if (extendedMessage->ExtendedArguments.Synchronous.ReqAckOffset > SYNCHRONOUS_OFFSET) { if (!ResponseExpected) { // // The negotiation failed for some reason, fall back to // asynchronous data transfer. // TargetState->SynchronousOffset = ASYNCHRONOUS_OFFSET; TargetState->SynchronousPeriod = ASYNCHRONOUS_PERIOD; TargetState->AckWidth = 0; TargetState->SreqSmplRate = 2; return(FALSE); } extendedMessage->ExtendedArguments.Synchronous.ReqAckOffset = SYNCHRONOUS_OFFSET; TargetState->SynchronousOffset = SYNCHRONOUS_OFFSET; } else { TargetState->SynchronousOffset = extendedMessage->ExtendedArguments.Synchronous.ReqAckOffset; } // // If the offset requests asynchronous transfers then set the default // period and return. // if (extendedMessage->ExtendedArguments.Synchronous.ReqAckOffset == ASYNCHRONOUS_OFFSET) { TargetState->SynchronousPeriod = ASYNCHRONOUS_PERIOD; TargetState->SynchronousOffset = ASYNCHRONOUS_OFFSET; TargetState->AckWidth = 0; TargetState->SreqSmplRate = 2; return(TRUE); } // // Check to see if the period is less than the SCSI protocol chip can // use. If it is then update the message with our minimum and return. // if (extendedMessage->ExtendedArguments.Synchronous.TransferPeriod < SYNCHRONOUS_PERIOD ) { if (!ResponseExpected) { // // The negotiation failed for some reason, fall back to // asynchronous data transfer. // TargetState->SynchronousOffset = ASYNCHRONOUS_OFFSET; TargetState->SynchronousPeriod = ASYNCHRONOUS_PERIOD; TargetState->AckWidth = 0; TargetState->SreqSmplRate = 2; return(FALSE); } extendedMessage->ExtendedArguments.Synchronous.TransferPeriod = SYNCHRONOUS_PERIOD; } period = extendedMessage->ExtendedArguments.Synchronous.TransferPeriod; for ( i=0; i< SyncMax ; i++) { if( period >= pSyncTable[i].StartPeriod && period <= pSyncTable[i].EndPeriod) break; } if (i >= SyncMax) { // // The requested transfer period is too long for the SCSI protocol // chip. Fall back to synchronous and reject the request. // TargetState->SynchronousOffset = ASYNCHRONOUS_OFFSET; TargetState->SynchronousPeriod = ASYNCHRONOUS_PERIOD; TargetState->AckWidth = 0; TargetState->SreqSmplRate = 2; return(FALSE); } else { TargetState->SynchronousPeriod = pSyncTable[i].TransferPeriod; TargetState->AckWidth = pSyncTable[i].AckWidth; } // // Set the synchronous data transfer parameter registers // to the new values. These must be set before a data transfer // is started. If a response message is received then the parameters // must be reset. // dataByte = 0; ((PSYNC_REG)&dataByte)->SyncPeriod = TargetState->SynchronousPeriod; ((PSYNC_REG)&dataByte)->SyncOffset = TargetState->SynchronousOffset; SCSI_WRITE(DeviceExtension, pAckWidth,TargetState->AckWidth); SCSI_WRITE(DeviceExtension, pSyncReg ,dataByte); return(TRUE); } //----------------------------------------------------------------------------- // //Routine Description: Ns3MessageDecode // // This function decodes the SCSI bus message-in the device extension message // buffer. After the message is decoded it decides what action to take in // response to the message. If an outgoing message needs to be sent, then // it is placed in the message buffer and true is returned. If the message // is acceptable, then the device state is set either to DisconnectExpected or // MessageAccepted and the MessageCount is reset to 0. // // Some messages are made up of serveral bytes. This funtion will simply // return false when an incomplete message is detected, allowing the target // to send the rest of the message. The message count is left unchanged. // //Arguments: // // DeviceExtension - Supplies a pointer to the specific device extension. // //Return Value: // // TRUE - Returns true if there is a reponse message to be sent. // // FALSE - If there is no response message. // //----------------------------------------------------------------------------- BOOLEAN Ns3MessageDecode( IN pnins32_host DeviceExtension ) { Scsi_Cmnd *srb = DeviceExtension->ActiveLogicalUnit->ActiveLuRequest; PSPECIFIC_TARGET_EXTENSION targetState = &DeviceExtension->TargetState[srb->target]; PSCSI_EXMSG extendedMessage; LONG offset; LONG i; Ns3DebugPrint(0x10, ( __FUNCTION__ " in\n")); extendedMessage = (PSCSI_EXTENDED_MESSAGE)DeviceExtension->MessageBuffer; switch (extendedMessage->MessageType) { case SCSIMESS_MODIFY_DATA_POINTER: // // Verify the message length. // if (extendedMessage->MessageLength != SCSIMESS_MODIFY_DATA_LENGTH) { // // Reject the message. // DeviceExtension->MessageSent = 0; DeviceExtension->MsgOutCount = 1; DeviceExtension->MsgOutBuffer[0] = MSG_MESSAGE_REJECT; return(TRUE); } // // Calculate the modification to be added to the data pointer. // offset = 0; for (i = 0; i < 4; i++) { offset <<= 8; offset += extendedMessage->ExtendedArguments.Modify.Modifier[i]; } // // Verify that the new data pointer is still within the range // of the buffer. // if (DeviceExtension->CurDataLength - offset > srb->request_bufflen || ((LONG) DeviceExtension->CurDataLength - offset) < 0 ) { // // The new pointer is not valid, so reject the message. // DeviceExtension->MessageSent = 0; DeviceExtension->MsgOutCount = 1; DeviceExtension->MsgOutBuffer[0] = MSG_MESSAGE_REJECT; return(TRUE); } // // Everything has checked out, so update the pointer. // DeviceExtension->CurDataPointer += offset; DeviceExtension->CurDataLength -= offset; // // Everything is ok, so accept the message as is. // DeviceExtension->MessageCount = 0; // DeviceExtension->ScsiState = MessageAccepted; return(FALSE); case SCSIMESS_SYNCHRONOUS_DATA_REQ: // // A SYNCHRONOUS DATA TRANSFER REQUEST message was received. // Make sure the length is correct. // if ( extendedMessage->MessageLength != SCSIMESS_SYNCH_DATA_LENGTH) { // // The length is invalid reject the message. // DeviceExtension->MessageSent = 0; DeviceExtension->MsgOutCount = 1; DeviceExtension->MsgOutBuffer[0] = MSG_MESSAGE_REJECT; return(TRUE); } // // If synchrouns negotiation has been disabled for this request, // then reject any synchronous messages; however, when synchronous // transfers are allowed then a new attempt can be made. // if (srb != NULL && !(targetState->TargetFlags & PD_SYNCHRONOUS_TRANSFER_SENT)) { // // Reject the synchronous transfer message since synchonrous // transfers are not desired at this time. // DeviceExtension->MessageSent = 0; DeviceExtension->MsgOutCount = 1; DeviceExtension->MsgOutBuffer[0] = MSG_MESSAGE_REJECT; return(TRUE); } // // Call WdDecodeSynchronousMessage to decode the message and // formulate a response if necessary. // NcrDecodeSynchronousRequest will return FALSE if the // message is not accepable and should be rejected. // if (!Ns3DecodeSynchronousRequest( DeviceExtension, targetState, srb->target, (BOOLEAN)!(targetState->TargetFlags & PD_SYNCHRONOUS_TRANSFER_SENT) )) { // // Indicate that a negotiation has been done in the logical // unit and clear the negotiation flags. // targetState->TargetFlags |= PD_SYNCHRONOUS_NEGOTIATION_DONE; targetState->TargetFlags &=~(PD_SYNCHRONOUS_TRANSFER_SENT); // // The message was not acceptable so send a MESSAGE_REJECT. // DeviceExtension->MessageSent = 0; DeviceExtension->MsgOutCount = 1; DeviceExtension->MsgOutBuffer[0] = MSG_MESSAGE_REJECT; return(TRUE); } // // If a reponse was expected, then set the state for a message-out. // Otherwise, NcrDecodeSynchronousRequest has put a reponse // in the message buffer to be returned to the target. // if (targetState->TargetFlags & PD_SYNCHRONOUS_TRANSFER_SENT){ // // We initiated the negotiation, so no response is necessary. // targetState->TargetFlags &= ~PD_SYNCHRONOUS_TRANSFER_SENT; targetState->TargetFlags |= PD_SYNCHRONOUS_NEGOTIATION_DONE; return(FALSE); } // // Set up the state to send the reponse. The message count is // still correct. // // DeviceExtension->ScsiState = MessageOut; targetState->TargetFlags &= ~PD_SYNCHRONOUS_TRANSFER_SENT; return(TRUE); case SCSIMESS_WIDE_DATA_REQUEST: // // A WIDE DATA TRANSFER REQUEST message was received. // #ifdef NINJA32UDE Ns3DebugPrint(0x10, ( __FUNCTION__ " SCSIMESS_WIDE_DATA_REQUEST\n")); if ( DeviceExtension->MessageBuffer[3] != 0 ) { //+[ude] DeviceExtension->MessageSent = 0; DeviceExtension->MsgOutCount = 1; DeviceExtension->MsgOutBuffer[0] = MSG_MESSAGE_REJECT; return(TRUE); } return(FALSE); break; #else // NINJA32UDE DeviceExtension->MessageSent = 0; DeviceExtension->MsgOutCount = 1; DeviceExtension->MsgOutBuffer[0] = MSG_MESSAGE_REJECT; return(TRUE); #endif // NINJA32UDE default: // // This is an unknown or illegal message, so send message REJECT. // DeviceExtension->MessageSent = 0; DeviceExtension->MsgOutCount = 1; DeviceExtension->MsgOutBuffer[0] = MSG_MESSAGE_REJECT; return(TRUE); } } //----------------------------------------------------------------------- // Routine Name: // // Ns3StartExecution // // Routine Description: // // This routine will start the execution of a SCSI request. // // //----------------------------------------------------------------------- static void Ns3StartExecution( IN pnin_softc DevExt, IN PSPECIFIC_LU_EXTENSION LuExtension, IN Scsi_Cmnd *Srb ) { PSPECIFIC_TARGET_EXTENSION targetState; ULONG i; Ns3DebugPrint(0x10,(__FUNCTION__" ID = %x, Lun = %x. ",Srb->target,Srb->lun)); if ((Srb->cmnd[1] >> 5) != Srb->lun) { Srb->cmnd[1] &= 0x1f; Srb->cmnd[1] |= (Srb->lun << 5); } DevExt->TargetId = Srb->target; DevExt->NextSrbRequest = Srb; DevExt->AdapterFlags |= PD_PENDING_START_IO; DevExt->TargetId = Srb->target; // // Setup the context for this adapter. // DevExt->ActiveLogicalUnit = LuExtension; DevExt->CurDataPointer = DevExt->ActiveLogicalUnit->SavedDataPointer; DevExt->CurDataLength = DevExt->ActiveLogicalUnit->SavedDataLength; Ns3DebugPrint(0x08, (" :DataPointer[%x] len[%x] ",DevExt->CurDataPointer,DevExt->CurDataLength)); targetState = &DevExt->TargetState[Srb->target]; LuExtension->XferMode = targetState->TransferMode; LuExtension->NextReq = FALSE; #ifdef NINJA32UDE LuExtension->TargetFlags = targetState->TargetFlags; //+[ude] #endif // // Create the identify command. // if ((DevExt->AdapterOption & OPT_NON_DISCONECT) || (is_dir_out(Srb))) { DevExt->MsgOutBuffer[0] = MSG_IDENTIFYFLAG | Srb->lun; } else { DevExt->MsgOutBuffer[0] = MSG_IDENTIFYFLAG_WITH_DISCON | Srb->lun; } DevExt->MessageSent = 0; DevExt->MsgOutCount = 1; // // make Sync Message // if (!(targetState->TargetFlags & PD_SYNCHRONOUS_NEGOTIATION_DONE ) && !(targetState->TargetFlags & PD_DO_NOT_NEGOTIATE) && (Srb->cmnd[0] != INQUIRY) // not Sync Nego ) { // Sync MESSAG change [sync] DevExt->MsgOutBuffer[1] = MSG_EXTENDED; DevExt->MsgOutBuffer[2] = MSG_EXT_SDTR_LEN; /* length */ DevExt->MsgOutBuffer[3] = SCSIMESS_SYNCHRONOUS_DATA_REQ;/* ext msg out cmd */ Ns3DebugPrint(0x10,(" NumConnect = %x ",DevExt->NumConnect)); #ifdef NINJA32UDE if ( DevExt->SynchronousPeriod == 0xff ) { DevExt->MsgOutBuffer[4] = targetState->SyncMax; } else #endif if ( DevExt->SynchronousPeriod == 0 ) { #ifdef LOGITEC_ONLY if ( DevExt->NumConnect <= 3 ) #else if ( DevExt->NumConnect == 1 ) #endif DevExt->MsgOutBuffer[4] = SYNCHRONOUS_PERIOD_20M; else DevExt->MsgOutBuffer[4] = SYNCHRONOUS_PERIOD_10M; } else DevExt->MsgOutBuffer[4] = DevExt->SynchronousPeriod; DevExt->MsgOutBuffer[5] = SYNCHRONOUS_OFFSET; // OFFSET 15 targetState->TargetFlags |= PD_SYNCHRONOUS_NEGOTIATION_DONE | PD_SYNCHRONOUS_TRANSFER_SENT; } LuExtension->SrbExtension = DevExt->SrbExtension; // buffer ? if ( (ULONG)(LuExtension->SrbExtension) & 3 ) { (ULONG)LuExtension->SrbExtension &= 0xfffffffc; (ULONG)LuExtension->SrbExtension += 4; } LuExtension->PhySrbExtension = virt_to_bus( LuExtension->SrbExtension ); #ifdef USE_SCATTERGATHER if ( Srb->request_bufflen ) { // DataTransferLength-> request_bufflen Ns3BuildSGlist( DevExt, Srb ); } #endif // USE_SCATTERGATHER // SET FIFO SLETHOLD if (LuExtension->XferMode == XMODE_DMA) { Ns3DebugPrint(0x10,(__FUNCTION__":XferMode == XMODE_DMA ")); SCSI_SWRITE(DevExt->BaseAddress, pFifoFullShld ,0x10); SCSI_SWRITE(DevExt->BaseAddress, pFifoEmptyShld ,0x60); } else { Ns3DebugPrint(0x10,(__FUNCTION__":XferMode == XMODE_PIO ")); SCSI_SWRITE(DevExt->BaseAddress, pFifoFullShld ,0x60); SCSI_SWRITE(DevExt->BaseAddress, pFifoEmptyShld ,0x40); } // Initialize Message In Buffer DevExt->MessageCount = 0; for (i = 0; i < 6 ; i++) DevExt->MessageBuffer[i] = 0; if (LuExtension->XferMode == XMODE_DMA && #ifdef NINJA32UDE LuExtension->TargetFlags & PD_NONCACHE && Srb->request_bufflen > 0) // [ude] #else targetState->TargetFlags & PD_NONCACHE && Srb->request_bufflen > 0 ) #endif { if (is_dir_out(Srb)) { memcpy( DevExt->NonCachedExtension->Address, (PVOID)DevExt->CurDataPointer, Srb->request_bufflen); } } Ns3DebugPrint(0x10,(__FUNCTION__" out\n")); } // end Ns3StartExecution() //----------------------------------------------------------------------- // Routine Name: // // Ns3NotifyCompletion // // Routine Description: // // This routine will perform any clean up operations for the Srb // and notify the ScsiPort driver of completion. // // Arguments: // // DeviceExtension - Device adapter context pointer. // // Return Value: // // None // //----------------------------------------------------------------------- VOID Ns3NotifyCompletion( IN pnins32_host DeviceExtension, IN BOOLEAN NextReq ) { PSPECIFIC_LU_EXTENSION luExtension; Scsi_Cmnd *srb; Ns3DebugPrint(0x100, (__FUNCTION__ " : in")); luExtension = DeviceExtension->ActiveLogicalUnit; if(!DeviceExtension){ Ns3DebugPrint(0x100, (" : DeviceExtension NULL!!\n")); panic(" : DeviceExtension NULL!!"); return; } if(!luExtension){ Ns3DebugPrint(0x100, (" : luExtension NULL!!\n")); panic(" : luExtension NULL!!"); return; } srb = luExtension->ActiveLuRequest; if(!srb){ Ns3DebugPrint(0x100, (" : NULL!!\n")); panic(" : luExtension NULL!!"); return; } Ns3DebugPrint(0x100, (__FUNCTION__" : target:lun(%x:%x) ",srb->target, srb->lun)); luExtension->ActiveLuRequest = NULL; DeviceExtension->ActiveLogicalUnit = NULL; // // Call notification routine. // srb->scsi_done(srb); } // end Ns3NotifyCompletion() //----------------------------------------------------------------------- // Routine Name: // // Ns3ResetBus // // Routine Description: // // Reset Ns3 SCSI adapter (no action for this) // and SCSI bus. // // Arguments: // // Context for the reset. // PathId // // Return Value: // // Nothing. // //----------------------------------------------------------------------- BOOLEAN Ns3ResetBus( IN PVOID Context,IN ULONG PathId ) { pnins32_host deviceExtension = Context; Ns3DebugPrint(0x800, ( "Ns3ResetBus: Reset Ns3 and SCSI bus\n")); Ns3ResetScsiBus( deviceExtension ); // // Complete all outstanding requests with SRB_STATUS_BUS_RESET. // /* tor SRB_STATUS_BUS_RESET); ScsiPortNotification(NextRequest,deviceExtension,NULL); */ return TRUE; } // end Ns3ResetBus() //----------------------------------------------------------------------- // Routine Name: // // Ns3ResetScsiBus // // Routine Description: // // Reset Ns3 SCSI adapter (no action for this) // and SCSI bus. // // Arguments: // // Context for the reset. // // Return Value: // // Nothing. // //----------------------------------------------------------------------- VOID Ns3ResetScsiBus( IN PVOID Context ) { pnins32_host DeviceExtension = Context; PSPECIFIC_TARGET_EXTENSION targetState; ULONG i; UCHAR dataByte; // PSCSI_REGISTER baseAddress = DeviceExtension->BaseAddress; USHORT dataWord; // Ns3DebugPrint(0x100, (__FUNCTION__ " : baseAddress[%lx]\n",(LONG)baseAddress)); if (DeviceExtension->DmaPending == TRUE) { DeviceExtension->DmaPending = FALSE; } DeviceExtension->InterruptPending = FALSE; SCSI_WRITEW(DeviceExtension, irq.pIrqControl, 0xf000); // IRQ all Mssk SCSI_WRITEW(DeviceExtension, trans.pTransferControl, 0); // BmStop SCSI_WRITED(DeviceExtension, pBmCnt, 0); // COUNTERCLEAR // INTERRUPT do { dataWord = SCSI_READW(DeviceExtension, irq.pIrqStatus); Ns3DebugPrint(0x100, (__FUNCTION__ " : IrqStatus[%x] ", dataWord)); }while ( dataWord & 0xff0 ); // // RESET SCSI bus. // dataByte = 0; ((PSCSI_BUS_CONTROL)&dataByte)->ScsiRst = 1; SCSI_WRITE(DeviceExtension, pScsiBusCtrl, dataByte); // SCSI RST On ! ScsiPortStallExecution(RESET_HOLD_TIME); ((PSCSI_BUS_CONTROL)&dataByte)->ScsiRst = 0; SCSI_WRITE(DeviceExtension, pScsiBusCtrl, dataByte); // SCSI RST Off ! // SCSI RST IRQ/Phase Change // dummy read for ( i= 0; i < 5; i++) { dataWord = SCSI_READ(DeviceExtension,irq.pIrqStatus); Ns3DebugPrint(0x100, (" : pIrqStatus[%lx]",dataWord)); } // SET Sync5MB for (i = 0; i < 8; i++) { targetState = &DeviceExtension->TargetState[i]; targetState->TargetFlags &= ~PD_SYNCHRONOUS_NEGOTIATION_DONE; #ifdef NT_INST targetState->TargetFlags |= PD_NONCACHE; #else if (DeviceExtension->AdapterOption & OPT_NOSG ) targetState->TargetFlags |= PD_NONCACHE; #endif targetState->SynchronousOffset = ASYNCHRONOUS_OFFSET; targetState->SynchronousPeriod = ASYNCHRONOUS_PERIOD; targetState->AckWidth = 0; targetState->SreqSmplRate = 2; targetState->TransferMode = DeviceExtension->TransferMode; } DeviceExtension->IrqMaskData = 0xf000; if (DeviceExtension->AdapterFlags & PD_PENDING_START_IO) { // // Ask for another request and clear the pending one. The pending // request will be processed when the rest of the active requests // are completed. DeviceExtension->NextSrbRequest = NULL; DeviceExtension->AdapterFlags &= ~PD_PENDING_START_IO; // tor ScsiPortNotification( NextRequest, DeviceExtension, NULL ); } DeviceExtension->ScsiState = SC_BUSFREE; Ns3DebugPrint(0x100, (__FUNCTION__ " : SC_BUSFREE !!\n")); ScsiPortStallExecution(RESET_RECOVER_TIME); } //---------------------------------------------------------------------------- // Ns3Timer //---------------------------------------------------------------------------- VOID Ns3Timer( unsigned long context ) { pnins32_host DeviceExtension = (pnins32_host)context; Ns3DebugPrint(0x400,(__FUNCTION__ " in ... " )); Ns3Interrupt(DeviceExtension); if (DeviceExtension->ActiveLogicalUnit) { Ns3DebugPrint(0x400, (__FUNCTION__ " : called by Ns3TimerRequest\n")); Ns3TimerRequest(DeviceExtension); } DeviceExtension->dev_timer.expires = 0; } VOID Ns3IntCheck( IN ULONG context ) { pnins32_host DeviceExtension = (pnins32_host)context; Ns3DebugPrint(0x20, (__FUNCTION__ " : in ")); DeviceExtension->dev_timer2.expires = 0; SCSI_WRITEW(DeviceExtension, timer.pTimerSet, 0x100); //Timer Stop // INTERRUPT? if (DeviceExtension->PollingMode == 0xff){ DeviceExtension->PollingMode = 0x7f; Ns3DebugPrint(0x20, (__FUNCTION__ " : PollingMode = 0x7f\n")); } // Wait Int? if (DeviceExtension->IntWait && DeviceExtension->PollingMode == 0x7f) { Ns3DebugPrint(0x20, (" PollingMode == 0x7f ")); Ns3TimerRequest(DeviceExtension); } Ns3DebugPrint(0x20, (__FUNCTION__ " : out\n")); } //----------------------------------------------------------------------- // Routine Name: // // Ns3Initialize // // Routine Description: // // Inititialize Ns3 adapter. // // Arguments: // // Context - Adapter object device extension. // // Return Value: // // Status. // //----------------------------------------------------------------------- BOOLEAN Ns3Initialize( IN PVOID Context ) { pnins32_host DeviceExtension = Context; UCHAR dataByte; USHORT dataWord; PSCSI_REGISTER baseAddress = DeviceExtension->BaseAddress; Ns3DebugPrint(0x20, (__FUNCTION__ " In [%x]...",baseAddress)); DeviceExtension->dev_timer.expires = 0; DeviceExtension->dev_timer2.expires = 0; //BUS-FREE INTERRUPT comes... // SCSI_SWRITEW(baseAddress, pIrqSelect ,0); // SCSI IRQ ALL DISABLE SCSI_WRITEW(DeviceExtension, irq.pIrqControl, 0xf000); // IRQ all Mssk #ifdef NINJA32UDE DeviceExtension->IrqMaskData = 0xf000; //+[ude] #endif // NINJA32UDE SCSI_WRITEW(DeviceExtension, trans.pTransferControl, 0); // BmStop SCSI_WRITED(DeviceExtension, pBmCnt, 0); // COUNTERCLEAR do { dataWord = SCSI_READW(DeviceExtension, irq.pIrqStatus); }while ( dataWord & 0xff0 ); Ns3DebugPrint(0x20, (" : pIrqStatus[%x] --",dataWord)); SCSI_SWRITE(baseAddress, pFifoFullShld ,0x10); SCSI_SWRITE(baseAddress, pFifoEmptyShld ,0x60); // Set clock divider if (DeviceExtension->AdapterOption & OPT_ULTRA) // UltraSCSI option dataByte = 2; else dataByte = 1; SCSI_SWRITE(baseAddress, pClockDiv , dataByte); *(PUSHORT)&DeviceExtension->wIrqSelect = 0; DeviceExtension->wIrqSelect.TimerIrqSel = 1; DeviceExtension->wIrqSelect.ScsiResetIrqSel = 1; DeviceExtension->wIrqSelect.FifoShldIrqSel= 1; DeviceExtension->wIrqSelect.ReselectIrqSel = 1; DeviceExtension->wIrqSelect.PhaseChgIrqSel = 1; DeviceExtension->wIrqSelect.AutoScsiSeqIrqSel = 1; // DeviceExtension->wIrqSelect.BmCntErrIrqSel = 1; //[test] DeviceExtension->wIrqSelect.TargetAbortIrqSel = 1; //[test] DeviceExtension->wIrqSelect.MasterAbortIrqSel = 1; //[test] SCSI_SWRITEW(baseAddress, pIrqSelect, (*(PUSHORT)&DeviceExtension->wIrqSelect)); Ns3DebugPrint(0x20,(" : IrqSelect[%x] --",*(PUSHORT)&DeviceExtension->wIrqSelect)); SCSI_WRITE(DeviceExtension, parity.pParityControl , 0); // Parity Disable SCSI_WRITE(DeviceExtension, sc.pClearCounter , 0x3f); // All Pointer Clear #ifdef NINJA32UDE //*[v1.01] for NEW G/A rev.2 dataWord = SCSI_READW(DeviceExtension,pIndexReg); Ns3DebugPrint(0x20,(" : NEW G/A rev.2[%x] >>8 = [%x]",dataWord,(dataWord>>8))); if ( (dataWord >> 8) >= 0x51) { dataWord =0; Ns3DebugPrint(0x20, (" : (pIndexReg >> 8) >= 0x51 ")); ((PMISC_REG)&dataWord)->ScsiDirDetector = 1; ((PMISC_REG)&dataWord)->DelayedBMStart = 1; ((PMISC_REG)&dataWord)->MasterTerm = 1; #ifndef PCI // ((PMISC_REG)&dataWord)->BMReqTiming = 1;// ToPIC対策 #endif ((PMISC_REG)&dataWord)->AutoSelTiming = 1; // ((PMISC_REG)&dataWord)->MAbortMask = 1; ((PMISC_REG)&dataWord)->BmStop_NDataPhase = 1; SCSI_SWRITEW(baseAddress,pMiscReg,dataWord); //[ude] dataByte = 0; ((PBM_CYCLE)&dataByte)->MemRdCmd1 = 1; ((PBM_CYCLE)&dataByte)->SGTAutoParaMemRd = 1; SCSI_SWRITE(baseAddress,pBmCycle,dataByte); //Memory Read Multipleをセット } else { Ns3DebugPrint(0x20, (" : (pIndexReg >> 8) < 0x51 !!!!!!!!!!! :")); } #else // not NINJA32UDE if ( (SCSI_READW(DeviceExtension,pIndexReg) >> 8) > 0x51) { SCSI_SWRITE(baseAddress, pMiscReg , 0x79); dataByte = 0; ((PBM_CYCLE)&dataByte)->MemRdCmd1 = 1; ((PBM_CYCLE)&dataByte)->SGTAutoParaMemRd = 1; SCSI_SWRITE(baseAddress,pBmCycle,dataByte); // Set Memory Read Multiple } else { SCSI_SWRITE(baseAddress, pMiscReg , 0x11); dataByte = 0; ((PBM_CYCLE)&dataByte)->MemRdCmd1 = 1; SCSI_SWRITE(baseAddress,pBmCycle,dataByte); // Set Memory Read Multiple } #endif // NINJA32UDE // // Reset Ns3 and SCSI bus. // DeviceExtension->InterruptPending = FALSE; DeviceExtension->DmaPending = FALSE; #ifndef NINJA32UDE // cardbusだったら //まず自分のタームパワーを切る #ifdef KME SCSI_SWRITE(baseAddress, pTermPwrCtrl, 1); // Terminator On ! #else SCSI_SWRITE(baseAddress, pTermPwrCtrl, 0); // Terminator Off ! #if 1 //カードバスではターミネータがきかないことはない!! dataByte = SCSI_SREAD(baseAddress, pTermPwrCtrl); DeviceExtension->bTermSence = 1; if ( ! ((PTermPwrControl)&dataByte)->TermPowerSense ) { // Term Power来てる ?; SCSI_SWRITE(baseAddress, pTermPwrCtrl, 1); // No ! Terminator ON ! DeviceExtension->bTermSence = 0; } #endif #endif #else // PCIだったら { UCHAR OutDev,InDev; SCSI_SWRITE(baseAddress, pExtPortDdr, 0x01); //p0:out, p1:in #ifdef PCI // +[kamii] vvv '99.09.06 LED対応 SCSI_SWRITE(baseAddress, pExtPort, 0x01); // LED消灯 #endif // +[kamii] ^^^ '99.09.06 InDev = SCSI_SREAD(baseAddress, pTermPwrCtrl) & 2; //外付け OutDev = SCSI_SREAD(baseAddress, pExtPort) & 2; //内蔵 dataByte =!(InDev | OutDev); dataByte >>=1; SCSI_SWRITE(baseAddress, pTermPwrCtrl, dataByte); Ns3DebugPrint(0x20, (" PCI: TermPwrCtrl[%x] ",dataByte)); } #endif // //--- SCSI BUS RESET --- // Ns3DebugPrint(0x20, (__FUNCTION__ " : Ns3ResetScsiBus ---- \n")); Ns3ResetScsiBus( DeviceExtension ); #ifdef NINJA32UDE ScsiPortStallExecution(DeviceExtension->ResetTimer); //*[ude] Ns3DebugPrint(0x20, (" : ResetTimer[%d]\n",DeviceExtension->ResetTimer)); #endif // NINJA32UDE // //--- CABLE CHECK --- // DeviceExtension->ScsiCable = TRUE; if ( (SCSI_READ(DeviceExtension,_22.pScsiDataIn)) || (SCSI_READ(DeviceExtension,sc.pScsiBusMonitor)) ) { DeviceExtension->ScsiCable = FALSE; DeviceExtension->bTermSence = 0xff; SCSI_SWRITE(baseAddress, pTermPwrCtrl, 0); // Terminator Off ! } // DeviceExtension->PollingMode = 0x0;// 0xff; DeviceExtension->TimerCount = 0; Ns3DebugPrint(0x20, (__FUNCTION__ " : Exit\n")); return TRUE; } // end Ns3Initialize() //----------------------------------------------------------------------------- //+[v1.06.00] // get current position from ack counter //----------------------------------------------------------------------------- ULONG Ns3GetCurrent_SG(IN PSPECIFIC_DEVICE_EXTENSION DeviceExtension, IN ULONG sack, IN ULONG Pre_SG_Entry, IN PSG_LIST SGlist) { ULONG Count,i; Count = 0; for ( i = Pre_SG_Entry; ; i++) { Count += SGlist->TransferDataBuffer[i].Length; Count &= 0x7fffffff; if ( Count > sack ) break; if ( SGlist->TransferDataBuffer[i].Length & 0x80000000 ) break; } return i; } #ifdef USE_SCATTERGATHER //-------------------------------------------------------------------------- //Routine Description: // // This routine builds a scatter/gather descriptor list for the SCRIPT // //Arguments: // // DeviceExtension // Srb // //Return Value: // // None // //-------------------------------------------------------------------------- BOOLEAN Ns3BuildSGlist( IN pnins32_host DeviceExtension, IN Scsi_Cmnd *Srb ) { PVOID dataPointer = (PVOID)DeviceExtension->CurDataPointer; ULONG bytesLeft = Srb->request_bufflen; PSG_LIST SGlist; ULONG length; ULONG descriptorCount = 0 ; PSPECIFIC_LU_EXTENSION luExtension = DeviceExtension->ActiveLogicalUnit; Ns3DebugPrint(0x100,(__FUNCTION__ " DataBuffer TOP: %lx ", dataPointer)); luExtension->Current_SG_Entry = 0; luExtension->SGListCount = 0; SGlist = luExtension->SrbExtension; (ULONG)SGlist += sizeof(AUTO_PARA); luExtension->pSGlist = SGlist; luExtension->PhySGlist = luExtension->PhySrbExtension + sizeof(AUTO_PARA); if (!(DeviceExtension->TargetState[Srb->target].TargetFlags & PD_NONCACHE)) { // // Create SGL segment descriptors. // do { // do ------------------------------------------ if ( (descriptorCount != 0) && ((ULONG)dataPointer & 1) ) { Ns3DebugPrint(0x100,(__FUNCTION__ "dataPointer & 1 return\n")); #ifndef PIO2NONCACHE luExtension->XferMode = XMODE_PIO32; return FALSE; #else luExtension->TargetFlags |= PD_NONCACHE; break; #endif } // // Get physical address and length of contiguous // physical buffer. // SGlist->TransferDataBuffer[descriptorCount].Address = Srb->use_sg ? virt_to_bus(((struct scatterlist *)Srb->buffer)[descriptorCount].address) : virt_to_bus(Srb->request_buffer); SGlist->TransferDataBuffer[descriptorCount].Length = Srb->use_sg ? ((struct scatterlist *)Srb->buffer)[descriptorCount].length : Srb->request_bufflen; length = SGlist->TransferDataBuffer[descriptorCount].Length; // // Adjust counts. // dataPointer = (PUCHAR)dataPointer + length; bytesLeft -= length; descriptorCount++; Ns3DebugPrint(0x1000,(" : SG Counter[%x]",descriptorCount)); } while (bytesLeft); // do --------------------------------------- luExtension->Current_SG_Entry = 0; luExtension->SGListCount = descriptorCount; } else { // NON CHCHE ... SGlist->TransferDataBuffer[0].Address = DeviceExtension->NonCachedPhysical; #ifdef NINJA32UDE SGlist->TransferDataBuffer[0].Length = Srb->request_bufflen; // DataTransferLength -> request_bufflen; //*[ude] #else // NINJA32UDE SGlist->TransferDataBuffer[0].Length = bytesLeft; #endif // NINJA32UDE luExtension->Current_SG_Entry = 0; luExtension->SGListCount = 1; descriptorCount = 1; } // TABLE MARKING SGlist->TransferDataBuffer[descriptorCount-1].Length |= BM_LAST; Ns3DebugPrint(0x1000,(__FUNCTION__ " : set BM_LAST [%x]\n",descriptorCount)); SCSI_WRITED(DeviceExtension, pBmCnt, 0); if ( !(DeviceExtension->AdapterOption & OPT_AUTOPARA) ){ //Set Scatter/Gather TABLE ADDRESS SCSI_WRITED(DeviceExtension, pSgAdr, luExtension->PhySGlist); } return TRUE; } #endif // USE_SCATTERGATHER //-------------------------------------------------------------------------- //Routine Description: // // This routine Get a scatter/gather Count list for the SCRIPT // //Arguments: // // DeviceExtension // //Return Value: // // None // //-------------------------------------------------------------------------- ULONG Ns3GetSgCount(IN pnins32_host DeviceExtension, IN ULONG Pre_SG_Entry, IN ULONG Current_SG_Entry, IN PSG_LIST SGlist) { ULONG Count,i; Ns3DebugPrint(0x10,(__FUNCTION__ ":PreEntry(%lx),Current%lx\n",Pre_SG_Entry ,Current_SG_Entry)); Count = 0; for ( i = Pre_SG_Entry; i<=Current_SG_Entry; i++){ Count += SGlist->TransferDataBuffer[i].Length; } Count &= 0x7fffffff; return Count; } PSPECIFIC_LU_EXTENSION ScsiPortGetLogicalUnit(pnins32_host devExt,unsigned char TargetId,unsigned char Lun) { if (!table[TargetId][Lun]) { Ns3DebugPrint(0x100,(__FUNCTION__" : kmalloc((SPECIFIC_LU_EXTENSION")); table[TargetId][Lun] = kmalloc(sizeof(SPECIFIC_LU_EXTENSION),GFP_KERNEL); if(table[TargetId][Lun] ) (table[TargetId][Lun])->SrbExtension = 0; } return table[TargetId][Lun]; } void ScsiPortFreeLogicalUnit(unsigned char TargetId,unsigned char Lun) { Ns3DebugPrint(0x100, (__FUNCTION__ " in")); if (table[TargetId][Lun]) { kfree(table[TargetId][Lun]); table[TargetId][Lun] = 0; } Ns3DebugPrint(0x100, (" out")); } /*====================================================================*/ //----------------------------------------------------------------------- // Routine Name: // // Ns3Interrupt // // Routine Description: // // This routine handles the interrupts for the Ns3. The intention is to // quickly determine the cause of the interrupt, clear the interrupt, and // setup to process the SCSI command that is affected by the // interrupt. // // Arguments: // // Context - Device adapter context pointer. // // Return Value: // // TRUE indicates that the interrupt was from this Ns3 adapter, // FALSE indicates that this interrupt was NOT from us. // //----------------------------------------------------------------------- void Ns3Interrupt( void *Context ) { pnins32_host DeviceExtension; PSCSI_REGISTER baseAddress; PSPECIFIC_TARGET_EXTENSION targetState; PSPECIFIC_LU_EXTENSION luExtension; LONG i; USHORT dataWord; SCSI_EXECUTE_PHASE ScsiExec; Scsi_Cmnd/*Scsi_Cmnd*/ *Srb; DeviceExtension = Context; baseAddress = DeviceExtension->BaseAddress; Ns3DebugPrint(0x1000,("\n" )); Ns3DebugPrint(0x1000,(__FUNCTION__ " in .... " )); if(DeviceExtension->dev_timer.expires){ Ns3DebugPrint(0x1000,(__FUNCTION__ " : del_timer(dev_timer) " )); del_timer(&(DeviceExtension->dev_timer)); } if(DeviceExtension->dev_timer2.expires){ Ns3DebugPrint(0x1000,(__FUNCTION__ " : del_timer(dev_timer2) " )); del_timer(&(DeviceExtension->dev_timer2)); } // 割り込みが来ないから暫定的に試してみる。 #ifdef GET_IRQINISR *((PUSHORT) &DevIntIrqStatus) = SCSI_READW(DeviceExtension,irq.pIrqStatus); Ns3DebugPrint(0x1000,(" IRQ[%x] \n",*((PUSHORT) &DevIntIrqStatus) )); #else DevIntIrqStatus = DeviceExtension->intIrqStatus2; #endif // GET_IRQINISR dataWord = 0; ((PIRQ_CONTROLP)&dataWord)->CardBusIrqMask = 1; ((PIRQ_CONTROLP)&dataWord)->FifoIrqMask = 1; ((PIRQ_CONTROLP)&dataWord)->TimerIrqMask = 1; ((PIRQ_CONTROLP)&dataWord)->ScsiIrqMask = 1; SCSI_WRITEW(DeviceExtension, irq.pIrqControl,dataWord); // IRQ All mask IntEntry: luExtension = DeviceExtension->ActiveLogicalUnit; targetState = &DeviceExtension->TargetState[DeviceExtension ->TargetId]; // Card out? if ( *((PUSHORT) &DevIntIrqStatus) == 0xffff ) { if ( luExtension ) { // tor luExtension->ActiveLuRequest->SrbStatus = SRB_STATUS_NO_DEVICE; DeviceExtension->ActiveLogicalUnit->ActiveLuRequest->result = DID_ERROR<< 16; Ns3NotifyCompletion(DeviceExtension, (BOOLEAN)(!luExtension->NextReq)); } DeviceExtension->ScsiState = SC_BUSFREE; DeviceExtension->IntWait = FALSE; Ns3DebugPrint(0x1000,(__FUNCTION__ ": card out? FALSE\n")); return; } if ( !( *((PUSHORT) &DevIntIrqStatus) & 0xff0) ) { SCSI_WRITEW(DeviceExtension, irq.pIrqControl,DeviceExtension->IrqMaskData); Ns3DebugPrint(0x1000,(__FUNCTION__ ": (DevIntIrqStatus & 0xff0) FALSE 1 return\n")); return; } DeviceExtension->InterruptPending = FALSE; if ( DevIntIrqStatus.BmCntErrIrq || DevIntIrqStatus.CardBusIrq) { __asm__("nop"); Ns3DebugPrint(0x1000, (__FUNCTION__ " : BmCntErrIrq || CardBusIrq\n")); } // //---- AUTO SCSI IRQ? ---- // if ( DevIntIrqStatus.AutoScsiIrq ) { // --------------- /* use value in get do_nins32_isr */ *((PUSHORT) &ScsiExec) = SCSI_READW(DeviceExtension, pScsiExecutePhase); Ns3DebugPrint(0x1000,(": AutoScsiIrq SCSIEXEC = %x ",*((PUSHORT)&ScsiExec))); if ( (ScsiExec.PausedMsgOut || ScsiExec.CommandPhase) && !luExtension->NextReq) { Ns3DebugPrint(0x1000,(": MULTREQ ? ")); #ifdef MULTREQ if (DeviceExtension->PollingMode == 0) { ScsiPortNotification(NextRequest,DeviceExtension,NULL); luExtension->NextReq = TRUE; DeviceExtension->IntWait = FALSE; } #endif } if (ScsiExec.DataInPhase || ScsiExec.DataOutPhase) { Ns3DebugPrint(0x1000,(": DataInPhase || DataOutPhase ")); if (luExtension->XferMode == XMODE_DMA) { ULONG remainCnt, Total, p, sack /*,dataSgAdr*/; PSG_LIST SGlist; // not use FIFO REST! 8BYTE buffer not count! #ifdef ARIENAI FifoRest = SCSI_READW(DeviceExtension, pFifoRestCnt) & 0x1ff; if (ScsiExec.DataOutPhase) FifoRest +=8; #endif ARIENAI // //Scatter/Gather TABLE // p = luExtension->Current_SG_Entry; #if 0 //-[v1.06.00] don't use register dataSgAdr = SCSI_READD(DeviceExtension, pSgAdr) ; Ns3DebugPrint(0x1000,(": XMODE_DMA Current_SG_Entry[%lx] SGT Pointer[%x] PhySGlist[%p]",p,dataSgAdr,luExtension->PhySGlist)); luExtension->Current_SG_Entry = (( dataSgAdr - luExtension->PhySGlist) / 8); luExtension->Current_SG_Entry --; #endif remainCnt = SCSI_READD(DeviceExtension, pBmCnt); Ns3DebugPrint(0x1000,(": remainCnt[%lx]",remainCnt)); i = luExtension->Current_SG_Entry ; SGlist = luExtension->pSGlist; // send BYTE number sack = SCSI_READD(DeviceExtension, pSackCnt) - ( SGlist->TransferDataBuffer[p].Address & 3); //*[v1.06.00] レジスタは信用しないでackカウンターから現在位置を算出 luExtension->Current_SG_Entry = i = Ns3GetCurrent_SG(DeviceExtension, sack, p ,SGlist); // 送ろうとしたBYTE数 Total = Ns3GetSgCount(DeviceExtension, p, i, SGlist); // remainCnt : 今回TRANSFERしようとした残り remainCnt = Total -sack; Ns3DebugPrint(0x1000,(__FUNCTION__":Total:%ulx ACK:%ulx RemainCnt:%x\n",Total,sack,remainCnt)); #ifdef NINJA32UDE if (luExtension->TargetFlags & PD_NONCACHE) #else if (targetState->TargetFlags & PD_NONCACHE) #endif { int iii; char *dst,*src; if(!DeviceExtension->NonCachedExtension->Address) { return ; } if(!DeviceExtension->NonCachedExtension) { return ; } dst = (DeviceExtension->NonCachedExtension->Address+ SGlist->TransferDataBuffer[i].Address - DeviceExtension->NonCachedPhysical); src = (char*)DeviceExtension->CurDataPointer; for(iii=0;iiiTransferDataBuffer[i].Length &= ~BM_LAST; Ns3DebugPrint(0x1000,(__FUNCTION__ "delete BM_LAST mark [%x]\n",i)); if ( remainCnt == 0) { luExtension->Current_SG_Entry++ ; } else { SGlist->TransferDataBuffer[i].Address += (SGlist->TransferDataBuffer[i].Length - remainCnt); SGlist->TransferDataBuffer[i].Length = remainCnt; } if ( i == (luExtension->SGListCount-1) ) { // 最後のTABLEにMARKING SGlist->TransferDataBuffer[i].Length |= BM_LAST; Ns3DebugPrint(0x1000,(__FUNCTION__ ": last teble marking BM_LAST [%x]\n",i)); } luExtension->TransferedLength += sack; DeviceExtension->CurDataPointer += sack; DeviceExtension->CurDataLength -= sack; // luExtension->TransferedLength += SCSI_READD(DeviceExtension, pSackCnt); DeviceExtension->IntWait = FALSE; } else { Ns3DebugPrint(0x1000, ( __FUNCTION__ " : not XMODE_DMA\n")); if (DeviceExtension->CurDataLength) { if (ScsiExec.DataInPhase) { Ns3DataInPhase(DeviceExtension); Ns3DebugPrint(0x1000, (" : out ")); } } if (ScsiExec.DataOutPhase) { ULONG remain; Ns3DebugPrint(0x1000, (__FUNCTION__ " : ScsiExec.DataOutPhase\n")); remain = DeviceExtension->ActiveLogicalUnit->TransferedLength - (luExtension->AckCounter + SCSI_READD(DeviceExtension, pSackCnt)); DeviceExtension->CurDataLength += remain; DeviceExtension->CurDataPointer -= remain; DeviceExtension->ActiveLogicalUnit->TransferedLength -= remain; } } // if xmode_dma } // if Exec.DataPhase if (ScsiExec.StatusPhase) { Ns3DebugPrint(0x1000, (__FUNCTION__" : ScsiExec.StatusPhase ")); Ns3AutoStatus(DeviceExtension); Ns3DebugPrint(0x1000, ("--Ns3AutoStatus - end-- ")); } // //---- BUSFREE ? ---- // if (ScsiExec.BusFree) { Ns3DebugPrint(0x1000, (__FUNCTION__" : ScsiExec.BusFree : ")); SCSI_WRITEW(DeviceExtension, trans.pTransferControl, 0); SCSI_WRITED(DeviceExtension, pBmCnt, 0); DevIntIrqStatus.FifoShldIrq = 0; // ERRORが発生してBUSFREEになったら来る #ifdef NINJA32UDE if (ScsiExec.MsgIn02Valid ) { Ns3DebugPrint(0x1000, (__FUNCTION__" : ScsiExec.MsgIn02Valid\n")); luExtension->SavedDataPointer = DeviceExtension->CurDataPointer; luExtension->SavedDataLength = DeviceExtension->CurDataLength; } #endif // NINJA32UDE 0411 if (ScsiExec.MsgIn00Valid || DeviceExtension->ScsiState == SC_COMPLETE) { DeviceExtension->ActiveLogicalUnit->ActiveLuRequest->result = DID_OK<< 16; Ns3NotifyCompletion(DeviceExtension, 0); DeviceExtension->ScsiState = SC_BUSFREE; DeviceExtension->IntWait = FALSE; Ns3DebugPrint(0x1000, (" : Ns3NotifyCompletion out\n")); if (DeviceExtension->AdapterFlags & PD_PENDING_START_IO){ // tor Ns3StartIo(DeviceExtension,DeviceExtension->NextSrbRequest ); } Ns3DebugPrint(0x1000, (" : MsgIn00Valid out\n")); } else if (ScsiExec.MsgIn04Valid || DeviceExtension->ScsiState == SC_DISCONNECT) { DeviceExtension->ScsiState = SC_BUSFREE; luExtension->SavedDataPointer = DeviceExtension->CurDataPointer; luExtension->SavedDataLength = DeviceExtension->CurDataLength; luExtension->AckCounter += SCSI_READD(DeviceExtension, pSackCnt); Ns3DebugPrint(0x1000,(__FUNCTION__": disconnect CurDataLength(%x)",DeviceExtension->CurDataLength)); if (DeviceExtension->AdapterFlags & PD_PENDING_START_IO) { // tor Ns3StartIo(DeviceExtension,DeviceExtension->NextSrbRequest ); Ns3DebugPrint(0x1000, (__FUNCTION__ ": Ns3StartIo(NextSrbRequest) 2\n")); } } else { Ns3DebugPrint(0x1000, (__FUNCTION__" : Unexpected bus disconnect\n")); if (targetState->TargetFlags & PD_SYNCHRONOUS_TRANSFER_SENT) { targetState->TargetFlags &= ~PD_SYNCHRONOUS_TRANSFER_SENT; targetState->TargetFlags |= PD_DO_NOT_NEGOTIATE; } Ns3DebugPrint(0x1000, (__FUNCTION__ " : ScsiExec[%x] ScsiState[%x]",ScsiExec,DeviceExtension->ScsiState)); DeviceExtension->IntWait = FALSE; DeviceExtension->ScsiState = SC_BUSFREE; Ns3DebugPrint(0x1000, (" : DID_ERROR : ")); DeviceExtension->ActiveLogicalUnit->ActiveLuRequest->result = DID_ERROR <<16; Ns3NotifyCompletion(DeviceExtension, TRUE); return ; } Ns3DebugPrint(0x1000, (__FUNCTION__ " : busfree : ")); } // busfree // //---- Paused MSGIN ? ----- // if ( ScsiExec.PausedMsgIN) { Ns3DebugPrint(0x1000, (__FUNCTION__" : ScsiExec.PausedMsgIN\n")); Ns3AutoMsgIn(DeviceExtension); // for RESELECTION luExtension = DeviceExtension->ActiveLogicalUnit; } // //---- Paused MSGOUT ? ----- // if ( ScsiExec.PausedMsgOut) { Ns3DebugPrint(0x1000, (__FUNCTION__" : ScsiExec.PausedMsgOut\n")); Ns3AutoMsgOut(DeviceExtension); } // // ---- SELECTION TIMEOUT ? ---- // if ( ScsiExec.SelectionTimeout ) { Ns3DebugPrint(0x1000, (__FUNCTION__" : ScsiExec.SelectionTimeout\n")); Srb = DeviceExtension->ActiveLogicalUnit->ActiveLuRequest; DeviceExtension->ScsiState = SC_BUSFREE; SCSI_WRITEW(DeviceExtension, trans.pTransferControl, 0); SCSI_WRITED(DeviceExtension, pBmCnt, 0); DeviceExtension->NextSrbRequest = NULL; DeviceExtension->AdapterFlags &= ~PD_PENDING_START_IO; Ns3DebugPrint(0x1000, (__FUNCTION__" : NextSrbRequest = NULL\n")); if(DeviceExtension->ActiveLogicalUnit) { Ns3DebugPrint(0x1000, (__FUNCTION__ " : TIME OUT ERROR")); DeviceExtension->ActiveLogicalUnit->ActiveLuRequest->result = DID_TIME_OUT<< 16; } Ns3NotifyCompletion(DeviceExtension, TRUE); if ( !DeviceExtension->ConCheckDone ) { if ( Srb->target == 7 ) DeviceExtension->ConCheckDone = TRUE; } SCSI_WRITEW(DeviceExtension, irq.pIrqControl,DeviceExtension->IrqMaskData); DeviceExtension->IntWait = FALSE; Ns3DebugPrint(0x1000, (__FUNCTION__" : return(TRUE) ----------\n")); return; } } // autoscsi ---------------------------------------------------------- // //--- TIMER INTERRUPT ? --- // if ( DevIntIrqStatus.TimerIrq ) { Ns3DebugPrint(0x1000, (__FUNCTION__ ": DevIntIrqStatus.TimerIrq ")); if (DeviceExtension->PollingMode == 0xff) { // POLLINGCheck中? DeviceExtension->PollingMode = 0; // Int きた! Ns3DebugPrint(0x1000, (__FUNCTION__ " : PollingMode (0xff -> 0)\n")); } Ns3DebugPrint(0x1000, (__FUNCTION__ " : (TimerCount[%x]) : ",DeviceExtension->TimerCount)); if ( DeviceExtension->TimerCount != 0 ) { Ns3DebugPrint(0x1000, (__FUNCTION__ " : (TimerCycle[%x]) \n",DeviceExtension->TimerCycle)); SCSI_WRITE(DeviceExtension, timer.pTimerSet, DeviceExtension->TimerCycle); // Next TIMER START DeviceExtension->TimerCount--; } } // //--- SCSI RESET INTERRUPT ?---- // if ( DevIntIrqStatus.ScsiResetIrq ) { Ns3DebugPrint(0x1000, (__FUNCTION__ ": DevIntIrqStatus.ScsiResetIrq\n")); //とりあえず非同期5MBに SET for (i = 0; i < 8; i++) { targetState = &DeviceExtension->TargetState[i]; targetState->TargetFlags &= ~PD_SYNCHRONOUS_NEGOTIATION_DONE; targetState->SynchronousOffset = ASYNCHRONOUS_OFFSET; targetState->SynchronousPeriod = ASYNCHRONOUS_PERIOD; targetState->AckWidth = 0; targetState->SreqSmplRate = 2; } //電源断? if ( SCSI_READ(DeviceExtension,sc.pScsiBusMonitor) == 0xef ) { // SCSI LINEすべての信号がたっている? DeviceExtension->wIrqSelect.ScsiResetIrqSel = 0; SCSI_SWRITEW(baseAddress, pIrqSelect, *(PUSHORT)&(DeviceExtension->wIrqSelect)); } if ( (DeviceExtension->ActiveLogicalUnit != NULL) && DeviceExtension->ActiveLogicalUnit->ActiveLuRequest != NULL ) { // // Set the SrbStatus in the SRB, complete the request and // clear the active pointers // luExtension = DeviceExtension->ActiveLogicalUnit; luExtension->ActiveLuRequest = NULL; DeviceExtension->ActiveLogicalUnit = NULL; } goto IntEnd; } // //--- PHASE CHANGE INTERRUPT ? --- // if ( DevIntIrqStatus.PhaseChgIrq ) { Ns3DebugPrint(0x1000, (__FUNCTION__ ": DevIntIrqStatus.PhaseChgIrq ")); Ns3DebugPrint(0x1000,(": Phase = %x\n",*((PUSHORT)&DevIntIrqStatus) & 0xf) ); Ns3RunPhase(DeviceExtension); if ( (*((PUSHORT) &DevIntIrqStatus) & 0xff0 )) { goto IntEntry; } } // // ---- FIFO INTERRUPT ? ---- // if ( DevIntIrqStatus.FifoShldIrq ) { Ns3DebugPrint(0x1000, (__FUNCTION__ ": FifoShldIrq CurDataLength[%x]",DeviceExtension->CurDataLength)); DevIntIrqStatus.FifoShldIrq = 0; // まだ残りがある? if ( DeviceExtension->CurDataLength ) { if ( (*((PUSHORT)&DevIntIrqStatus) & 7) == BP_DATA_IN) { // さっきのPHASE Ns3DebugPrint(0x1000, (" : call Ns3DataInPhase ")); Ns3DataInPhase(DeviceExtension); } else if ( (*((PUSHORT)&DevIntIrqStatus) & 7) == BP_DATA_OUT) { Ns3DebugPrint(0x1000, (" : call Ns3DataOutPhase ")); Ns3DataOutPhase(DeviceExtension); } } if ( (*((PUSHORT) &DevIntIrqStatus) & 0xff0 )) { Ns3DebugPrint(0x1000, (__FUNCTION__ " : goto IntEntry!!!\n")); goto IntEntry; } } IntEnd: Ns3DebugPrint(0x1000, (__FUNCTION__ ": IntEnd : ")); // COMPLETEの時はScsiPortNotificationの時間があるので1回だけ見る // if ( !DeviceExtension->IntWait ) { *((PUSHORT) &DevIntIrqStatus) = SCSI_READW(DeviceExtension,irq.pIrqStatus); Ns3DebugPrint(0x1000,(" IRQ[%x] \n",*((PUSHORT) &DevIntIrqStatus) )); if ( *((PUSHORT)&DevIntIrqStatus) & 0xff0 ){ Ns3DebugPrint(0x1000, (__FUNCTION__ ": goto IntEntry[%x] !!!\n", *((PUSHORT) &DevIntIrqStatus) )); goto IntEntry; // INT また来た? } // } else { // for ( i = 0; i< INT_POLL_IRQ ; i++) { // *((PUSHORT) &DevIntIrqStatus) = SCSI_READW(DeviceExtension,irq.pIrqStatus); // if ( *((PUSHORT)&DevIntIrqStatus) & 0xff0 ) goto IntEntry; // INT また来た? // ScsiPortStallExecution(5); // } // } // //--- IRQ MASK MODEを元に戻す ---- // SCSI_WRITEW(DeviceExtension, irq.pIrqControl,DeviceExtension->IrqMaskData); // 試しに2回連続で設定してみる。 SCSI_WRITEW(DeviceExtension, irq.pIrqControl,DeviceExtension->IrqMaskData); Ns3DebugPrint(0x1000, ( " IrqMaskData[%x] ", DeviceExtension->IrqMaskData)); return; } // end Ns3Interrupt() #ifdef NINS32DBG u_int irq_counter= 0; #endif void do_nins32_isr(int irq, void *dev_id, struct pt_regs *regs) { long flags; // for save_flags() pnins32_host p; p = (pnins32_host )dev_id; if(!p) { Ns3DebugPrint(0x20,(__FUNCTION__ " dev_id is NULL error\n" )); panic(" isr dev_id is NULL error" ); return; } #ifdef GET_IRQINISR #else *((PUSHORT) &(p->intIrqStatus2)) = SCSI_READW(p,irq.pIrqStatus); #endif // GET_IRQINISR save_flags(flags); cli(); Ns3DebugPrint(0x20,(__FUNCTION__ " in " )); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,95)) /* look __asm__-i386\spinlock.h */ #ifdef USE_SPINUNLOCK spin_lock_irqsave(&io_request_lock, cpu_flags); #endif // USE_SPINUNLOCK #ifdef USE_QUEUETASK ns3_tq.routine = Ns3Interrupt; ns3_tq.data = (void *)p; queue_task(&ns3_tq,&tq_immediate); mark_bh(IMMEDIATE_BH); #else // USE_QUEUETASK Ns3Interrupt(p); #endif // USE_QUEUETASK #ifdef USE_SPINUNLOCK spin_unlock_irqrestore(&io_request_lock, cpu_flags); #endif // USE_SPINUNLOCK #else #endif Ns3DebugPrint(0x20,(__FUNCTION__ " out\n " )); Ns3DebugPrint(0x1000, ( " restore_flags[%x] ", flags)); restore_flags(flags); } #define PCI //#if defined(PCI) && defined(NINJA32UDE) #ifdef PCI #ifdef NINJA32UDE //;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* //; //; NjSCSI-32UDE SerialEEPRomアクセス サブルーチン //; //;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* //;;----------------------------------------------------------------------;; //;; ;; //;; ---->-->-> AT24C01A 用です。 ;; //;; ;; //;;----------------------------------------------------------------------;; // ;; I/O を空読みしてWAITをとる (( PCI I/OのREADはキャッシュが効かない? )) // ;; // ;; // ;; 2400n=27回なので 10000n=10u=140ぐらいかな // ;; VOID sprom_wait(VOID ); VOID sprom_wait( VOID ) { ScsiPortStallExecution(20); } //;;------------------------------------- //;; SDATAのみを"HIGH"にする VOID datahigh( IN PSCSI_REGISTER baseAddress ) { UCHAR dataByte; dataByte = SCSI_SREAD(baseAddress, pSerialRomCtl); dataByte |= 6; SCSI_SWRITE(baseAddress, pSerialRomCtl,dataByte); sprom_wait( ); } //;;------------------------------------- //;; SDATAのみを"LOW"にする VOID datalow( IN PSCSI_REGISTER baseAddress ) { UCHAR dataByte; dataByte = SCSI_SREAD(baseAddress, pSerialRomCtl); dataByte &= 1; // CLKはそのまま dataByte |= 2; // 0を出力 SCSI_SWRITE(baseAddress, pSerialRomCtl,dataByte); sprom_wait( ); } //;;------------------------------------- //;; SCLKのみを"LOW"にする VOID clklow( IN PSCSI_REGISTER baseAddress ) { UCHAR dataByte; dataByte = SCSI_SREAD(baseAddress, pSerialRomCtl); dataByte &= 6; SCSI_SWRITE(baseAddress, pSerialRomCtl,dataByte); sprom_wait( ); } //;;------------------------------------- //;; SCLKのみを"HIGH"にする VOID clkhigh( IN PSCSI_REGISTER baseAddress ) { UCHAR dataByte; dataByte = SCSI_SREAD(baseAddress, pSerialRomCtl); dataByte |= 1; SCSI_SWRITE(baseAddress, pSerialRomCtl,dataByte); sprom_wait( ); } //;;------------------------------------- //;; アドレスを出力 VOID sad_out( IN PSCSI_REGISTER baseAddress ,IN UCHAR RomAdr ) { ULONG i; UCHAR mask = 0x80; for ( i = 0; i < 8 ; i++) { if ( RomAdr & mask ) { clklow( baseAddress ); datahigh( baseAddress ); } else { clklow( baseAddress ); datalow( baseAddress ); } mask >>= 1; clkhigh( baseAddress ); } clklow( baseAddress ); } // ;;-------------------------------------- // ;; // ;; "0"を出力 // ;; VOID zeroout( IN PSCSI_REGISTER baseAddress ) { datalow( baseAddress ); clkhigh( baseAddress ); clklow( baseAddress ); } // ;;-------------------------------------- // ;; // ;; "1"を出力 // ;; VOID oneout ( IN PSCSI_REGISTER baseAddress ) { datahigh( baseAddress ); clkhigh( baseAddress ); clklow( baseAddress ); } //;;------------------------------------- //;; //;; デバイスアドレスを出力 ;A2,1,0pinは"GND"です。 //;; VOID dev_address( IN PSCSI_REGISTER baseAddress ) { oneout( baseAddress ); //;1 zeroout( baseAddress ); //;0 oneout( baseAddress ); //;1 zeroout( baseAddress ); //;0 zeroout( baseAddress ); //;0 - A2:GND zeroout( baseAddress ); //;0 - A1:GND zeroout( baseAddress ); //;0 - A1:GND } ;///////////////////////////////////////////////////////////// ; //;;------------------------------------- //;; SCLK,SDATA両方を"HIGH"にする VOID sshigh( IN PSCSI_REGISTER baseAddress ) { SCSI_SWRITE(baseAddress, pSerialRomCtl,7); sprom_wait( ); } // ;; // ;; SDATA,を出力モードにする // ;; VOID gpio_outmode( IN PSCSI_REGISTER baseAddress ) { UCHAR dataByte; dataByte = SCSI_SREAD(baseAddress, pSerialRomCtl); dataByte |= 2; SCSI_SWRITE(baseAddress, pSerialRomCtl, dataByte); } VOID ack_wait( IN PSCSI_REGISTER baseAddress ) { UCHAR dataByte; ULONG retry; SCSI_SWRITE(baseAddress, pSerialRomCtl, 1); clkhigh( baseAddress ); retry = 10; dataByte = 0; do { sprom_wait( ); dataByte = SCSI_SREAD(baseAddress, pSerialRomCtl); if (retry-- == 0 ) break; } while ( dataByte & 4 ); clklow ( baseAddress ); } //;;------------------------------------- //;; データを得る UCHAR sdata_in( IN PSCSI_REGISTER baseAddress ) { UCHAR readData = 0; UCHAR dataByte; ULONG i; // まずSDATAを入力モードにする dataByte = SCSI_SREAD(baseAddress, pSerialRomCtl); dataByte &= 1; SCSI_SWRITE(baseAddress, pSerialRomCtl,dataByte); for ( i = 0; i < 7; i++ ) { clkhigh( baseAddress ); // データを得る dataByte = SCSI_SREAD(baseAddress, pSerialRomCtl); dataByte >>= 2; readData |= dataByte; readData <<= 1; clklow( baseAddress ); } clkhigh( baseAddress ); // 最後の1bitは回さない // データを得る dataByte = SCSI_SREAD(baseAddress, pSerialRomCtl); dataByte >>= 2; readData |= dataByte; clklow( baseAddress ); // そしてSDATAを出力モードにする dataByte = SCSI_SREAD(baseAddress, pSerialRomCtl); dataByte |= 2; SCSI_SWRITE(baseAddress, pSerialRomCtl,dataByte); return (readData); } //;;------------------------------------- //;; byte read コマンド発行 //;; //;; Input BH=アドレス //;; DX=BASE ADRESS //;; //;; Out BH=アドレス,BL=データ //;; UCHAR Ns3SpromRead (IN PSPECIFIC_DEVICE_EXTENSION DeviceExtension, IN UCHAR RomAdr) { PSCSI_REGISTER baseAddress; UCHAR readData; ULONG i; baseAddress = DeviceExtension->BaseAddress; gpio_outmode( baseAddress ); // Dummy Write ;;その心は"アドレス"をセット // STARTコンディション datalow( baseAddress ); clklow( baseAddress ); // デバイスアドレスを出力 dev_address( baseAddress ); // R/W Writeモードは "0" zeroout( baseAddress ); //ACK -------------------- ack_wait( baseAddress ); //------------------------- // アドレスを出力 sad_out( baseAddress , RomAdr); //ACK -------------------- ack_wait( baseAddress ); //------------------------- //Current Address Read //STARTコンディション sshigh( baseAddress ); datalow( baseAddress ); clklow( baseAddress ); //デバイスアドレスを出力 dev_address( baseAddress ); //R/W readモードは "1" oneout( baseAddress ); //ACK -------------------- ack_wait( baseAddress ); //------------------------- //データを得る readData = sdata_in( baseAddress ); //NO ACK datahigh( baseAddress ); clkhigh( baseAddress ); clklow( baseAddress ); //STOP datalow( baseAddress ); clkhigh( baseAddress ); clkhigh( baseAddress ); datahigh( baseAddress ); //次のアクセスまでのWait for ( i= 0; i<0x10 ; i++){ sprom_wait( ); } return (readData); } //----------------------------------------------------------------------------- // ボードの設定内容をシリアルROMから得る //Routine Description: // // This routine is called from to find // and claim BIOS space. // //Arguments: // // HwDeviceExtension - HBA miniport driver's adapter data storage // BaseIoAddress - IO address of adapter // ConfigInfo - Miniport configuration information // //Return Value: // // None. // //----------------------------------------------------------------------------- BOOLEAN Ns3GetSetting(IN PSPECIFIC_DEVICE_EXTENSION DeviceExtension) { PSPECIFIC_TARGET_EXTENSION targetState; UCHAR syncMax; UCHAR AutoSync; ULONG id; ULONG RstTimer; if(!DeviceExtension) { Ns3DebugPrint(0x20,(__FUNCTION__ ": DeviceExtension == NULL\n")); return FALSE; } if (!((Ns3SpromRead(DeviceExtension,0x7e) == 0x55) && (Ns3SpromRead(DeviceExtension,0x7f) == 0xaa) )) { Ns3DebugPrint(0x20,(__FUNCTION__ ": Ns3SpromRead 0x55 or 0xaa\n")); return FALSE; } RstTimer = Ns3SpromRead(DeviceExtension,0x12); if (!( RstTimer == 0 || RstTimer == 0xff)) { RstTimer *= 1000000; DeviceExtension->ResetTimer = RstTimer; } // オプションに何も書いてなければ if (DeviceExtension->SynchronousPeriod == 0 ) { AutoSync = Ns3SpromRead(DeviceExtension,7); Ns3DebugPrint(0x20,(__FUNCTION__ ": AutoSync = [%x]\n",AutoSync)); if ( AutoSync == 0 ) { DeviceExtension->SynchronousPeriod = 0; // 自動 Ns3DebugPrint(0x20,(__FUNCTION__ ": SynchronousPeriod = 0\n")); } else { DeviceExtension->SynchronousPeriod = 0xff; Ns3DebugPrint(0x20,(__FUNCTION__ ": SynchronousPeriod = 0xff\n")); } for (id = 0; id < 7 ; id++) { targetState = &DeviceExtension->TargetState[id]; syncMax = Ns3SpromRead(DeviceExtension,(UCHAR)id ); if ( syncMax == 0 && AutoSync == 1) { targetState->TargetFlags |= PD_DO_NOT_NEGOTIATE; Ns3DebugPrint(0x20,(": PD_DO_NOT_NEGOTIATE ")); } if ( syncMax == 0xc || syncMax == 0x19) { targetState->SyncMax = syncMax; Ns3DebugPrint(0x20,(": SyncMax = syncMax ")); } else { targetState->SyncMax = SYNCHRONOUS_PERIOD_10M; Ns3DebugPrint(0x20,(": SYNCHRONOUS_PERIOD_10M ")); } } } return TRUE; } #endif // NINJA32UDE #endif /*+F************************************************************************* * Function: * nins32_alloc * * Description: * Allocate and initialize a host structure. Returns NULL upon error * and a pointer to a nins32_host struct upon success. *-F*************************************************************************/ static pnins32_host nins32_alloc(Scsi_Host_Template *sht, pnins32_host temp) { pnins32_host p = NULL; struct Scsi_Host *host; /* * Allocate a storage area by registering us with the mid-level * SCSI layer. */ host = scsi_register(sht, sizeof(nins32_host)); if (host != NULL) { p = (pnins32_host) host->hostdata; memset(p, 0, sizeof(nins32_host)); *p = *temp; p->host = host; p->host_no = host->host_no; } return (p); } // //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ // Athlon Check //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ +[v1.05.14] vvvv BOOL isAthlon(void){ //register UCHAR CpuType; // Athlon volatile UCHAR CpuType; // Athlon CpuType = 0xff; __asm__ __volatile__(" pushal pushfl pop %%eax movl %%ecx,%%eax xor $00200000,%%eax push %%eax popfl pushfl popl %%eax cmpl %%eax,%%ecx jz no_cpuid xorl %%eax,%%eax .byte 0x0f .byte 0x0a2 //cpuid andl $0x0ffffff00,%%ecx cmpl $0x444d4100,%%ecx // 'AMD' jnz no_cpuid movl $1,%%eax .byte 0x0f .byte 0x0a2 //cpuid movb %%ah,%0 no_cpuid: popal;\n" : "=c" (CpuType) ::"eax","ecx","al"); // :"=g" (CpuType) -> c if ( CpuType > 5 ) { return TRUE; } return FALSE; } static int nins32_register(Scsi_Host_Template *template, pnins32_host DevExt, int reset_delay) { int result; int found = 1; struct Scsi_Host *host; PSCSI_REGISTER baseAddress; ULONG i; PSPECIFIC_TARGET_EXTENSION targetState; baseAddress = DevExt->BaseAddress; // Determine IRQ // Note: In future release of NT (after .404 March Beta), this value // can be returned as 0 and NT will assume we are polling and won't // reserve an IRQ for us. Until then, we need to give him something. // See Note Above // // Allocate a Noncached Extension to use for Transfer Buffer // DevExt->NonCachedExtension = kmalloc( sizeof(NONCACHED_EXTENSION),GFP_KERNEL); if (DevExt->NonCachedExtension == NULL) { Ns3DebugPrint(0x20,(__FUNCTION__ "DevExt->NonCachedExtension == NULL")); return( 0 ); } if ( (ULONG)(DevExt->NonCachedExtension) & 3) { //+[atapci] (ULONG)(DevExt->NonCachedExtension) &= 0xfffffffc; //+[atapci] (ULONG)DevExt->NonCachedExtension += 0x4; } Ns3DebugPrint(0x20,("NonCachedExtension: %lux\n", DevExt->NonCachedExtension->Address)); DevExt->NonCachedPhysical = virt_to_phys(DevExt->NonCachedExtension->Address); DevExt->SrbExtension = kmalloc( (sizeof(SG_LIST)+sizeof(AUTO_PARA) ) ,GFP_KERNEL); Ns3DebugPrint(0x20,(__FUNCTION__ " : SrbExtension [%x]\n",DevExt->SrbExtension)); if (DevExt->TransferMode == XMODE_MMIO) { Ns3DebugPrint(0x20,(__FUNCTION__ " DevExt->pXferRead = mmio32_datain\n")); DevExt->pXferRead = mmio32_datain; DevExt->pXferWrite = mmio32_dataout; } else { Ns3DebugPrint(0x20,(__FUNCTION__ " DevExt->pXferRead = pio32_datain\n")); DevExt->pXferRead = pio32_datain; DevExt->pXferWrite = pio32_dataout; } Ns3DebugPrint(0x20, ("Exit FindAdapter.\n")); DevExt->NumConnect = 0; DevExt->ConCheckDone = FALSE; // Set Unsync 5MB for (i = 0; i < 8; i++) { targetState = &DevExt->TargetState[i]; targetState->TargetFlags = 0; #ifdef NT_INST targetState->TargetFlags |= PD_NONCACHE; #else if (DevExt->AdapterOption & OPT_NOSG ) targetState->TargetFlags |= PD_NONCACHE; #endif targetState->SynchronousOffset = ASYNCHRONOUS_OFFSET; targetState->SynchronousPeriod = ASYNCHRONOUS_PERIOD; targetState->AckWidth = 0; targetState->SreqSmplRate = 2; targetState->TransferMode = DevExt->TransferMode; DevExt->DeviceType[i] = 0xff; // for NT Easy-CD } DevExt->BaseAddress = (PSCSI_REGISTER)DevExt->maddr; #ifdef NINJA32UDE DevExt->ResetTimer = RESET_RECOVER_TIME; //+[ude] Ns3GetSetting(DevExt); //+[ude] #endif // NINJA32UDE #ifdef NINJA32UDE { USHORT dataWord,dataWordH; dataWord = SCSI_SREADW(DevExt->BaseAddress,pCfgLataCache); dataWordH = SCSI_READ(DevExt,pDataRegH); if ( (dataWord & 0xff00) == 0 ) { Ns3DebugPrint(0x20, (" SCSI_SWRITEW(pCfgLataCache) ")); dataWord |= DevExt->Latency << 8; SCSI_SWRITEW(DevExt->BaseAddress,pCfgLataCache,dataWord); } } DevExt->IrqMaskData = 0xf000; //+[ude] #endif // NINJA32UDE // integer from pointer without a cast host = DevExt->host; host->this_id = 7; host->io_port = DevExt->base; host->n_io_port = 0xFF; host->base = (unsigned char *) DevExt->mbase; host->irq = DevExt->irq; Ns3DebugPrint(0x20,(__FUNCTION__ ": host->irq[%x]\n",host->irq)); DevExt->BaseAddress = (PSCSI_REGISTER)DevExt->maddr; /* * Register IRQ with the kernel. Only allow sharing IRQs with * PCI devices. */ result = (request_irq(DevExt->irq, do_nins32_isr, SA_INTERRUPT, "nins32", DevExt)); if (result) { result = (request_irq(DevExt->irq, do_nins32_isr, SA_INTERRUPT | SA_SHIRQ, "nins32", DevExt)); Ns3DebugPrint(0x20,(__FUNCTION__ ":request_irq SA_INTERRUPT | SA_SHIRQ\n")); }else { Ns3DebugPrint(0x20,(__FUNCTION__ ":request_irq SA_SHIRQ only\n")); } Ns3DebugPrint(0x20,(__FUNCTION__ ":request_irq DevExt->irq[%x] result[%x]\n",DevExt->irq,result)); if (result < 0) { printk(KERN_WARNING "(scsi%d) Couldn't register IRQ %d, ignoring " "controller.\n", DevExt->host_no, DevExt->irq); DevExt->irq = 0; return (0); } host->irq = DevExt->irq; Ns3DebugPrint(0x20, ("Exit FindAdapter. \n")); return (found); } /*----------------------------------------------------------------*/ /* global functions */ /*----------------------------------------------------------------*/ static int ninja3_precommand( PSPECIFIC_LU_EXTENSION *luExt, pnin_softc devExt, Scsi_Cmnd * Srb) { Ns3DebugPrint(0x10,(KERN_DEBUG __FUNCTION__ " in ")); /* ** Determine the logical unit that this request is for. */ (*luExt) = ScsiPortGetLogicalUnit(devExt, Srb->target, Srb->lun); if( !(*luExt) ) { Ns3DebugPrint(0x10,( " ScsiPortGetLogicalUnit error!!\n")); Srb->result = DID_ERROR << 16;/*XS_DRIVER_STUFFUP;*/ return FALSE; /*TRY_AGAIN_LATER;*/ } srbStatus = SRB_STATUS_SUCCESS; /* ** Setup the context for this target/lun. */ (*luExt)->ActiveLuRequest = Srb; (*luExt)->SavedDataPointer = (ULONG)Srb->request_buffer; (*luExt)->SavedDataLength = Srb->request_bufflen; Ns3DebugPrint(0x10,( ": Length[%x] \n",(*luExt)->SavedDataLength)); devExt->ActiveLogicalUnit = (*luExt); (*luExt)->PhaseWaitCounter = 0; return TRUE; } /*ninja3_precommand end*/ #ifdef USE_SCSIDUMP static void scsi_dump(Scsi_Cmnd * SCpnt, int flag){ int i; #if 0 unsigned char * pnt; #endif unsigned int * lpnt; struct scatterlist * sgpnt = NULL; printk(__FUNCTION__ " use_sg: %d ",SCpnt->use_sg); if (SCpnt->use_sg){ sgpnt = (struct scatterlist *) SCpnt->buffer; for(i=0; iuse_sg; i++) { lpnt = (int *) sgpnt[i].alt_address; printk(":%p %p %d\n",sgpnt[i].alt_address, sgpnt[i].address, sgpnt[i].length); if (lpnt) printk(" (Alt %x) ",lpnt[15]); }; } else { printk("nosg: request.buffer%p buffer%p bufflen%d\n", SCpnt->request.buffer, SCpnt->buffer,SCpnt->bufflen); lpnt = (int *) SCpnt->request.buffer; if (lpnt) printk(" (Alt %x) ",lpnt[15]); }; lpnt = (unsigned int *) SCpnt; for (i=0;ihost->hostdata; PSCSI_REGISTER baseAddress = DevExt->BaseAddress; #ifdef USE_SELECTSAVEFLAG long flags;// for save_flags() #endif /* USE_SELECTSAVEFLAG */ Ns3DebugPrint(0x1010,(__FUNCTION__ " in ")); cmd->result = DID_OK << 16; cmd->scsi_done = done; #ifdef USE_SCSIDUMP scsi_dump(cmd, 0); # endif // USE_SCSIDUMP if( cmd->target == 7/*DevExt->HostId TargetId??*/ ) { Ns3DebugPrint(0x10,(__FUNCTION__ " cmd->target == 7 return\n")); cmd->result = DID_BAD_TARGET << 16; done(cmd); return 0; } if (( baseAddress->pIndexReg) == 0xffff) { Ns3DebugPrint(0x10,(KERN_DEBUG __FUNCTION__ " IntIrqStatus == 0xffff \n")); if ( luExtension ) { // Ns3NotifyCompletion(DevExt, (BOOLEAN)(!luExtension->NextReq)); } DevExt->ScsiState = SC_BUSFREE; DevExt->IntWait = FALSE; cmd->result = DID_NO_CONNECT << 16; done(cmd); Ns3DebugPrint(0x20,(__FUNCTION__ ": card out? FALSE\n")); return 0; } if (DevExt->PollingMode == 0xff) { USHORT dataWord; // ScsiPortNotification(RequestTimerCall,deviceExtension,Ns3IntCheck,1000); Ns3DebugPrint(0x1020,(__FUNCTION__ ": DevExt->PollingMode == 0xff\n")); if(DevExt->dev_timer2.expires){ del_timer(&(DevExt->dev_timer2)); } Ns3DebugPrint(0x20,(__FUNCTION__ ": Ns3IntCheck add_timer\n")); init_timer(&DevExt->dev_timer2); DevExt->dev_timer2.expires = jiffies + 1000; DevExt->dev_timer2.data = (unsigned long)DevExt; DevExt->dev_timer2.function = Ns3IntCheck; /* timer handler */ add_timer(&(DevExt->dev_timer2)); SCSI_WRITEW(DevExt, timer.pTimerSet, 4);//100us Timer Start dataWord = 0; ((PIRQ_CONTROLP)&dataWord)->CardBusIrqMask = 1; ((PIRQ_CONTROLP)&dataWord)->FifoIrqMask = 1; ((PIRQ_CONTROLP)&dataWord)->ScsiIrqMask = 1; Ns3DebugPrint(0x10,(": pIrqControl[%x]\n",dataWord)); SCSI_WRITEW(DevExt, irq.pIrqControl,dataWord);// Timer Irq Enable DevExt->IntWait = FALSE; } if( !ninja3_precommand(&luExtension,DevExt,cmd) ) { return cmd->result; } Ns3StartExecution(DevExt, luExtension, cmd); #ifdef USE_SELECTSAVEFLAG save_flags(flags); Ns3DebugPrint(0x20, ( " save_flags[%x] " ,flags)); cli(); #endif /* USE_SELECTSAVEFLAG */ #ifdef USE_IRQ_POLL if ( Ns3Select(DevExt,cmd) ) Ns3IrqPolling ( DevExt); #else Ns3Select(DevExt,cmd); #endif // USE_IRQ_POLL Ns3DebugPrint(0x20, (__FUNCTION__ "( Ns3Select end ) ")); #ifdef USE_SELECTSAVEFLAG Ns3DebugPrint(0x20, ( " restore_flags[%x] ", flags)); restore_flags(0x82); #endif /* USE_SELECTSAVEFLAG */ #if NINS32DBG { USHORT data; data = SCSI_SREADW(DevExt->BaseAddress, pIrqSelect); Ns3DebugPrint(0x20,(" : IrqSelect[%x] --",data)); } #endif return 0; } int nins32_biosparam(Disk *disk, kdev_t dev, int geom[]) { Ns3DebugPrint(0x20,(__FUNCTION__ " \n")); // not implemented return (0); } int nins32_release(struct Scsi_Host *host) { pnins32_host p; int i,j; Ns3DebugPrint(0x20,(__FUNCTION__ " \n")); for(i=0;i<7;i++) { for(j=0;j<10;j++) { ScsiPortFreeLogicalUnit(i,j); } } p = (pnins32_host)host->hostdata; if(p->irq) { Ns3DebugPrint(0x20,(__FUNCTION__ " free_irq[%d]\n",p->irq)); free_irq(p->irq, p); } if(p->maddr) { #if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) vfree((void *) (((unsigned long) p->maddr) & PAGE_MASK)); #else iounmap((void *) (((unsigned long) p->maddr) & PAGE_MASK)); #endif } return(0); } //static u_long remap_pci_mem(u_long base, u_long size) static void * remap_pci_mem(u_long base, u_long size) { u_long page_base = ((u_long) base) & PAGE_MASK; u_long page_offs = ((u_long) base) - page_base; u_long page_remapped = (u_long) ioremap_nocache(page_base, page_offs+size); return (void *) (page_remapped? (page_remapped + page_offs) : 0UL); } int nins32_detect(Scsi_Host_Template *template) { PSCSI_REGISTER BaseAddress; // Port address of adapter. USHORT ChipId; USHORT *workp; /*char *workp,work;*/ #ifdef CONFIG_PCI /* * PCI-bus probe. */ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92) if (pci_present()) #else if (pcibios_present()) #endif { #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92) struct pci_dev *pdev = NULL; #else int index; unsigned int piobase, mmapbase; unsigned char pci_bus, pci_devfn, pci_irq; #endif pnins32_host temp_p = NULL; unsigned short command; unsigned long page_offset = 0; pnins32_host p; ULONG xferMode = XMODE_DMA; int i; struct { unsigned short vendor_id; unsigned short device_id; } const nin32bi_dev[] = { {PCI_VENDOR_ID_IODATA, PCI_DEVICE_ID_IODATA_NJS32BI}, {PCI_VENDOR_ID_WORKBIT, PCI_DEVICE_ID_KME_NJS32BI}, {PCI_VENDOR_ID_WORKBIT, PCI_DEVICE_ID_WORKBIT_NJS32BI}, {PCI_VENDOR_ID_WORKBIT, PCI_DEVICE_ID_LOGITEC_TEST}, {PCI_VENDOR_ID_WORKBIT, PCI_DEVICE_ID_LOGITEC_NJS32BI}, {PCI_VENDOR_ID_WORKBIT, PCI_DEVICE_ID_LOGITEC_NJS32BIB}, {0, 0}, }; template->proc_dir = &proc_scsi_nins32; #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92) pdev = NULL;i=0; do { pdev = pci_find_device(nin32bi_dev[i].vendor_id,nin32bi_dev[i].device_id,pdev); Ns3DebugPrint(0x20,(__FUNCTION__ " pci_find_device(%x,%x) = [%x]\n",nin32bi_dev[i].vendor_id,nin32bi_dev[i].device_id,pdev)); i++; } while(!pdev && (nin32bi_dev[i].vendor_id && nin32bi_dev[i].device_id) ); if(!pdev){ Ns3DebugPrint(0x20,(__FUNCTION__ " pdev is NULL\n")); return 0; } #else index = 0; #endif #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92) temp_p = kmalloc(sizeof( nins32_host), GFP_ATOMIC); temp_p->irq = pdev->irq; temp_p->pdev = pdev; temp_p->pci_bus = pdev->bus->number; temp_p->pci_device_fn = pdev->devfn; temp_p->base = pdev->base_address[0]; temp_p->mbase = pdev->base_address[1]; Ns3DebugPrint(0x20,( __FUNCTION__ " base[%lux],mbase[%ux] irq[%d],pci_bus[%d],pci_device_fn[%d]\n",temp_p->base,(int)temp_p->mbase,pdev->irq,pdev->bus->number,pdev->devfn)); temp_p->base &= PCI_BASE_ADDRESS_IO_MASK; temp_p->mbase &= PCI_BASE_ADDRESS_MEM_MASK; Ns3DebugPrint(0x20,("nins32: at PCI %d/%d : \n", PCI_SLOT(temp_p->pdev->devfn), PCI_FUNC(temp_p->pdev->devfn)) ); pci_read_config_word(pdev, PCI_COMMAND, &command); Ns3DebugPrint(0x20,( __FUNCTION__ " : pci_read_config_word[%x]\n",command)); command |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO ; pci_write_config_word(pdev, PCI_COMMAND, command); #endif temp_p->AdapterOption = 0; temp_p->AdapterFlags = 0; temp_p->AdapterOption |= OPT_ULTRA; temp_p->AdapterOption |= OPT_AUTOPARA; temp_p->AdapterOption &= ~OPT_AUTOPARA; temp_p->MCLK = 20;//Ns3GetArgumentString(ArgumentString, "mclk",4, TRUE); temp_p->MCLK = 40; temp_p->Latency = 0x20; temp_p->bPcicSetup = 0xff; temp_p->bPcicCmd = 0xff; temp_p->bMmSpeed = 0xff; temp_p->SynchronousPeriod = 0; // SYNCHRONOUS_PERIOD_10M; if(drvOption.isConfig) { if(drvOption.useDisconnect) { } else { temp_p->AdapterOption |= OPT_NON_DISCONECT; } if(drvOption.transferMode == XMODE_PIO32) { temp_p->TransferMode = XMODE_PIO32; template->sg_tablesize = 0; } else { temp_p->TransferMode = XMODE_DMA; } }else { /*0613 */ if(pci_find_device(PCI_VENDOR_ID_WORKBIT,PCI_DEVICE_ID_LOGITEC_NJS32BIB,pdev)){ xferMode = XMODE_DMA; } else { if(pci_find_device(PCI_VENDOR_ID_ALADIN_MB,PCI_DEVICE_ID_ALADIN_MB,pdev)){ xferMode = XMODE_PIO32; } if(pci_find_device(PCI_VENDOR_ID_ToPIC95,PCI_DEVICE_ID_ToPIC95,pdev)){ xferMode = XMODE_PIO32; } else { if(isAthlon()) { xferMode = XMODE_PIO32; } } } temp_p->TransferMode = xferMode; if(xferMode == XMODE_PIO32){ template->sg_tablesize = 0; } } temp_p->maddr = remap_pci_mem(temp_p->mbase, 0x128+ 0x800); temp_p->maddr += 0x800; request_region(temp_p->base, page_offset + 256 + 0x800, "nins32"); if(temp_p->maddr) { /* * We need to check the I/O with the MMAPed address. Some machines * simply fail to work with MMAPed I/O and certain controllers. */ BaseAddress = (PSCSI_REGISTER)(temp_p->maddr); workp = (USHORT *)BaseAddress; ChipId = (BaseAddress->pIndexReg); Ns3DebugPrint(0x20,(__FUNCTION__" :ChipId[%x] >> 8 = [%x]",ChipId,(ChipId >> 8) )); ChipId >>= 8; if (0x51 <= ChipId && ChipId <= 0x51f) { Ns3DebugPrint(0x20,(":SP_RETURN_FOUND\n")); } p = nins32_alloc(template, temp_p); Ns3DebugPrint(0x20,(" \n")); if (p != NULL) { p->BaseAddress = BaseAddress; if (!nins32_register(template, p, 0)) { Ns3DebugPrint(0x20,(__FUNCTION__ "nins32_register failed\n")); nins32_release(p->host); scsi_unregister(p->host); return FALSE; } else { Ns3DebugPrint(0x20,(__FUNCTION__ "nins32_register OK!!\n")); Ns3Initialize( (PVOID) p ); return TRUE; } } //if (((PUCHAR)&(BaseAddress)->pIndexReg) != 0xff) if (ChipId >= 0x51 && ChipId <= 0x51f) { Ns3DebugPrint(0x20,(__FUNCTION__ " (ChipId >= 0x51 && ChipId <= 0x51f)\n")); return (TRUE); } } /* * OK.....we failed our test....go back to programmed I/O */ printk(KERN_INFO "nin32: MMAPed I/O failed, reverting to Programmed I/O.\n"); Ns3DebugPrint(0x20,(__FUNCTION__ " iounmap\n")); #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0) iounmap((void *) (((unsigned long) temp_p->maddr) & PAGE_MASK)); #else vfree((void *) (((unsigned long) temp_p->maddr) & PAGE_MASK)); #endif temp_p->maddr = 0; return FALSE; } Ns3DebugPrint(0x20,( __FUNCTION__ " : ???\n")); #endif /* CONFIG_PCI */ return (0); } int nins32_reset(Scsi_Cmnd *cmd, unsigned int flags) { Ns3DebugPrint(0x20,(__FUNCTION__ " \n")); Ns3ResetScsiBus((PVOID)(cmd->host->hostdata)); cmd->result = DID_RESET << 16; cmd->scsi_done(cmd); return(SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET); } int nins32_abort(Scsi_Cmnd *cmd) { Ns3DebugPrint(0x20,(__FUNCTION__ " \n")); cmd->result = DID_ABORT << 16; cmd->scsi_done(cmd); return(SCSI_ABORT_SUCCESS); } #ifdef MODULE #define ARG_SEP ' ' #else #define ARG_SEP ',' #endif /*+F************************************************************************* * Function: * nins32_setup *-F*************************************************************************/ void nins32_setup(char *str, int *ints) { char *cur = str; char *pc, *pv; int val; int base; int c; if(!drvOption.isConfig) { drvOption.isConfig = TRUE; drvOption.useDisconnect = TRUE; drvOption.transferMode = XMODE_DMA; } while (cur != NULL && (pc = strchr(cur, ':')) != NULL) { char *pe; val = 0; pv = pc; c = *++pv; if (c == 'n') val = 0; else if (c == 'y') val = 1; else { base = 0; val = (int) simple_strtoul(pv, &pe, base); } if (!strncmp(cur, "pio", 3)) { drvOption.transferMode = XMODE_PIO32; printk(__FUNCTION__ "transferMode = XMODE_PIO32\n"); } else if (!strncmp(cur, "dma", 3)) { printk(__FUNCTION__ "transferMode = XMODE_DMA\n"); } else if (!strncmp(cur, "disconnect:", 11)) { if(val) { drvOption.useDisconnect = TRUE; }else { drvOption.useDisconnect = FALSE; } } else printk("nins32_setup: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur); if ((cur = strchr(cur, ARG_SEP)) != NULL) ++cur; } } const char * nins32_info(struct Scsi_Host *dooh) { return("Workbit NinjaSCSI-32Bi \n"); }