/* * Parts of http://www.diskwarez.com/disklib.htm combined: * dos\gcc\ dosmem.h dosmem.c read.c write.c - just the parts * that we need for DPMI raw DOS disk access. Cut and paste by * Eric Auer 2002 ... Imre Leber mails: * * Notice that i we have special written confirmation from Gregg * Jennings that anybody in the FreeDOS project is allowed to use * the disklib for anything. * * This file was part of the BETA version of DISKLIB * Copyright (C) 1998, Gregg Jennings * * See README.TXT for information about re-distribution. * See DISKLIB.TXT for information about usage. * */ #include #include #include #include #include "types.h" /* __{u,s}{8,16,32,64} */ #include #include #pragma pack(1) /* needed for the following struct */ struct DCB { __u32 sector; __u16 number; void *buffer; }; /* control block for the > 32 MB disk access with "int" 25/26h */ #pragma pack() #define DISK_OK 0 #define DOS_ERR (-1) #define MEM_ERR (-3) #define secsize 512 /* ************************************************************** */ #define dosmalloc(siz,sel) __dpmi_allocate_dos_memory((siz+15)>>4,sel) /* dosmalloc returns a seg, -1 if memory exhausted */ #define setdosmem(b,siz,sel) _movedatab(_my_ds(),(unsigned int)b,sel,0,siz) #define getdosmem(b,siz,sel) _movedatab(sel,0,_my_ds(),(unsigned int)b,siz) #define dosfree(sel) __dpmi_free_dos_memory(sel) #define _MK_FP(seg) (void *)(seg << 16) /* ************************************************************** */ /* * from: dos\gcc\read.c absolute disk read */ /* * disk_read absolute disk read (INT 25h) */ extern int disk_read(int disk, long sector, void *buffer, int nsecs) { __dpmi_regs regs; int seg,sel; if ((seg = dosmalloc(secsize*nsecs,&sel)) == -1) return MEM_ERR; regs.x.ax = disk; regs.x.dx = sector; regs.x.cx = nsecs; regs.x.ds = seg; regs.x.bx = 0; __dpmi_int(0x25,®s); /* READ */ /* This is read specific: */ getdosmem(buffer,secsize*nsecs,sel); dosfree(sel); if (regs.x.flags & 1) { return regs.h.al; } return DISK_OK; } /* * disk_read_ext absolute disk read (INT 25h), > 32MB */ extern int disk_read_ext(int disk, long sector, void *buffer, int nsecs) { __dpmi_regs regs; struct DCB dcb; int seg,sel; int bseg,bsel; if ((seg = dosmalloc(sizeof(struct DCB),&sel)) == -1) return MEM_ERR; if ((bseg = dosmalloc(secsize*nsecs,&bsel)) == -1) { dosfree(sel); return MEM_ERR; } regs.x.ax = disk; regs.x.cx = 0xffff; dcb.sector = sector; dcb.number = nsecs; dcb.buffer = _MK_FP(bseg); setdosmem((void *)&dcb,sizeof(struct DCB),sel); regs.x.ds = seg; regs.x.bx = 0; __dpmi_int(0x25,®s); /* READ */ /* This is read specific: */ getdosmem(buffer,secsize*nsecs,bsel); dosfree(sel); dosfree(bsel); if (regs.x.flags & 1) { return regs.h.al; } return DISK_OK; } /* * disk_read32 absolute disk read FAT12/16/32 * * Note: This function will fail without setting the carry flag * under MS-DOS and Windows NT 4.0 !?!? * This function fails under Windows 95. * This function reads all drives under Windows 98. */ extern int disk_read32(int disk, long sec, void *buf, int nsecs) { __dpmi_regs regs; int seg,sel; struct DCB Dcb; struct DCB *dcb = &Dcb; if ((seg = dosmalloc(secsize*nsecs,&sel)) == -1) return MEM_ERR; /* could zero buffer here: buf, nsecs*secsize */ dcb->sector = sec; dcb->number = (unsigned short)nsecs; dcb->buffer = buf; regs.x.ax = 0x7305; /* DOS_EXT_ABS_READ_WRITE */ regs.x.dx = disk+1; regs.x.cx = (unsigned short)-1; regs.x.bx = 0; regs.x.ds = (int)dcb; /* dangerous function! SI:0 MUST BE 0 for READ, 1 for WRITE */ regs.x.si = 0; __dpmi_int(0x21,®s); /* FAT32 */ if (regs.x.ax == 0x7300) { /* fail indication DOS/NT */ regs.x.flags = 1; setdoserror(1); } /* This is read specific: */ getdosmem(buf,secsize*nsecs,sel); dosfree(sel); if (regs.x.flags & 1) { return DOS_ERR; } return DISK_OK; } /* ************************************************************** */ /* * from: dos\gcc\write.c absolute disk write */ /* * disk_write absolute disk write (INT 26h) */ extern int disk_write(int disk, long sector, void *buffer, int nsecs) { int seg,sel; __dpmi_regs regs; if ((seg = dosmalloc(secsize*nsecs,&sel)) == -1) return MEM_ERR; /* This is write specific: */ setdosmem(buffer,secsize*nsecs,sel); regs.x.ax = disk; regs.x.dx = sector; regs.x.cx = nsecs; regs.x.ds = seg; regs.x.bx = 0; __dpmi_int(0x26,®s); /* WRITE */ dosfree(sel); if (regs.x.flags & 1) { return regs.h.al; } return DISK_OK; } /* * disk_write_ext absolute disk write (INT 26h), > 32MB */ extern int disk_write_ext(int disk, long sector, void *buffer, int nsecs) { int seg,sel; int bseg,bsel; struct DCB dcb; __dpmi_regs regs; if ((seg = dosmalloc(sizeof(struct DCB),&sel)) == -1) return MEM_ERR; if ((bseg = dosmalloc(secsize*nsecs,&bsel)) == -1) { dosfree(sel); return MEM_ERR; } /* This is write specific: */ setdosmem((void *)buffer,secsize*nsecs,bsel); regs.x.ax = disk; regs.x.cx = 0xffff; dcb.sector = sector; dcb.number = nsecs; dcb.buffer = _MK_FP(bseg); setdosmem((void *)&dcb,sizeof(struct DCB),sel); regs.x.ds = seg; regs.x.bx = 0; __dpmi_int(0x26,®s); /* WRITE */ dosfree(sel); dosfree(bsel); if (regs.x.flags & 1) { return regs.h.al; } return DISK_OK; } /* * disk_write32 absolute disk write FAT12/16/32 * * Note: This function will fail without setting the carry flag * under MS-DOS and Windows NT 4.0 !?!? * This function fails under Windows 95. * This function writes all drives under Windows 98. ??? */ extern int disk_write32(int disk, long sec, void *buf, int nsecs) { int seg,sel; __dpmi_regs regs; struct DCB dcb; if ((seg = dosmalloc(secsize*nsecs,&sel)) == -1) return MEM_ERR; /* This is write specific: */ /* seems to have been wrong in disklib! */ setdosmem((void *)buf,secsize*nsecs,sel); dcb.sector = sec; dcb.number = (unsigned short)nsecs; dcb.buffer = buf; regs.x.ax = 0x7305; /* DOS_EXT_ABS_READ_WRITE */ regs.x.dx = disk+1; regs.x.cx = (unsigned short)-1; regs.x.bx = 0; regs.x.ds = (int)&dcb; /* dangerous function! SI:0 MUST BE 0 for READ, 1 for WRITE */ regs.x.si = 1; __dpmi_int(0x21,®s); /* FAT32 */ if (regs.x.ax == 0x7300) { /* fail indication DOS/NT */ regs.x.flags = 1; setdoserror(1); } dosfree(sel); if (regs.x.flags & 1) { return DOS_ERR; } return DISK_OK; }