|
|
1.1 root 1: / $Header: /kernel/kersrc/i286/RCS/as2.s,v 1.1 92/07/17 15:21:20 bin Exp Locker: bin $
2: /
3: / (lgl-
4: / The information contained herein is a trade secret of Mark Williams
5: / Company, and is confidential information. It is provided under a
6: / license agreement, and may be copied or disclosed only under the
7: / terms of that agreement. Any reproduction or disclosure of this
8: / material without the express written authorization of Mark Williams
9: / Company or persuant to the license agreement is unlawful.
10: /
11: / COHERENT Version 2.3.37
12: / Copyright (c) 1982, 1983, 1984.
13: / An unpublished work by Mark Williams Company, Chicago.
14: / All rights reserved.
15: / -lgl)
16: ////////
17: /
18: / Machine language assist for
19: / Coherent on the IBM personal computer.
20: /
21: / $Log: as2.s,v $
22: / Revision 1.1 92/07/17 15:21:20 bin
23: / Initial revision
24: /
25: / Revision 1.3 92/01/21 16:10:37 hal
26: / Use read_cmos_ routine.
27: / Allows merged 386 C code compatibility.
28: /
29: / Revision 1.2 91/06/06 18:14:46 norm
30: / Get memory size by reading CMOS.
31:
32: / Revision 1.3 88/08/05 15:37:32 src
33: / AMD 286 hardware specific fixes removed - hardware now correct.
34: / Virtual Selector F000 initialized to access ROM at F0000.
35: / Normal kernel stack now used during initialization.
36: /
37: / Revision 1.2 88/06/29 19:05:31 src
38: / AT Coherent can now come up in real-mode by patching 'realmode' variable.
39: /
40: / Revision 1.1 88/03/24 17:33:18 src
41: / Initial revision
42: /
43: / 88/03/10 Allan Cornish /usr/src/sys/i8086/ibm_at/as2.s
44: / Numerous temporary fixes due to AMD 286 chip being buggy in protected mode.
45: / These partial fixes will be removed once all CPU's are replaced.
46: /
47: / 88/03/07 Allan Cornish /usr/src/sys/i8086/ibm_at/as2.s
48: / Obsolete video() function deleted - not used, or usable in protected mode.
49: / Auto-increment mode no longer assumed, but enforced on block moves.
50: /
51: / 88/03/04 Allan Cornish /usr/src/sys/i8086/ibm_at/as2.s
52: / Memory sizing now flushes instruction pipeline before read-verify.
53: / Otherwise bus capacitance on some machines gives invalid memory indication.
54: / plrcopy, prlcopy, pclear, upcopy, kpcopy, pucopy, and pkcopy now ensure
55: / registers DS and ES refer to kernel data before calling ptov() or vrelse().
56: / MAXMEM variable added to specify maximum low memory in clicks.
57: /
58: / 87/11/22 Allan Cornish /usr/src/sys/i8086/ibm_at/as2.s
59: / Added check for extended memory in protected mode.
60: /
61: / 87/11/14 Allan Cornish /usr/src/sys/i8086/ibm_at/as2.s
62: / boot() now requests 8042 controller to initiate processor reset.
63: /
64: / 87/11/05 Allan Cornish /usr/src/sys/i8086/ibm_at/as2.s
65: / slrcopy/srlcopy/sclear renamed plrcopy/prlcopy/pclear and moved here.
66: /
67: / 87/10/27 Allan Cornish /usr/src/sys/i8086/ibm_at/as2.s
68: / System stack/data segments now setup here rather than in as1.s
69: / System stack/data moved to next 128 byte boundary for protected mode.
70: /
71: / 87/08/31 Allan Cornish /usr/src/sys/i8086/ibm_at/as2.s
72: / Timer channel 1 now reprogrammed for memory refresh.
73: /
74: / 87/07/08 Allan Cornish /usr/src/sys/i8086/ibm_at/as2.s
75: / Timer chip now programmed for 100 hz clock interrupt rather than 20 hz.
76: /
77: ////////
78:
79: EFAULT = 14 / Bad argument
80: EXTMEML = 0x17 / Ext. mem size (low) offset in CMOS
81: EXTMEMH = 0x18 / (high)
82: PFLAGS = 0x22 / Offset int PROC.
83: PFKERN = 0x80 / Kernel process flag bit.
84: PIC = 0x20 / 8259 CSR I/O port.
85: PICM = 0x21 / 8259 IMR I/O port.
86: PIT = 0x40 / 8253 base I/O port.
87: KBDATA = 0x60 / 8042 keyboard mpu data I/O port.
88: KBCTRL = 0x64 / 8042 keyboard mpu ctrl I/O port.
89: CMOSA = 0x70 / Real-time Clock/CMOS addr I/O port.
90: CMOSD = 0x71 / Real-time Clock/CMOS data I/O port.
91: SPIC = 0xA0 / Slave 8259 CSR I/O port.
92: SPICM = 0xA1 / Slave 8259 IMR I/O port.
93: UPASIZE = 1024 / Size of uproc and stack
94:
95: ////////
96: /
97: / System entry point. Under PC-DOS,
98: / which thinks that Coherent is just a large
99: / user program, the code is offset by 0x100
100: / to allow space for the base page.
101: /
102: ////////
103:
104: .blkb 0x0100 / PC-DOS base page. | MLK --\
105: call iabios_r_ / Before we go into protected mode, init the abios
106:
107: cli / No interrupts, please.
108: int 0x11 / Obtain int 11 value before printf().
109: mov cs:val11, ax /Use boot block's stack for last time.
110: /
111: / Enable the A20 address line, which is normally disabled by the ROM BIOS.
112: / This line is under the control of the 8042 keyboard interface controller.
113: /
114: sub cx, cx /
115: 0: inb al, KBCTRL / Wait for 8042 input buffer to empty.
116: testb al, $2 /
117: loopne 0b /
118: jmp .+2 / DELAY /
119: /
120: movb al, $0xD1 / Request next output byte to be
121: outb KBCTRL, al / sent to the 8042 output port.
122: /
123: sub cx, cx /
124: 0: inb al, KBCTRL / Wait for 8042 input buffer to empty.
125: testb al, $2 /
126: loopne 0b /
127: jmp .+2 / DELAY /
128: /
129: movb al, $0xDF / Enable A20 address line.
130: outb KBDATA, al / See Page 1-44, IBM-AT Tech Ref.
131: /
132: sub cx, cx /
133: 0: inb al, KBCTRL / Wait for 8042 input buffer to empty.
134: testb al, $2 / NOTE: A20 not enabled for up to 20 us.
135: loopne 0b /
136:
137: /
138: / Reprogram the 8253 timer so that channel 0,
139: / which is used as the clock, interrupts at exactly
140: / 100 HZ, instead of 18.2 HZ.
141: /
142: movb al, $0x36 / Timer 0, LSB, MSB, mode 3
143: outb PIT+3, al
144: jmp .+2 / DELAY /
145: jmp .+2 / DELAY /
146: movb al, $0x9C / Lsb of 59659/5 = 11932
147: outb PIT, al
148: jmp .+2 / DELAY /
149: jmp .+2 / DELAY /
150: movb al, $0x2E / Msb of 59659/5 = 11932
151: outb PIT, al
152: jmp .+2 / DELAY /
153: jmp .+2 / DELAY /
154:
155: / Reprogram channel 1 on the 8253 timer which is used for memory refresh.
156: / movb al, $0x54 / Timer 1, LSB, mode 2
157: / outb PIT+3, al
158: / jmp .+2 / DELAY /
159: / jmp .+2 / DELAY /
160: / movb al, $18 / LSB of 18.
161: / outb PIT+1, al
162: / jmp .+2 / DELAY /
163: / jmp .+2 / DELAY /
164:
165: / Reprogram the 1st programmable interrupt controller.
166: / It's default vector table collides with iAPX 286 protection vectors.
167:
168: / movb al, $0x11 / ICW1 - edge, master, ICW4
169: movb al, $0x19 / ICW1 - level, master, ICW4 MLK
170: outb PIC, al
171: jmp .+2 / DELAY /
172: jmp .+2 / DELAY /
173: movb al, $0x20 / ICW2 - Reserve 1st 32 vectors for 286
174: outb PICM, al
175: jmp .+2 / DELAY /
176: jmp .+2 / DELAY /
177: movb al, $0x04 / ICW3 - master level 2
178: outb PICM, al
179: jmp .+2 / DELAY /
180: jmp .+2 / DELAY /
181: movb al, $0x01 / ICW4 - 8086 mode, master.
182: outb PICM, al
183: jmp .+2 / DELAY /
184: jmp .+2 / DELAY /
185:
186: movb al, $0xFE / Disable interrupts from master PIC.
187: outb PICM, al / (except for clock interrupt).
188:
189: movb al, $0xFF
190: outb SPICM, al / Disable interrupts from slave PIC.
191:
192:
193: / Set up all trap vectors.
194: / The machine traps all have their own
195: / linkages. We have to steal the clock from
196: / the ROM, because the stacks might get switched
197: / during the INT 1C, and the EOI would get sent
198: / to the 8259 at a strange time.
199:
200: sub ax, ax / Map DS over the 8088
201: mov ds, ax / vector area.
202:
203: mov 0x0000, $trap0 / Divide error vector
204: mov 0x0002, cs
205: mov 0x0004, $trap1 / Single step.
206: mov 0x0006, cs
207: mov 0x0008, $trap2 / NMI
208: mov 0x000A, cs
209: mov 0x000C, $trap3 / INT 3 (break)
210: mov 0x000E, cs
211: mov 0x0010, $trap4 / Overflow.
212: mov 0x0012, cs
213: mov 0x0014, $trap5 / Bound range exceeded.
214: mov 0x0016, cs
215: mov 0x0018, $trap6 / Invalid Opcode
216: mov 0x001A, cs
217: mov 0x001C, $trap7 / Processor extension not available
218: mov 0x001E, cs
219: mov 0x0020, $trap8 / Double exception detected.
220: mov 0x0022, cs
221: mov 0x0024, $trap9 / Processor extension segment overrun.
222: mov 0x0026, cs
223: mov 0x0028, $trap10 / Invalid task state segment.
224: mov 0x002A, cs
225: mov 0x002C, $trap11 / Segment not present.
226: mov 0x002E, cs
227: mov 0x0030, $trap12 / Stack segment overrun or not present.
228: mov 0x0032, cs
229: mov 0x0034, $trap13 / General protection.
230: mov 0x0036, cs
231:
232: mov 0x0080, $clk_ps / Clock for PS2 MLK
233: / mov 0x0080, $clk / Clock.
234: mov 0x0082, cs
235: mov 0x0084, $dev1 / Device 1
236: mov 0x0086, cs
237: mov 0x0088, $dev9 / Device 2 maps into Device 9
238: mov 0x008A, cs
239: mov 0x008C, $dev3 / Device 3
240: mov 0x008E, cs
241: mov 0x0090, $dev4 / Device 4
242: mov 0x0092, cs
243: mov 0x0094, $dev5 / Device 5
244: mov 0x0096, cs
245: mov 0x0098, $dev6 / Device 6
246: mov 0x009A, cs
247: mov 0x009C, $dev7 / Device 7
248: mov 0x009E, cs
249:
250: mov 0x01C0, $dev8 / Device 8
251: mov 0x01C2, cs
252: mov 0x01C4, $dev9 / Device 9
253: mov 0x01C6, cs
254: mov 0x01C8, $dev10 / Device 10
255: mov 0x01CA, cs
256: mov 0x01CC, $dev11 / Device 11
257: mov 0x01CE, cs
258: mov 0x01D0, $dev12 / Device 12
259: mov 0x01D2, cs
260: mov 0x01D4, $dev13 / Device 13
261: mov 0x01D6, cs
262: mov 0x01D8, $dev14 / Device 14
263: mov 0x01DA, cs
264: mov 0x01DC, $dev15 / Device 15
265: mov 0x01DE, cs
266:
267: mov bx, $0x0200 / INT 80 (sys 0)
268: 0: mov (bx), $syc / Set up the system call
269: mov 2(bx), cs / trap vector.
270: add bx, $4 / Move to next vector and
271: cmp bx, $0x0400 / loop until all
272: jb 0b / vectors are reset.
273:
274: / Set up the system stack and data segments, by looking at the size of
275: / the text and adding this to the base address already in the CS.
276: / Relocate the stack and data to a 128 byte boundary.
277:
278: mov ax, $etext_+15 / End of text segment
279: shr ax, $4 / Convert to paragraphs.
280: mov cx, cs / Get code segment base.
281: add ax, cx /
282: mov ds, ax / Current data segment
283: add ax, $31 / Allow virtual-physical alignment
284: and ax, $~31 / [use 512 byte, need 128 byte]
285: /
286: cmp realmode_, $0 / Virtual Addressing enabled?
287: jne 0f /
288: mov idtsel_, ax / Interrupt descriptor table [2 Kbytes]
289: add ax, $0x0080 / 2K >> 4
290: mov gdtsel_, ax / Global descriptor table [64 Kbytes]
291: add ax, $0x1000 / 64K >> 4
292: 0: /
293: mov es, ax /
294: mov si, $edata_-1 / Copy data to new location, backwards.
295: mov di, $edata_-1 /
296: mov cx, $edata_ /
297: std /
298: rep /
299: movsb /
300: /
301: mov ds, ax / Update data segment,
302: mov ss, ax / and stack segment.
303: mov sp, $u_+UPASIZE-32 / Set up initial stack.
304: mov scs_, cs / Save code segment and
305: mov sds_, ds / data segment bases.
306: mov cs:cds, ds / For interrupts.
307:
308: / Size up memory, starting just above the system.
309: / The memory is cleared, because somebody has to do a write
310: / to set up the parity bits.
311:
312: mov di, $edata_ / Clear at edata...
313: mov cx, $512 / for 1 Kbyte
314: sub ax, ax
315: cld
316: rep
317: stosw
318:
319: mov bp, $edata_+1023 / Compute base.
320: shr bp, $4
321: add bp, sds_
322: shr bp, $6 / Round down to a Kbyte boundary
323: shl bp, $6 / so's we're in sync.
324:
325: 0: sub di, di / Destination.
326: mov es, bp / Set extra segment and
327: mov es:(di), ax / clear a word.
328: jmp .+2 / FLUSH /
329: cmp es:(di), ax / Should be zero now.
330: jne 0f / Branch if memory end
331:
332: mov cx, $512 / 1K bytes, in words.
333: cld
334: rep
335: stosw / Clear this 1K
336: add bp, $64 / Move along by 1K
337: cmp bp, MAXMEM
338: jb 0b / If not at video ram yet
339:
340: 0: mov es, sds_ / Map extra.
341:
342: mov ax, bp / Calculate top of low memory.
343: rol ax, $4 /
344: mov dx, ax /
345: and ax, $0xFFF0 /
346: xor dx, ax /
347:
348: cmp realmode_, $0 / Real Addressing Mode?
349: je 0f /
350: mov coretop_, ax / Yes, Record top of memory,
351: mov coretop_+2, dx /
352: jmp start / and bring up system.
353: 0:
354: mov holebot_, ax / Record bottom of I/O memory.
355: mov holebot_+2, dx /
356:
357: mov ax, gdtsel_ / Format global descriptor table map.
358: rol ax, $4 /
359: mov dx, ax /
360: and ax, $0xFFF0 /
361: xor dx, ax /
362: mov gdtmap_+0, $0xFFFF / Limit: 64K bytes.
363: mov gdtmap_+2, ax /
364: mov gdtmap_+4, dx /
365: /
366: sub ax, ax / Erase global descriptor table.
367: mov cx, $0x8000 / [32K words = 64K bytes]
368: mov es, gdtsel_ /
369: sub di, di /
370: cld /
371: rep /
372: stosw /
373: /
374: mov ax, idtsel_ / Format interrupt descriptor table map
375: rol ax, $4 /
376: mov dx, ax /
377: and ax, $0xFFF0 /
378: xor dx, ax /
379: mov idtmap_+0, $2047 / Limit: 2K bytes.
380: mov idtmap_+2, ax /
381: mov idtmap_+4, dx /
382: /
383: sub ax, ax / Erase interrupt descriptor table.
384: mov cx, $1024 / [1K words = 2K bytes]
385: mov es, idtsel_ /
386: sub di, di /
387: cld /
388: rep /
389: stosw /
390: /
391: mov es, gdtsel_ /
392: mov di, cs / Define kernel code global selector.
393: mov ax, $etext_-1 / Limit: etext.
394: stosw /
395: mov dx, $0x9A00 / Flags: Present, executable.
396: mov ax, cs / Base: cs << 4.
397: rol ax, $4 /
398: xor dx, ax /
399: and ax, $0xFFF0 /
400: stosw /
401: xor ax, dx /
402: stosw /
403: sub ax, ax /
404: stosw /
405: /
406: mov di, ss / Define kernel data global selector.
407: mov ax, $0xFFFF / Limit: 64K bytes.
408: stosw /
409: mov dx, $0x9200 / Flags: Present, writable.
410: mov ax, ss / Base: ss << 4.
411: rol ax, $4 /
412: xor dx, ax /
413: and ax, $0xFFF0 /
414: stosw /
415: xor ax, dx /
416: stosw /
417: sub ax, ax /
418: stosw /
419: /
420: mov di, $8 / Define task state segment selector[8]
421: mov ax, $43 / Limit: 44 bytes.
422: stosw /
423: mov dx, $0x8100 / Flags: Present, avail tss seg.
424: mov ax, ss / Base: (ss << 4) + &tss.
425: rol ax, $4 /
426: xor dx, ax /
427: and ax, $0xFFF0 /
428: xor dx, ax /
429: add ax, $tss_ /
430: adc dx, $0 /
431: stosw /
432: mov ax, dx /
433: stosw /
434: sub ax, ax /
435: stosw /
436: /
437: mov di, gdtsel_ / Define gdt access global selector.
438: mov ax, $0xFFFF / Limit: 64K bytes.
439: stosw /
440: mov dx, $0x9200 / Flags: Present, writable.
441: mov ax, gdtsel_ / Base: gdtsel << 4.
442: rol ax, $4 /
443: xor dx, ax /
444: and ax, $0xFFF0 /
445: stosw /
446: xor ax, dx /
447: stosw /
448: sub ax, ax /
449: stosw /
450: /
451: mov di, idtsel_ / Define idt access global selector.
452: mov ax, $2047 / Limit: 2K bytes.
453: stosw /
454: mov dx, $0x9200 / Flags: Present, writable.
455: mov ax, idtsel_ / Base: idtsel << 4.
456: rol ax, $4 /
457: xor dx, ax /
458: and ax, $0xFFF0 /
459: stosw /
460: xor ax, dx /
461: stosw /
462: sub ax, ax /
463: stosw /
464: /
465: mov di, $0xB000 / Define video access global selector.
466: mov ax, $0xFFFF / Limit: 64K bytes.
467: stosw /
468: mov dx, $0x9200 / Flags: Present, writable.
469: mov ax, $0xB000 / Base: 0xB000 << 4.
470: rol ax, $4 /
471: xor dx, ax /
472: and ax, $0xFFF0 /
473: stosw /
474: xor ax, dx /
475: stosw /
476: sub ax, ax /
477: stosw /
478: /
479: mov di, $0xB800 / Define video access global selector.
480: mov ax, $0x7FFF / Limit: 32 Kbytes.
481: stosw /
482: mov dx, $0x9200 / Flags: Present, writable.
483: mov ax, $0xB800 / Base: 0xB800 << 4.
484: rol ax, $4 /
485: xor dx, ax /
486: and ax, $0xFFF0 /
487: stosw /
488: xor ax, dx /
489: stosw /
490: sub ax, ax /
491: stosw /
492:
493: mov di, $0xF000 / Define ROM access global selector.
494: mov ax, $0xFFFF / Limit: 64 Kbytes.
495: stosw /
496: mov dx, $0x9000 / Flags: Present, read only.
497: mov ax, $0xF000 / Base: 0xF000 << 4.
498: rol ax, $4 /
499: xor dx, ax /
500: and ax, $0xFFF0 /
501: stosw /
502: xor ax, dx /
503: stosw /
504: sub ax, ax /
505: stosw /
506:
507: mov es, idtsel_ / Map ES over the intr descr table.
508: sub ax, ax / Map DS over the 8088 vector area.
509: mov ds, ax /
510: sub si, si /
511: sub di, di /
512: mov bx, cs / Make CS available for comparison.
513: mov cx, $256 / Install 256 interrupt descriptors.
514: /
515: 0: lodsw / Copy interrupt IP
516: stosw /
517: lodsw / Copy interrupt CS
518: stosw /
519: /
520: cmp ax, bx / Coherent interrupt handler?
521: mov ax, $0x8600 /
522: je 1f /
523: sub ax, ax / No, clear flags.
524: /
525: 1: stosw / Define IDT flags.
526: sub ax, ax / Reserved IDT word.
527: stosw /
528: loop 0b / Repeat for all 256 entries.
529: /
530: mov ax, ss / Restore data and extra segments.
531: mov ds, ax /
532: mov es, ax /
533: /
534: clts / Clear task switched flag.
535: lgdt gdtmap_ / Load global descriptor table map.
536: lidt idtmap_ / Load interrupt descriptor table map.
537: /
538: smsw ax / Enter protected mode.
539: or ax, $1 /
540: lmsw ax /
541: jmp .+2 / Clear pipeline.
542: /
543: mov ax, $0x0008 / Load task state segment register.
544: ltr ax /
545: sub ax, ax / Load local descriptor table register.
546: lldt ax /
547: /
548: /
549: / Register usage:
550: / DX:AX = extended mem physical addr.
551: / BX = scratch, then 0.
552: / SI = selector into extended memory.
553: / ES = selector into extended memory.
554: / DS = selector into global descr table
555: /
556: push $EXTMEMH / high byte of pair
557: call read_cmos_ / result in ax
558: add sp, $2 / pop argument
559: movb bl, al / save al to bl
560: push $EXTMEML / low byte of pair
561: call read_cmos_ / result in ax
562: add sp, $2 / pop argument
563: movb ah, bl / restore high byte to ah
564: shr ax, $6 / K -> 64K conversion
565: add ax, $0x0010 / bias up to 1MB
566: mov CMOSmax_, ax / save count of 64K hunks
567: sub ax, ax /
568: mov dx, $0x0010 / Initial 64 Kbyte bank of extended mem.
569: mov holetop_, ax / Recorded extended memory bot in bytes.
570: mov holetop_+2, dx /
571: /
572: mov ds, gdtsel_ / Map DS onto global descr table.
573: mov si, $0xFFF8 / Define scratch access global selector.
574: mov 0(si), $0xFFFF / Limit: 64K bytes.
575: mov 2(si), $0x0000 / Base: 1 Mbyte.
576: mov 4(si), $0x9210 / Flags: Present, writable.
577: mov 6(si), $0x0000 /
578: /
579: sub bx, bx /
580: 0: sub di, di / Destination.
581: mov cx, $0x8000 / 64K bytes, in words.
582: mov 2(si), ax / Adjust gdt to desired DX:AX mem locn.
583: movb 4(si), dl /
584: mov es, si / Map ES onto 64K bank of extended mem.
585: mov es:(di), bx / Write word of extended memory.
586: jmp .+2 / FLUSH /
587: cmp es:(di), bx / Verify word was correctly written.
588: jne 0f / Branch if memory end.
589: /
590: cld /
591: rep /
592: stosw / Clear this 64K of extended memory.
593: /
594: inc dx / Step to next 64K bank.
595: cmp dx, ss:CMOSmax_ / See if we're beyond what the CMOS
596: jge 0f / says we have.
597: cmp dx, $0x00F0 / Stop at 15 Mbyte boundary; the last
598: jl 0b / Mbyte is a dup of the 1st Mbyte.
599: /
600: 0: movb 5(si), $0 / Free the scratch selector.
601: /
602: mov bx, ss / Restore data and extra segments.
603: mov ds, bx / NOTE: Do not modify DX:AX.
604: mov es, bx /
605: /
606: mov coretop_, ax / Recorded top of extended core memory.
607: mov coretop_+2, dx /
608: jmp start / Bring up system.
609:
610: ////////
611: /
612: / Trap an interrupt linkage.
613: / Each of the machine traps has a special little
614: / linkage, that sets up the type code and sends
615: / control off to the common trap processor. Device
616: / interrupts, other than the clock (IR0), are
617: / done here.
618: /
619: ////////
620:
621: trap0:
622: call tsave
623: mov 16(bx), $0x0000 / Divide error.
624: jmp trap_
625:
626: trap1:
627: call tsave
628: mov 16(bx), $0x0100 / Single step.
629: jmp trap_
630:
631: trap2:
632: call tsave
633: mov 16(bx), $0x0200 / Non-maskable interrupt.
634: jmp trap_
635:
636: trap3:
637: call tsave
638: mov 16(bx), $0x0300 / INT 3 (breakpoint).
639: jmp trap_
640:
641: trap4:
642: call tsave
643: mov 16(bx), $0x0400 / Overflow.
644: jmp trap_
645:
646: trap5:
647: call tsave
648: mov 16(bx), $0x0500 / Bound check.
649: jmp trap_
650:
651: trap6:
652: call tsave
653: mov 16(bx), $0x0600 / Invalid opcode.
654: jmp trap_
655:
656: trap7:
657: call tsave
658: mov 16(bx), $0x0700 / Processor Extension not available.
659: jmp trap_
660:
661: trap8:
662: pop ax / Get error code from stack [always 0]
663: call tsave
664: mov 16(bx), $0x0800 / Double Exception detected
665: jmp trap_
666:
667: trap9:
668: call tsave
669: mov 16(bx), $0x0900 / Processor extension segment overrun
670: jmp trap_
671:
672: trap10:
673: pop ax / Get error code from stack
674: call tsave
675: mov 16(bx), $0x0A00 / Invalid task state segment
676: jmp trap_
677:
678: trap11:
679: pop ax / Get error code from stack
680: call tsave
681: mov 16(bx), $0x0B00 / Segment not present
682: jmp trap_
683:
684: trap12:
685: pop ax / Get error code from stack
686: call tsave
687: mov 16(bx), $0x0C00 / Stack segment overrun or not present
688: jmp trap_
689:
690: trap13:
691: pop ax / Get error code from stack
692: call tsave
693: mov 16(bx), $0x0D00 / General protection
694: jmp trap_
695:
696: .globl syc
697:
698: syc:
699: call tsave
700: mov 16(bx), $0x2000 / System calls.
701: jmp trap_
702:
703: ran:
704: call tsave
705: mov 16(bx), $0x2100 / Random trap.
706: jmp trap_
707:
708: dev1:
709: call tsave
710: mov 16(bx), $0x4001 / Device 1: keyboard
711: ijmp vecs_+[2*1]
712:
713: /dev2: call tsave / Device 2: mapped into device 9
714: / mov 16(bx), $0x4002
715: / ijmp vecs_+[2*2]
716:
717: dev3:
718: call tsave
719: mov 16(bx), $0x4003 / Device 3: al1
720: ijmp vecs_+[2*3]
721:
722: dev4:
723: call tsave
724: mov 16(bx), $0x4004 / Device 4: al0
725: ijmp vecs_+[2*4]
726:
727: dev5:
728: call tsave
729: mov 16(bx), $0x4005 / Device 5: hard disk
730: ijmp vecs_+[2*5]
731:
732: dev6:
733: call tsave
734: mov 16(bx), $0x4006 / Device 6: floppy
735: ijmp vecs_+[2*6]
736:
737: dev7:
738: call tsave
739: mov 16(bx), $0x4007 / Device 7: lp
740: ijmp vecs_+[2*7]
741:
742: dev8:
743: call tsave
744: mov 16(bx), $0x4008 / Device 8:
745: ijmp vecs_+[2*8]
746:
747: dev9:
748: call tsave
749: mov 16(bx), $0x4009 / Device 9:
750: ijmp vecs_+[2*9]
751:
752: dev10:
753: call tsave
754: mov 16(bx), $0x400A / Device 10:
755: ijmp vecs_+[2*10]
756:
757: dev11:
758: call tsave
759: mov 16(bx), $0x400B / Device 11:
760: ijmp vecs_+[2*11]
761:
762: dev12:
763: call tsave
764: mov 16(bx), $0x400C / Device 12:
765: ijmp vecs_+[2*12]
766:
767: dev13:
768: call tsave
769: mov 16(bx), $0x400D / Device 13:
770: ijmp vecs_+[2*13]
771:
772: dev14:
773: call tsave
774: mov 16(bx), $0x400E / Device 14:
775: ijmp vecs_+[2*14]
776:
777: dev15:
778: call tsave
779: mov 16(bx), $0x400F / Device 15:
780: ijmp vecs_+[2*15]
781:
782: ////////
783: /
784: / Clock interrupt.
785: / The clock interrupt is stolen from the ROM;
786: / if you don't do this the EOI sequence for the 8259
787: / may get mangled on context switches.
788: /
789: ////////
790:
791: clk_ps: / MLK
792: push ax
793: inb al, 0x61 / PS/2 8259 needs to be told to
794: jmp .+2 / stop interrupting the CPU, or
795: jmp .+2
796: orb al,$0x80 / we will hang.
797: outb 0x61,al
798: pop ax / MLK
799:
800: clk:
801: call tsave / Perform trap save.
802: mov 16(bx), $0x4000
803:
804: sub ax, ax / Assume system mode, push user flag
805: push ax
806: push 18(bx) / IP at tick time
807:
808: cmpb depth_, $0 / Correct ?
809: jne 0f / If ne, yes.
810: mov bx, cprocp_ / User depth, check if the
811: test PFLAGS(bx), $PFKERN / current process is a kernel process.
812: jne 0f / If ne, yes.
813: mov bx, sp / Load stack index
814: inc 2(bx) / and set user mode.
815:
816: 0: call clock_ / Call common clock and
817: add sp, $4 / pop arguments.
818:
819: ret / Back to "tsave".
820:
821: ////////
822: /
823: / This routine is called by "tsave" to dismiss an interrupt.
824: / The interrupt code is in "ax".
825: /
826: ////////
827:
828: .globl eoi
829:
830: eoi:
831: cmpb al, $8 / Is this on the slave PIC?
832: jb 0f / Jump if not.
833: movb al, $0x20 / Send a non specific EOI
834: outb SPIC, al / to the slave PIC.
835: 0: movb al, $0x20 / Send a non specific EOI
836: outb PIC, al / to the master PIC.
837: ret / Done.
838:
839: ////////
840: /
841: / Block I/O to ports.
842: / Mainly used to read and write the silo memories in the discs.
843: / Delibrately only transfers 1 byte per loop to avoid
844: / timing problems on AT I/O chips.
845: /
846: / void outcopy(port, off, seg, n);
847: / int port; /* Port address */
848: / char *off; /* Offset in segment */
849: / unsigned seg; /* Segment register base */
850: / int n; /* Byte count */
851: /
852: / void incopy(port, off, seg, n);
853: / int port; /* Device */
854: / char *off; /* Offset */
855: / unsigned seg; /* Segment register base */
856: / int n; /* Byte count */
857: /
858: ////////
859:
860: .globl incopy_
861: .globl outcopy_
862:
863: incopy_:
864: push di
865: push es
866: push bp
867: mov bp, sp
868: mov dx, 8(bp) /device port
869: les di, 10(bp) /seg,off pair
870: mov cx, 14(bp) /n bytes
871: jcxz 1f
872:
873: cld /auto-increment
874: 0: inb al, dx
875: stosb
876: loop 0b
877:
878: 1: pop bp
879: pop es /restore regs
880: pop di
881: ret
882:
883: outcopy_:
884: push si
885: push ds
886: push bp
887: mov bp, sp
888: mov dx, 8(bp) /device port
889: lds si, 10(bp) /offset
890: mov cx, 14(bp) /count
891: jcxz 1f
892:
893: cld /auto-increment
894: 0: lodsb
895: outb dx, al
896: loop 0b
897:
898: 1: pop bp
899: pop ds
900: pop si
901: ret
902:
903: ////////
904: /
905: / Copy "n" bytes of memory from base "p1" to base "p2".
906: / The copy must be done from left to right.
907: /
908: / plrcopy(p1, p2, n)
909: / paddr_t p1, p2;
910: / size_t n;
911: /
912: ////////
913:
914: .globl plrcopy_
915:
916: plrcopy_:
917: push si / Save sequence
918: push di
919: push bp
920: mov bp, sp
921:
922: push ds / Save ds
923: push es / Save es
924:
925: push 18(bp) / Map SI:DI at destination ptov(p2,n).
926: push 16(bp)
927: push 14(bp)
928: push 12(bp)
929: call ptov_
930: add sp, $8
931: mov si, dx
932: mov di, ax
933:
934: push 18(bp) / Map DX:AX at source ptov(p1,n);
935: push 16(bp)
936: push 10(bp)
937: push 8(bp)
938: call ptov_
939: add sp, $8
940:
941: mov es, si / Map ES:DI at destination.
942: mov ds, dx / Map DS:SI at source.
943: mov si, ax
944:
945: mov cx, 16(bp) / Transfer count in bytes.
946: cld / Auto Increment.
947: clc /
948: rcr cx, $1 / Word count
949: rep /
950: movsw / Move words
951: rcl cx, $1 /
952: rep /
953: movsb / Move odd byte
954:
955: mov si, es / Remember mapped selectors.
956: mov di, ds /
957: pop es / Restore es
958: pop ds / Restore ds
959:
960: push si / Release mapped selectors.
961: push ax / NOTE: Offset is ignored.
962: call vrelse_ /
963: add sp, $4 /
964: /
965: push di /
966: push ax /
967: call vrelse_ /
968: add sp, $4 /
969:
970: pop bp / Standard return
971: pop di
972: pop si
973: ret / Return
974:
975: ////////
976: /
977: / Copy "n" bytes of memory from base "p1" to base "p2".
978: / The copy must be done from right to left.
979: /
980: / prlcopy(p1, p2, n)
981: / paddr_t p1, p2;
982: / size_t n;
983: /
984: ////////
985:
986: .globl prlcopy_
987:
988: prlcopy_:
989: push si / Save sequence
990: push di
991: push bp
992: mov bp, sp
993:
994: push ds / Save ds
995: push es / Save es
996:
997: push 18(bp) / Map SI:DI at destination ptov(p2,n).
998: push 16(bp)
999: push 14(bp)
1000: push 12(bp)
1001: call ptov_
1002: add sp, $8
1003: mov si, dx
1004: mov di, ax
1005:
1006: push 18(bp) / Map DX:AX at source ptov(p1,n);
1007: push 16(bp)
1008: push 10(bp)
1009: push 8(bp)
1010: call ptov_
1011: add sp, $8
1012:
1013: mov es, si / Map ES:DI at destination.
1014: mov ds, dx / Map DS:SI at source.
1015: mov si, ax
1016:
1017: mov cx, 16(bp) / Transfer count in bytes
1018: add si, cx / Point DS:SI at the end
1019: dec si / of the source.
1020: add di, cx / Point ES:DI at the end
1021: dec di / of the destination.
1022:
1023: std / Auto decrement
1024: clc /
1025: rcr cx, $1 / Word Count
1026: rep /
1027: movsw / Move words
1028: rcl cx, $1 /
1029: rep /
1030: movsb / Move odd byte
1031: cld / Auto increment
1032:
1033: mov si, es / Remember mapped selectors.
1034: mov di, ds /
1035: pop es / Restore es
1036: pop ds / Restore ds
1037:
1038: push si / Release mapped selectors.
1039: push ax / NOTE: Offset is ignored.
1040: call vrelse_ /
1041: add sp, $4 /
1042: /
1043: push di /
1044: push ax /
1045: call vrelse_ /
1046: add sp, $4 /
1047: /
1048: mov ax, 16(bp) / Return transfer count.
1049: pop bp / Standard return
1050: pop di
1051: pop si
1052: ret
1053:
1054: ////////
1055: /
1056: / Clear "n" bytes of memory starting at physical address "p".
1057: /
1058: / pclear( p, n )
1059: / paddr_t p;
1060: / size_t n;
1061: /
1062: /
1063: / Notes: At most 64K bytes of memory can be cleared.
1064: /
1065: ////////
1066:
1067: .globl pclear_
1068:
1069: pclear_:
1070: push si / Standard save
1071: push di
1072: push bp
1073: mov bp, sp
1074:
1075: push es / Save es
1076:
1077: push 14(bp) / Map ES:DI at ptov(p2,n).
1078: push 12(bp)
1079: push 10(bp)
1080: push 8(bp)
1081: call ptov_
1082: add sp, $8
1083: mov es, dx
1084: mov di, ax
1085:
1086: shr 14(bp), $1 / Convert count from bytes to words.
1087: rcr 12(bp), $1
1088: mov cx, 12(bp) / Count in words.
1089:
1090: sub ax, ax / Get a 0.
1091: cld / Zero the block.
1092: rep
1093: stosw
1094:
1095: mov ax, es / Remember mapped selector.
1096: pop es / Restore es.
1097:
1098: push ax / Release mapped selector.
1099: push ax / NOTE: Offset is ignored.
1100: call vrelse_ /
1101: add sp, $4 /
1102:
1103: pop bp / Standard return.
1104: pop di
1105: pop si
1106: ret
1107:
1108: ////////
1109: /
1110: / Block copy chunks of memory to a physical
1111: / location from a location in either the system
1112: / or user data space.
1113: /
1114: / upcopy(u, p, n)
1115: / char *u;
1116: / paddr_t p;
1117: / int n;
1118: /
1119: / kpcopy(k, p, n);
1120: / char *k;
1121: / paddr_t p;
1122: / int n;
1123: /
1124: ////////
1125:
1126: .globl upcopy_
1127:
1128: upcopy_:
1129: mov bx, sp / Get set for stack index.
1130: mov ax, 2(bx) / User address
1131: dec ax / Don't wrap too soon
1132: add ax, 8(bx) / Count
1133: jc kuerr / Out of bounds
1134: cmp ax, udl_ / In range?
1135: ja kuerr / No
1136: push uds_ / Mark transfer ds as being user ds.
1137: jmp 1f / Finish in common code.
1138:
1139: .globl kpcopy_
1140:
1141: kpcopy_:
1142: push ds / Mark transfer ds as being kernel ds.
1143:
1144: 1: push si / Standard save
1145: push di
1146: push bp
1147: mov bp, sp
1148:
1149: push ds / Save ds, es
1150: push es
1151:
1152: sub ax, ax / ES:DI = ptov(p,n).
1153: push ax /
1154: push 16(bp) /
1155: push 14(bp) /
1156: push 12(bp) /
1157: call ptov_ /
1158: add sp, $8 /
1159: mov es, dx /
1160: mov di, ax /
1161: /
1162: mov ds, 6(bp) / DS:SI = source address.
1163: mov si, 10(bp) /
1164: mov cx, 16(bp) / Byte count
1165: /
1166: cld / Auto Increment
1167: clc /
1168: rcr cx, $1 / Word count
1169: rep /
1170: movsw / Move words
1171: rcl cx, $1 / Move odd byte
1172: rep /
1173: movsb /
1174: /
1175: mov ax, es / Remember mapped selector.
1176: pop es / Restore es, ds.
1177: pop ds /
1178: /
1179: push ax / Release mapped selector.
1180: push ax / NOTE: Offset is ignored.
1181: call vrelse_ /
1182: add sp, $4 /
1183: /
1184: mov ax, 16(bp) / Return transfer count.
1185: /
1186: pop bp / Standard return.
1187: pop di
1188: pop si
1189: add sp, $2 / Discard marked transfer ds.
1190: ret
1191:
1192: ////////
1193: /
1194: / Block copy memory from physical address "p"
1195: / to either user or system data space.
1196: /
1197: / pucopy(p, u, n)
1198: / paddr_t p;
1199: / char *u;
1200: / int n;
1201: /
1202: / pkcopy(p, k, n);
1203: / paddr_t p;
1204: / char *k;
1205: / int n;
1206: /
1207: ////////
1208:
1209: .globl pucopy_
1210:
1211: pucopy_:
1212: mov bx, sp / Stack index
1213: mov ax, 6(bx) / User address
1214: dec ax / Don't wrap too soon
1215: add ax, 8(bx) / Count
1216: jc kuerr / Out of bounds
1217: cmp ax, udl_ / In range?
1218: ja kuerr / No
1219: push uds_ / Mark transfer es as being user ds.
1220: jmp 1f / Common code
1221:
1222: .globl pkcopy_
1223:
1224: pkcopy_:
1225: push ds / Mark transfer es as being kernel ds.
1226:
1227: 1: push si / Standard save
1228: push di
1229: push bp
1230: mov bp, sp
1231:
1232: push ds / Save ds, es.
1233: push es
1234:
1235: sub ax, ax / DS:SI = ptov(p,n).
1236: push ax
1237: push 16(bp)
1238: push 12(bp)
1239: push 10(bp)
1240: call ptov_
1241: add sp, $8
1242: mov ds, dx
1243: mov si, ax
1244:
1245: mov es, 6(bp) / ES:DI = destination.
1246: mov di, 14(bp) /
1247: mov cx, 16(bp) / Count
1248:
1249: cld / Incremental move
1250: clc /
1251: rcr cx, $1 / Word count
1252: rep /
1253: movsw / Move words.
1254: rcl cx, $1 / Move odd byte.
1255: rep /
1256: movsb /
1257: /
1258: mov ax, ds / Rememember mapped selector.
1259: pop es / Restore es, ds.
1260: pop ds /
1261: /
1262: push ax / Release mapped selector.
1263: push ax / NOTE: Offset is ignored.
1264: call vrelse_ /
1265: add sp, $4 /
1266: /
1267: mov ax, 16(bp) / Return transfer count.
1268: /
1269: pop bp / Restore registers.
1270: pop di /
1271: pop si /
1272: add sp, $2 / Discard marked transfer es.
1273: ret / Fin
1274:
1275: ////////
1276: /
1277: / All of the above copy routines jump to
1278: / "kuerr", with the stack untouched, if they detect
1279: / a bounds error on a user address.
1280: /
1281: ////////
1282:
1283: kuerr:
1284: mov bx,$u_ / Pointer to user area
1285: movb (bx),$EFAULT / Bad parameter error
1286: sub ax,ax / Didn't copy anything
1287: ret / Return
1288:
1289: ////////
1290: / Read a byte from the CMOS. Takes one argument--the
1291: / CMOS address to read from as an int; returns the
1292: / value read in ax.
1293: /
1294: / int read_cmos(addr)
1295: / int addr;
1296: /
1297: ////////
1298: .globl read_cmos_
1299: read_cmos_:
1300: push bp
1301: mov bp, sp
1302: movb al, 4(bp) / Fetch address from stack.
1303: outb CMOSA, al / Send address to CMOS.
1304: jmp .+2 / DELAY
1305: sub ax, ax / Zero out everything we don't want.
1306: inb al, CMOSD / Get Value from CMOS into al.
1307: pop bp
1308: ret / Return from read_cmos().
1309:
1310:
1311: / Read timer channel 0 into int value.
1312: / Clock counts down from 11932 to 0 with each clock tick.
1313: .globl read_t0_
1314: read_t0_:
1315: pushf
1316: cli
1317: xor ax,ax / Counter latch timer 0 and clear return val
1318: outb PIT+3,al
1319: jmp .+2 / DELAY /
1320: jmp .+2 / DELAY /
1321: inb al,PIT / low byte of counter latch
1322: movb ah,al
1323: jmp .+2 / DELAY /
1324: jmp .+2 / DELAY /
1325: inb al,PIT / high byte of counter latch
1326: xchgb al,ah
1327: jmp .+2 / DELAY /
1328: jmp .+2 / DELAY /
1329: popf
1330: ret
1331:
1332: / return current contents of psw
1333: .globl read_psw_
1334: read_psw_:
1335: pushf
1336: pop ax
1337: ret
1338:
1339: ////////
1340: /
1341: / Read the equipment description. Use
1342: / the "int 11" interface, so that the IBM
1343: / ROM will do all the details.
1344: /
1345: ////////
1346:
1347: .globl int11_
1348:
1349: int11_: mov ax, cs:val11 / Ask the ROM
1350: ret / to put stuff in AX
1351:
1352: ////////
1353: /
1354: / Bootstrap.
1355: / Called by the keyboard driver on control-alt-del.
1356: / Requests the 8042 controller to initiate a processor reset,
1357: / which is the only way to terminate protected mode operation.
1358: /
1359: / Reference: IBM-AT Technical Reference Manual,
1360: / Real-time Clock/CMOS RAM [Page 1-45]
1361: / Keyboard controller [Page 1-40]
1362: / Test 3, Page 5-68.
1363: /
1364: ////////
1365:
1366: .globl boot_
1367: boot_:
1368: cli / Disable interrupts.
1369: /
1370: sub cx, cx /
1371: 0: inb al, KBCTRL / Wait for 8042 input buffer to empty.
1372: testb al, $2 /
1373: loopne 0b /
1374: jmp .+2 / DELAY /
1375: /
1376: movb al, $0xFE / Issue a shutdown command
1377: outb KBCTRL, al / to the 8042 control port.
1378: /
1379: 0: hlt / Halt until processor reset occurs.
1380: jmp 0b
1381:
1382: ////////
1383: /
1384: / Data.
1385: /
1386: ////////
1387:
1388: .globl MAXMEM
1389: .globl vecs_
1390: .globl realmode_
1391: .globl gdtsel_, gdtmap_
1392: .globl idtsel_, idtmap_
1393: .globl CMOSmax_
1394:
1395: .shri
1396: val11: .word 0 / Value obtained from int11 [in code].
1397:
1398: .prvd
1399: MAXMEM: .word 0xA000 / In paragraphs, must be mult. of 64
1400: CMOSmax_:.word 0x0000 / Max extended memory according ...
1401: / ... to CMOS bytes 0x17 and 0x18 ...
1402: / ... in 64K chunks.
1403: realmode_:.word 0 / Virtual Addressing Mode Enabled
1404: gdtmap_:.blkw 3 / Global descriptor table definition
1405: idtmap_:.blkw 3 / Interrupt descriptor table definition
1406: gdtsel_:.word 0 / Global descriptor table selector
1407: idtsel_:.word 0 / Interrupt descriptor table selector
1408: vecs_: .word vret_ / Interrupt vector table
1409: .word vret_
1410: .word vret_
1411: .word vret_
1412: .word vret_
1413: .word vret_
1414: .word vret_
1415: .word vret_
1416: .word vret_
1417: .word vret_
1418: .word vret_
1419: .word vret_
1420: .word vret_
1421: .word vret_
1422: .word vret_
1423: .word vret_
1424:
1425: ////////
1426: /
1427: / Task State Segment - Coherent runs as a single protected mode task.
1428: /
1429: ////////
1430: .globl tss_
1431:
1432: .prvd
1433: tss_: / Task State Segment.
1434: tss_lnk:.word 0 / 0: Back link selector to TSS.
1435: tss_sp0:.word 0 / 2: SP for CPL 0.
1436: tss_ss0:.word 0 / 4: SS for CPL 0.
1437: tss_sp1:.word 0 / 6: SP for CPL 1.
1438: tss_ss1:.word 0 / 8: SS for CPL 1.
1439: tss_sp2:.word 0 / 10: SP for CPL 2.
1440: tss_ss2:.word 0 / 12: SS for CPL 2.
1441: tss_ip: .word 0 / 14: IP (Entry point).
1442: tss_psw:.word 0 / 16: Flag word.
1443: tss_ax: .word 0 / 18: Register AX.
1444: tss_cx: .word 0 / 20: Register CX.
1445: tss_dx: .word 0 / 22: Register DX.
1446: tss_bx: .word 0 / 24: Register BX.
1447: tss_bp: .word 0 / 26: Register BP.
1448: tss_sp: .word 0 / 28: Register SP.
1449: tss_si: .word 0 / 30: Register SI.
1450: tss_di: .word 0 / 32: Register DI.
1451: tss_es: .word 0 / 34: Register ES.
1452: tss_cs: .word 0 / 36: Register CS.
1453: tss_ss: .word 0 / 38: Register SS.
1454: tss_ds: .word 0 / 40: Register DS.
1455: tss_ldt:.word 0 / 42: Task LDT Selector.
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.