Mike Chambers
Veteran Member
- Joined
- Sep 2, 2006
- Messages
- 2,621
so i'm taking over int 13h to add a virtual disk via TCP like i mentioned in another thread. a raw image that can by accessed sector-by-sector like a hard disk. fdisk can see my virtual disk a second fixed disk, but when i examine it it thinks it's only 10 MB in size. i've specified the geometry as 1024/16/63 CHS so it should be over 500 MB.
my handler checks the value of DL immediately, and if it matches 81h (or whatever drive number i'm taking control of) it continues on to my handling code, otherwise it does a _chain_intr to the original handler so that it is handled normally.
to try and see what the problem is i manually set AX to 0x1500 (get disk type function) and DX to 0x0081. here's what's returned:
AX = 0x0300 (what it should be, AH 3 returned says it's a hard disk)
CX = 0x0000
DX = 0x5104
when this function returns, CX-DX (<--should be a : but vbulletin turns it into a smiley) is actually used as a 32-bit value specifying the amount of 512 byte sectors on the disk in total. 0x00005104 = decimal 20740 times 512 = 10,618,880 bytes. about 10 MB.
if you have a look at my code (TCP stuff not added yet, i'm trying to get fdisk to see the proper size first) it is (at least to me, maybe i'm mistaken) clearly written so that CX-DX should be returning decimal 1,032,192. multiplied by 512, that's 528,482,304 bytes. 504 MB.
i can't see where the problem lies. according to the QuickC help files to properly modify the register in an interrupt handler i simply change the value of _ax, _bx, etc and any changes will returned back to the caller.
is it a problem that i'm using the small memory model or something like that? this is frustrating. oh, and i've used INTSPY to watch every int 13h call that fdisk makes, and NONE of them are a function that my code doesn't support yet, so it's not that.
EDIT: P.S. i shelled out $65 for the WATTCP programmer's reference yesterday, now i get to have all kinds of fun.
yet another edit: do you think it might be any difference to make the handler simply a void far (with no passed args) instead of void interrupt far, and then manually pop/push the values from/to the stack?
my handler checks the value of DL immediately, and if it matches 81h (or whatever drive number i'm taking control of) it continues on to my handling code, otherwise it does a _chain_intr to the original handler so that it is handled normally.
to try and see what the problem is i manually set AX to 0x1500 (get disk type function) and DX to 0x0081. here's what's returned:
AX = 0x0300 (what it should be, AH 3 returned says it's a hard disk)
CX = 0x0000
DX = 0x5104
when this function returns, CX-DX (<--should be a : but vbulletin turns it into a smiley) is actually used as a 32-bit value specifying the amount of 512 byte sectors on the disk in total. 0x00005104 = decimal 20740 times 512 = 10,618,880 bytes. about 10 MB.
if you have a look at my code (TCP stuff not added yet, i'm trying to get fdisk to see the proper size first) it is (at least to me, maybe i'm mistaken) clearly written so that CX-DX should be returning decimal 1,032,192. multiplied by 512, that's 528,482,304 bytes. 504 MB.
Code:
#include <stdio.h>
//#include <tcp.h>
#include <dos.h>
#include <stdlib.h>
//static tcp_Socket sock;
//tcp_Socket *s;
int status;
//word tickreturn;
char buffer[2049];
char outbuf[518];
char tmpsector[511];
//longword host;
int running = 0;
struct virtualDisk {
int cyls;
int heads;
int spt;
} vdisk;
int usecyl = 0;
int usehead = 0;
int usesect = 1;
int triperr = 0;
int fakedrive;
char _huge *tsrstack;
char _huge *appstack;
char _huge *tsrbottom;
unsigned tsrsize;
int tmpval;
long tmplong;
long tmplong2;
int sectorcount;
int savestate = 0;
int savecarry = 0;
unsigned char far *BIOSarea = 0x400; //offset 0x75 from this is the byte holding the HDD count from BIOS
unsigned char far *tmpfarchar;
void (_interrupt _far *oldtimer)();
void _interrupt _far newtimer();
void (_interrupt _far *old13h)();
void _interrupt _far new13h( unsigned _es, unsigned _ds, unsigned _di,
unsigned _si, unsigned _bp, unsigned _sp,
unsigned _bx, unsigned _dx, unsigned _cx,
unsigned _ax, unsigned _ip, unsigned _cs,
unsigned flags );
void _interrupt _far new13h(unsigned _es, unsigned _ds,
unsigned _di, unsigned _si,
unsigned _bp, unsigned _sp,
unsigned _bx, unsigned _dx,
unsigned _cx, unsigned _ax,
unsigned _ip, unsigned _cs,
unsigned flags)
{
if (_dx&&0xFF!=fakedrive) _chain_intr(old13h);
_asm cli //disable other interrupts while we're working
if ((flags&&1)==1) flags = flags - 1;
switch(_ax>>8) {
case 0x00: //RESET DISK DRIVE (always just return success)
_ax = 0x0000;
break;
case 0x01: //CHECK DRIVE STATUS
_ax = savestate;
if (savecarry==1) flags = flags + 1;
savecarry = 0;
_asm sti //turn interrupts back on
return;
case 0x02: //READ SECTOR(S) INTO MEMORY
_ax = _ax&&0xFF; // for now, let's just trick the caller into thinking we were successful
break;
case 0x08: //GET DISK PARAMETERS
_ax = 0x0000;
_cx = ((vdisk.cyls-1)<<6)+vdisk.spt;
_dx = ((vdisk.heads-1)<<8)+BIOSarea[0x75];
break;
case 0x15: //GET DISK TYPE
_ax = 0x0300;
tmplong = vdisk.cyls * vdisk.heads * vdisk.spt;
_dx = tmplong&&0xFFFF;
_cx = tmplong>>8;
break;
default: //IF WE DONT SUPPORT THE COMMAND THE CALLER WANTS YET
_ax = 0x0080; //WE TELL IT THERE WAS AN UNSPECIFIED ERROR
flags = flags + 1;
}
savestate = _ax;
savecarry = flags&&1;
_asm sti //turn interrupts back on
}
void _interrupt _far newtimer() {
(*oldtimer)();
if (running==0) { //we need to take care to not allow re-entry
running = 1;
// tickreturn = tcp_tick(s);
running = 0;
}
}
int main() {
printf("LAN Drive version blah blah blah (c)2010 Mike Chambers\n");
printf("WATTCP library (c)1990, 1999 Erick Engelke\n\n");
vdisk.cyls = 1024;
vdisk.heads = 16;
vdisk.spt = 63;
printf("Initializing TCP/IP core... "); // let's not worry about this for the moment
//sock_init();
//*oldtimer = _dos_getvect(0x1c);
//_dos_setvect(0x1c, newtimer); //hook the timer interrupt to keep WATTCP processing
printf("OK!\nConnecting to remote server... ");
//host = resolve("192.168.1.2"); //not worrying about this either yet
//status = tcp_open(s, 0, host, 5150, NULL);
//sock_wait_established(s, 10, NULL, NULL);
printf("OK!\nCurrent hard drive count: %u. (New count is %u.)\n", BIOSarea[0x75]++, BIOSarea[0x75]);
fakedrive = 0x80+BIOSarea[0x75]-1; //figure out the value we look for in DL when int 13h is called
printf("LAN Drive is simulating a hard disk at %xh.\n", fakedrive);
printf("Virtual disk geometry: %u cyls, %u heads, %u sectors/track.\n", vdisk.cyls, vdisk.heads, vdisk.spt);
printf("Installing TSR on interrupt 13h... ");
old13h = _dos_getvect(0x13);
_dos_setvect(0x13, new13h);
/* Initialize stack and bottom of program. */
_asm mov WORD PTR tsrstack[0], sp
_asm mov WORD PTR tsrstack[2], ss
FP_SEG( tsrbottom ) = _psp;
FP_OFF( tsrbottom ) = 0;
tsrsize = ((tsrstack - tsrbottom) >> 4) + 64;
_dos_freemem(_psp);
printf("OK!\n\nLAN Drive is now memory-resident. Returning to DOS...\n");
_dos_keep(0, tsrsize);
//sock_shutdown();
return 0;
sock_err:
{ } //i'll put stuff in here later to deal with socket errors. for now, this wont even be called.
}
i can't see where the problem lies. according to the QuickC help files to properly modify the register in an interrupt handler i simply change the value of _ax, _bx, etc and any changes will returned back to the caller.
is it a problem that i'm using the small memory model or something like that? this is frustrating. oh, and i've used INTSPY to watch every int 13h call that fdisk makes, and NONE of them are a function that my code doesn't support yet, so it's not that.
EDIT: P.S. i shelled out $65 for the WATTCP programmer's reference yesterday, now i get to have all kinds of fun.
yet another edit: do you think it might be any difference to make the handler simply a void far (with no passed args) instead of void interrupt far, and then manually pop/push the values from/to the stack?
Last edited: