00001
00010
#include <dpmi.h>
00011
#include <sys/farptr.h>
00012
#include <sys/movedata.h>
00013
00014
#include "int13ext.h"
00015
00016
00017
00018
00019
00020 int int13ext_check()
00021 {
00022 __dpmi_regs r;
00023 r.x.ax = 0x4100;
00024 r.x.bx = 0x55AA;
00025 r.h.dl = 0x80;
00026 __dpmi_int (0x13, &r);
00027
00028
if (r.x.flags & 1)
return 0;
00029
if (r.x.bx != 0xAA55)
return 0;
00030
return -1;
00031 }
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 int int13ext_getdrvparams(
int drv,
struct driveparams* DParam)
00044 {
00045
const int DP_size =
sizeof(
struct driveparams);
00046 DParam->
crsize = DP_size;
00047
int selector, segress;
00048 __dpmi_regs r;
00049
00050 segress = __dpmi_allocate_dos_memory((DP_size + 15) >> 4, &selector);
00051
if (segress == -1)
return NO_CTLDOS_MEMORY;
00052 r.x.ax = 0x4800;
00053 r.h.dl = (
unsigned short int) drv;
00054 r.x.ds = segress;
00055 r.x.si = 0;
00056 _farpokew(selector, 0, 0x1A);
00057 __dpmi_int (0x13, &r);
00058
00059 dosmemget(segress << 4, DP_size, DParam);
00060 __dpmi_free_dos_memory(selector);
00061
00062
if (r.x.flags & 1)
return r.h.ah;
00063
00064
return 0;
00065 }
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 int int13ext_read(
int drv,
struct driveparams *DParam,
U64B block, U64B nblocks,
void *buffer)
00076 {
00077
struct diskaddrpacket DAP = {
sizeof(
struct diskaddrpacket), 0};
00078
int selDAP, segDAP, selBuff, segBuff, segBound;
00079
U64B transfd;
00080
U32B rdbuffsize =
00081 (nblocks * DParam->
bytes_per_sect < 0x8000)? nblocks*DParam->
bytes_per_sect :0x8000;
00082
U32B blocks_per_buff = rdbuffsize/DParam->
bytes_per_sect;
00083
00084 segDAP = __dpmi_allocate_dos_memory((DAP.
packetsize + 15) >> 4, &selDAP);
00085
if (segDAP == -1)
return NO_CTLDOS_MEMORY;
00086
00087
00088
00089
00090 segBuff = __dpmi_allocate_dos_memory(((rdbuffsize + 15) >> 4) + 0x800, &selBuff);
00091
if (segBuff == -1) {
00092 __dpmi_free_dos_memory(selDAP);
00093
return NO_BUFDOS_MEMORY;
00094 }
00095
00096 segBound = segBuff + 0x800 - (segBuff % 0x800);
00097
00098 __dpmi_regs r;
00099
00100
U64B tailblock = (nblocks/blocks_per_buff) * blocks_per_buff + block;
00101
for (transfd = block; transfd < block+nblocks; transfd += blocks_per_buff) {
00102 r.h.ah = 0x42;
00103 r.h.dl = (
unsigned short int) drv;
00104 r.x.ds = segDAP;
00105 r.x.si = 0;
00106
00107 DAP.
packetsize =
sizeof(
struct diskaddrpacket);
00108
if (transfd == tailblock) blocks_per_buff = nblocks + block - transfd;
00109 DAP.
nblocks = blocks_per_buff;
00110
00111 DAP.
buffer_segment = segBound;
00112 DAP.
buffer_offset = 0;
00113 DAP.
startblock = transfd;
00114 dosmemput(&DAP,
sizeof(DAP), segDAP << 4);
00115
00116 __dpmi_int (0x13, &r);
00117
00118
if (r.x.flags & 1) { __dpmi_free_dos_memory(selBuff);
00119 __dpmi_free_dos_memory(selDAP);
return r.h.ah; }
00120
00121
00122 dosmemget(segBound << 4, blocks_per_buff * DParam->
bytes_per_sect,
00123 (
char *) buffer + (transfd - block)*DParam->
bytes_per_sect);
00124 }
00125
00126 __dpmi_free_dos_memory(selBuff);
00127 __dpmi_free_dos_memory(selDAP);
00128
return 0;
00129 }
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 int int13ext_write(
int drv,
struct driveparams *DParam, U64B block, U64B nblocks,
void *buffer)
00141 {
00142
struct diskaddrpacket DAP = {
sizeof(
struct diskaddrpacket), 0};
00143
int selDAP, segDAP, selBuff, segBuff, segBound;
00144
U64B transfd;
00145
U32B rdbuffsize =
00146 (nblocks * DParam->
bytes_per_sect < 0x8000)? nblocks*DParam->
bytes_per_sect :0x8000;
00147
U32B blocks_per_buff = rdbuffsize/DParam->
bytes_per_sect;
00148
00149 segDAP = __dpmi_allocate_dos_memory((DAP.
packetsize + 15) >> 4, &selDAP);
00150
if (segDAP == -1)
return NO_CTLDOS_MEMORY;
00151
00152
00153
00154
00155 segBuff = __dpmi_allocate_dos_memory(((rdbuffsize + 15) >> 4) + 0x800, &selBuff);
00156
if (segBuff == -1) {
00157 __dpmi_free_dos_memory(selDAP);
00158
return NO_BUFDOS_MEMORY;
00159 }
00160
00161 segBound = segBuff + 0x800 - (segBuff % 0x800);
00162
00163 __dpmi_regs r;
00164
00165
U64B tailblock = (nblocks/blocks_per_buff) * blocks_per_buff + block;
00166
for (transfd = block; transfd < block+nblocks; transfd += blocks_per_buff) {
00167 r.x.ax = 0x4300;
00168 r.h.dl = (
unsigned short int) drv;
00169 r.x.ds = segDAP;
00170 r.x.si = 0;
00171
00172 DAP.
packetsize =
sizeof(
struct diskaddrpacket);
00173
if (transfd == tailblock) blocks_per_buff = nblocks + block - transfd;
00174 DAP.
nblocks = blocks_per_buff;
00175
00176 DAP.
buffer_segment = segBound;
00177 DAP.
buffer_offset = 0;
00178 DAP.
startblock = transfd;
00179 dosmemput(&DAP,
sizeof(DAP), segDAP << 4);
00180
00181 dosmemput((
char *) buffer + (transfd - block)*DParam->
bytes_per_sect,
00182 blocks_per_buff * DParam->
bytes_per_sect, segBound << 4);
00183
00184 __dpmi_int (0x13, &r);
00185
00186
if (r.x.flags & 1) { __dpmi_free_dos_memory(selBuff);
00187 __dpmi_free_dos_memory(selDAP);
return r.h.ah; }
00188 }
00189
00190 __dpmi_free_dos_memory(selBuff);
00191 __dpmi_free_dos_memory(selDAP);
00192
return 0;
00193 }