I am trying to download microcode to an ATA hard disk using DeviceIoControl with IOCTL_ATA_PASS_THROUGH_DIRECT. When downloading microcode to ATA drive the entire microcode must be sent in one contiguous buffer which can be as large as 2MB, depending on the drive. DeviceIoControl() was returning a fail status with System Error 87 - Invalid Parameter. I set the transfer length to 0x9000 and I got a pass status. The microcode did not download but DeviceIoControl did not fail. I did an IOCTL_STORAGE_QUERY_PROPERTY and found out that the STORAGE_ADAPTER_DESRIPTOR MaximumTransferLength is set to 0x10000 (64k) and MaximumPhysicalPages is set to 0x10. I believe this is what is limiting the amount of data that I can send, but I have no idea how to change theses settings. The driver is atapi.sys and I can not find anything that points me to the location where these values can be changed. I have tried this using WinXP SP2 and W2K3 Server SP3 and get the same response. Below is my code .... BOOL StorageCommands::StorageQueryBusType(HANDLE hDevice, int * BusType, int * AdptrBus) { DWORD NumberOfBytesReturned; BOOL Status = 0; // set up Storage Property Query and Storage Adapter Descriptor Structures STORAGE_PROPERTY_QUERY StoragePropertyQuery; STORAGE_DEVICE_DESCRIPTOR StDescript = { 0 }; STORAGE_ADAPTER_DESCRIPTOR AdDescript = { 0 }; // get the Adapter bus type StoragePropertyQuery.PropertyId = StorageAdapterProperty; StoragePropertyQuery.QueryType = PropertyStandardQuery; // get Adapter Bus Status = DeviceIoControl( hDevice, IOCTL_STORAGE_QUERY_PROPERTY, &StoragePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY), &AdDescript, sizeof(STORAGE_ADAPTER_DESCRIPTOR), &NumberOfBytesReturned, NULL ); if (Status) { // set Adapter BusType *AdptrBus=AdDescript.BusType; } // set up Storage Property Query and Storage Device Descriptor Structures StoragePropertyQuery.PropertyId = StorageDeviceProperty; Status = DeviceIoControl( hDevice, IOCTL_STORAGE_QUERY_PROPERTY, &StoragePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY), &StDescript, sizeof(STORAGE_DEVICE_DESCRIPTOR), &NumberOfBytesReturned, NULL ); if (Status) { // set Device BusType *BusType=StDescript.BusType; } return (Status); } BOOL ATA_Commands::DownloadMicrocode(HANDLE hDevice, ATA_PASS_THROUGH_DIRECT *pATAData, unsigned char *buffer, DWORD datasize) { BOOL status = 0; DWORD sectors = datasize / 512; DWORD dsize = sizeof(ATA_PASS_THROUGH_DIRECT); DWORD bytescopied = 0; // clear contents of pATAData ZeroMemory(pATAData, dsize); // Fill in WRITE SECTORS query data pATAData->Length = (USHORT) dsize; pATAData->DataTransferLength = datasize; pATAData->AtaFlags = ATA_FLAGS_DATA_OUT; pATAData->TimeOutValue = 180; // Seconds pATAData->DataBuffer= (PVOID) buffer; pATAData->CurrentTaskFile[0] = 0x07; // FEATURES REG - save download code pATAData->CurrentTaskFile[1] = LOBYTE(LOWORD(sectors)); // SECTOR COUNT REG - LSB of sectors pATAData->CurrentTaskFile[2] = HIBYTE(LOWORD(sectors)); // LBA LOW REG - MSB of sectors pATAData->CurrentTaskFile[3] = 0x00; // LBA MID REG pATAData->CurrentTaskFile[4] = 0x00; // LBA HIGH REG pATAData->CurrentTaskFile[5] = 0x00; // DEVICE REG pATAData->CurrentTaskFile[6] = 0x92; // COMMAND REG status = DeviceIoControl( hDevice, IOCTL_ATA_PASS_THROUGH_DIRECT, pATAData, datasize, /* input buffer and size */ pATAData, datasize, /* output buffer and size */ &bytescopied, /* bytes copied to output buffer */ NULL); /* not overlapped */ if (status == 0) { printf("Error: %ld", GetLastError()); } return (status); } Thanks for any help in this.