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