Implement CDROM_ScsiPassThrough and CDROM_ScsiPassThroughDirect on NetBSD in dlls/ntdll/cdrom.c The patch for CDROM_GetIdeInterface on NetBSD should be applied first. -- Yorick Hardy --- dlls/ntdll/cdrom.c Mon May 19 20:54:02 2003 +++ dlls/ntdll/cdrom.c Mon May 19 21:03:49 2003 @@ -1359,11 +1359,15 @@ static DWORD CDROM_ScsiPassThroughDirect(int dev, PSCSI_PASS_THROUGH_DIRECT pPacket) { int ret = STATUS_NOT_SUPPORTED; + int io; #if defined(linux) && defined(CDROM_SEND_PACKET) struct linux_cdrom_generic_command cmd; struct request_sense sense; - int io; +#elif defined(__NetBSD__) + scsireq_t cmd; +#endif +#if defined(linux) && defined(CDROM_SEND_PACKET) if (pPacket->Length < sizeof(SCSI_PASS_THROUGH_DIRECT)) return STATUS_BUFFER_TOO_SMALL; @@ -1410,6 +1414,64 @@ pPacket->ScsiStatus = cmd.stat; ret = CDROM_GetStatusCode(io); + +#elif defined(__NetBSD__) + if (pPacket->Length < sizeof(SCSI_PASS_THROUGH_DIRECT)) + return STATUS_BUFFER_TOO_SMALL; + + if (pPacket->CdbLength > 12) + return STATUS_INVALID_PARAMETER; + + if (pPacket->SenseInfoLength > SENSEBUFLEN) + return STATUS_INVALID_PARAMETER; + + memset(&cmd, 0, sizeof(cmd)); + memcpy(&(cmd.cmd), &(pPacket->Cdb), pPacket->CdbLength); + + cmd.cmdlen = pPacket->CdbLength; + cmd.databuf = pPacket->DataBuffer; + cmd.datalen = pPacket->DataTransferLength; + cmd.senselen = pPacket->SenseInfoLength; + cmd.timeout = pPacket->TimeOutValue*1000; /* in milliseconds */ + + switch (pPacket->DataIn) + { + case SCSI_IOCTL_DATA_OUT: + cmd.flags |= SCCMD_WRITE; + break; + case SCSI_IOCTL_DATA_IN: + cmd.flags |= SCCMD_READ; + break; + case SCSI_IOCTL_DATA_UNSPECIFIED: + cmd.flags = 0; + break; + default: + return STATUS_INVALID_PARAMETER; + } + + io = ioctl(cdrom_cache[dev].fd, SCIOCCOMMAND, &cmd); + + switch (cmd.retsts) + { + case SCCMD_OK: break; + case SCCMD_TIMEOUT: return STATUS_TIMEOUT; + break; + case SCCMD_BUSY: return STATUS_DEVICE_BUSY; + break; + case SCCMD_SENSE: break; + case SCCMD_UNKNOWN: return STATUS_UNSUCCESSFUL; + break; + } + + if (pPacket->SenseInfoLength != 0) + { + memcpy((char*)pPacket + pPacket->SenseInfoOffset, + cmd.sense, pPacket->SenseInfoLength); + } + + pPacket->ScsiStatus = cmd.status; + + ret = CDROM_GetStatusCode(io); #endif return ret; } @@ -1422,11 +1484,15 @@ static DWORD CDROM_ScsiPassThrough(int dev, PSCSI_PASS_THROUGH pPacket) { int ret = STATUS_NOT_SUPPORTED; + int io; #if defined(linux) && defined(CDROM_SEND_PACKET) struct linux_cdrom_generic_command cmd; struct request_sense sense; - int io; +#elif defined(__NetBSD__) + scsireq_t cmd; +#endif +#if defined(linux) && defined(CDROM_SEND_PACKET) if (pPacket->Length < sizeof(SCSI_PASS_THROUGH)) return STATUS_BUFFER_TOO_SMALL; @@ -1478,6 +1544,72 @@ } pPacket->ScsiStatus = cmd.stat; + + ret = CDROM_GetStatusCode(io); + +#elif defined(__NetBSD__) + if (pPacket->Length < sizeof(SCSI_PASS_THROUGH)) + return STATUS_BUFFER_TOO_SMALL; + + if (pPacket->CdbLength > 12) + return STATUS_INVALID_PARAMETER; + + if (pPacket->SenseInfoLength > SENSEBUFLEN) + return STATUS_INVALID_PARAMETER; + + memset(&cmd, 0, sizeof(cmd)); + memcpy(&(cmd.cmd), &(pPacket->Cdb), pPacket->CdbLength); + + if ( pPacket->DataBufferOffset > 0x1000 ) + { + cmd.databuf = (void*)pPacket->DataBufferOffset; + } + else + { + cmd.databuf = (char*)pPacket + pPacket->DataBufferOffset; + } + + cmd.cmdlen = pPacket->CdbLength; + cmd.datalen = pPacket->DataTransferLength; + cmd.senselen = pPacket->SenseInfoLength; + cmd.timeout = pPacket->TimeOutValue*1000; /* in milliseconds */ + + switch (pPacket->DataIn) + { + case SCSI_IOCTL_DATA_OUT: + cmd.flags |= SCCMD_WRITE; + break; + case SCSI_IOCTL_DATA_IN: + cmd.flags |= SCCMD_READ; + break; + case SCSI_IOCTL_DATA_UNSPECIFIED: + cmd.flags = 0; + break; + default: + return STATUS_INVALID_PARAMETER; + } + + io = ioctl(cdrom_cache[dev].fd, SCIOCCOMMAND, &cmd); + + switch (cmd.retsts) + { + case SCCMD_OK: break; + case SCCMD_TIMEOUT: return STATUS_TIMEOUT; + break; + case SCCMD_BUSY: return STATUS_DEVICE_BUSY; + break; + case SCCMD_SENSE: break; + case SCCMD_UNKNOWN: return STATUS_UNSUCCESSFUL; + break; + } + + if (pPacket->SenseInfoLength != 0) + { + memcpy((char*)pPacket + pPacket->SenseInfoOffset, + cmd.sense, pPacket->SenseInfoLength); + } + + pPacket->ScsiStatus = cmd.status; ret = CDROM_GetStatusCode(io); #endif