/*++ Copyright (c) 1994 Microsoft Corporation Module Name: Dacioctl.c Abstract: This module provides support for DAC960 configuration IOCTls. Author: Mouli (mouli@mylex.com) Environment: kernel mode only Revision History: --*/ #include "miniport.h" #include "Dmc960Nt.h" #include "Dac960Nt.h" #include "d960api.h" BOOLEAN SubmitRequest( IN PDEVICE_EXTENSION DeviceExtension, IN PSCSI_REQUEST_BLOCK Srb ); BOOLEAN SubmitCdbDirect( IN PDEVICE_EXTENSION DeviceExtension, IN PSCSI_REQUEST_BLOCK Srb ); BOOLEAN IsAdapterReady( IN PDEVICE_EXTENSION DeviceExtension ); VOID SendRequest( IN PDEVICE_EXTENSION DeviceExtension ); VOID SendCdbDirect( IN PDEVICE_EXTENSION DeviceExtension ); BOOLEAN SendIoctlDcmdRequest( IN PDEVICE_EXTENSION DeviceExtension, IN PSCSI_REQUEST_BLOCK Srb ) /*++ Routine Description: Build and submit IOCTL Request-DAC960(Non-DCDB) command to DAC960. Arguments: DeviceExtension - Adapter state. SRB - System request. Return Value: TRUE if command was started FALSE if host adapter is busy --*/ { ULONG physicalAddress; PIOCTL_REQ_HEADER IoctlReqHeader; ULONG i; UCHAR busyCurrentIndex; // // Determine if adapter can accept new request. // if(!IsAdapterReady(DeviceExtension)) { return FALSE; } // // Check that next slot is vacant. // if (DeviceExtension->ActiveRequests[DeviceExtension->CurrentIndex]) { // // Collision occurred. // busyCurrentIndex = DeviceExtension->CurrentIndex++; do { if (! DeviceExtension->ActiveRequests[DeviceExtension->CurrentIndex]) { break; } } while (++DeviceExtension->CurrentIndex != busyCurrentIndex) ; if (DeviceExtension->CurrentIndex == busyCurrentIndex) { // // We should never encounter this condition. // DebugPrint((0, "DAC960: SendIoctlDcmdRequest-Collision in active request array\n")); return FALSE; } } IoctlReqHeader = (PIOCTL_REQ_HEADER) Srb->DataBuffer; physicalAddress = ScsiPortConvertPhysicalAddressToUlong( ScsiPortGetPhysicalAddress(DeviceExtension, Srb, ((PUCHAR)Srb->DataBuffer + sizeof(IOCTL_REQ_HEADER)), &i)); // // The buffer passed in may not be physically contiguous. // if (i < Srb->DataTransferLength - sizeof(IOCTL_REQ_HEADER)) { DebugPrint((1, "Dac960: DCMD IOCTL buffer is not contiguous\n")); return FALSE; } // // Write physical address in mailbox. // DeviceExtension->MailBox.PhysicalAddress = physicalAddress; // // Write command in mailbox. // DeviceExtension->MailBox.OperationCode = IoctlReqHeader->GenMailBox.Reg0; // // Write request in mailbox. // DeviceExtension->MailBox.CommandIdSubmit = DeviceExtension->CurrentIndex; // // Write Mail Box Registers 2 and 3. // DeviceExtension->MailBox.BlockCount = (USHORT) (IoctlReqHeader->GenMailBox.Reg2 | (IoctlReqHeader->GenMailBox.Reg3 << 8)); // // Write Mail Box Registers 4, 5 and 6. // DeviceExtension->MailBox.BlockNumber[0] = IoctlReqHeader->GenMailBox.Reg4; DeviceExtension->MailBox.BlockNumber[1] = IoctlReqHeader->GenMailBox.Reg5; DeviceExtension->MailBox.BlockNumber[2] = IoctlReqHeader->GenMailBox.Reg6; // // Write Mail Box Register 7. // DeviceExtension->MailBox.DriveNumber = IoctlReqHeader->GenMailBox.Reg7; // // Write Mail Box Register C. // DeviceExtension->MailBox.ScatterGatherCount = IoctlReqHeader->GenMailBox.RegC; // // Start writing mailbox to controller. // SendRequest(DeviceExtension); return(TRUE); } // SendIoctlDcmdRequest() BOOLEAN SendIoctlCdbDirect( IN PDEVICE_EXTENSION DeviceExtension, IN PSCSI_REQUEST_BLOCK Srb ) /*++ Routine Description: Send IOCTL Request-CDB directly to device. Arguments: DeviceExtension - Adapter state. SRB - System request. Return Value: TRUE if command was started FALSE if host adapter is busy --*/ { ULONG physicalAddress; PDIRECT_CDB directCdb; PIOCTL_REQ_HEADER IoctlReqHeader; ULONG i; UCHAR busyCurrentIndex; // // Determine if adapter can accept new request. // if(!IsAdapterReady(DeviceExtension)) { return FALSE; } // // Check that next slot is vacant. // if (DeviceExtension->ActiveRequests[DeviceExtension->CurrentIndex]) { // // Collision occurred. // busyCurrentIndex = DeviceExtension->CurrentIndex++; do { if (! DeviceExtension->ActiveRequests[DeviceExtension->CurrentIndex]) { break; } } while (++DeviceExtension->CurrentIndex != busyCurrentIndex) ; if (DeviceExtension->CurrentIndex == busyCurrentIndex) { // // We should never encounter this condition. // DebugPrint((0, "DAC960: SendIoctlCdbDirect-Collision in active request array\n")); return FALSE; } } IoctlReqHeader = (PIOCTL_REQ_HEADER) Srb->DataBuffer; directCdb = (PDIRECT_CDB)((PUCHAR)Srb->DataBuffer + sizeof(IOCTL_REQ_HEADER)); // // Get address of data buffer offset. // physicalAddress = ScsiPortConvertPhysicalAddressToUlong( ScsiPortGetPhysicalAddress(DeviceExtension, Srb, ((PUCHAR)Srb->DataBuffer + sizeof(IOCTL_REQ_HEADER) + sizeof(DIRECT_CDB)), &i)); // // The buffer passed in may not be physically contiguous. // if (i < Srb->DataTransferLength - (sizeof(IOCTL_REQ_HEADER) + sizeof(DIRECT_CDB))) { DebugPrint((1, "Dac960: DCDB IOCTL buffer is not contiguous\n")); return FALSE; } directCdb->DataBufferAddress = physicalAddress; if (directCdb->DataTransferLength == 0) { // // mask off data xfer in/out bits // directCdb->CommandControl &= ~(DAC960_CONTROL_DATA_IN | DAC960_CONTROL_DATA_OUT); } // // Disable Early-status on command bit // directCdb->CommandControl &= 0xfb; // // Get physical address of direct CDB packet. // physicalAddress = ScsiPortConvertPhysicalAddressToUlong( ScsiPortGetPhysicalAddress(DeviceExtension, Srb, directCdb, &i)); // // Write physical address in mailbox. // DeviceExtension->MailBox.PhysicalAddress = physicalAddress; // // Write command in mailbox. // DeviceExtension->MailBox.OperationCode = IoctlReqHeader->GenMailBox.Reg0; // // Write request id in mailbox. // DeviceExtension->MailBox.CommandIdSubmit = DeviceExtension->CurrentIndex; // // Start writing mailbox to controller. // SendCdbDirect(DeviceExtension); return(TRUE); } // SendIoctlCdbDirect() VOID SetupAdapterInfo( IN PDEVICE_EXTENSION DeviceExtension, IN PSCSI_REQUEST_BLOCK Srb ) /*++ Routine Description: Copy Adapter Information to Application Buffer. Arguments: DeviceExtension - Adapter state. SRB - System request. Return Value: None. --*/ { PADAPTER_INFO AdpInfo; AdpInfo = (PADAPTER_INFO)((PUCHAR) Srb->DataBuffer + sizeof(IOCTL_REQ_HEADER)); // // Fill in Adapter Features Information. // if (DeviceExtension->AdapterInterfaceType == MicroChannel) { AdpInfo->AdpFeatures.Model = (UCHAR) DeviceExtension->PosData.AdapterId; AdpInfo->AdpFeatures.SubModel = DeviceExtension->PosData.OptionData3; } else { AdpInfo->AdpFeatures.Model = 0; AdpInfo->AdpFeatures.SubModel = 0; } if (DeviceExtension->AdapterType == DAC960_NEW_ADAPTER) { AdpInfo->AdpFeatures.MaxSysDrv = 32; AdpInfo->AdpFeatures.MaxTgt = 16; } else { AdpInfo->AdpFeatures.MaxSysDrv = 8; if (AdpInfo->AdpFeatures.MaxChn == 5) { AdpInfo->AdpFeatures.MaxTgt = 4; } else { AdpInfo->AdpFeatures.MaxTgt = 7; } } AdpInfo->AdpFeatures.MaxChn = (UCHAR) DeviceExtension->NumberOfChannels; AdpInfo->AdpFeatures.AdapterType = (UCHAR) DeviceExtension->AdapterType; AdpInfo->AdpFeatures.PktFormat = 0; AdpInfo->AdpFeatures.Reserved1 = 0; AdpInfo->AdpFeatures.Reserved2 = 0; AdpInfo->AdpFeatures.CacheSize = 0; AdpInfo->AdpFeatures.OemCode = 0; AdpInfo->AdpFeatures.Reserved3 = 0; // // Fill in the System Resources information. // AdpInfo->SysResources.BusInterface = (UCHAR) DeviceExtension->AdapterInterfaceType; AdpInfo->SysResources.BusNumber = (UCHAR) DeviceExtension->SystemIoBusNumber; AdpInfo->SysResources.IrqVector = (UCHAR) DeviceExtension->BusInterruptLevel; AdpInfo->SysResources.IrqType = (UCHAR) DeviceExtension->InterruptMode; AdpInfo->SysResources.Slot = DeviceExtension->Slot; AdpInfo->SysResources.Reserved2 = 0; AdpInfo->SysResources.IoAddress = (ULONG) DeviceExtension->BaseIoAddress; AdpInfo->SysResources.MemAddress = 0; AdpInfo->SysResources.BiosAddress = (ULONG) DeviceExtension->BaseBiosAddress; AdpInfo->SysResources.Reserved3 = 0; // // Fill in the Firmware & BIOS version information. // if (DeviceExtension->AdapterType == DAC960_NEW_ADAPTER) { AdpInfo->VerControl.MinorFirmwareRevision = ((PDAC960_ENQUIRY_3X)DeviceExtension->NoncachedExtension)->MinorFirmwareRevision; } else { AdpInfo->VerControl.MajorFirmwareRevision = ((PDAC960_ENQUIRY)DeviceExtension->NoncachedExtension)->MajorFirmwareRevision; } AdpInfo->VerControl.MinorBIOSRevision = 0; AdpInfo->VerControl.MajorBIOSRevision = 0; AdpInfo->VerControl.Reserved = 0; } VOID SetupDriverVersionInfo( IN PDEVICE_EXTENSION DeviceExtension, IN PSCSI_REQUEST_BLOCK Srb ) /*++ Routine Description: Copy Driver Version Information to Application Buffer. Arguments: DeviceExtension - Adapter state. SRB - System request. Return Value: None. --*/ { PDRIVER_VERSION driverVersion; driverVersion = (PDRIVER_VERSION)((PUCHAR) Srb->DataBuffer + sizeof(IOCTL_REQ_HEADER)); driverVersion->DriverMajorVersion = (UCHAR) (DRIVER_REVISION >> 8); driverVersion->DriverMinorVersion = (UCHAR) DRIVER_REVISION; driverVersion->Month = (UCHAR) (DRIVER_BUILD_DATE >> 16); driverVersion->Date = (UCHAR) (DRIVER_BUILD_DATE >> 8); driverVersion->Year = (UCHAR) DRIVER_BUILD_DATE; }