|
|
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: mov bx, bp
229: add bx, $2
230: xcall (bx)
231: ret
232:
233:
234: ////////
235: /
236: / Initilize hard disk parameters
237: /
238: ////////
239: .globl hdinit_
240: hdinit_:
241: push si / Save registers.
242: push di
243: push bp
244:
245: mov si, bp / set si to partition table
246:
247: movb dl, (si) / get drive number
248: movb ah, $8 / get drive parameters
249: int DISK
250: jc 1f / abort on error (just return)
251:
252: movb al, ch / fetch cyl(lo)
253: movb ah, cl / move cyl(hi), sects
254: rolb ah, $1 / shift cylinder high to
255: rolb ah, $1 / the least sig bits
256: andb ah, $3 / mask out cylinder bits
257:
258: mov di, $traks / point to drive
259: stosw / set number of tracks
260:
261: movb al, $0x3F / sector mask
262: andb al, cl / mask sector
263: stosb / set sector
264:
265: movb al, dh / get max head
266: inc ax / change to # of heads (incb al)
267: stosb / set number of heads
268:
269: movsb / set drive
270: add si, $FIRST-1 / point to first block
271: movsw / fetch first block
272: movsw
273:
274: 1: pop bp / Restore registers.
275: pop di
276: pop si
277:
278: ret
279:
280: ////////
281: /
282: / Invoke the native monitor.
283: / Useful for debugging.
284: /
285: ////////
286:
287: .globl intmon_
288: intmon_:
289: int MON
290: ret
291:
292: ////////
293: /
294: / void _ffcopy(from_fp, to_fp, count)
295: / faddr_t from_fp, to_fp;
296: / int count;
297: /
298: / Copy count bytes from from_fp to to_fp.
299: /
300: / Here is the stack after initial "push bp":
301: /
302: / 12(bp) count
303: / 10(bp) FP_SEL(to_fp)
304: / 8(bp) FP_OFF(to_fp)
305: / 6(bp) FP_SEL(from_fp)
306: / 4(bp) FP_OFF(from_fp)
307: / 2(bp) return IP
308: / 0(bp) old bp
309: /
310: ////////
311:
312: .globl _ffcopy_
313: _ffcopy_:
314: push bp
315: mov bp, sp
316: push es
317: push di
318: push ds
319: push si
320:
321: lds si, 4(bp) / from_fp to DS:SI
322: les di, 8(bp) / to_fp to ES:DI
323: mov cx, 12(bp) / rep count to CX
324: rep
325: movsb
326:
327: pop si
328: pop ds
329: pop di
330: pop es
331: pop bp
332: ret / return from _ffcopy()
333:
334:
335:
336: ////////
337: /
338: / Read a block from disk, relative to start of disk,
339: / using the code in the IBM firmware.
340: /
341: / It takes two parameters:
342: / daddr_t blockno; /* 32 bit block number. */
343: / char *buff; /* Must point to a 512 byte buffer. */
344: /
345: / The buffer must not cross a 4K boundry. Disk input should generally
346: / be done through the C routine xbread(), which calls _xbread() with an
347: / aligned buffer.
348: /
349: ////////
350:
351: .globl _xbread_
352: _xbread_:
353: push es / Save registers
354: push si
355: push di
356: push bp
357: push dx
358:
359: push ds
360: pop es / Set es:bp to address of the buffer.
361:
362: mov bp, sp
363: mov ax, 12(bp) / Get low word of block number.
364: mov dx, 14(bp) / Get high word of block number.
365: mov bx, 16(bp) / Get a buffer to put it in.
366: mov bp, bx
367:
368: / Translate block number into cylinder, head, and sector.
369: 3:
370: mov bx, ax / save block number
371: movb al, heads / get number of heads
372: movb cl, sects / get number of sectors
373: mulb cl / calculate sectors per cylinder
374: xchg bx,ax / swap block/sectors
375: div bx / calculate track
376: xchg dx, ax / put track in DX
377: divb cl / calculate head/sector
378:
379: movb cl, ah / set sector
380: inc cx / sectors start at 1 [incb cl]
381:
382: cmp dx, traks / check for second side
383: jb 0f
384: sub dx, traks / fold track
385: inc ax / next head [incb al]
386:
387: 0: rorb dh, $1 / rotate track(low) into
388: rorb dh, $1 / msbits of DX
389: orb cl, dh / set track(high)
390: movb ch, dl / set track(low)
391: movb dh, al / set head
392: movb dl, drive / set drive
393: mov bx, bp / set offset [bbuf]
394:
395: mov ax, $READ1 / Read, 1 sector.
396: int DISK / Disk I/O.
397: jnc 2f / Jump if no error.
398: mov ax, $READ1 / try again
399: int DISK
400: jc berror
401:
402: 2:
403: / al contains the number of blocks read (should be 1).
404: pop dx / restore registers.
405: pop bp
406: pop di
407: pop si
408: pop es
409: ret / return.
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.