|
|
coherent
/ $Header: /var/lib/cvsd/repos/coherent/coherent/d/kernel/USRSRC/i8086/ibm_at/as2.s,v 1.1.1.1 2019/05/29 04:56:39 root Exp $ / / (lgl- / The information contained herein is a trade secret of Mark Williams / Company, and is confidential information. It is provided under a / license agreement, and may be copied or disclosed only under the / terms of that agreement. Any reproduction or disclosure of this / material without the express written authorization of Mark Williams / Company or persuant to the license agreement is unlawful. / / COHERENT Version 2.3.37 / Copyright (c) 1982, 1983, 1984. / An unpublished work by Mark Williams Company, Chicago. / All rights reserved. / -lgl) //////// / / Machine language assist for / Coherent on the IBM personal computer. / / $Log: as2.s,v $ / Revision 1.1.1.1 2019/05/29 04:56:39 root / coherent / / Revision 1.2 91/06/06 18:14:46 norm / Get memory size by reading CMOS. / Revision 1.3 88/08/05 15:37:32 src / AMD 286 hardware specific fixes removed - hardware now correct. / Virtual Selector F000 initialized to access ROM at F0000. / Normal kernel stack now used during initialization. / / Revision 1.2 88/06/29 19:05:31 src / AT Coherent can now come up in real-mode by patching 'realmode' variable. / / Revision 1.1 88/03/24 17:33:18 src / Initial revision / / 88/03/10 Allan Cornish /usr/src/sys/i8086/ibm_at/as2.s / Numerous temporary fixes due to AMD 286 chip being buggy in protected mode. / These partial fixes will be removed once all CPU's are replaced. / / 88/03/07 Allan Cornish /usr/src/sys/i8086/ibm_at/as2.s / Obsolete video() function deleted - not used, or usable in protected mode. / Auto-increment mode no longer assumed, but enforced on block moves. / / 88/03/04 Allan Cornish /usr/src/sys/i8086/ibm_at/as2.s / Memory sizing now flushes instruction pipeline before read-verify. / Otherwise bus capacitance on some machines gives invalid memory indication. / plrcopy, prlcopy, pclear, upcopy, kpcopy, pucopy, and pkcopy now ensure / registers DS and ES refer to kernel data before calling ptov() or vrelse(). / MAXMEM variable added to specify maximum low memory in clicks. / / 87/11/22 Allan Cornish /usr/src/sys/i8086/ibm_at/as2.s / Added check for extended memory in protected mode. / / 87/11/14 Allan Cornish /usr/src/sys/i8086/ibm_at/as2.s / boot() now requests 8042 controller to initiate processor reset. / / 87/11/05 Allan Cornish /usr/src/sys/i8086/ibm_at/as2.s / slrcopy/srlcopy/sclear renamed plrcopy/prlcopy/pclear and moved here. / / 87/10/27 Allan Cornish /usr/src/sys/i8086/ibm_at/as2.s / System stack/data segments now setup here rather than in as1.s / System stack/data moved to next 128 byte boundary for protected mode. / / 87/08/31 Allan Cornish /usr/src/sys/i8086/ibm_at/as2.s / Timer channel 1 now reprogrammed for memory refresh. / / 87/07/08 Allan Cornish /usr/src/sys/i8086/ibm_at/as2.s / Timer chip now programmed for 100 hz clock interrupt rather than 20 hz. / //////// EFAULT = 14 / Bad argument EXTMEML = 0x17 / Ext. mem size (low) offset in CMOS EXTMEMH = 0x18 / (high) PFLAGS = 0x22 / Offset int PROC. PFKERN = 0x80 / Kernel process flag bit. PIC = 0x20 / 8259 CSR I/O port. PICM = 0x21 / 8259 IMR I/O port. PIT = 0x40 / 8253 base I/O port. KBDATA = 0x60 / 8042 keyboard mpu data I/O port. KBCTRL = 0x64 / 8042 keyboard mpu ctrl I/O port. CMOSA = 0x70 / Real-time Clock/CMOS addr I/O port. CMOSD = 0x71 / Real-time Clock/CMOS data I/O port. SPIC = 0xA0 / Slave 8259 CSR I/O port. SPICM = 0xA1 / Slave 8259 IMR I/O port. UPASIZE = 1024 / Size of uproc and stack //////// / / System entry point. Under PC-DOS, / which thinks that Coherent is just a large / user program, the code is offset by 0x100 / to allow space for the base page. / //////// .blkb 0x0100 / PC-DOS base page. cli / No interrupts, please. int 0x11 / Obtain int 11 value before printf(). mov cs:val11, ax / Use boot block's stack for last time. / / Enable the A20 address line, which is normally disabled by the ROM BIOS. / This line is under the control of the 8042 keyboard interface controller. / sub cx, cx / 0: inb al, KBCTRL / Wait for 8042 input buffer to empty. testb al, $2 / loopne 0b / jmp .+2 / DELAY / / movb al, $0xD1 / Request next output byte to be outb KBCTRL, al / sent to the 8042 output port. / sub cx, cx / 0: inb al, KBCTRL / Wait for 8042 input buffer to empty. testb al, $2 / loopne 0b / jmp .+2 / DELAY / / movb al, $0xDF / Enable A20 address line. outb KBDATA, al / See Page 1-44, IBM-AT Tech Ref. / sub cx, cx / 0: inb al, KBCTRL / Wait for 8042 input buffer to empty. testb al, $2 / NOTE: A20 not enabled for up to 20 us. loopne 0b / / / Reprogram the 8253 timer so that channel 0, / which is used as the clock, interrupts at exactly / 100 HZ, instead of 18.2 HZ. / movb al, $0x36 / Timer 0, LSB, MSB, mode 3 outb PIT+3, al jmp .+2 / DELAY / jmp .+2 / DELAY / movb al, $0x9C / Lsb of 59659/5 = 11932 outb PIT, al jmp .+2 / DELAY / jmp .+2 / DELAY / movb al, $0x2E / Msb of 59659/5 = 11932 outb PIT, al jmp .+2 / DELAY / jmp .+2 / DELAY / / Reprogram channel 1 on the 8253 timer which is used for memory refresh. / movb al, $0x54 / Timer 1, LSB, mode 2 / outb PIT+3, al / jmp .+2 / DELAY / / jmp .+2 / DELAY / / movb al, $18 / LSB of 18. / outb PIT+1, al / jmp .+2 / DELAY / / jmp .+2 / DELAY / / Reprogram the 1st programmable interrupt controller. / It's default vector table collides with iAPX 286 protection vectors. movb al, $0x11 / ICW1 - edge, master, ICW4 outb PIC, al jmp .+2 / DELAY / jmp .+2 / DELAY / movb al, $0x20 / ICW2 - Reserve 1st 32 vectors for 286 outb PICM, al jmp .+2 / DELAY / jmp .+2 / DELAY / movb al, $0x04 / ICW3 - master level 2 outb PICM, al jmp .+2 / DELAY / jmp .+2 / DELAY / movb al, $0x01 / ICW4 - 8086 mode, master. outb PICM, al jmp .+2 / DELAY / jmp .+2 / DELAY / movb al, $0xFE / Disable interrupts from master PIC. outb PICM, al / (except for clock interrupt). movb al, $0xFF outb SPICM, al / Disable interrupts from slave PIC. / Set up all trap vectors. / The machine traps all have their own / linkages. We have to steal the clock from / the ROM, because the stacks might get switched / during the INT 1C, and the EOI would get sent / to the 8259 at a strange time. sub ax, ax / Map DS over the 8088 mov ds, ax / vector area. mov 0x0000, $trap0 / Divide error vector mov 0x0002, cs mov 0x0004, $trap1 / Single step. mov 0x0006, cs mov 0x0008, $trap2 / NMI mov 0x000A, cs mov 0x000C, $trap3 / INT 3 (break) mov 0x000E, cs mov 0x0010, $trap4 / Overflow. mov 0x0012, cs mov 0x0014, $trap5 / Bound range exceeded. mov 0x0016, cs mov 0x0018, $trap6 / Invalid Opcode mov 0x001A, cs mov 0x001C, $trap7 / Processor extension not available mov 0x001E, cs mov 0x0020, $trap8 / Double exception detected. mov 0x0022, cs mov 0x0024, $trap9 / Processor extension segment overrun. mov 0x0026, cs mov 0x0028, $trap10 / Invalid task state segment. mov 0x002A, cs mov 0x002C, $trap11 / Segment not present. mov 0x002E, cs mov 0x0030, $trap12 / Stack segment overrun or not present. mov 0x0032, cs mov 0x0034, $trap13 / General protection. mov 0x0036, cs mov 0x0080, $clk / Clock. mov 0x0082, cs mov 0x0084, $dev1 / Device 1 mov 0x0086, cs mov 0x0088, $dev9 / Device 2 maps into Device 9 mov 0x008A, cs mov 0x008C, $dev3 / Device 3 mov 0x008E, cs mov 0x0090, $dev4 / Device 4 mov 0x0092, cs mov 0x0094, $dev5 / Device 5 mov 0x0096, cs mov 0x0098, $dev6 / Device 6 mov 0x009A, cs mov 0x009C, $dev7 / Device 7 mov 0x009E, cs mov 0x01C0, $dev8 / Device 8 mov 0x01C2, cs mov 0x01C4, $dev9 / Device 9 mov 0x01C6, cs mov 0x01C8, $dev10 / Device 10 mov 0x01CA, cs mov 0x01CC, $dev11 / Device 11 mov 0x01CE, cs mov 0x01D0, $dev12 / Device 12 mov 0x01D2, cs mov 0x01D4, $dev13 / Device 13 mov 0x01D6, cs mov 0x01D8, $dev14 / Device 14 mov 0x01DA, cs mov 0x01DC, $dev15 / Device 15 mov 0x01DE, cs mov bx, $0x0200 / INT 80 (sys 0) 0: mov (bx), $syc / Set up the system call mov 2(bx), cs / trap vector. add bx, $4 / Move to next vector and cmp bx, $0x0400 / loop until all jb 0b / vectors are reset. / Set up the system stack and data segments, by looking at the size of / the text and adding this to the base address already in the CS. / Relocate the stack and data to a 128 byte boundary. mov ax, $etext_+15 / End of text segment shr ax, $4 / Convert to paragraphs. mov cx, cs / Get code segment base. add ax, cx / mov ds, ax / Current data segment add ax, $31 / Allow virtual-physical alignment and ax, $~31 / [use 512 byte, need 128 byte] / cmp realmode_, $0 / Virtual Addressing enabled? jne 0f / mov idtsel_, ax / Interrupt descriptor table [2 Kbytes] add ax, $0x0080 / 2K >> 4 mov gdtsel_, ax / Global descriptor table [64 Kbytes] add ax, $0x1000 / 64K >> 4 0: / mov es, ax / mov si, $edata_-1 / Copy data to new location, backwards. mov di, $edata_-1 / mov cx, $edata_ / std / rep / movsb / / mov ds, ax / Update data segment, mov ss, ax / and stack segment. mov sp, $u_+UPASIZE-32 / Set up initial stack. mov scs_, cs / Save code segment and mov sds_, ds / data segment bases. mov cs:cds, ds / For interrupts. / Size up memory, starting just above the system. / The memory is cleared, because somebody has to do a write / to set up the parity bits. mov di, $edata_ / Clear at edata... mov cx, $512 / for 1 Kbyte sub ax, ax cld rep stosw mov bp, $edata_+1023 / Compute base. shr bp, $4 add bp, sds_ shr bp, $6 / Round down to a Kbyte boundary shl bp, $6 / so's we're in sync. 0: sub di, di / Destination. mov es, bp / Set extra segment and mov es:(di), ax / clear a word. jmp .+2 / FLUSH / cmp es:(di), ax / Should be zero now. jne 0f / Branch if memory end mov cx, $512 / 1K bytes, in words. cld rep stosw / Clear this 1K add bp, $64 / Move along by 1K cmp bp, MAXMEM jb 0b / If not at video ram yet 0: mov es, sds_ / Map extra. mov ax, bp / Calculate top of low memory. rol ax, $4 / mov dx, ax / and ax, $0xFFF0 / xor dx, ax / cmp realmode_, $0 / Real Addressing Mode? je 0f / mov coretop_, ax / Yes, Record top of memory, mov coretop_+2, dx / jmp start / and bring up system. 0: mov holebot_, ax / Record bottom of I/O memory. mov holebot_+2, dx / mov ax, gdtsel_ / Format global descriptor table map. rol ax, $4 / mov dx, ax / and ax, $0xFFF0 / xor dx, ax / mov gdtmap_+0, $0xFFFF / Limit: 64K bytes. mov gdtmap_+2, ax / mov gdtmap_+4, dx / / sub ax, ax / Erase global descriptor table. mov cx, $0x8000 / [32K words = 64K bytes] mov es, gdtsel_ / sub di, di / cld / rep / stosw / / mov ax, idtsel_ / Format interrupt descriptor table map rol ax, $4 / mov dx, ax / and ax, $0xFFF0 / xor dx, ax / mov idtmap_+0, $2047 / Limit: 2K bytes. mov idtmap_+2, ax / mov idtmap_+4, dx / / sub ax, ax / Erase interrupt descriptor table. mov cx, $1024 / [1K words = 2K bytes] mov es, idtsel_ / sub di, di / cld / rep / stosw / / mov es, gdtsel_ / mov di, cs / Define kernel code global selector. mov ax, $etext_-1 / Limit: etext. stosw / mov dx, $0x9A00 / Flags: Present, executable. mov ax, cs / Base: cs << 4. rol ax, $4 / xor dx, ax / and ax, $0xFFF0 / stosw / xor ax, dx / stosw / sub ax, ax / stosw / / mov di, ss / Define kernel data global selector. mov ax, $0xFFFF / Limit: 64K bytes. stosw / mov dx, $0x9200 / Flags: Present, writable. mov ax, ss / Base: ss << 4. rol ax, $4 / xor dx, ax / and ax, $0xFFF0 / stosw / xor ax, dx / stosw / sub ax, ax / stosw / / mov di, $8 / Define task state segment selector[8] mov ax, $43 / Limit: 44 bytes. stosw / mov dx, $0x8100 / Flags: Present, avail tss seg. mov ax, ss / Base: (ss << 4) + &tss. rol ax, $4 / xor dx, ax / and ax, $0xFFF0 / xor dx, ax / add ax, $tss_ / adc dx, $0 / stosw / mov ax, dx / stosw / sub ax, ax / stosw / / mov di, gdtsel_ / Define gdt access global selector. mov ax, $0xFFFF / Limit: 64K bytes. stosw / mov dx, $0x9200 / Flags: Present, writable. mov ax, gdtsel_ / Base: gdtsel << 4. rol ax, $4 / xor dx, ax / and ax, $0xFFF0 / stosw / xor ax, dx / stosw / sub ax, ax / stosw / / mov di, idtsel_ / Define idt access global selector. mov ax, $2047 / Limit: 2K bytes. stosw / mov dx, $0x9200 / Flags: Present, writable. mov ax, idtsel_ / Base: idtsel << 4. rol ax, $4 / xor dx, ax / and ax, $0xFFF0 / stosw / xor ax, dx / stosw / sub ax, ax / stosw / / mov di, $0xB000 / Define video access global selector. mov ax, $0xFFFF / Limit: 64K bytes. stosw / mov dx, $0x9200 / Flags: Present, writable. mov ax, $0xB000 / Base: 0xB000 << 4. rol ax, $4 / xor dx, ax / and ax, $0xFFF0 / stosw / xor ax, dx / stosw / sub ax, ax / stosw / / mov di, $0xB800 / Define video access global selector. mov ax, $0x7FFF / Limit: 32 Kbytes. stosw / mov dx, $0x9200 / Flags: Present, writable. mov ax, $0xB800 / Base: 0xB800 << 4. rol ax, $4 / xor dx, ax / and ax, $0xFFF0 / stosw / xor ax, dx / stosw / sub ax, ax / stosw / mov di, $0xF000 / Define ROM access global selector. mov ax, $0xFFFF / Limit: 64 Kbytes. stosw / mov dx, $0x9000 / Flags: Present, read only. mov ax, $0xF000 / Base: 0xF000 << 4. rol ax, $4 / xor dx, ax / and ax, $0xFFF0 / stosw / xor ax, dx / stosw / sub ax, ax / stosw / mov es, idtsel_ / Map ES over the intr descr table. sub ax, ax / Map DS over the 8088 vector area. mov ds, ax / sub si, si / sub di, di / mov bx, cs / Make CS available for comparison. mov cx, $256 / Install 256 interrupt descriptors. / 0: lodsw / Copy interrupt IP stosw / lodsw / Copy interrupt CS stosw / / cmp ax, bx / Coherent interrupt handler? mov ax, $0x8600 / je 1f / sub ax, ax / No, clear flags. / 1: stosw / Define IDT flags. sub ax, ax / Reserved IDT word. stosw / loop 0b / Repeat for all 256 entries. / mov ax, ss / Restore data and extra segments. mov ds, ax / mov es, ax / / clts / Clear task switched flag. lgdt gdtmap_ / Load global descriptor table map. lidt idtmap_ / Load interrupt descriptor table map. / smsw ax / Enter protected mode. or ax, $1 / lmsw ax / jmp .+2 / Clear pipeline. / mov ax, $0x0008 / Load task state segment register. ltr ax / sub ax, ax / Load local descriptor table register. lldt ax / / / / Register usage: / DX:AX = extended mem physical addr. / BX = 0. / SI = selector into extended memory. / ES = selector into extended memory. / DS = selector into global descr table / movb al, $EXTMEMH / high byte of pair outb CMOSA, al / to CMOS memory port jmp .+2 / DELAY inb al, CMOSD / get value from CMOS xchgb ah, al jmp .+2 / DELAY movb al, $EXTMEML / low byte of pair outb CMOSA, al / to CMOS memory port jmp .+2 / DELAY inb al, CMOSD / get rest of pair from CMOS shr ax, $6 / K -> 64K conversion add ax, $0x0010 / bias up to 1MB mov CMOSmax_, ax / save count of 64K hunks sub ax, ax / mov dx, $0x0010 / Initial 64 Kbyte bank of extended mem. mov holetop_, ax / Recorded extended memory bot in bytes. mov holetop_+2, dx / / mov ds, gdtsel_ / Map DS onto global descr table. mov si, $0xFFF8 / Define scratch access global selector. mov 0(si), $0xFFFF / Limit: 64K bytes. mov 2(si), $0x0000 / Base: 1 Mbyte. mov 4(si), $0x9210 / Flags: Present, writable. mov 6(si), $0x0000 / / sub bx, bx / 0: sub di, di / Destination. mov cx, $0x8000 / 64K bytes, in words. mov 2(si), ax / Adjust gdt to desired DX:AX mem locn. movb 4(si), dl / mov es, si / Map ES onto 64K bank of extended mem. mov es:(di), bx / Write word of extended memory. jmp .+2 / FLUSH / cmp es:(di), bx / Verify word was correctly written. jne 0f / Branch if memory end. / cld / rep / stosw / Clear this 64K of extended memory. / inc dx / Step to next 64K bank. cmp dx, ss:CMOSmax_ / See if we're beyond what the CMOS jge 0f / says we have. cmp dx, $0x00F0 / Stop at 15 Mbyte boundary; the last jl 0b / Mbyte is a dup of the 1st Mbyte. / 0: movb 5(si), $0 / Free the scratch selector. / mov bx, ss / Restore data and extra segments. mov ds, bx / NOTE: Do not modify DX:AX. mov es, bx / / mov coretop_, ax / Recorded top of extended core memory. mov coretop_+2, dx / jmp start / Bring up system. //////// / / Trap an interrupt linkage. / Each of the machine traps has a special little / linkage, that sets up the type code and sends / control off to the common trap processor. Device / interrupts, other than the clock (IR0), are / done here. / //////// trap0: call tsave mov 16(bx), $0x0000 / Divide error. jmp trap_ trap1: call tsave mov 16(bx), $0x0100 / Single step. jmp trap_ trap2: call tsave mov 16(bx), $0x0200 / Non-maskable interrupt. jmp trap_ trap3: call tsave mov 16(bx), $0x0300 / INT 3 (breakpoint). jmp trap_ trap4: call tsave mov 16(bx), $0x0400 / Overflow. jmp trap_ trap5: call tsave mov 16(bx), $0x0500 / Bound check. jmp trap_ trap6: call tsave mov 16(bx), $0x0600 / Invalid opcode. jmp trap_ trap7: call tsave mov 16(bx), $0x0700 / Processor Extension not available. jmp trap_ trap8: pop ax / Get error code from stack [always 0] call tsave mov 16(bx), $0x0800 / Double Exception detected jmp trap_ trap9: call tsave mov 16(bx), $0x0900 / Processor extension segment overrun jmp trap_ trap10: pop ax / Get error code from stack call tsave mov 16(bx), $0x0A00 / Invalid task state segment jmp trap_ trap11: pop ax / Get error code from stack call tsave mov 16(bx), $0x0B00 / Segment not present jmp trap_ trap12: pop ax / Get error code from stack call tsave mov 16(bx), $0x0C00 / Stack segment overrun or not present jmp trap_ trap13: pop ax / Get error code from stack call tsave mov 16(bx), $0x0D00 / General protection jmp trap_ .globl syc syc: call tsave mov 16(bx), $0x2000 / System calls. jmp trap_ ran: call tsave mov 16(bx), $0x2100 / Random trap. jmp trap_ dev1: call tsave mov 16(bx), $0x4001 / Device 1: keyboard ijmp vecs_+[2*1] /dev2: call tsave / Device 2: mapped into device 9 / mov 16(bx), $0x4002 / ijmp vecs_+[2*2] dev3: call tsave mov 16(bx), $0x4003 / Device 3: al1 ijmp vecs_+[2*3] dev4: call tsave mov 16(bx), $0x4004 / Device 4: al0 ijmp vecs_+[2*4] dev5: call tsave mov 16(bx), $0x4005 / Device 5: hard disk ijmp vecs_+[2*5] dev6: call tsave mov 16(bx), $0x4006 / Device 6: floppy ijmp vecs_+[2*6] dev7: call tsave mov 16(bx), $0x4007 / Device 7: lp ijmp vecs_+[2*7] dev8: call tsave mov 16(bx), $0x4008 / Device 8: ijmp vecs_+[2*8] dev9: call tsave mov 16(bx), $0x4009 / Device 9: ijmp vecs_+[2*9] dev10: call tsave mov 16(bx), $0x400A / Device 10: ijmp vecs_+[2*10] dev11: call tsave mov 16(bx), $0x400B / Device 11: ijmp vecs_+[2*11] dev12: call tsave mov 16(bx), $0x400C / Device 12: ijmp vecs_+[2*12] dev13: call tsave mov 16(bx), $0x400D / Device 13: ijmp vecs_+[2*13] dev14: call tsave mov 16(bx), $0x400E / Device 14: ijmp vecs_+[2*14] dev15: call tsave mov 16(bx), $0x400F / Device 15: ijmp vecs_+[2*15] //////// / / Clock interrupt. / The clock interrupt is stolen from the ROM; / if you don't do this the EOI sequence for the 8259 / may get mangled on context switches. / //////// clk: call tsave / Perform trap save. mov 16(bx), $0x4000 sub ax, ax / Assume system mode, push user flag push ax push 18(bx) / IP at tick time cmpb depth_, $0 / Correct ? jne 0f / If ne, yes. mov bx, cprocp_ / User depth, check if the test PFLAGS(bx), $PFKERN / current process is a kernel process. jne 0f / If ne, yes. mov bx, sp / Load stack index inc 2(bx) / and set user mode. 0: call clock_ / Call common clock and add sp, $4 / pop arguments. ret / Back to "tsave". //////// / / This routine is called by "tsave" to dismiss an interrupt. / The interrupt code is in "ax". / //////// .globl eoi eoi: cmpb al, $8 / Is this on the slave PIC? jb 0f / Jump if not. movb al, $0x20 / Send a non specific EOI outb SPIC, al / to the slave PIC. 0: movb al, $0x20 / Send a non specific EOI outb PIC, al / to the master PIC. ret / Done. //////// / / Block I/O to ports. / Mainly used to read and write the silo memories in the discs. / Delibrately only transfers 1 byte per loop to avoid / timing problems on AT I/O chips. / / void outcopy(port, off, seg, n); / int port; /* Port address */ / char *off; /* Offset in segment */ / unsigned seg; /* Segment register base */ / int n; /* Byte count */ / / void incopy(port, off, seg, n); / int port; /* Device */ / char *off; /* Offset */ / unsigned seg; /* Segment register base */ / int n; /* Byte count */ / //////// .globl incopy_ .globl outcopy_ incopy_: push di push es push bp mov bp, sp mov dx, 8(bp) /device port les di, 10(bp) /seg,off pair mov cx, 14(bp) /n bytes jcxz 1f cld /auto-increment 0: inb al, dx stosb loop 0b 1: pop bp pop es /restore regs pop di ret outcopy_: push si push ds push bp mov bp, sp mov dx, 8(bp) /device port lds si, 10(bp) /offset mov cx, 14(bp) /count jcxz 1f cld /auto-increment 0: lodsb outb dx, al loop 0b 1: pop bp pop ds pop si ret //////// / / Copy "n" bytes of memory from base "p1" to base "p2". / The copy must be done from left to right. / / plrcopy(p1, p2, n) / paddr_t p1, p2; / size_t n; / //////// .globl plrcopy_ plrcopy_: push si / Save sequence push di push bp mov bp, sp push ds / Save ds push es / Save es push 18(bp) / Map SI:DI at destination ptov(p2,n). push 16(bp) push 14(bp) push 12(bp) call ptov_ add sp, $8 mov si, dx mov di, ax push 18(bp) / Map DX:AX at source ptov(p1,n); push 16(bp) push 10(bp) push 8(bp) call ptov_ add sp, $8 mov es, si / Map ES:DI at destination. mov ds, dx / Map DS:SI at source. mov si, ax mov cx, 16(bp) / Transfer count in bytes. cld / Auto Increment. clc / rcr cx, $1 / Word count rep / movsw / Move words rcl cx, $1 / rep / movsb / Move odd byte mov si, es / Remember mapped selectors. mov di, ds / pop es / Restore es pop ds / Restore ds push si / Release mapped selectors. push ax / NOTE: Offset is ignored. call vrelse_ / add sp, $4 / / push di / push ax / call vrelse_ / add sp, $4 / pop bp / Standard return pop di pop si ret / Return //////// / / Copy "n" bytes of memory from base "p1" to base "p2". / The copy must be done from right to left. / / prlcopy(p1, p2, n) / paddr_t p1, p2; / size_t n; / //////// .globl prlcopy_ prlcopy_: push si / Save sequence push di push bp mov bp, sp push ds / Save ds push es / Save es push 18(bp) / Map SI:DI at destination ptov(p2,n). push 16(bp) push 14(bp) push 12(bp) call ptov_ add sp, $8 mov si, dx mov di, ax push 18(bp) / Map DX:AX at source ptov(p1,n); push 16(bp) push 10(bp) push 8(bp) call ptov_ add sp, $8 mov es, si / Map ES:DI at destination. mov ds, dx / Map DS:SI at source. mov si, ax mov cx, 16(bp) / Transfer count in bytes add si, cx / Point DS:SI at the end dec si / of the source. add di, cx / Point ES:DI at the end dec di / of the destination. std / Auto decrement clc / rcr cx, $1 / Word Count rep / movsw / Move words rcl cx, $1 / rep / movsb / Move odd byte cld / Auto increment mov si, es / Remember mapped selectors. mov di, ds / pop es / Restore es pop ds / Restore ds push si / Release mapped selectors. push ax / NOTE: Offset is ignored. call vrelse_ / add sp, $4 / / push di / push ax / call vrelse_ / add sp, $4 / / mov ax, 16(bp) / Return transfer count. pop bp / Standard return pop di pop si ret //////// / / Clear "n" bytes of memory starting at physical address "p". / / pclear( p, n ) / paddr_t p; / size_t n; / / / Notes: At most 64K bytes of memory can be cleared. / //////// .globl pclear_ pclear_: push si / Standard save push di push bp mov bp, sp push es / Save es push 14(bp) / Map ES:DI at ptov(p2,n). push 12(bp) push 10(bp) push 8(bp) call ptov_ add sp, $8 mov es, dx mov di, ax shr 14(bp), $1 / Convert count from bytes to words. rcr 12(bp), $1 mov cx, 12(bp) / Count in words. sub ax, ax / Get a 0. cld / Zero the block. rep stosw mov ax, es / Remember mapped selector. pop es / Restore es. push ax / Release mapped selector. push ax / NOTE: Offset is ignored. call vrelse_ / add sp, $4 / pop bp / Standard return. pop di pop si ret //////// / / Block copy chunks of memory to a physical / location from a location in either the system / or user data space. / / upcopy(u, p, n) / char *u; / paddr_t p; / int n; / / kpcopy(k, p, n); / char *k; / paddr_t p; / int n; / //////// .globl upcopy_ upcopy_: mov bx, sp / Get set for stack index. mov ax, 2(bx) / User address dec ax / Don't wrap too soon add ax, 8(bx) / Count jc kuerr / Out of bounds cmp ax, udl_ / In range? ja kuerr / No push uds_ / Mark transfer ds as being user ds. jmp 1f / Finish in common code. .globl kpcopy_ kpcopy_: push ds / Mark transfer ds as being kernel ds. 1: push si / Standard save push di push bp mov bp, sp push ds / Save ds, es push es sub ax, ax / ES:DI = ptov(p,n). push ax / push 16(bp) / push 14(bp) / push 12(bp) / call ptov_ / add sp, $8 / mov es, dx / mov di, ax / / mov ds, 6(bp) / DS:SI = source address. mov si, 10(bp) / mov cx, 16(bp) / Byte count / cld / Auto Increment clc / rcr cx, $1 / Word count rep / movsw / Move words rcl cx, $1 / Move odd byte rep / movsb / / mov ax, es / Remember mapped selector. pop es / Restore es, ds. pop ds / / push ax / Release mapped selector. push ax / NOTE: Offset is ignored. call vrelse_ / add sp, $4 / / mov ax, 16(bp) / Return transfer count. / pop bp / Standard return. pop di pop si add sp, $2 / Discard marked transfer ds. ret //////// / / Block copy memory from physical address "p" / to either user or system data space. / / pucopy(p, u, n) / paddr_t p; / char *u; / int n; / / pkcopy(p, k, n); / paddr_t p; / char *k; / int n; / //////// .globl pucopy_ pucopy_: mov bx, sp / Stack index mov ax, 6(bx) / User address dec ax / Don't wrap too soon add ax, 8(bx) / Count jc kuerr / Out of bounds cmp ax, udl_ / In range? ja kuerr / No push uds_ / Mark transfer es as being user ds. jmp 1f / Common code .globl pkcopy_ pkcopy_: push ds / Mark transfer es as being kernel ds. 1: push si / Standard save push di push bp mov bp, sp push ds / Save ds, es. push es sub ax, ax / DS:SI = ptov(p,n). push ax push 16(bp) push 12(bp) push 10(bp) call ptov_ add sp, $8 mov ds, dx mov si, ax mov es, 6(bp) / ES:DI = destination. mov di, 14(bp) / mov cx, 16(bp) / Count cld / Incremental move clc / rcr cx, $1 / Word count rep / movsw / Move words. rcl cx, $1 / Move odd byte. rep / movsb / / mov ax, ds / Rememember mapped selector. pop es / Restore es, ds. pop ds / / push ax / Release mapped selector. push ax / NOTE: Offset is ignored. call vrelse_ / add sp, $4 / / mov ax, 16(bp) / Return transfer count. / pop bp / Restore registers. pop di / pop si / add sp, $2 / Discard marked transfer es. ret / Fin //////// / / All of the above copy routines jump to / "kuerr", with the stack untouched, if they detect / a bounds error on a user address. / //////// kuerr: mov bx,$u_ / Pointer to user area movb (bx),$EFAULT / Bad parameter error sub ax,ax / Didn't copy anything ret / Return //////// / / Read the equipment description. Use / the "int 11" interface, so that the IBM / ROM will do all the details. / //////// .globl int11_ int11_: mov ax, cs:val11 / Ask the ROM ret / to put stuff in AX //////// / / Bootstrap. / Called by the keyboard driver on control-alt-del. / Requests the 8042 controller to initiate a processor reset, / which is the only way to terminate protected mode operation. / / Reference: IBM-AT Technical Reference Manual, / Real-time Clock/CMOS RAM [Page 1-45] / Keyboard controller [Page 1-40] / Test 3, Page 5-68. / //////// .globl boot_ boot_: cli / Disable interrupts. / sub cx, cx / 0: inb al, KBCTRL / Wait for 8042 input buffer to empty. testb al, $2 / loopne 0b / jmp .+2 / DELAY / / movb al, $0xFE / Issue a shutdown command outb KBCTRL, al / to the 8042 control port. / 0: hlt / Halt until processor reset occurs. jmp 0b //////// / / Data. / //////// .globl MAXMEM .globl vecs_ .globl realmode_ .globl gdtsel_, gdtmap_ .globl idtsel_, idtmap_ .globl CMOSmax_ .shri val11: .word 0 / Value obtained from int11 [in code]. .prvd MAXMEM: .word 0xA000 / In paragraphs, must be mult. of 64 CMOSmax_:.word 0x0000 / Max extended memory according ... / ... to CMOS bytes 0x17 and 0x18 ... / ... in 64K chunks. realmode_:.word 0 / Virtual Addressing Mode Enabled gdtmap_:.blkw 3 / Global descriptor table definition idtmap_:.blkw 3 / Interrupt descriptor table definition gdtsel_:.word 0 / Global descriptor table selector idtsel_:.word 0 / Interrupt descriptor table selector vecs_: .word vret_ / Interrupt vector table .word vret_ .word vret_ .word vret_ .word vret_ .word vret_ .word vret_ .word vret_ .word vret_ .word vret_ .word vret_ .word vret_ .word vret_ .word vret_ .word vret_ .word vret_ //////// / / Task State Segment - Coherent runs as a single protected mode task. / //////// .globl tss_ .prvd tss_: / Task State Segment. tss_lnk:.word 0 / 0: Back link selector to TSS. tss_sp0:.word 0 / 2: SP for CPL 0. tss_ss0:.word 0 / 4: SS for CPL 0. tss_sp1:.word 0 / 6: SP for CPL 1. tss_ss1:.word 0 / 8: SS for CPL 1. tss_sp2:.word 0 / 10: SP for CPL 2. tss_ss2:.word 0 / 12: SS for CPL 2. tss_ip: .word 0 / 14: IP (Entry point). tss_psw:.word 0 / 16: Flag word. tss_ax: .word 0 / 18: Register AX. tss_cx: .word 0 / 20: Register CX. tss_dx: .word 0 / 22: Register DX. tss_bx: .word 0 / 24: Register BX. tss_bp: .word 0 / 26: Register BP. tss_sp: .word 0 / 28: Register SP. tss_si: .word 0 / 30: Register SI. tss_di: .word 0 / 32: Register DI. tss_es: .word 0 / 34: Register ES. tss_cs: .word 0 / 36: Register CS. tss_ss: .word 0 / 38: Register SS. tss_ds: .word 0 / 40: Register DS. 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.