NTSTATUS LsuWriteBlocks( IN PLANSCSI_SESSION LSS, IN PBYTE Buffer, IN UINT64 LogicalBlockAddress, IN ULONG TransferBlocks, IN ULONG BlockBytes, IN ULONG PduFlags ) { NTSTATUS status; LANSCSI_PDUDESC PduDesc; BYTE PduResponse; LSS_INITIALIZE_PDUDESC(LSS, &PduDesc, IDE_COMMAND, WIN_WRITE, PduFlags, LogicalBlockAddress, TransferBlocks, TransferBlocks * BlockBytes, Buffer, NULL); status = LspRequest( LSS, &PduDesc, &PduResponse ); if(!NT_SUCCESS(status)) { KDPrintM(DBG_OTHER_ERROR, ("Error: logicalBlockAddress = %I64x, transferBlocks = %x\n", LogicalBlockAddress, TransferBlocks)); } else if(PduResponse != LANSCSI_RESPONSE_SUCCESS) { KDPrintM(DBG_OTHER_ERROR, ("Error: logicalBlockAddress = %I64x, transferBlocks = %x PduResponse:%x\n", LogicalBlockAddress, TransferBlocks, PduResponse)); status = STATUS_REQUEST_NOT_ACCEPTED; } return status; }
NTSTATUS LsuGetIdentify( PLANSCSI_SESSION LSS, struct hd_driveid *info ){ NTSTATUS status; LANSCSI_PDUDESC PduDesc; BYTE PduResponse; status = STATUS_SUCCESS; // identify. LSS_INITIALIZE_PDUDESC(LSS, &PduDesc, IDE_COMMAND, WIN_IDENTIFY, 0, 0, 1, sizeof(struct hd_driveid), info, NULL); status = LspRequest(LSS, &PduDesc, &PduResponse); if(!NT_SUCCESS(status) || PduResponse != LANSCSI_RESPONSE_SUCCESS) { KDPrintM(DBG_OTHER_ERROR, ("Identify Failed...\n")); return status; } return status; }
NTSTATUS LsuConfigureIdeDisk( IN PLANSCSI_SESSION LSS, IN UCHAR UdmaRestrict, OUT PULONG PduFlags, OUT PBOOLEAN Dma, OUT PULONG BlockBytes ){ NTSTATUS status; struct hd_driveid info; ULONG pduFlags; BOOLEAN setDmaMode; ULONG blockBytes; LANSCSI_PDUDESC pduDesc; UCHAR pduResponse; // // Get identify // status = LsuGetIdentify(LSS, &info); if(!NT_SUCCESS(status)) { KDPrint(1, ("LsuGetIdentify(1) failed. NTSTATUS: %08lx.\n", status)); return status; } // // IO mode: DMA/PIO Mode. // KDPrintM(DBG_OTHER_INFO, ("Major 0x%x, Minor 0x%x, Capa 0x%x\n", info.major_rev_num, info.minor_rev_num, info.capability)); KDPrintM(DBG_OTHER_INFO, ("DMA 0x%x, U-DMA 0x%x\n", info.dma_mword, info.dma_ultra)); // // determine IO mode ( UltraDMA, DMA, and PIO ) according to hardware versions and disk capacity. // setDmaMode = FALSE; pduFlags = 0; blockBytes = 512; do { UCHAR DmaFeature; UCHAR DmaMode; DmaFeature = 0; DmaMode = 0; // // Ultra DMA if NDAS chip is 2.0 or higher. // /* We don't support UDMA for 2.0 rev 0 due to the bug. The bug : Written data using UDMA will be corrupted */ if ( (info.dma_ultra & 0x00ff) && ( (LANSCSIIDE_VERSION_2_0 < LSS->HWVersion) || ((LANSCSIIDE_VERSION_2_0 == LSS->HWVersion) && (0 != LSS->HWRevision)) )) { // Find Fastest Mode. if(info.dma_ultra & 0x0001) DmaMode = 0; if(info.dma_ultra & 0x0002) DmaMode = 1; if(info.dma_ultra & 0x0004) DmaMode = 2; // if Cable80, try higher Ultra Dma Mode. #ifdef __DETECT_CABLE80__ if(info.hw_config & 0x2000) { #endif if(info.dma_ultra & 0x0008) DmaMode = 3; if(info.dma_ultra & 0x0010) DmaMode = 4; if(info.dma_ultra & 0x0020) DmaMode = 5; if(info.dma_ultra & 0x0040) DmaMode = 6; if(info.dma_ultra & 0x0080) DmaMode = 7; // // If the ndas device is version 2.0 revision 100Mbps, // Restrict UDMA to mode 2. // if (LSS->HWVersion == LANSCSIIDE_VERSION_2_0 && LSS->HWRevision == LANSCSIIDE_VER20_REV_100M) { if(DmaMode > 2) DmaMode = 2; } // // Restrict UDMA mode when requested. // if(UdmaRestrict != 0xff) { if(DmaMode > UdmaRestrict) { DmaMode = UdmaRestrict; KDPrintM(DBG_LURN_INFO, ("UDMA restriction applied. UDMA=%d\n", (ULONG)DmaMode)); } } #ifdef __DETECT_CABLE80__ } #endif KDPrintM(DBG_OTHER_INFO, ("Ultra DMA %d detected.\n", (int)DmaMode)); DmaFeature = DmaMode | 0x40; // Ultra DMA mode. pduFlags |= PDUDESC_FLAG_DMA|PDUDESC_FLAG_UDMA; // Set Ultra DMA mode if needed if(!(info.dma_ultra & (0x0100 << DmaMode))) { setDmaMode = TRUE; } // // detect DMA // Lower 8 bits of dma_mword represent supported dma modes. // } else if(info.dma_mword & 0x00ff) { if(info.dma_mword & 0x0001) DmaMode = 0; if(info.dma_mword & 0x0002) DmaMode = 1; if(info.dma_mword & 0x0004) DmaMode = 2; KDPrintM(DBG_OTHER_INFO, ("DMA mode %d detected.\n", (int)DmaMode)); DmaFeature = DmaMode | 0x20; pduFlags |= PDUDESC_FLAG_DMA; // Set DMA mode if needed if(!(info.dma_mword & (0x0100 << DmaMode))) { setDmaMode = TRUE; } } // Set DMA mode if needed. if(setDmaMode) { LSS_INITIALIZE_PDUDESC(LSS, &pduDesc, IDE_COMMAND, WIN_SETFEATURES, 0, 0, 0, 0, NULL, NULL); pduDesc.Feature = SETFEATURES_XFER; pduDesc.BlockCount = DmaFeature; status = LspRequest(LSS, &pduDesc, &pduResponse); if(!NT_SUCCESS(status)) { KDPrintM(DBG_OTHER_ERROR, ("Set Feature Failed...\n")); return status; } if(pduResponse != LANSCSI_RESPONSE_SUCCESS) { KDPrintM(DBG_OTHER_ERROR, ("SETFEATURES: PduResponse=%x\n", (ULONG)pduResponse)); return STATUS_UNSUCCESSFUL; } // identify. status = LsuGetIdentify(LSS, &info); if(!NT_SUCCESS(status)) { KDPrint(1, ("LsuGetIdentify(2) failed. NTSTATUS: %08lx.\n", status)); return status; } KDPrintM(DBG_OTHER_INFO, ("After Set Feature DMA 0x%x, U-DMA 0x%x\n", info.dma_mword, info.dma_ultra)); } if(pduFlags & PDUDESC_FLAG_DMA) { break; } // // PIO. // KDPrintM(DBG_OTHER_ERROR, ("NetDisk does not support DMA mode. Turn to PIO mode.\n")); pduFlags |= PDUDESC_FLAG_PIO; } while(0); // // Bytes of sector // blockBytes = AtaGetBytesPerBlock(&info); // // LBA support // if(!(info.capability & 0x02)) { pduFlags &= ~PDUDESC_FLAG_LBA; ASSERT(FALSE); } else { pduFlags |= PDUDESC_FLAG_LBA; } // // LBA48 support // if(info.command_set_2 & 0x0400 || info.cfs_enable_2 & 0x0400) { // Support LBA48bit pduFlags |= PDUDESC_FLAG_LBA48; // // If LBA48 is on, LBA is also on. // pduFlags |= PDUDESC_FLAG_LBA; } KDPrint(1, ("LBA support: LBA %d, LBA48 %d\n", (pduFlags & PDUDESC_FLAG_LBA) != 0, (pduFlags & PDUDESC_FLAG_LBA48) != 0 )); // // Set return values // if(PduFlags) { *PduFlags = pduFlags; } if(Dma) { if(pduFlags & (PDUDESC_FLAG_DMA|PDUDESC_FLAG_UDMA)) { *Dma = TRUE; } else { *Dma = FALSE; } } if(BlockBytes) { *BlockBytes = blockBytes; } return status; }
////////////////////////////////////////////////////////////////////////// // // IDE devices // NTSTATUS LsuConfigureIdeDisk( PLANSCSI_SESSION LSS, PULONG PduFlags, PBOOLEAN Dma ){ NTSTATUS status; struct hd_driveid info; ULONG pduFlags; BOOLEAN setDmaMode; LANSCSI_PDUDESC pduDesc; UCHAR pduResponse; // // Get identify // status = LsuGetIdentify(LSS, &info); if(!NT_SUCCESS(status)) { KDPrint(1, ("LsuGetIdentify(1) failed. NTSTATUS: %08lx.\n", status)); return status; } // // IO mode: DMA/PIO Mode. // KDPrintM(DBG_OTHER_INFO, ("Major 0x%x, Minor 0x%x, Capa 0x%x\n", info.major_rev_num, info.minor_rev_num, info.capability)); KDPrintM(DBG_OTHER_INFO, ("DMA 0x%x, U-DMA 0x%x\n", info.dma_mword, info.dma_ultra)); // // determine IO mode ( UltraDMA, DMA, and PIO ) according to hardware versions and disk capacity. // setDmaMode = FALSE; pduFlags = 0; do { UCHAR DmaFeature; UCHAR DmaMode; DmaFeature = 0; DmaMode = 0; // // Ultra DMA if NDAS chip is 2.0 or higher. // Lower 8 bits of dma_ultra represent supported ultra dma modes. // if(LSS->HWVersion >= LANSCSIIDE_VERSION_2_0 && (info.dma_ultra & 0x00ff)) { // Find Fastest Mode. if(info.dma_ultra & 0x0001) DmaMode = 0; if(info.dma_ultra & 0x0002) DmaMode = 1; if(info.dma_ultra & 0x0004) DmaMode = 2; // if Cable80, try higher Ultra Dma Mode. #ifdef __DETECT_CABLE80__ if(info.hw_config & 0x2000) { #endif if(info.dma_ultra & 0x0008) DmaMode = 3; if (!(LSS->HWVersion == LANSCSIIDE_VERSION_2_0 && (LSS->HWRevision == 0))) { if(info.dma_ultra & 0x0010) DmaMode = 4; if(info.dma_ultra & 0x0020) DmaMode = 5; if(info.dma_ultra & 0x0040) DmaMode = 6; if(info.dma_ultra & 0x0080) DmaMode = 7; } #ifdef __DETECT_CABLE80__ } #endif // Limit UDMA mode 2 for 2.0G 100M test revision if (LSS->HWVersion == LANSCSIIDE_VERSION_2_0 && LSS->HWRevision == 0x01f) { if (DmaMode > 2) DmaMode = 2; } KDPrintM(DBG_OTHER_INFO, ("Ultra DMA %d detected.\n", (int)DmaMode)); DmaFeature = DmaMode | 0x40; // Ultra DMA mode. pduFlags |= PDUDESC_FLAG_DMA|PDUDESC_FLAG_UDMA; // Set Ultra DMA mode if needed if(!(info.dma_ultra & (0x0100 << DmaMode))) { setDmaMode = TRUE; } // // detect DMA // Lower 8 bits of dma_mword represent supported dma modes. // } else if(info.dma_mword & 0x00ff) { if(info.dma_mword & 0x0001) DmaMode = 0; if(info.dma_mword & 0x0002) DmaMode = 1; if(info.dma_mword & 0x0004) DmaMode = 2; KDPrintM(DBG_OTHER_INFO, ("DMA mode %d detected.\n", (int)DmaMode)); DmaFeature = DmaMode | 0x20; pduFlags |= PDUDESC_FLAG_DMA; // Set DMA mode if needed if(!(info.dma_mword & (0x0100 << DmaMode))) { setDmaMode = TRUE; } } // Set DMA mode if needed. if(setDmaMode) { LSS_INITIALIZE_PDUDESC(LSS, &pduDesc, IDE_COMMAND, WIN_SETFEATURES, 0, 0, 0, NULL); pduDesc.Feature = SETFEATURES_XFER; pduDesc.Param8[0] = DmaFeature; status = LspRequest(LSS, &pduDesc, &pduResponse); if(!NT_SUCCESS(status)) { KDPrintM(DBG_OTHER_ERROR, ("Set Feature Failed...\n")); return status; } if(pduResponse != LANSCSI_RESPONSE_SUCCESS) { KDPrintM(DBG_OTHER_ERROR, ("SETFEATURES: PduResponse=%x\n", (ULONG)pduResponse)); return STATUS_UNSUCCESSFUL; } // identify. status = LsuGetIdentify(LSS, &info); if(!NT_SUCCESS(status)) { KDPrint(1, ("LsuGetIdentify(2) failed. NTSTATUS: %08lx.\n", status)); return status; } KDPrintM(DBG_OTHER_INFO, ("After Set Feature DMA 0x%x, U-DMA 0x%x\n", info.dma_mword, info.dma_ultra)); } if(pduFlags & PDUDESC_FLAG_DMA) { break; } // // PIO. // KDPrintM(DBG_OTHER_ERROR, ("NetDisk does not support DMA mode. Turn to PIO mode.\n")); pduFlags |= PDUDESC_FLAG_PIO; } while(0); // // LBA support // if(!(info.capability & 0x02)) { pduFlags &= ~PDUDESC_FLAG_LBA; ASSERT(FALSE); } else { pduFlags |= PDUDESC_FLAG_LBA; } // // LBA48 support // if(info.command_set_2 & 0x0400 || info.cfs_enable_2 & 0x0400) { // Support LBA48bit pduFlags |= PDUDESC_FLAG_LBA48; // // If LBA48 is on, LBA is also on. // pduFlags |= PDUDESC_FLAG_LBA; } KDPrint(1, ("LBA support: LBA %d, LBA48 %d\n", (pduFlags & PDUDESC_FLAG_LBA) != 0, (pduFlags & PDUDESC_FLAG_LBA48) != 0 )); // // Set return values // if(PduFlags) { *PduFlags = pduFlags; } if(Dma) { if(pduFlags & (PDUDESC_FLAG_DMA|PDUDESC_FLAG_UDMA)) { *Dma = TRUE; } else { *Dma = FALSE; } } return status; }