Rev 3 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2 | pj | 1 | /* Project: OSLib |
2 | * Description: The OS Construction Kit |
||
3 | * Date: 1.6.2000 |
||
4 | * Idea by: Luca Abeni & Gerardo Lamastra |
||
5 | * |
||
6 | * OSLib is an SO project aimed at developing a common, easy-to-use |
||
7 | * low-level infrastructure for developing OS kernels and Embedded |
||
8 | * Applications; it partially derives from the HARTIK project but it |
||
9 | * currently is independently developed. |
||
10 | * |
||
11 | * OSLib is distributed under GPL License, and some of its code has |
||
12 | * been derived from the Linux kernel source; also some important |
||
13 | * ideas come from studying the DJGPP go32 extender. |
||
14 | * |
||
15 | * We acknowledge the Linux Community, Free Software Foundation, |
||
16 | * D.J. Delorie and all the other developers who believe in the |
||
17 | * freedom of software and ideas. |
||
18 | * |
||
19 | * For legalese, check out the included GPL license. |
||
20 | */ |
||
21 | |||
22 | /* DOS Interface toward disk */ |
||
23 | |||
24 | #include <ll/i386/mem.h> |
||
25 | #include <ll/i386/error.h> |
||
26 | #include <ll/string.h> |
||
27 | #include <ll/i386/x-dos.h> |
||
28 | #include <ll/i386/x-dosmem.h> |
||
29 | |||
40 | pj | 30 | FILE(X-Dos-File); |
2 | pj | 31 | |
32 | /* Basic DOS I/O Flag */ |
||
33 | |||
34 | /*#define __DEBUG__*/ |
||
35 | |||
36 | #define DOS_READ 0 |
||
37 | #define DOS_WRITE 1 |
||
38 | #define DOS_RW 2 |
||
39 | |||
40 | pj | 40 | #define DOS_BUFSIZE 1024 /* I/O auxiliary buffer */ |
41 | #define DOS_MAXDESCR 16 /* Maximum number of DOS file */ |
||
2 | pj | 42 | |
43 | static DOS_FILE DOS_descr[DOS_MAXDESCR]; |
||
44 | /* I Hope this array is initialized with 0... */ |
||
45 | static BYTE busy[DOS_MAXDESCR]; |
||
46 | |||
47 | /* The Last DOS Error occurred! */ |
||
48 | static unsigned _DOS_error = 0; |
||
49 | |||
50 | |||
51 | int DOS_init(void) |
||
52 | { |
||
40 | pj | 53 | /* Init the DOS memory allocator */ |
54 | DOS_mem_init(); |
||
2 | pj | 55 | |
40 | pj | 56 | /* TODO: Add a check if we are run through X */ |
57 | return 1; |
||
2 | pj | 58 | } |
59 | |||
60 | unsigned DOS_error(void) |
||
61 | { |
||
62 | unsigned v = _DOS_error; |
||
63 | _DOS_error = 0; |
||
40 | pj | 64 | return(v); |
2 | pj | 65 | } |
66 | |||
40 | pj | 67 | DOS_FILE *DOS_fopen(char *name,char *mode) |
2 | pj | 68 | { |
40 | pj | 69 | X_REGS16 ir,or; |
2 | pj | 70 | X_SREGS16 sr; |
71 | DOS_FILE *f; |
||
72 | register int i; |
||
73 | |||
40 | pj | 74 | #ifdef __DEBUG__ |
75 | char xname[80]; |
||
76 | #endif |
||
2 | pj | 77 | |
78 | for (i = 0; busy[i] && i < DOS_MAXDESCR; i++); |
||
79 | /* Return NULL if no descriptor is available... */ |
||
40 | pj | 80 | if (i == DOS_MAXDESCR) return(NULL); |
2 | pj | 81 | /* Otherwise, lock the descriptor & remember the index */ |
40 | pj | 82 | f = &DOS_descr[i]; busy[i] = 1; f->index = i; |
2 | pj | 83 | /* Allocate a DOS buffer for the file name */ |
84 | f->n1 = DOS_alloc(80); |
||
40 | pj | 85 | strcpy(f->n2,name); |
2 | pj | 86 | if (mode[0] == 'r') { |
87 | /* DOS Call: Intr 0x21 |
||
40 | pj | 88 | AH = 0x3D - Open existing file |
89 | AL = 0,1,2 - Read,Write, R/W |
||
90 | */ |
||
2 | pj | 91 | f->mode = DOS_READ; |
92 | ir.h.ah = 0x3D; |
||
93 | ir.h.al = f->mode; |
||
40 | pj | 94 | } |
95 | else if (mode[0] == 'w') { |
||
2 | pj | 96 | /* DOS Call: Intr 0x21 |
40 | pj | 97 | AH = 0x3C - Create a file |
98 | AL = File attribute [0x20 = Standard,r/w,archive] |
||
99 | */ |
||
2 | pj | 100 | f->mode = DOS_WRITE; |
101 | ir.h.ah = 0x3C; |
||
102 | ir.x.cx = 0x20; |
||
103 | } |
||
104 | f->offset = 0; |
||
105 | /* Copy th \0 also! */ |
||
106 | memcpy(f->n1, name, strlen(name) + 1); |
||
40 | pj | 107 | #ifdef __DEBUG__ |
108 | memcpy(xname, f->n1, strlen(name) + 1); |
||
109 | message("Name is : %s -- Mode : %d\n",xname,f->mode); |
||
110 | #endif |
||
2 | pj | 111 | |
112 | /* Ask DOS to open File */ |
||
113 | ir.x.dx = DOS_OFF(f->n1); |
||
114 | sr.ds = DOS_SEG(f->n1); |
||
40 | pj | 115 | X_callBIOS(0x21,&ir,&or,&sr); |
2 | pj | 116 | f->handle = (!(or.x.cflag) ? or.x.ax : -1); |
117 | |||
118 | if (f->handle == -1) { |
||
119 | /* DOS request failed! Release the used resources */ |
||
40 | pj | 120 | DOS_free(f->n1,80); |
2 | pj | 121 | busy[i] = 0; |
122 | _DOS_error = or.x.ax; |
||
40 | pj | 123 | return(NULL); |
2 | pj | 124 | } |
40 | pj | 125 | |
2 | pj | 126 | /* Allocate the DOS buffer for temporary I/O */ |
127 | f->buf = DOS_alloc(DOS_BUFSIZE); |
||
40 | pj | 128 | return(f); |
2 | pj | 129 | } |
130 | |||
40 | pj | 131 | void DOS_fclose(DOS_FILE *f) |
2 | pj | 132 | { |
40 | pj | 133 | X_REGS16 ir,or; |
2 | pj | 134 | X_SREGS16 sr; |
135 | |||
40 | pj | 136 | if (f == NULL || busy[f->index] == 0) return; |
2 | pj | 137 | /* DOS Call: Intr 0x21 |
40 | pj | 138 | AH = 0x3E - Close a file |
139 | BX = File handle |
||
140 | */ |
||
2 | pj | 141 | ir.h.ah = 0x3E; |
142 | ir.x.bx = f->handle; |
||
40 | pj | 143 | X_callBIOS(0x21,&ir,&or,&sr); |
144 | DOS_free(f->buf,DOS_BUFSIZE); |
||
145 | DOS_free(f->n1,80); |
||
2 | pj | 146 | busy[f->index] = 0; |
147 | } |
||
148 | |||
40 | pj | 149 | DWORD DOS_fread(void *abuf,DWORD size,DWORD num,DOS_FILE *f) |
2 | pj | 150 | { |
40 | pj | 151 | X_REGS16 ir,or; |
2 | pj | 152 | X_SREGS16 sr; |
40 | pj | 153 | DWORD count = size*num,now = 0,chunk; |
2 | pj | 154 | BYTE done = 0; |
40 | pj | 155 | BYTE *buf = (BYTE *)(abuf); |
156 | |||
2 | pj | 157 | while (done == 0) { |
158 | /* Fragment the read operation ... */ |
||
40 | pj | 159 | if (count > DOS_BUFSIZE) chunk = DOS_BUFSIZE; |
160 | else chunk = count; |
||
2 | pj | 161 | /* DOS Call: Intr 0x21 |
40 | pj | 162 | AH = 0x3F - Read data using a file handle |
163 | BX = File handle |
||
164 | CX = Buffer size |
||
165 | DS:DX = Segment:Offset of the Buffer |
||
166 | */ |
||
2 | pj | 167 | ir.h.ah = 0x3F; |
168 | ir.x.bx = f->handle; |
||
169 | ir.x.cx = chunk; |
||
170 | ir.x.dx = DOS_OFF(f->buf); |
||
171 | sr.ds = DOS_SEG(f->buf); |
||
40 | pj | 172 | X_callBIOS(0x21,&ir,&or,&sr); |
2 | pj | 173 | /* If it was OK ... */ |
174 | if (!(or.x.cflag)) { |
||
175 | /* Copy data into application buffer */ |
||
176 | memcpy(buf, f->buf, or.x.ax); |
||
177 | buf += or.x.ax; |
||
178 | now += or.x.ax; |
||
179 | f->offset += or.x.ax; |
||
180 | count -= or.x.ax; |
||
181 | /* |
||
40 | pj | 182 | Finish if we have read all the data or |
183 | if we have read less data than how expected |
||
184 | */ |
||
185 | if (now == size*num || or.x.ax != chunk) done = 1; |
||
2 | pj | 186 | } else { |
187 | done = -1; |
||
188 | _DOS_error = or.x.ax; |
||
189 | } |
||
190 | } |
||
40 | pj | 191 | return(now); |
2 | pj | 192 | } |
193 | |||
40 | pj | 194 | DWORD DOS_fwrite(void *abuf,DWORD size,DWORD num,DOS_FILE *f) |
2 | pj | 195 | { |
40 | pj | 196 | X_REGS16 ir,or; |
2 | pj | 197 | X_SREGS16 sr; |
40 | pj | 198 | DWORD count = size*num,now = 0,chunk; |
2 | pj | 199 | BYTE done = 0; |
40 | pj | 200 | BYTE *buf = (BYTE *)(abuf); |
201 | |||
2 | pj | 202 | while (done == 0) { |
203 | /* Fragment the write operation ... */ |
||
40 | pj | 204 | if (count > DOS_BUFSIZE) chunk = DOS_BUFSIZE; |
205 | else chunk = count; |
||
2 | pj | 206 | /* Copy data from application buffer */ |
207 | memcpy(f->buf, buf, chunk); |
||
208 | /* DOS Call: Intr 0x21 |
||
40 | pj | 209 | AH = 0x40 - Write data using a file handle |
210 | BX = File handle |
||
211 | CX = Buffer size |
||
212 | DS:DX = Segment:Offset of the Buffer |
||
213 | */ |
||
2 | pj | 214 | ir.h.ah = 0x40; |
215 | ir.x.bx = f->handle; |
||
216 | ir.x.cx = chunk; |
||
217 | ir.x.dx = DOS_OFF(f->buf); |
||
218 | sr.ds = DOS_SEG(f->buf); |
||
40 | pj | 219 | X_callBIOS(0x21,&ir,&or,&sr); |
2 | pj | 220 | /* If it was OK ... */ |
221 | if (!(or.x.cflag)) { |
||
222 | f->offset += or.x.ax; |
||
223 | count -= or.x.ax; |
||
224 | buf += or.x.ax; |
||
225 | now += or.x.ax; |
||
40 | pj | 226 | if (now == size*num || or.x.ax != chunk) done = 1; |
2 | pj | 227 | } else { |
228 | done = -1; |
||
229 | _DOS_error = or.x.ax; |
||
230 | } |
||
231 | } |
||
40 | pj | 232 | return(now); |
2 | pj | 233 | } |
40 | pj | 234 |