Slightly better REQUEST SENSE dumping, fixed GET_DEV_TYPE returns, work around EXEC SCSI commands which do not set the host<->target data flags, ignore errors on DVD REPORT KEY/DVD SEND KEY.
diff --git a/dlls/winaspi/winaspi32.c b/dlls/winaspi/winaspi32.c index 9a02fd3..b465f36 100644 --- a/dlls/winaspi/winaspi32.c +++ b/dlls/winaspi/winaspi32.c
@@ -1,5 +1,6 @@ #include "config.h" +#include <assert.h> #include <stdlib.h> #include <stdio.h> #include <sys/types.h> @@ -71,6 +72,7 @@ #endif /* defined(linux) */ } + #ifdef linux static int @@ -131,7 +133,7 @@ switch (prb->CDBByte[0]) { case CMD_INQUIRY: - TRACE("{\n"); + TRACE("INQUIRY {\n"); TRACE("\tEVPD: %d\n", prb->CDBByte[1] & 1); TRACE("\tLUN: %d\n", (prb->CDBByte[1] & 0xc) >> 1); TRACE("\tPAGE CODE: %d\n", prb->CDBByte[2]); @@ -171,8 +173,7 @@ TRACE("POST Proc: %lx\n", (DWORD) prb->SRB_PostProc); cdb = &prb->CDBByte[0]; cmd = prb->CDBByte[0]; - if (TRACE_ON(aspi)) - { + if (TRACE_ON(aspi)) { DPRINTF("CDB buffer["); for (i = 0; i < prb->SRB_CDBLen; i++) { if (i != 0) DPRINTF(","); @@ -186,15 +187,34 @@ ASPI_PrintSenseArea(SRB_ExecSCSICmd *prb) { int i; - BYTE *cdb; + BYTE *rqbuf = &prb->CDBByte[16]; if (TRACE_ON(aspi)) { - cdb = &prb->CDBByte[16]; + DPRINTF("Request Sense reports:\n"); + if ((rqbuf[0]&0x7f)!=0x70) { + DPRINTF("\tInvalid sense header.\n"); + return; + } + DPRINTF("\tCurrent command read filemark: %s\n",(rqbuf[2]&0x80)?"yes":"no"); + DPRINTF("\tEarly warning passed: %s\n",(rqbuf[2]&0x40)?"yes":"no"); + DPRINTF("\tIncorrect blocklengt: %s\n",(rqbuf[2]&0x20)?"yes":"no"); + DPRINTF("\tSense Key: %d\n",rqbuf[2]&0xf); + if (rqbuf[0]&0x80) + DPRINTF("\tResidual Length: %d\n",rqbuf[3]*0x1000000+rqbuf[4]*0x10000+rqbuf[5]*0x100+rqbuf[6]); + DPRINTF("\tAdditional Sense Length: %d\n",rqbuf[7]); + DPRINTF("\tAdditional Sense Code: %d\n",rqbuf[12]); + DPRINTF("\tAdditional Sense Code Qualifier: %d\n",rqbuf[13]); + if (rqbuf[15]&0x80) { + DPRINTF("\tIllegal Param is in %s\n",(rqbuf[15]&0x40)?"the CDB":"the Data Out Phase"); + if (rqbuf[15]&0x8) { + DPRINTF("Pointer at %d, bit %d\n",rqbuf[16]*256+rqbuf[17],rqbuf[15]&0x7); + } + } DPRINTF("SenseArea["); for (i = 0; i < prb->SRB_SenseLen; i++) { - if (i) DPRINTF(","); - DPRINTF("%02x", *cdb++); + if (i) DPRINTF(","); + DPRINTF("%02x", *rqbuf++); } DPRINTF("]\n"); } @@ -263,11 +283,40 @@ int fd; DWORD SRB_Status; + /* FIXME: hackmode */ +#define MAKE_TARGET_TO_HOST(lpPRB) \ + if (!TARGET_TO_HOST(lpPRB)) { \ + WARN("program was not sending target_to_host for cmd %x (flags=%x),correcting.\n",lpPRB->CDBByte[0],lpPRB->SRB_Flags); \ + lpPRB->SRB_Flags |= 8; \ + } +#define MAKE_HOST_TO_TARGET(lpPRB) \ + if (!HOST_TO_TARGET(lpPRB)) { \ + WARN("program was not sending host_to_target for cmd %x (flags=%x),correcting.\n",lpPRB->CDBByte[0],lpPRB->SRB_Flags); \ + lpPRB->SRB_Flags |= 0x10; \ + } + switch (lpPRB->CDBByte[0]) { + case 0x12: /* INQUIRY */ + case 0x5a: /* MODE_SENSE_10 */ + case 0xa4: /* REPORT_KEY (DVD) MMC-2 */ + case 0xad: /* READ DVD STRUCTURE MMC-2 */ + MAKE_TARGET_TO_HOST(lpPRB) + break; + case 0xa3: /* SEND KEY (DVD) MMC-2 */ + MAKE_HOST_TO_TARGET(lpPRB) + break; + default: + if ((((lpPRB->SRB_Flags & 0x18) == 0x00) || + ((lpPRB->SRB_Flags & 0x18) == 0x18) + ) && lpPRB->SRB_BufLen + ) { + FIXME("command 0x%02x, no data transfer specified, but buflen is %ld!!!\n",lpPRB->CDBByte[0],lpPRB->SRB_BufLen); + } + break; + } ASPI_DebugPrintCmd(lpPRB); - fd = ASPI_OpenDevice(lpPRB); if (fd == -1) { - ERR("Failed: could not open device c%01dt%01dd%01d. Device permissions !?\n", + TRACE("Failed: could not open device c%01dt%01dd%01d. Device permissions !?\n", lpPRB->SRB_HaId,lpPRB->SRB_Target,lpPRB->SRB_Lun); return WNASPI32_DoPosting( lpPRB, SS_NO_DEVICE ); } @@ -278,7 +327,7 @@ lpPRB->SRB_Status = SS_PENDING; if (!lpPRB->SRB_CDBLen) { - WARN("Failed: lpPRB->SRB_CDBLen = 0.\n"); + ERR("Failed: lpPRB->SRB_CDBLen = 0.\n"); return WNASPI32_DoPosting( lpPRB, SS_INVALID_SRB ); } @@ -353,8 +402,17 @@ HeapFree(GetProcessHeap(), 0, sg_hd); /* FIXME: Should this be != 0 maybe? */ - if( lpPRB->SRB_TargStat == 2 ) + if( lpPRB->SRB_TargStat == 2 ) { SRB_Status = SS_ERR; + switch (lpPRB->CDBByte[0]) { + case 0xa4: /* REPORT_KEY (DVD) MMC-2 */ + case 0xa3: /* SEND KEY (DVD) MMC-2 */ + SRB_Status = SS_COMP; + lpPRB->SRB_TargStat = 0; + FIXME("Program wants to do DVD Region switching, but fails (non compliant DVD drive). Ignoring....\n"); + break; + } + } ASPI_DebugPrintResult(lpPRB); /* now do posting */ @@ -367,10 +425,8 @@ if (error_code == EBUSY) { WNASPI32_DoPosting( lpPRB, SS_ASPI_IS_BUSY ); TRACE("Device busy\n"); - } - else { - WARN("Failed\n"); - } + } else + FIXME("Failed\n"); /* I'm not sure exactly error codes work here * We probably should set lpPRB->SRB_TargStat, SRB_HaStat ? @@ -423,30 +479,33 @@ /* FIXME: We should return SS_INVALID_HA if HostAdapter!=0 */ SRB tmpsrb; char inqbuf[200]; + DWORD ret; memset(&tmpsrb,0,sizeof(tmpsrb)); - tmpsrb.cmd.SRB_Cmd = SC_EXEC_SCSI_CMD; -#define X(x) tmpsrb.cmd.SRB_##x = lpSRB->devtype.SRB_##x - X(Status);X(HaId);X(Flags);X(Target);X(Lun); -#undef X + /* Copy header */ + memcpy(&tmpsrb.common,&(lpSRB->common),sizeof(tmpsrb.common)); + + tmpsrb.cmd.SRB_Flags |= 8; /* target to host */ + tmpsrb.cmd.SRB_Cmd = SC_EXEC_SCSI_CMD; + tmpsrb.cmd.SRB_Target = lpSRB->devtype.SRB_Target; + tmpsrb.cmd.SRB_Lun = lpSRB->devtype.SRB_Lun; tmpsrb.cmd.SRB_BufLen = sizeof(inqbuf); - tmpsrb.cmd.SRB_Flags = 8;/*target->host data. FIXME: anything more?*/ tmpsrb.cmd.SRB_BufPointer = inqbuf; tmpsrb.cmd.CDBByte[0] = 0x12; /* INQUIRY */ + /* FIXME: handle lun */ tmpsrb.cmd.CDBByte[4] = sizeof(inqbuf); tmpsrb.cmd.SRB_CDBLen = 6; - ASPI_ExecScsiCmd(&tmpsrb.cmd); + ret = ASPI_ExecScsiCmd(&tmpsrb.cmd); #define X(x) lpSRB->devtype.SRB_##x = tmpsrb.cmd.SRB_##x X(Status); #undef X lpSRB->devtype.SRB_DeviceType = inqbuf[0]&0x1f; TRACE("returning devicetype %d for target %d\n",inqbuf[0]&0x1f,tmpsrb.cmd.SRB_Target); - break; + return ret; } case SC_EXEC_SCSI_CMD: return ASPI_ExecScsiCmd(&lpSRB->cmd); - break; case SC_ABORT_SRB: FIXME("Not implemented SC_ABORT_SRB\n"); break; @@ -456,11 +515,11 @@ #ifdef SC_GET_DISK_INFO case SC_GET_DISK_INFO: /* NT Doesn't implement this either.. so don't feel bad */ - WARN("Not implemented SC_GET_DISK_INFO\n"); + FIXME("Not implemented SC_GET_DISK_INFO\n"); break; #endif default: - WARN("Unknown command %d\n", lpSRB->common.SRB_Cmd); + FIXME("Unknown command %d\n", lpSRB->common.SRB_Cmd); } return SS_INVALID_SRB; #else