📄 mirrordrive95_kernel.cpp
字号:
void __stdcall ILBInternalRequest(IOP* iop, DCB* dcb) {
__asm {
pushad
mov edi,[esp+36]
mov ebx,[esp+40]
xor edx,edx
call [ilb.ILB_internal_request]
popad
retn 8
}
}
struct IOPBlock {
UCHAR* dcb_expansion;
IOP* iop;
SGD* sgd_list;
SRB* srb;
UCHAR* srb_extension;
// SenseData* sense;
};
bool CreateIOP(DCB* dcb, IOPBlock* result) {
ISP_IOP_create i_c;
i_c.ISP_i_c_hdr.ISP_func = ISP_CREATE_IOP;
i_c.ISP_delta_to_ior = dcb->DCB_cmn.DCB_expansion_length + offset_of_ior_in_iop;
i_c.ISP_IOP_size = USHORT(
dcb->DCB_cmn.DCB_expansion_length
+ sizeof(IOP)
+ dcb->DCB_max_sg_elements*2*sizeof(SGD)
+ sizeof(SRB)
+ dcb->DCB_srb_ext_size
// + sizeof(SenseData)
);
i_c.ISP_i_c_flags = ISP_M_FL_INTERRUPT_TIME; /* ISP_M_FL_MUST_SUCCEED */
ILBServiceRtn(&i_c.ISP_i_c_hdr);
if (i_c.ISP_i_c_hdr.ISP_result != 0 || i_c.ISP_IOP_ptr == 0) {
return false;
} else {
unsigned char* p = (unsigned char*)i_c.ISP_IOP_ptr;
result->dcb_expansion = p;
p += dcb->DCB_cmn.DCB_expansion_length;
result->iop = (IOP*)p;
p += sizeof(IOP);
result->sgd_list = (SGD*)p;
p += dcb->DCB_max_sg_elements*2*sizeof(SGD);
result->srb = (SRB*)p;
p += sizeof(SRB);
result->srb_extension = p;
// p += dcb->DCB_srb_ext_size;
// result->sense = (SenseData*)p;
//#ifdef _DEBUG
ULONG phys_addr = result->iop->IOP_physical;
for (int i=0; i<i_c.ISP_IOP_size; ++i) {
((char*)i_c.ISP_IOP_ptr)[i] = char(0xEE);
}
result->iop->IOP_physical = phys_addr;
//#endif
result->iop->IOP_ior.urequestor_usage[0] = i_c.ISP_IOP_ptr; // prob. unnecessary
return true;
}
}
bool FreeIOP(IOPBlock* block) {
ISP_mem_dealloc mem_da;
mem_da.ISP_mem_da_hdr.ISP_func = ISP_DEALLOC_MEM;
mem_da.ISP_mem_ptr_da = (ULONG)block->dcb_expansion; // iop->IOP_ior.urequestor_usage[0];
ILBServiceRtn(&mem_da.ISP_mem_da_hdr);
return (mem_da.ISP_mem_da_hdr.ISP_result == 0);
}
unsigned scsi_command_semaphore;
void __cdecl CompletionHandler() {
Signal_Semaphore_No_Switch(scsi_command_semaphore);
}
unsigned Lin2Phys(unsigned lin) {
unsigned page_table_entry;
_CopyPageTable(lin >> 12, 1, &page_table_entry, 0);
return (lin & 0x00000FFF) + (page_table_entry & 0xFFFFF000);
}
unsigned SetPhysicalSGDs(void* lin_start, int len, SGD* sgds, int max_sgds) {
int num_sgds = 0;
unsigned addr = (unsigned)lin_start;
unsigned end = addr + len;
while (addr < end) {
unsigned page_end = (addr & ~4095) + 4096;
unsigned length_in_page = min(page_end, end) - addr;
unsigned phys = Lin2Phys(addr);
if (num_sgds > 0 && phys == sgds[num_sgds-1].SG_buff_ptr + sgds[num_sgds-1].SG_buff_size) {
sgds[num_sgds-1].SG_buff_size += length_in_page;
} else if (num_sgds >= max_sgds) {
// Exceeded the max. number of SGDs! What should we do?
// I don't really know, so I just return as much as I
// can...
break;
} else {
sgds[num_sgds].SG_buff_ptr = phys;
sgds[num_sgds].SG_buff_size = length_in_page;
++num_sgds;
}
addr += length_in_page;
}
return num_sgds;
}
unsigned char* LockMem(unsigned char* p, unsigned len) {
if (len==0) return 0;
unsigned first_page = unsigned(p)>>12;
unsigned last_page = (unsigned(p)+len-1)>>12;
return (unsigned char*)_LinPageLock(first_page, last_page-first_page+1, PAGEMAPGLOBAL);
}
bool UnlockMem(unsigned char* p, int len) {
if (p==0 || len==0) return true;
unsigned first_page = unsigned(p)>>12;
unsigned last_page = (unsigned(p)+len-1)>>12;
return !!_LinPageUnLock(first_page, last_page-first_page+1, PAGEMAPGLOBAL);
}
extern "C"
scsi_result_t SendScsiCommand(DCB* dcb, const unsigned char* cdb, int cdblen, unsigned char* buffer, unsigned long* pbuflen, int inout, SenseData* sense) {
if (scsi_command_semaphore == 0) {
// FIXME: never destroyed
scsi_command_semaphore = Create_Semaphore(0);
}
//g_callbacks->DebugPrintf("SendSCSICommand(%X, %X, %d, %X, %d, %d, %X)\n", dcb, cdb, cdblen, buffer, *pbuflen, inout, sense);
IOPBlock block;
if (!CreateIOP(dcb, &block))
return MAKE_SCSIRESULT(SRB_STATUS_BUSY, 0, 0, 0, 0);
//g_callbacks->DebugPrintf("SendSCSICommand: IOP = %X\n", iop);
IOP* iop = block.iop;
iop->IOP_original_dcb = dcb;
iop->IOP_srb = ULONG(block.srb);
iop->IOP_ior.IOR_func = IOR_SCSI_PASS_THROUGH;
iop->IOP_ior.IOR_status = IORS_CMD_IN_PROGRESS; // Necessary? A good idea?
// ASPI doesn't set IORF_SYNC_COMMAND or IORF_BYPASS_VOLTRK
iop->IOP_ior.IOR_flags = IORF_CHAR_COMMAND | IORF_VERSION_002 | IORF_INHIBIT_GEOM_RECOMPUTE | IORF_SRB_VALID;
iop->IOP_ior.IOR_flags |= IORF_BYPASS_VOLTRK;
iop->IOP_ior.IOR_callback = CompletionHandler;
iop->IOP_ior.IOR_xfer_count = *pbuflen;
iop->IOP_ior.IOR_buffer_ptr = buffer;
iop->IOP_ior.IOR_req_req_handle = iop;
iop->IOP_ior.IOR_req_vol_handle = 0;
iop->IOP_ior.IOR_sgd_lin_phys = ULONG(block.sgd_list);
iop->IOP_ior.IOR_num_sgds = 0; // ???
iop->IOP_ior.IOR_vol_designtr = dcb->DCB_cmn.DCB_unit_number;
/*
SGD* sgds = (SGD*)(iop->IOP_ior.IOR_sgd_lin_phys);
if (dcb->DCB_cmn.DCB_dmd_flags & DCB_dmd_phys_sgd) {
iop->IOP_ior.IOR_num_sgds = SetPhysicalSGDs(buffer, *pbuflen, sgds, dcb->DCB_max_sg_elements);
} else {
iop->IOP_ior.IOR_num_sgds = 1;
sgds[0].SG_buff_ptr = ULONG(buffer);
sgds[0].SG_buff_size = *pbuflen;
}
if (dcb->DCB_cmn.DCB_dmd_flags & DCB_dmd_phys_sgd_ptr) {
iop->IOP_ior.IOR_sgd_lin_phys = Lin2Phys(iop->IOP_ior.IOR_sgd_lin_phys);
}
*/
SRB* srb = block.srb;
srb->Length = sizeof(SRB);
srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
srb->SrbStatus = 0;
srb->ScsiStatus = 0;
srb->PathId = dcb->DCB_bus_number;
srb->TargetId = dcb->DCB_scsi_target_id;
srb->Lun = dcb->DCB_scsi_lun;
srb->CdbLength = cdblen;
srb->SenseInfoBufferLength = 14;
unsigned long buflen = *pbuflen;
srb->SrbFlags = (buflen == 0) ? 0 : ((inout & 3) << 6);
srb->DataTransferLength = buflen;
srb->TimeOutValue = 0;
srb->DataBuffer = buffer;
srb->SenseInfoBuffer = sense;
srb->NextSrb = 0;
srb->OriginalRequest = 0;
srb->SrbExtension = (char*)srb + sizeof(SRB);
for (int i=0; i<cdblen; ++i)
srb->Cdb[i] = cdb[i];
srb->SrbIopPointer = block.iop;
srb->SrbNextSrb = 0;
scsi_result_t result = MAKE_SCSIRESULT(SRB_STATUS_BUSY, 0, 0, 0, 0);
if (ILBIntIOCriteriaRtn(iop)) {
iop->IOP_ior.IOR_next = 0;
//iop->IOP_ior.IOR_flags &= ~(IORF_SYNC_COMMAND | IORF_BYPASS_VOLTRK);
g_callbacks->DebugPrintf("SendSCSICommand: entering IOS_SendCommand\n");
IOS_SendCommand(&iop->IOP_ior, &dcb->DCB_bdd);
//#ifdef IOS_SPY
// IOSHookFunc(&iop->IOP_ior, &dcb->DCB_bdd, 0);
//#endif
// ILBInternalRequest(iop, dcb);
g_callbacks->DebugPrintf("SendSCSICommand: waiting for completion\n");
Wait_Semaphore(scsi_command_semaphore, BLOCK_SVC_INTS|BLOCK_THREAD_IDLE);
g_callbacks->DebugPrintf("SendSCSICommand: completed (IOP=%X,status=%d)\n", iop, iop->IOP_ior.IOR_status);
g_callbacks->DebugPrintf("SrbStatus = %X ScsiStatus = %X sense_key = %X asc = %X ascq = %X\n", srb->SrbStatus, srb->ScsiStatus, sense->sense_key, sense->asc, sense->ascq);
*pbuflen = srb->DataTransferLength;
if (iop->IOP_ior.IOR_status == IORS_INVALID_COMMAND) {
return MAKE_SCSIRESULT_ERROR(0x52000); // INVALID COMMAND OPERATION CODE
} else if (iop->IOP_ior.IOR_status == IORS_NO_MEDIA) {
return MAKE_SCSIRESULT_ERROR(0x23A00); // MEDIUM NOT PRESENT
} else if (iop->IOP_ior.IOR_status == IORS_UNCERTAIN_MEDIA) {
return MAKE_SCSIRESULT_ERROR(0x62800); // NOT READY TO READY CHANGE
} else if (srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) {
// Assume ERROR / CHECK CONDITION in this case.
// The actual SRB status is sometimes 0x80 ==
// SRB_STATUS_PENDING | SRB_STATUS_AUTOSENSE_VALID.
// What the heck???
result = MAKE_SCSIRESULT(SRB_STATUS_ERROR, SCSISTAT_CHECK_CONDITION, sense->sense_key, sense->asc, sense->ascq);
// g_callbacks->MemCpy(sense, block.sense, srb->SenseInfoBufferLength);
} else if (srb->SrbStatus == 0) {
// probably was never changed from the value I set???
} else {
unsigned char scsierror = (srb->SrbStatus == SRB_STATUS_ERROR) ? srb->ScsiStatus : 0;
result = MAKE_SCSIRESULT(srb->SrbStatus, scsierror, 0, 0, 0);
}
}
//g_callbacks->DebugPrintf("SendSCSICommand: entering FreeIOP\n");
if (!FreeIOP(&block)) {
g_callbacks->DebugPrintf("FreeIOP failed!\n");
}
//g_callbacks->DebugPrintf("SendSCSICommand: exiting FreeIOP\n");
return result;
}
extern "C"
DCB* GetNextDCB(DCB* last_dcb) {
ISP_GET_FRST_NXT_DCB gfnd;
g_callbacks->MemSet(&gfnd, 0, sizeof(gfnd));
gfnd.ISP_gfnd_hdr.ISP_func = ISP_GET_FIRST_NEXT_DCB;
gfnd.ISP_gfnd_dcb_offset = (ULONG)last_dcb;
gfnd.ISP_gfnd_dcb_type = 0xFF;
ILBServiceRtn(&gfnd.ISP_gfnd_hdr);
DCB* rtn = (DCB*)gfnd.ISP_gfnd_found_dcb;
if (gfnd.ISP_gfnd_hdr.ISP_result != 0)
rtn = 0;
return rtn;
}
scsi_result_t __cdecl ScsiCommand(DvsDeviceKernel* self, const unsigned char* cdb, int cdblen, unsigned char* buffer, unsigned long* pbuflen, int inout, SenseData* sense) {
return SendScsiCommand(((MirrorDriveKernel*)self)->dcb, cdb, cdblen, buffer, pbuflen, inout, sense);
}
extern "C"
dvs_scsi_func* GetDispatchFunc() { return ScsiCommand; }
extern "C"
void __cdecl DvdsynthDriverInit(DvsDockingBayKernelGlobal* callbacks) {
g_callbacks = callbacks;
SPTInit();
}
extern "C"
unsigned __stdcall DLLEntry(void*, unsigned, void*) { return 1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -