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