|
|
1.1 root 1: ////////
2: /
3: / I/O library for use with boot programs. Uses the BIOS.
4: /
5: / La Monte H. Yarroll <[email protected]>, September 1991
6: /
7: ////////
8:
9: ////////
10: /
11: / Magic constants.
12: /
13: ////////
14:
15: RETF = 0xCB / Far return
16: VIDEO = 0x10 / video swi
17: DISK = 0x13 / disk io swi
18: KEYBD = 0x16 / keyboard swi
19: MON = 0x00 / Monitor swi
20: READ1 = 0x0201 / read 1 sector
21:
22: BUFSIZE = 0x200 / Size of a physical disk block.
23:
24: NTRK = 40 / Number of tracks on a floppy.
25: NSPT = 9 / Number of sectors per track on a floppy.
26: NHD = 1 / Number of heads per drive on a floppy.
27:
28: FIRST = 8 / Relative start of partition.
29:
30: .shri / Shared code segment, initialized.
31: ////////
32: /
33: / Read a block from disk, relative to the start of the boot partition,
34: / using the code in the IBM firmware.
35: /
36: / It takes two parameters:
37: / daddr_t blockno; /* 32 bit block number. */
38: / char *buff; /* Must point to a 512 byte buffer. */
39: /
40: / The buffer must not cross a 4K boundry. Disk input should generally
41: / be done through the C routine bread(), which calls bread() with an
42: / aligned buffer.
43: /
44: ////////
45:
46: .globl _bread_
47: _bread_:
48: push es / Save registers
49: push si
50: push di
51: push bp
52: push dx
53:
54: push ds
55: pop es / Set es:bp to address of the buffer.
56:
57: mov bp, sp
58: mov ax, 12(bp) / Get low word of block number.
59: mov dx, 14(bp) / Get high word of block number.
60: mov bx, 16(bp) / Get a buffer to put it in.
61: mov bp, bx
62:
63: mov di, bp / Blast the buffer contents.
64: mov cx, $BUFSIZE / For block 0, this fills the buffer
65: rep / with zeros.
66: stosb
67:
68: / Block #0 is the sparse block--it means a block of all zeros.
69: test ax, ax / if block 0, return zeroed buffer
70: jnz 3f
71: test dx, dx
72: jnz 3f
73: movb al, $1 / Say that we read 1 block.
74: jmp 2f
75: / Translate block number into cylinder, head, and sector.
76: 3: add ax, first / add first block
77: adc dx, first+2 / add rest
78:
79: mov bx, ax / save block number
80: movb al, heads / get number of heads
81: movb cl, sects / get number of sectors
82: mulb cl / calculate sectors per cylinder
83: xchg bx,ax / swap block/sectors
84: div bx / calculate track
85: xchg dx, ax / put track in DX
86: divb cl / calculate head/sector
87:
88: movb cl, ah / set sector
89: inc cx / sectors start at 1 [incb cl]
90:
91: cmp dx, traks / check for second side
92: jb 0f
93: sub dx, traks / fold track
94: inc ax / next head [incb al]
95:
96: 0: rorb dh, $1 / rotate track(low) into
97: rorb dh, $1 / msbits of DX
98: orb cl, dh / set track(high)
99: movb ch, dl / set track(low)
100: movb dh, al / set head
101: movb dl, drive / set drive
102: mov bx, bp / set offset [bbuf]
103:
104: mov ax, $READ1 / Read, 1 sector.
105: int DISK / Disk I/O.
106: jnc 2f / Jump if no error.
107: mov ax, $READ1 / try again
108: int DISK
109: jc berror
110:
111: 2:
112: / al contains the number of blocks read (should be 1).
113: pop dx / restore registers.
114: pop bp
115: pop di
116: pop si
117: pop es
118: ret / return.
119:
120: berror: / error handling for _bread.
121: xorb al, al / ah contains an error code.
122: jmp 2b
123:
124: ////////
125: /
126: / Write the character in "al" out to
127: / the display, using routines in the ROM.
128: / Like most calls to the ROM, this routine spends
129: / most of its time saving and restoring the
130: / registers.
131: /
132: ////////
133:
134: .globl putchar_
135: putchar_: push si / Save registers.
136: push di
137: push bp
138:
139: mov bp, sp
140: mov ax, 8(bp) / Fetch the single argument.
141:
142: mov bx, $0x0007 / Page 0, white on black
143: movb ah, $0x0E / Write TTY.
144: int VIDEO / Call video I/O in ROM.
145:
146: pop bp / Restore registers.
147: pop di
148: pop si
149: ret
150:
151:
152: ////////
153: /
154: / Fetch character from keyboard, using
155: / routines in the ROM.
156: /
157: ////////
158:
159: .globl getchar_
160: getchar_:
161: push si / Save registers.
162: push di
163: push bp
164:
165: movb ah, $0x00 / Read keystroke.
166: int KEYBD
167:
168: movb ah, $0x00
169: pop bp / Restore registers.
170: pop di
171: pop si
172: ret
173:
174: ////////
175: /
176: / Check for a pending keystroke using
177: / routines in the ROM.
178: /
179: ////////
180:
181: .globl iskey_
182: iskey_:
183: push si / Save registers.
184: push di
185: push bp
186:
187: movb ah, $0x01 / Check for keystroke.
188: int KEYBD
189: jne 0f
190: xor ax, ax / Set false.
191: jmp 1f
192: 0: xor ax, ax
193: inc ax / Set true.
194: 1: pop bp / Restore registers.
195: pop di
196: pop si
197: ret
198:
199:
200: ////////
201: /
202: / Goto a far address
203: / Takes two integer arguments: an offset, and a segment, in that order.
204: /
205: ////////
206:
207: .globl gotofar_
208: gotofar_:
209: add sp, $2
210: .byte RETF
211:
212:
213: ////////
214: /
215: / Goto a kernel.
216: / Takes three integer arguments: an offset, a segment, and a new data segment
217: / in that order.
218: /
219: ////////
220:
221: .globl gotoker_
222: gotoker_:
223: mov bp, sp
224: mov es, 6(bp) / Point es at the new data segment.
225: mov si, $seconddat / Point ds:si at useful data.
226: add sp, $2
227: .byte RETF
228:
229:
230: ////////
231: /
232: / Initilize hard disk parameters
233: /
234: ////////
235: .globl hdinit_
236: hdinit_:
237: push si / Save registers.
238: push di
239: push bp
240:
241: mov si, bp / set si to partition table
242:
243: movb dl, (si) / get drive number
244: movb ah, $8 / get drive parameters
245: int DISK
246: jc 1f / abort on error (just return)
247:
248: movb al, ch / fetch cyl(lo)
249: movb ah, cl / move cyl(hi), sects
250: rolb ah, $1 / shift cylinder high to
251: rolb ah, $1 / the least sig bits
252: andb ah, $3 / mask out cylinder bits
253:
254: mov di, $traks / point to drive
255: stosw / set number of tracks
256:
257: movb al, $0x3F / sector mask
258: andb al, cl / mask sector
259: stosb / set sector
260:
261: movb al, dh / get max head
262: inc ax / change to # of heads (incb al)
263: stosb / set number of heads
264:
265: movsb / set drive
266: add si, $FIRST-1 / point to first block
267: movsw / fetch first block
268: movsw
269:
270: 1: pop bp / Restore registers.
271: pop di
272: pop si
273:
274: ret
275:
276: ////////
277: /
278: / Invoke the native monitor.
279: / Useful for debugging.
280: /
281: ////////
282:
283: .globl intmon_
284: intmon_:
285: int MON
286: ret
287:
288: ////////
289: /
290: / void _ffcopy(from_fp, to_fp, count)
291: / faddr_t from_fp, to_fp;
292: / int count;
293: /
294: / Copy count bytes from from_fp to to_fp.
295: /
296: / Here is the stack after initial "push bp":
297: /
298: / 12(bp) count
299: / 10(bp) FP_SEL(to_fp)
300: / 8(bp) FP_OFF(to_fp)
301: / 6(bp) FP_SEL(from_fp)
302: / 4(bp) FP_OFF(from_fp)
303: / 2(bp) return IP
304: / 0(bp) old bp
305: /
306: ////////
307:
308: .globl _ffcopy_
309: _ffcopy_:
310: push bp
311: mov bp, sp
312: push es
313: push di
314: push ds
315: push si
316:
317: lds si, 4(bp) / from_fp to DS:SI
318: les di, 8(bp) / to_fp to ES:DI
319: mov cx, 12(bp) / rep count to CX
320: rep
321: movsb
322:
323: pop si
324: pop ds
325: pop di
326: pop es
327: pop bp
328: ret / return from _ffcopy()
329:
330:
331:
332: ////////
333: /
334: / Read a block from disk, relative to start of disk,
335: / using the code in the IBM firmware.
336: /
337: / It takes two parameters:
338: / daddr_t blockno; /* 32 bit block number. */
339: / char *buff; /* Must point to a 512 byte buffer. */
340: /
341: / The buffer must not cross a 4K boundry. Disk input should generally
342: / be done through the C routine bread(), which calls bread() with an
343: / aligned buffer.
344: /
345: ////////
346:
347: .globl _xbread_
348: _xbread_:
349: push es / Save registers
350: push si
351: push di
352: push bp
353: push dx
354:
355: push ds
356: pop es / Set es:bp to address of the buffer.
357:
358: mov bp, sp
359: mov ax, 12(bp) / Get low word of block number.
360: mov dx, 14(bp) / Get high word of block number.
361: mov bx, 16(bp) / Get a buffer to put it in.
362: mov bp, bx
363:
364: / Translate block number into cylinder, head, and sector.
365: 3:
366: mov bx, ax / save block number
367: movb al, heads / get number of heads
368: movb cl, sects / get number of sectors
369: mulb cl / calculate sectors per cylinder
370: xchg bx,ax / swap block/sectors
371: div bx / calculate track
372: xchg dx, ax / put track in DX
373: divb cl / calculate head/sector
374:
375: movb cl, ah / set sector
376: inc cx / sectors start at 1 [incb cl]
377:
378: cmp dx, traks / check for second side
379: jb 0f
380: sub dx, traks / fold track
381: inc ax / next head [incb al]
382:
383: 0: rorb dh, $1 / rotate track(low) into
384: rorb dh, $1 / msbits of DX
385: orb cl, dh / set track(high)
386: movb ch, dl / set track(low)
387: movb dh, al / set head
388: movb dl, drive / set drive
389: mov bx, bp / set offset [bbuf]
390:
391: mov ax, $READ1 / Read, 1 sector.
392: int DISK / Disk I/O.
393: jnc 2f / Jump if no error.
394: mov ax, $READ1 / try again
395: int DISK
396: jc berror
397:
398: 2:
399: / al contains the number of blocks read (should be 1).
400: pop dx / restore registers.
401: pop bp
402: pop di
403: pop si
404: pop es
405: ret / return.
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.