Subversion Repositories shark

Rev

Rev 3 | Go to most recent revision | 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
}