Rev 1683 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/* Project: OSLib
* Description: The OS Construction Kit
* Date: 1.6.2000
* Idea by: Luca Abeni & Gerardo Lamastra
*
* OSLib is an SO project aimed at developing a common, easy-to-use
* low-level infrastructure for developing OS kernels and Embedded
* Applications; it partially derives from the HARTIK project but it
* currently is independently developed.
*
* OSLib is distributed under GPL License, and some of its code has
* been derived from the Linux kernel source; also some important
* ideas come from studying the DJGPP go32 extender.
*
* We acknowledge the Linux Community, Free Software Foundation,
* D.J. Delorie and all the other developers who believe in the
* freedom of software and ideas.
*
* For legalese, check out the included GPL license.
*/
/* DOS Interface toward disk */
#include <arch/string.h>
#include <ll/i386/error.h>
#include <ll/i386/mem.h>
#include <ll/i386/x-dos.h>
#include <ll/i386/x-dosmem.h>
FILE
(X
-Dos
-File
);
/* Basic DOS I/O Flag */
/*#define __DEBUG__*/
#define DOS_READ 0
#define DOS_WRITE 1
#define DOS_RW 2
#define DOS_BUFSIZE 1024 /* I/O auxiliary buffer */
#define DOS_MAXDESCR 16 /* Maximum number of DOS file */
static DOS_FILE DOS_descr
[DOS_MAXDESCR
];
/* I Hope this array is initialized with 0... */
static BYTE busy
[DOS_MAXDESCR
];
/* The Last DOS Error occurred! */
static unsigned _DOS_error
= 0;
int DOS_init
(void)
{
/* Init the DOS memory allocator */
DOS_mem_init
();
/* TODO: Add a check if we are run through X */
return 1;
}
unsigned DOS_error
(void)
{
unsigned v
= _DOS_error
;
_DOS_error
= 0;
return(v
);
}
DOS_FILE
*DOS_fopen
(char *name
,char *mode
)
{
X_REGS16 ir
,or
;
X_SREGS16 sr
;
DOS_FILE
*f
;
register int i
;
#ifdef __DEBUG__
char xname
[80];
#endif
for (i
= 0; busy
[i
] && i
< DOS_MAXDESCR
; i
++);
/* Return NULL if no descriptor is available... */
if (i
== DOS_MAXDESCR
) return(NULL
);
/* Otherwise, lock the descriptor & remember the index */
f
= &DOS_descr
[i
]; busy
[i
] = 1; f
->index
= i
;
/* Allocate a DOS buffer for the file name */
f
->n1
= DOS_alloc
(80);
strcpy(f
->n2
,name
);
if (mode
[0] == 'r') {
/* DOS Call: Intr 0x21
AH = 0x3D - Open existing file
AL = 0,1,2 - Read,Write, R/W
*/
f
->mode
= DOS_READ
;
ir.
h.
ah = 0x3D;
ir.
h.
al = f
->mode
;
}
else if (mode
[0] == 'w') {
/* DOS Call: Intr 0x21
AH = 0x3C - Create a file
AL = File attribute [0x20 = Standard,r/w,archive]
*/
f
->mode
= DOS_WRITE
;
ir.
h.
ah = 0x3C;
ir.
x.
cx = 0x20;
}
f
->offset
= 0;
/* Copy th \0 also! */
memcpy(f
->n1
, name
, strlen(name
) + 1);
#ifdef __DEBUG__
memcpy(xname
, f
->n1
, strlen(name
) + 1);
message
("Name is : %s -- Mode : %d\n",xname
,f
->mode
);
#endif
/* Ask DOS to open File */
ir.
x.
dx = DOS_OFF
(f
->n1
);
sr.
ds = DOS_SEG
(f
->n1
);
X_callBIOS
(0x21,&ir
,&or
,&sr
);
f
->handle
= (!(or.
x.
cflag) ? or.
x.
ax : -1);
if (f
->handle
== -1) {
/* DOS request failed! Release the used resources */
DOS_free
(f
->n1
,80);
busy
[i
] = 0;
_DOS_error
= or.
x.
ax;
return(NULL
);
}
/* Allocate the DOS buffer for temporary I/O */
f
->buf
= DOS_alloc
(DOS_BUFSIZE
);
return(f
);
}
void DOS_fclose
(DOS_FILE
*f
)
{
X_REGS16 ir
,or
;
X_SREGS16 sr
;
if (f
== NULL
|| busy
[f
->index
] == 0) return;
/* DOS Call: Intr 0x21
AH = 0x3E - Close a file
BX = File handle
*/
ir.
h.
ah = 0x3E;
ir.
x.
bx = f
->handle
;
X_callBIOS
(0x21,&ir
,&or
,&sr
);
DOS_free
(f
->buf
,DOS_BUFSIZE
);
DOS_free
(f
->n1
,80);
busy
[f
->index
] = 0;
}
DWORD DOS_fread
(void *abuf
,DWORD size
,DWORD num
,DOS_FILE
*f
)
{
X_REGS16 ir
,or
;
X_SREGS16 sr
;
DWORD count
= size
*num
,now
= 0,chunk
;
BYTE done
= 0;
BYTE
*buf
= (BYTE
*)(abuf
);
while (done
== 0) {
/* Fragment the read operation ... */
if (count
> DOS_BUFSIZE
) chunk
= DOS_BUFSIZE
;
else chunk
= count
;
/* DOS Call: Intr 0x21
AH = 0x3F - Read data using a file handle
BX = File handle
CX = Buffer size
DS:DX = Segment:Offset of the Buffer
*/
ir.
h.
ah = 0x3F;
ir.
x.
bx = f
->handle
;
ir.
x.
cx = chunk
;
ir.
x.
dx = DOS_OFF
(f
->buf
);
sr.
ds = DOS_SEG
(f
->buf
);
X_callBIOS
(0x21,&ir
,&or
,&sr
);
/* If it was OK ... */
if (!(or.
x.
cflag)) {
/* Copy data into application buffer */
memcpy(buf
, f
->buf
, or.
x.
ax);
buf
+= or.
x.
ax;
now
+= or.
x.
ax;
f
->offset
+= or.
x.
ax;
count
-= or.
x.
ax;
/*
Finish if we have read all the data or
if we have read less data than how expected
*/
if (now
== size
*num
|| or.
x.
ax != chunk
) done
= 1;
} else {
done
= -1;
_DOS_error
= or.
x.
ax;
}
}
return(now
);
}
DWORD DOS_fwrite
(void *abuf
,DWORD size
,DWORD num
,DOS_FILE
*f
)
{
X_REGS16 ir
,or
;
X_SREGS16 sr
;
DWORD count
= size
*num
,now
= 0,chunk
;
BYTE done
= 0;
BYTE
*buf
= (BYTE
*)(abuf
);
while (done
== 0) {
/* Fragment the write operation ... */
if (count
> DOS_BUFSIZE
) chunk
= DOS_BUFSIZE
;
else chunk
= count
;
/* Copy data from application buffer */
memcpy(f
->buf
, buf
, chunk
);
/* DOS Call: Intr 0x21
AH = 0x40 - Write data using a file handle
BX = File handle
CX = Buffer size
DS:DX = Segment:Offset of the Buffer
*/
ir.
h.
ah = 0x40;
ir.
x.
bx = f
->handle
;
ir.
x.
cx = chunk
;
ir.
x.
dx = DOS_OFF
(f
->buf
);
sr.
ds = DOS_SEG
(f
->buf
);
X_callBIOS
(0x21,&ir
,&or
,&sr
);
/* If it was OK ... */
if (!(or.
x.
cflag)) {
f
->offset
+= or.
x.
ax;
count
-= or.
x.
ax;
buf
+= or.
x.
ax;
now
+= or.
x.
ax;
if (now
== size
*num
|| or.
x.
ax != chunk
) done
= 1;
} else {
done
= -1;
_DOS_error
= or.
x.
ax;
}
}
return(now
);
}