File: [local] / sys / arch / i386 / stand / libsa / gidt.S (download)
Revision 1.1.1.1 (vendor branch), Tue Mar 4 16:06:03 2008 UTC (16 years, 4 months ago) by nbrk
Branch: OPENBSD_4_2_BASE, MAIN
CVS Tags: jornada-partial-support-wip, HEAD Changes since 1.1: +0 -0 lines
Import of OpenBSD 4.2 release kernel tree with initial code to support
Jornada 720/728, StrongARM 1110-based handheld PC.
At this point kernel roots on NFS and boots into vfs_mountroot() and traps.
What is supported:
- glass console, Jornada framebuffer (jfb) works in 16bpp direct color mode
(needs some palette tweaks for non black/white/blue colors, i think)
- saic, SA11x0 interrupt controller (needs cleanup)
- sacom, SA11x0 UART (supported only as boot console for now)
- SA11x0 GPIO controller fully supported (but can't handle multiple interrupt
handlers on one gpio pin)
- sassp, SSP port on SA11x0 that attaches spibus
- Jornada microcontroller (jmcu) to control kbd, battery, etc throught
the SPI bus (wskbd attaches on jmcu, but not tested)
- tod functions seem work
- initial code for SA-1111 (chip companion) : this is TODO
Next important steps, i think:
- gpio and intc on sa1111
- pcmcia support for sa11x0 (and sa1111 help logic)
- REAL root on nfs when we have PCMCIA support (we may use any of supported pccard NICs)
- root on wd0! (using already supported PCMCIA-ATA)
|
/* $OpenBSD: gidt.S,v 1.32 2006/12/26 19:30:44 tom Exp $ */
/*
* Copyright (c) 1997 Michael Shalayeff
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
.file "gidt.S"
#include <machine/asm.h>
#define _LOCORE
#include <machine/trap.h>
#include <debug_md.h>
#undef _LOCORE
#include <assym.h>
#include "gidt.h"
#ifdef GIDT_DEBUG
#define gidt_debug0 ; \
mov $0xb8000, %eax ; \
mov $0x47314730, (%eax)
#define gidt_debug1 ; \
mov $(0xb8000 - LINKADDR), %eax ; \
mov $0x4f314f30, (%eax)
#define gidt_debug2 ; \
mov $0xb8004, %eax ; \
mov $0x47334732, (%eax)
#define gidt_debug3 ; \
mov $0xb8004, %eax ; \
mov $0x4f334f32, (%eax)
#define gidt_debug4 ; \
movl $0xb8008, %eax ; \
movl $0x47344733, (%eax)
#else
#define gidt_debug0 /* gidt_debug0 */
#define gidt_debug1 /* gidt_debug1 */
#define gidt_debug2 /* gidt_debug2 */
#define gidt_debug3 /* gidt_debug3 */
#define gidt_debug4 /* gidt_debug4 */
#endif
#define prot2real \
gidt_debug0; \
\
ljmp $S16TEXT, $1f - LINKADDR; \
1: \
.code16; \
movw $S16DATA, %ax; \
movw %ax, %ds; \
movw %ax, %es; \
gidt_debug1; \
\
movl %cr0, %eax; /* disable pmmm */ \
andl $~CR0_PE, %eax; \
movl %eax, %cr0; \
\
/* reload real cs:ip */ \
data32 ljmp $(LINKADDR >> 4), $1f - LINKADDR; \
1: \
movw %cs, %ax; /* setup: %ds, %es, %ss = %cs */ \
movw %ax, %ds; \
movw %ax, %es; \
xorw %ax, %ax; \
movw %ax, %ss; \
\
gidt_debug2; \
\
data32 addr32 lidt (Idtr_real - LINKADDR); /* load idtr for real mode */
#define real2prot \
gidt_debug3; \
\
movw $LINKADDR >> 4, %ax; \
movw %ax, %ds; \
data32 addr32 lgdt (Gdtr - LINKADDR); /* load the gdtr */ \
\
movl %cr0, %eax; /* enable pmmm */ \
orl $CR0_PE, %eax; \
movl %eax, %cr0; \
\
data32 ljmp $S32TEXT, $1f; /* reload %cs,flush pipeline */\
1: \
.code32; \
/* reload 32bit %ds, %ss, %es */ \
mov $S32DATA, %eax; \
mov %ax, %ds; \
mov %ax, %ss; \
mov %ax, %es; \
\
gidt_debug4; \
\
/* load idtr for debugger and DOS/BIOS iface */ \
lidt Idtr;
.globl _C_LABEL(BIOS_regs)
.text
.code32
.globl _ASM_LABEL(pmm_init)
.globl _C_LABEL(_rtt)
ENTRY(_rtt)
#ifdef GIDT_DEBUG
movl $0xb8000, %ebx
movl $0x4f514f51, (%ebx)
#endif
movw $0x1234, %ax
movw %ax, 0x472 /* warm boot */
/* Try to use the KBD to reboot system */
movb $0xfe, %al
outb %al, $0x64
movl $0x5000, %ecx
1: inb $0x84, %al
loop 1b
movb $0xfe, %al
outb %al, $0x64
#ifdef GIDT_DEBUG
movl $0xb8000, %ebx
movl $0x07310731, (%ebx)
#endif
/* Try to cause a triple fault... */
lidt Idtr_reset
xorl %eax, %eax
divl %eax, %eax
/* Again... */
int $0x8
/* Again... */
movl $0, %esp /* segment violation */
ret
.align 8, 0x90
pmm_init:
/* load idtr for interrupts */
lidt Idtr
ret
#ifdef __STDC__
#define IPROC(n) X##n
#define IEMU(n) IPROC(emu##n)
#else
#define IPROC(n) X/**/n
#define IEMU(n) IPROC(emu/**/n)
#endif
.align 8, 0x90
idt:
#define idte(e) \
.short IPROC(e); .short (S32TEXT); \
.short ((0x80|SDT_SYS386TGT) << 8); .short (LINKADDR >> 16)
/* internal (0-31) */
idte(de); idte(db); idte(nmi); idte(bp); idte(of); idte(br)
idte(ud); idte(nm); idte(df); idte(fo); idte(ts); idte(np)
idte(ss); idte(gp); idte(pf); idte(xx); idte(mf); idte(ac)
idte(mc)
idte(xx); idte(xx); idte(xx); idte(xx); idte(xx); idte(xx)
idte(xx); idte(xx); idte(xx); idte(xx); idte(xx); idte(xx)
idte(xx)
/* Maskable interrupts (32-255) */
/* BIOS entry points (32-63) */
/* DOS entry points (64-80) */
#ifdef __STDC__
#define idtb(b) idte(emu##b)
#else
#define idtb(b) idte(emu/**/b)
#endif
idtb(0); idtb(1); idtb(2); idtb(3); idtb(4); idtb(5)
idtb(6); idtb(7); idtb(8); idtb(9); idtb(10); idtb(11)
idtb(12); idtb(13); idtb(14); idtb(15); idtb(16); idtb(17)
idtb(18); idtb(19); idtb(20); idtb(21); idtb(22); idtb(23)
idtb(24); idtb(25); idtb(26); idtb(27); idtb(28); idtb(29)
idtb(30); idtb(31); idtb(32); idtb(33); idtb(34); idtb(35)
idtb(36); idtb(37); idtb(38); idtb(39); idtb(40); idtb(41)
idtb(42); idtb(43); idtb(44); idtb(45); idtb(46); idtb(47)
#undef idte
.globl Idtr
Idtr: .word . - idt - 1
.long idt
.word 0
.align 8
.globl Idtr_real
Idtr_real: .word 1023
.long 0
.word 0
.align 8
Idtr_reset: .long 0, 0
.align 8
gdt:
/* 0x00 : null */
.space 8
/* 0x08 : flat code */
.word 0xFFFF # lolimit
.word 0 # lobase
.byte 0 # midbase
.byte SDT_MEMERAC | 0 | 0x80 # RXAC, dpl = 0, present
.byte 0xf | 0 | 0x40 | 0x80 # hilimit, xx, 32bit, 4k granularity
.byte 0 # hibase
/* 0x10 : flat data */
.word 0xFFFF # lolimit
.word 0 # lobase
.byte 0 # midbase
.byte SDT_MEMRWA | 0 | 0x80 # RWA, dpl = 0, present
.byte 0xf | 0 | 0x40 | 0x80 # hilimit, xx, 32bit, 4k granularity
.byte 0 # hibase
/* 0x18 : 16 bit code */
.word 0xFFFF # lolimit
.word (LINKADDR & 0xffff) # lobase
.byte (LINKADDR >> 16) & 0xff # midbase
.byte SDT_MEMERAC | 0 | 0x80 # RXAC, dpl = 0, present
.byte 0x0 | 0 | 0 | 0 # hilimit, xx, 16bit, byte granularity
.byte (LINKADDR >> 20) & 0xff # hibase
/* 0x20 : 16 bit data */
.word 0xFFFF # lolimit
.word (LINKADDR & 0xffff) # lobase
.byte (LINKADDR >> 16) & 0xff # midbase
.byte SDT_MEMRWA | 0 | 0x80 # RWA, dpl = 0, present
.byte 0x0 | 0 | 0 | 0 # hilimit, xx, 16bit, byte granularity
.byte (LINKADDR >> 20) & 0xff # hibase
.globl Gdtr
Gdtr: .word . - gdt - 1
.long gdt
.word 0
#define IENTRY(name,type) \
IPROC(name): \
pushl $type ; \
jmp 1f
#define IENTRY_ERR(name,err,type) \
IPROC(name): \
pushl $err ; \
pushl $type ; \
jmp 1f
IPROC(xx):
pushl $1
pushl $T_RESERVED
jmp 1f
IENTRY_ERR(de,0,T_DIVIDE) /* #DE divide by zero */
IENTRY_ERR(db,0,T_TRCTRAP) /* #DB debug */
IENTRY_ERR(nmi,0,T_NMI) /* NMI */
IENTRY_ERR(bp,0,T_BPTFLT) /* #BP breakpoint */
IENTRY_ERR(of,0,T_OFLOW) /* #OF overflow */
IENTRY_ERR(br,0,T_BOUND) /* #BR BOUND range exceeded */
IENTRY_ERR(ud,0,T_PRIVINFLT) /* #UD invalid opcode */
IENTRY_ERR(nm,0,T_DNA) /* #NM device not available */
IENTRY(df,T_DOUBLEFLT) /* #DF double fault */
IENTRY_ERR(fo,0,T_FPOPFLT) /* #FO coprocessor segment overrun */
IENTRY(ts,T_TSSFLT) /* #TS invalid TSS */
IENTRY(np,T_SEGNPFLT) /* #NP segment not present */
IENTRY(ss,T_STKFLT) /* #SS stack fault */
IENTRY(gp,T_PROTFLT) /* #GP general protection */
IENTRY(pf,T_PAGEFLT) /* #PF page fault */
IENTRY_ERR(mf,0,T_ARITHTRAP) /* #MF floating point error */
IENTRY(ac,T_ALIGNFLT) /* #AC alignment check */
IENTRY(mc,T_MACHK) /* #MC machine check */
.globl alltraps
1: /* save on jumps */
jmp alltraps
#define IEMUENT(n) IEMU(n): pushl $n; jmp 1f
IEMUENT(0); IEMUENT(1); IEMUENT(2); IEMUENT(3)
IEMUENT(4); IEMUENT(5); IEMUENT(6); IEMUENT(7)
IEMUENT(8); IEMUENT(9); IEMUENT(10); IEMUENT(11)
IEMUENT(12); IEMUENT(13); IEMUENT(14); IEMUENT(15)
IEMUENT(16); IEMUENT(17); IEMUENT(18); IEMUENT(19)
IEMUENT(20); IEMUENT(21); IEMUENT(22); IEMUENT(23)
IEMUENT(24); IEMUENT(25); IEMUENT(26); IEMUENT(27)
IEMUENT(28); IEMUENT(29); IEMUENT(30); IEMUENT(31)
1: jmp EMUh /* redirect for short jumps */
IEMUENT(32); IEMUENT(33); IEMUENT(34); IEMUENT(35)
IEMUENT(36); IEMUENT(37); IEMUENT(38); IEMUENT(39)
IEMUENT(40); IEMUENT(41); IEMUENT(42); IEMUENT(43)
IEMUENT(44); IEMUENT(45); IEMUENT(46); IEMUENT(47)
1: jmp EMUh
/*
* entry point for BIOS real-mode interface
* all the magic for real-prot mode switching is here
*
* Call: %eax, %ecx, %edx, %ebx, %ebp, %esi, %edi, %es, %ds
* Return: %eax, %edx, %ecx, %eflags (as returned from BIOS)
*
*/
.globl EMUh
.align 8, 0x90
EMUh:
/* save %eax */
mov %eax, 3f
pop %eax
pusha
push %ds
push %es
push %fs
push %gs
/* save BIOS int vector */
mov %al, intno
prot2real
push %ds
addr32 movw (_C_LABEL(BIOS_regs)+(BIOSR_ES) - LINKADDR), %ax
movw %ax, %es
addr32 movw (_C_LABEL(BIOS_regs)+(BIOSR_DS) - LINKADDR), %ax
movw %ax, %ds
# data32 movl $Leax, %eax
.byte 0x66, 0xb8
3: .long 0x90909090
;sti
int $0
intno = . - 1
;cli
pop %ds
addr32 movl %ebx, (_C_LABEL(BIOS_regs)+(BIOSR_BX) - LINKADDR)
movw %es, %bx
addr32 movw %bx, (_C_LABEL(BIOS_regs)+(BIOSR_ES) - LINKADDR)
movb %ah, %bh
lahf
xchgb %ah, %bh
addr32 movl %eax, (2f - LINKADDR)
real2prot
# movl $Leax, %eax
.byte 0xb8
2: .long 0x90909090
/* pass BIOS return values back to caller */
movl %eax, 0xb*4(%esp)
movl %ecx, 0xa*4(%esp)
movl %edx, 0x9*4(%esp)
movb %bh , 0xe*4(%esp)
/* clear NT flag in eflags */
/* Martin Fredriksson <martin@gbg.netman.se> */
pushf
pop %eax
and $0xffffbfff, %eax
push %eax
popf
/* save registers into save area */
movl %eax, _C_LABEL(BIOS_regs)+BIOSR_AX
movl %ecx, _C_LABEL(BIOS_regs)+BIOSR_CX
movl %edx, _C_LABEL(BIOS_regs)+BIOSR_DX
movl %ebp, _C_LABEL(BIOS_regs)+BIOSR_BP
movl %esi, _C_LABEL(BIOS_regs)+BIOSR_SI
movl %edi, _C_LABEL(BIOS_regs)+BIOSR_DI
pop %gs
pop %fs
pop %es
pop %ds
popa
iret
/* Call buffer at 07c0:0000 in real mode to simulate a BIOS boot */
ENTRY(bootbuf)
pop %eax /* Don't need return address */
pop %esi /* Buffer */
pop %edx /* Device */
prot2real /* Switch */
/* Set up stack */
cli
xor %ax, %ax
mov %ax, %ss
mov $0xfffc, %esp
sti
/* Jump to buffer */
ljmp $0x0, $0x7c00
.end