Details | 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 | |||
30 | FILE(X - Dos - File); |
||
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 | #define DOS_BUFSIZE 1024 /* I/O auxiliary buffer */ |
||
41 | #define DOS_MAXDESCR 16 /* Maximum number of DOS file */ |
||
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 | #ifdef __NOH4__ |
||
51 | |||
52 | int DOS_init(void) |
||
53 | { |
||
54 | /* Init the DOS memory allocator */ |
||
55 | DOS_mem_init(); |
||
56 | |||
57 | /* TODO: Add a check if we are run through X */ |
||
58 | return 1; |
||
59 | } |
||
60 | |||
61 | #endif |
||
62 | |||
63 | unsigned DOS_error(void) |
||
64 | { |
||
65 | unsigned v = _DOS_error; |
||
66 | _DOS_error = 0; |
||
67 | return (v); |
||
68 | } |
||
69 | |||
70 | DOS_FILE *DOS_fopen(char *name, char *mode) |
||
71 | { |
||
72 | X_REGS16 ir, or; |
||
73 | X_SREGS16 sr; |
||
74 | DOS_FILE *f; |
||
75 | register int i; |
||
76 | |||
77 | #ifdef __DEBUG__ |
||
78 | char xname[80]; |
||
79 | #endif |
||
80 | |||
81 | for (i = 0; busy[i] && i < DOS_MAXDESCR; i++); |
||
82 | /* Return NULL if no descriptor is available... */ |
||
83 | if (i == DOS_MAXDESCR) |
||
84 | return (NULL); |
||
85 | /* Otherwise, lock the descriptor & remember the index */ |
||
86 | f = &DOS_descr[i]; |
||
87 | busy[i] = 1; |
||
88 | f->index = i; |
||
89 | /* Allocate a DOS buffer for the file name */ |
||
90 | f->n1 = DOS_alloc(80); |
||
91 | strcpy(f->n2, name); |
||
92 | if (mode[0] == 'r') { |
||
93 | /* DOS Call: Intr 0x21 |
||
94 | AH = 0x3D - Open existing file |
||
95 | AL = 0,1,2 - Read,Write, R/W |
||
96 | */ |
||
97 | f->mode = DOS_READ; |
||
98 | ir.h.ah = 0x3D; |
||
99 | ir.h.al = f->mode; |
||
100 | } else if (mode[0] == 'w') { |
||
101 | /* DOS Call: Intr 0x21 |
||
102 | AH = 0x3C - Create a file |
||
103 | AL = File attribute [0x20 = Standard,r/w,archive] |
||
104 | */ |
||
105 | f->mode = DOS_WRITE; |
||
106 | ir.h.ah = 0x3C; |
||
107 | ir.x.cx = 0x20; |
||
108 | } |
||
109 | f->offset = 0; |
||
110 | /* Copy th \0 also! */ |
||
111 | memcpy(f->n1, name, strlen(name) + 1); |
||
112 | #ifdef __DEBUG__ |
||
113 | memcpy(xname, f->n1, strlen(name) + 1); |
||
114 | message("Name is : %s -- Mode : %d\n", xname, f->mode); |
||
115 | #endif |
||
116 | |||
117 | /* Ask DOS to open File */ |
||
118 | ir.x.dx = DOS_OFF(f->n1); |
||
119 | sr.ds = DOS_SEG(f->n1); |
||
120 | X_callBIOS(0x21, &ir, &or, &sr); |
||
121 | f->handle = (!(or.x.cflag) ? or.x.ax : -1); |
||
122 | |||
123 | if (f->handle == -1) { |
||
124 | /* DOS request failed! Release the used resources */ |
||
125 | DOS_free(f->n1, 80); |
||
126 | busy[i] = 0; |
||
127 | _DOS_error = or.x.ax; |
||
128 | return (NULL); |
||
129 | } |
||
130 | |||
131 | /* Allocate the DOS buffer for temporary I/O */ |
||
132 | f->buf = DOS_alloc(DOS_BUFSIZE); |
||
133 | return (f); |
||
134 | } |
||
135 | |||
136 | void DOS_fclose(DOS_FILE * f) |
||
137 | { |
||
138 | X_REGS16 ir, or; |
||
139 | X_SREGS16 sr; |
||
140 | |||
141 | if (f == NULL || busy[f->index] == 0) |
||
142 | return; |
||
143 | /* DOS Call: Intr 0x21 |
||
144 | AH = 0x3E - Close a file |
||
145 | BX = File handle |
||
146 | */ |
||
147 | ir.h.ah = 0x3E; |
||
148 | ir.x.bx = f->handle; |
||
149 | X_callBIOS(0x21, &ir, &or, &sr); |
||
150 | DOS_free(f->buf, DOS_BUFSIZE); |
||
151 | DOS_free(f->n1, 80); |
||
152 | busy[f->index] = 0; |
||
153 | } |
||
154 | |||
155 | DWORD DOS_fread(void *abuf, DWORD size, DWORD num, DOS_FILE * f) |
||
156 | { |
||
157 | X_REGS16 ir, or; |
||
158 | X_SREGS16 sr; |
||
159 | DWORD count = size * num, now = 0, chunk; |
||
160 | BYTE done = 0; |
||
161 | BYTE *buf = (BYTE *) (abuf); |
||
162 | |||
163 | while (done == 0) { |
||
164 | /* Fragment the read operation ... */ |
||
165 | if (count > DOS_BUFSIZE) |
||
166 | chunk = DOS_BUFSIZE; |
||
167 | else |
||
168 | chunk = count; |
||
169 | /* DOS Call: Intr 0x21 |
||
170 | AH = 0x3F - Read data using a file handle |
||
171 | BX = File handle |
||
172 | CX = Buffer size |
||
173 | DS:DX = Segment:Offset of the Buffer |
||
174 | */ |
||
175 | ir.h.ah = 0x3F; |
||
176 | ir.x.bx = f->handle; |
||
177 | ir.x.cx = chunk; |
||
178 | ir.x.dx = DOS_OFF(f->buf); |
||
179 | sr.ds = DOS_SEG(f->buf); |
||
180 | X_callBIOS(0x21, &ir, &or, &sr); |
||
181 | /* If it was OK ... */ |
||
182 | if (!(or.x.cflag)) { |
||
183 | /* Copy data into application buffer */ |
||
184 | memcpy(buf, f->buf, or.x.ax); |
||
185 | buf += or.x.ax; |
||
186 | now += or.x.ax; |
||
187 | f->offset += or.x.ax; |
||
188 | count -= or.x.ax; |
||
189 | /* |
||
190 | Finish if we have read all the data or |
||
191 | if we have read less data than how expected |
||
192 | */ |
||
193 | if (now == size * num || or.x.ax != chunk) |
||
194 | done = 1; |
||
195 | } else { |
||
196 | done = -1; |
||
197 | _DOS_error = or.x.ax; |
||
198 | } |
||
199 | } |
||
200 | return (now); |
||
201 | } |
||
202 | |||
203 | DWORD DOS_fwrite(void *abuf, DWORD size, DWORD num, DOS_FILE * f) |
||
204 | { |
||
205 | X_REGS16 ir, or; |
||
206 | X_SREGS16 sr; |
||
207 | DWORD count = size * num, now = 0, chunk; |
||
208 | BYTE done = 0; |
||
209 | BYTE *buf = (BYTE *) (abuf); |
||
210 | |||
211 | while (done == 0) { |
||
212 | /* Fragment the write operation ... */ |
||
213 | if (count > DOS_BUFSIZE) |
||
214 | chunk = DOS_BUFSIZE; |
||
215 | else |
||
216 | chunk = count; |
||
217 | /* Copy data from application buffer */ |
||
218 | memcpy(f->buf, buf, chunk); |
||
219 | /* DOS Call: Intr 0x21 |
||
220 | AH = 0x40 - Write data using a file handle |
||
221 | BX = File handle |
||
222 | CX = Buffer size |
||
223 | DS:DX = Segment:Offset of the Buffer |
||
224 | */ |
||
225 | ir.h.ah = 0x40; |
||
226 | ir.x.bx = f->handle; |
||
227 | ir.x.cx = chunk; |
||
228 | ir.x.dx = DOS_OFF(f->buf); |
||
229 | sr.ds = DOS_SEG(f->buf); |
||
230 | X_callBIOS(0x21, &ir, &or, &sr); |
||
231 | /* If it was OK ... */ |
||
232 | if (!(or.x.cflag)) { |
||
233 | f->offset += or.x.ax; |
||
234 | count -= or.x.ax; |
||
235 | buf += or.x.ax; |
||
236 | now += or.x.ax; |
||
237 | if (now == size * num || or.x.ax != chunk) |
||
238 | done = 1; |
||
239 | } else { |
||
240 | done = -1; |
||
241 | _DOS_error = or.x.ax; |
||
242 | } |
||
243 | } |
||
244 | return (now); |
||
245 | } |