-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathPCDOSDK.C
243 lines (197 loc) · 4.88 KB
/
PCDOSDK.C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
/* @(#)pcdosdk.c 1.7 */
/*
* This module contains the PC-DOS disk routines used by the
* VME/10 booter for Concurrent DOS-68K.
*
* ASSUMPTIONS:
*
* - The file to be read must be in the root directory. (*** will
* change to allow path searching).
*/
#include "portab.h"
#include "cdosboot.h"
/* MACROS */
/* convert to upper case */
#define TOUPPER(c) if ((c) >= 'a') (c) -= 'a' - 'A'
/* CONSTANTS */
/* EXTERNALS */
extern FILESYS fs;
/* structure for one directory entry */
typedef struct
{
BYTE d_name[11];
BYTE d_attr;
WORD d_curclust; /* used only by these routines, not by DOS */
BYTE d_fill[12];
WORD d_cluster; /* starting cluster */
LONG d_size;
} DIRENTRY;
MLOCAL DIRENTRY direntry;
/* buffers for fat */
MLOCAL BYTE fat[MAXFATBUF]; /* used only to store the FAT */
MLOCAL BYTE name[11]; /* parsed name of open file */
/*********** FAT I/O ROUTINES ***********/
/* NextClust - get next cluster number from FAT, given current cluster no. */
MLOCAL WORD NextCluster(cluster)
REG WORD cluster;
{
WORD index;
REG WORD fatword;
if( fs.mformat == ONEANDAHALF )
{
index = cluster + (cluster / 2); /* multiply by 1.5 */
fatword = getword(&fat[index]); /* get word from fat */
if (cluster & 1) fatword >>= 4; /* keep high 12 bits */
return (fatword & 0xfff); /* mask off top 4 */
}
else if( fs.mformat == TWO ) /* two byte fat entries */
{
index = cluster * 2; /* multiply by 2 */
fatword = getword(&fat[index]); /* get word from fat */
return (fatword);
}
else
{
PutMsg("Format byte is bad, can't do FAT entry calculation.");
Exit();
}
}
/* readfat - read the fat into the fat array */
MLOCAL VOID ReadFat()
{
if( (fs.nfrecs*fs.sectsize) > MAXFATBUF )
{
PutMsg("Can't buffer FAT, MAXFATBUF is too small.");
Exit();
}
/*
* WE NEED TO IMPLEMENT READING THE OTHER FAT TABLE!
* JUST TRY FIRST COPY FOR NOW.
*/
ReadSector((LONG)fs.firstsec,fs.nfrecs,fat);
}
/*********** CLUSTER I/O ***********/
/*
* ReadCluster
*
* Read the cluster into the buffer array
*
* NOTE: I made this a simple macro.
*/
#define ReadCluster(bp,cluster) \
ReadSector((LONG)((cluster - 2) * fs.secblk + fs.datasect),fs.secblk,bp)
/*********** DIRECTORY I/O ***********/
/* SearchDir
*
* Read the directory entry into buffer which corresponds to
* the name parameter.
*
* Return ERROR if no match and no more entries. Else return OK.
*/
SearchDir(dp)
REG DIRENTRY *dp;
{
WORD dirsect; /* current directory sector */
WORD nextdir; /* index to next directory entry to read */
BYTE dirbuf[MAXSECTSIZE]; /* used for directory search */
dirsect = 0;
nextdir = 0;
ReadSector((LONG)fs.dirsect,1,dirbuf);
for (;;)
{
if (nextdir >= fs.sectsize)
{
if (++dirsect >= fs.dirsize) return ERROR;
ReadSector((LONG)(dirsect+fs.dirsect),1,dirbuf);
nextdir = 0;
}
if (dirbuf[nextdir] == 0) /* end of directory */
return ERROR;
if (dirbuf[nextdir] == 0xe5) /* available entry */
nextdir += sizeof(DIRENTRY);
else
{
movb(&dirbuf[nextdir],dp,sizeof(DIRENTRY));
if (strncmp(dp->d_name,name,sizeof(name)) == 0)
{
/* fix swapped pointers */
dp->d_cluster = swapw(dp->d_cluster);
dp->d_size = swapl(dp->d_size);
ReadFat();
return OK;
}
else
nextdir += sizeof(DIRENTRY);
}
}
}
/*********** FILE READ ***********/
/* ReadPcdos
*
* Read the next cluster from the file to the user
* specified buffer. The actual number of bytes
* read is returned.
*/
ReadPcdos(buffer)
BYTE *buffer;
{
WORD actual;
if (direntry.d_cluster >= 0xff8 || direntry.d_size == 0)
return (0);
ReadCluster(buffer,direntry.d_cluster);
direntry.d_cluster = NextCluster(direntry.d_cluster);
actual = direntry.d_size < fs.blksz ? direntry.d_size : fs.blksz;
direntry.d_size -= actual;
return (actual);
}
/* Parse - parse a filename, put parsed name in "name" */
Parse(fname)
BYTE *fname;
{
WORD i;
BYTE c;
setb(' ',name,sizeof(name));
i = 0;
while (c = *fname++) /* terminated by null */
{
if (i >= sizeof(name)) return ERROR;
if (c == '.') /* start of extension */
{
if (i > 8) return ERROR;
else i = 8;
}
else
{
TOUPPER(c);
name[i++] = c;
}
}
return OK;
}
/* OpenPcdos
*
* Search directory for pcdos file. If not found, return ERROR.
* Otherwise, read the directory entry into direntry,
* and return OK.
*/
OpenPcdos(fname)
BYTE *fname;
{
if (Parse(fname) == ERROR)
{
PutMsg("Bad file name.");
return ERROR;
}
if( SearchDir(&direntry) == ERROR )
{
PutStr(OURNAME);
PutStr("Can't find file: ");
PutStr(fname);
PutStr("\r\n");
return ERROR; /* couldn't find the file */
}
return OK;
}
"Can't find file: ");
PutStr(fname);
PutStr("\