📄 ramdisk.c
字号:
bsp->secsize = 512; // each sector is 512 bytes long
bsp->clustsize = 1; // one sector per cluster
bsp->numrsv = 1; // no reserved sectors besides this one
bsp->numfat = 1; // one FAT should be enough
bsp->numfiles = 128; // more than enough to prove the point!
bsp->numsectors = 0; // fill in totsectors instead
bsp->media = 0xF8; // claim we're a fixed disk
bsp->fatsectors = (WORD) ((nsec + nsec + 511) / 512);
bsp->tracksectors = (WORD) nsec; // only 1 track, so all sectors are on it
bsp->numtracks = 1; // 1 track
bsp->numhidden = 0; // no hidden sectors
bsp->totsectors = nsec; // this many sectors
bsp->drive = 0x80; // flag for a hard drive
bsp->xboot = 0x29; // flag as extended boot sector
bsp->volid = base; // use base address as volume ID
memcpy(bsp->label, "NO NAME ", 11);
memcpy(bsp->fattype, "FAT16 ", 8);
bsp->part[0].indicator = 0x80;
bsp->part[0].parttype = 4; // DOS 16-bit FAT
bsp->part[0].bias = 0;
bsp->part[0].partsize = nsec;
bsp->signature = 0xAA55; // boot sector signature
// Initialize the start of the FAT at sector 1
fat[0] = 0xFFF8; // reserved bytes
fat[1] = 0xFFFF;
} // InitRamDisk
///////////////////////////////////////////////////////////////////////////////
// AEP_UNCONFIG_DCB informs us that the physical device represented by a DCB
// is going away
#pragma VxD_PAGEABLE_CODE_SEG
USHORT OnUnconfigDcb(PAEP_dcb_unconfig aep)
{ // OnUnconfigDcb
PDCB dcb = (PDCB) aep->AEP_d_u_dcb;
ASSERT(dcb);
// We will get UNCONFIG calls for logical DCBs that are associated
// with the physical device. We need to ignore these calls! We will
// also occasionally get calls for DCBs that have nothing to do with
// us at all (?)
if (!(dcb->DCB_cmn.DCB_device_flags & DCB_DEV_PHYSICAL)
|| memcmp(dcb->DCB_vendor_id, "WALTONEY", 8) != 0)
return AEP_SUCCESS; // ignore unconfig of logical DCB
if (dcb->DCB_Port_Specific)
{ // release memory
_PageFree((PVOID) dcb->DCB_Port_Specific, 0);
dcb->DCB_Port_Specific = 0;
} // release memory
--ndevices; // this will cause to unload after next AEP_BOOT_COMPLETE
ASSERT(ndevices >= 0);
return AEP_SUCCESS;
} // OnUnconfigDcb
///////////////////////////////////////////////////////////////////////////////
// AEP_DEVICE_INQUIRY asks us whether there's a physical device at a given
// controller-relative index. In this sample, we support one device per
// controller. A real device would examine BIOS entries or use some hardware-
// oriented method to enumerate the devices
#pragma VxD_PAGEABLE_CODE_SEG
USHORT OnDeviceInquiry(PAEP_inquiry_device aep)
{ // OnDeviceInquiry
PDCB dcb = (PDCB) aep->AEP_i_d_dcb;
ASSERT(dcb);
if (dcb->DCB_unit_on_ctl > 0)
return AEP_NO_MORE_DEVICES;
memcpy(dcb->DCB_vendor_id, "WALTONEY", 8);
memcpy(dcb->DCB_product_id, "RAM Disk ", 16);
memcpy(dcb->DCB_rev_level, "0001", 4);
return AEP_SUCCESS;
} // OnDeviceInquiry
///////////////////////////////////////////////////////////////////////////////
// AEP_UNINITIALIZE means the DDB is about to be deleted, meaning
// the controller is about to be removed.
#pragma VxD_PAGEABLE_CODE_SEG
USHORT OnUninitialize(PAEP_bi_uninit aep)
{ // OnUninitialize
return AEP_SUCCESS;
} // OnUninitialize
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// I/O request processing:
#pragma VxD_LOCKED_CODE_SEG
void DoCallDown(PIOP iop);
void DoCallBack(PIOP iop);
VOID OnRequest(PIOP iop)
{ // OnRequest
#define ior iop->IOP_ior
DWORD funcode = ior.IOR_func;
PDCB dcb = (PDCB) iop->IOP_physical_dcb;
ior.IOR_status = IORS_SUCCESS; // assume it'll succeed
dcb->DCB_cmn.DCB_device_flags |= DCB_DEV_IO_ACTIVE;
switch (funcode)
{ // dispatch function processor
///////////////////////////////////////////////////////////////////////
case IOR_READ: // IOR_func == 0
{ // IOR_READ
DWORD sector = ior.IOR_start_addr[0];
PBYTE diskdata = (PBYTE) (dcb->DCB_Port_Specific + sector * dcb->DCB_actual_blk_size);
ASSERT(sector < dcb->DCB_actual_sector_cnt[0]);
ASSERT(ior.IOR_start_addr[1] == 0);
if (ior.IOR_flags & IORF_SCATTER_GATHER)
{ // have scatter/gather structures
_BlockDev_Scatter_Gather* sgd = (_BlockDev_Scatter_Gather*) ior.IOR_buffer_ptr;
PBYTE memdata;
DWORD nbytes;
while ((nbytes = sgd->BD_SG_Count))
{ // for each s/g structure
memdata = (PBYTE) sgd->BD_SG_Buffer_Ptr; // linear address!
if (!(ior.IOR_flags & IORF_CHAR_COMMAND))
nbytes *= dcb->DCB_actual_blk_size;
memcpy(memdata, diskdata, nbytes);
diskdata += nbytes;
++sgd;
} // for each s/g structure
} // have scatter/gather structures
else
{ // have simple buffer address
PBYTE memdata = (PBYTE) ior.IOR_buffer_ptr;
DWORD nbytes = ior.IOR_xfer_count;
if (!(ior.IOR_flags & IORF_CHAR_COMMAND))
nbytes *= dcb->DCB_actual_blk_size;
memcpy(memdata, diskdata, nbytes);
} // have simple buffer address
break;
} // IOR_READ
///////////////////////////////////////////////////////////////////////
case IOR_WRITE: // IOR_func == 1
{ // IOR_WRITE
DWORD sector = ior.IOR_start_addr[0];
PBYTE diskdata = (PBYTE) (dcb->DCB_Port_Specific + sector * dcb->DCB_actual_blk_size);
ASSERT(sector); // why is anyone rewriting the boot sector??
ASSERT(sector < dcb->DCB_actual_sector_cnt[0]);
ASSERT(ior.IOR_start_addr[1] == 0);
if (ior.IOR_flags & IORF_SCATTER_GATHER)
{ // have scatter/gather structures
_BlockDev_Scatter_Gather* sgd = (_BlockDev_Scatter_Gather*) ior.IOR_buffer_ptr;
PBYTE memdata;
DWORD nbytes;
while ((nbytes = sgd->BD_SG_Count))
{ // for each s/g structure
memdata = (PBYTE) sgd->BD_SG_Buffer_Ptr; // linear address!
if (!(ior.IOR_flags & IORF_CHAR_COMMAND))
nbytes *= dcb->DCB_actual_blk_size;
memcpy(diskdata, memdata, nbytes);
diskdata += nbytes;
++sgd;
} // for each s/g structure
} // have scatter/gather structures
else
{ // have simple buffer address
PBYTE memdata = (PBYTE) ior.IOR_buffer_ptr;
DWORD nbytes = ior.IOR_xfer_count;
if (!(ior.IOR_flags & IORF_CHAR_COMMAND))
nbytes *= dcb->DCB_actual_blk_size;
memcpy(diskdata, memdata, nbytes);
} // have simple buffer address
break;
} // IOR_WRITE
///////////////////////////////////////////////////////////////////////
default:
dcb->DCB_cmn.DCB_device_flags &= ~DCB_DEV_IO_ACTIVE;
DoCallDown(iop);
return;
} // dispatch function processor
dcb->DCB_cmn.DCB_device_flags &= ~DCB_DEV_IO_ACTIVE;
DoCallBack(iop); // we're done with this request
#undef ior
} // OnRequest
// DoCallDown passes a request to the next lower layer. Note that the
// documentation about how to do this is totally wrong: you don't just
// add sizeof(DCB_cd_entry) to the calldown pointer, you follow a
// linked list from one calldown entry to the next.
void __declspec(naked) DoCallDown(PIOP iop)
{ // DoCallDown
_asm
{ // call down to next layer
mov ecx, [esp+4]
mov eax, [ecx]IOP.IOP_calldown_ptr
mov eax, [eax]DCB_cd_entry.DCB_cd_next
mov [ecx]IOP.IOP_calldown_ptr, eax
jmp [eax]DCB_cd_entry.DCB_cd_io_address
} // call down to next layer
} // DoCallDown
// DoCallBack handles completion of an I/O request by calling the
// previous level's callback routine.
void __declspec(naked) DoCallBack(PIOP iop)
{ // DoCallBack
_asm
{ // call back to previous layer
mov ecx, [esp+4]
sub [ecx]IOP.IOP_callback_ptr, size IOP_callback_entry
mov eax, [ecx]IOP.IOP_callback_ptr
jmp [eax]IOP_callback_entry.IOP_CB_address
} // call back to previous layer
} // DoCallBack
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -