⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mirrordrive95_kernel.cpp

📁 DVD工具dvdsynth的源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
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 + -