diff options
Diffstat (limited to 'sys/amd64/isa')
-rw-r--r-- | sys/amd64/isa/atpic_vector.S | 250 | ||||
-rw-r--r-- | sys/amd64/isa/clock.c | 1182 | ||||
-rw-r--r-- | sys/amd64/isa/icu.h | 161 | ||||
-rw-r--r-- | sys/amd64/isa/icu_ipl.S | 170 | ||||
-rw-r--r-- | sys/amd64/isa/icu_ipl.s | 170 | ||||
-rw-r--r-- | sys/amd64/isa/icu_vector.S | 250 | ||||
-rw-r--r-- | sys/amd64/isa/icu_vector.s | 250 | ||||
-rw-r--r-- | sys/amd64/isa/intr_machdep.c | 501 | ||||
-rw-r--r-- | sys/amd64/isa/intr_machdep.h | 206 | ||||
-rw-r--r-- | sys/amd64/isa/isa.c | 1079 | ||||
-rw-r--r-- | sys/amd64/isa/isa.h | 200 | ||||
-rw-r--r-- | sys/amd64/isa/nmi.c | 501 | ||||
-rw-r--r-- | sys/amd64/isa/npx.c | 687 | ||||
-rw-r--r-- | sys/amd64/isa/timerreg.h | 110 | ||||
-rw-r--r-- | sys/amd64/isa/vector.S | 95 | ||||
-rw-r--r-- | sys/amd64/isa/vector.s | 95 |
16 files changed, 0 insertions, 5907 deletions
diff --git a/sys/amd64/isa/atpic_vector.S b/sys/amd64/isa/atpic_vector.S deleted file mode 100644 index 042614b829e2..000000000000 --- a/sys/amd64/isa/atpic_vector.S +++ /dev/null @@ -1,250 +0,0 @@ -/* - * from: vector.s, 386BSD 0.1 unknown origin - * $Id: icu_vector.s,v 1.8 1998/08/11 15:08:12 bde Exp $ - */ - -/* - * modified for PC98 by Kakefuda - */ - -#ifdef PC98 -#define ICU_IMR_OFFSET 2 /* IO_ICU{1,2} + 2 */ -#else -#define ICU_IMR_OFFSET 1 /* IO_ICU{1,2} + 1 */ -#endif - -#define ICU_EOI 0x20 /* XXX - define elsewhere */ - -#define IRQ_BIT(irq_num) (1 << ((irq_num) % 8)) -#define IRQ_BYTE(irq_num) ((irq_num) >> 3) - -#ifdef AUTO_EOI_1 -#define ENABLE_ICU1 /* use auto-EOI to reduce i/o */ -#define OUTB_ICU1 -#else -#define ENABLE_ICU1 \ - movb $ICU_EOI,%al ; /* as soon as possible send EOI ... */ \ - OUTB_ICU1 /* ... to clear in service bit */ -#define OUTB_ICU1 \ - outb %al,$IO_ICU1 -#endif - -#ifdef AUTO_EOI_2 -/* - * The data sheet says no auto-EOI on slave, but it sometimes works. - */ -#define ENABLE_ICU1_AND_2 ENABLE_ICU1 -#else -#define ENABLE_ICU1_AND_2 \ - movb $ICU_EOI,%al ; /* as above */ \ - outb %al,$IO_ICU2 ; /* but do second icu first ... */ \ - OUTB_ICU1 /* ... then first icu (if !AUTO_EOI_1) */ -#endif - -/* - * Macros for interrupt interrupt entry, call to handler, and exit. - */ - -#define FAST_INTR(irq_num, vec_name, enable_icus) \ - .text ; \ - SUPERALIGN_TEXT ; \ -IDTVEC(vec_name) ; \ - pushl %eax ; /* save only call-used registers */ \ - pushl %ecx ; \ - pushl %edx ; \ - pushl %ds ; \ - MAYBE_PUSHL_ES ; \ - movl $KDSEL,%eax ; \ - movl %ax,%ds ; \ - MAYBE_MOVW_AX_ES ; \ - FAKE_MCOUNT((4+ACTUALLY_PUSHED)*4(%esp)) ; \ - pushl _intr_unit + (irq_num) * 4 ; \ - call *_intr_handler + (irq_num) * 4 ; /* do the work ASAP */ \ - enable_icus ; /* (re)enable ASAP (helps edge trigger?) */ \ - addl $4,%esp ; \ - incl _cnt+V_INTR ; /* book-keeping can wait */ \ - movl _intr_countp + (irq_num) * 4,%eax ; \ - incl (%eax) ; \ - movl _cpl,%eax ; /* are we unmasking pending HWIs or SWIs? */ \ - notl %eax ; \ - andl _ipending,%eax ; \ - jne 2f ; /* yes, maybe handle them */ \ -1: ; \ - MEXITCOUNT ; \ - MAYBE_POPL_ES ; \ - popl %ds ; \ - popl %edx ; \ - popl %ecx ; \ - popl %eax ; \ - iret ; \ -; \ - ALIGN_TEXT ; \ -2: ; \ - cmpb $3,_intr_nesting_level ; /* is there enough stack? */ \ - jae 1b ; /* no, return */ \ - movl _cpl,%eax ; \ - /* XXX next line is probably unnecessary now. */ \ - movl $HWI_MASK|SWI_MASK,_cpl ; /* limit nesting ... */ \ - incb _intr_nesting_level ; /* ... really limit it ... */ \ - sti ; /* ... to do this as early as possible */ \ - MAYBE_POPL_ES ; /* discard most of thin frame ... */ \ - popl %ecx ; /* ... original %ds ... */ \ - popl %edx ; \ - xchgl %eax,4(%esp) ; /* orig %eax; save cpl */ \ - pushal ; /* build fat frame (grrr) ... */ \ - pushl %ecx ; /* ... actually %ds ... */ \ - pushl %es ; \ - movl $KDSEL,%eax ; \ - movl %ax,%es ; \ - movl (2+8+0)*4(%esp),%ecx ; /* ... %ecx from thin frame ... */ \ - movl %ecx,(2+6)*4(%esp) ; /* ... to fat frame ... */ \ - movl (2+8+1)*4(%esp),%eax ; /* ... cpl from thin frame */ \ - pushl %eax ; \ - subl $4,%esp ; /* junk for unit number */ \ - MEXITCOUNT ; \ - jmp _doreti - -#define INTR(irq_num, vec_name, icu, enable_icus, reg) \ - .text ; \ - SUPERALIGN_TEXT ; \ -IDTVEC(vec_name) ; \ - pushl $0 ; /* dummy error code */ \ - pushl $0 ; /* dummy trap type */ \ - pushal ; \ - pushl %ds ; /* save our data and extra segments ... */ \ - pushl %es ; \ - movl $KDSEL,%eax ; /* ... and reload with kernel's own ... */ \ - movl %ax,%ds ; /* ... early for obsolete reasons */ \ - movl %ax,%es ; \ - movb _imen + IRQ_BYTE(irq_num),%al ; \ - orb $IRQ_BIT(irq_num),%al ; \ - movb %al,_imen + IRQ_BYTE(irq_num) ; \ - outb %al,$icu+ICU_IMR_OFFSET ; \ - enable_icus ; \ - movl _cpl,%eax ; \ - testb $IRQ_BIT(irq_num),%reg ; \ - jne 2f ; \ - incb _intr_nesting_level ; \ -__CONCAT(Xresume,irq_num): ; \ - FAKE_MCOUNT(12*4(%esp)) ; /* XXX late to avoid double count */ \ - incl _cnt+V_INTR ; /* tally interrupts */ \ - movl _intr_countp + (irq_num) * 4,%eax ; \ - incl (%eax) ; \ - movl _cpl,%eax ; \ - pushl %eax ; \ - pushl _intr_unit + (irq_num) * 4 ; \ - orl _intr_mask + (irq_num) * 4,%eax ; \ - movl %eax,_cpl ; \ - sti ; \ - call *_intr_handler + (irq_num) * 4 ; \ - cli ; /* must unmask _imen and icu atomically */ \ - movb _imen + IRQ_BYTE(irq_num),%al ; \ - andb $~IRQ_BIT(irq_num),%al ; \ - movb %al,_imen + IRQ_BYTE(irq_num) ; \ - outb %al,$icu+ICU_IMR_OFFSET ; \ - sti ; /* XXX _doreti repeats the cli/sti */ \ - MEXITCOUNT ; \ - /* We could usually avoid the following jmp by inlining some of */ \ - /* _doreti, but it's probably better to use less cache. */ \ - jmp _doreti ; \ -; \ - ALIGN_TEXT ; \ -2: ; \ - /* XXX skip mcounting here to avoid double count */ \ - orb $IRQ_BIT(irq_num),_ipending + IRQ_BYTE(irq_num) ; \ - popl %es ; \ - popl %ds ; \ - popal ; \ - addl $4+4,%esp ; \ - iret - -MCOUNT_LABEL(bintr) - FAST_INTR(0,fastintr0, ENABLE_ICU1) - FAST_INTR(1,fastintr1, ENABLE_ICU1) - FAST_INTR(2,fastintr2, ENABLE_ICU1) - FAST_INTR(3,fastintr3, ENABLE_ICU1) - FAST_INTR(4,fastintr4, ENABLE_ICU1) - FAST_INTR(5,fastintr5, ENABLE_ICU1) - FAST_INTR(6,fastintr6, ENABLE_ICU1) - FAST_INTR(7,fastintr7, ENABLE_ICU1) - FAST_INTR(8,fastintr8, ENABLE_ICU1_AND_2) - FAST_INTR(9,fastintr9, ENABLE_ICU1_AND_2) - FAST_INTR(10,fastintr10, ENABLE_ICU1_AND_2) - FAST_INTR(11,fastintr11, ENABLE_ICU1_AND_2) - FAST_INTR(12,fastintr12, ENABLE_ICU1_AND_2) - FAST_INTR(13,fastintr13, ENABLE_ICU1_AND_2) - FAST_INTR(14,fastintr14, ENABLE_ICU1_AND_2) - FAST_INTR(15,fastintr15, ENABLE_ICU1_AND_2) - INTR(0,intr0, IO_ICU1, ENABLE_ICU1, al) - INTR(1,intr1, IO_ICU1, ENABLE_ICU1, al) - INTR(2,intr2, IO_ICU1, ENABLE_ICU1, al) - INTR(3,intr3, IO_ICU1, ENABLE_ICU1, al) - INTR(4,intr4, IO_ICU1, ENABLE_ICU1, al) - INTR(5,intr5, IO_ICU1, ENABLE_ICU1, al) - INTR(6,intr6, IO_ICU1, ENABLE_ICU1, al) - INTR(7,intr7, IO_ICU1, ENABLE_ICU1, al) - INTR(8,intr8, IO_ICU2, ENABLE_ICU1_AND_2, ah) - INTR(9,intr9, IO_ICU2, ENABLE_ICU1_AND_2, ah) - INTR(10,intr10, IO_ICU2, ENABLE_ICU1_AND_2, ah) - INTR(11,intr11, IO_ICU2, ENABLE_ICU1_AND_2, ah) - INTR(12,intr12, IO_ICU2, ENABLE_ICU1_AND_2, ah) - INTR(13,intr13, IO_ICU2, ENABLE_ICU1_AND_2, ah) - INTR(14,intr14, IO_ICU2, ENABLE_ICU1_AND_2, ah) - INTR(15,intr15, IO_ICU2, ENABLE_ICU1_AND_2, ah) -MCOUNT_LABEL(eintr) - - .data - .globl _ihandlers -_ihandlers: /* addresses of interrupt handlers */ - /* actually resumption addresses for HWI's */ - .long Xresume0, Xresume1, Xresume2, Xresume3 - .long Xresume4, Xresume5, Xresume6, Xresume7 - .long Xresume8, Xresume9, Xresume10, Xresume11 - .long Xresume12, Xresume13, Xresume14, Xresume15 - .long _swi_null, swi_net, _swi_null, _swi_null - .long _swi_vm, _swi_null, _swi_null, _swi_null - .long _swi_null, _swi_null, _swi_null, _swi_null - .long _swi_null, _swi_null, _softclock, swi_ast - -imasks: /* masks for interrupt handlers */ - .space NHWI*4 /* padding; HWI masks are elsewhere */ - - .long SWI_TTY_MASK, SWI_NET_MASK, SWI_CAMNET_MASK, SWI_CAMBIO_MASK - .long SWI_VM_MASK, 0, 0, 0 - .long 0, 0, 0, 0 - .long 0, 0, SWI_CLOCK_MASK, SWI_AST_MASK - -/* - * Interrupt counters and names. The format of these and the label names - * must agree with what vmstat expects. The tables are indexed by device - * ids so that we don't have to move the names around as devices are - * attached. - */ -#include "vector.h" - .globl _intrcnt, _eintrcnt -_intrcnt: - .space (NR_DEVICES + ICU_LEN) * 4 -_eintrcnt: - - .globl _intrnames, _eintrnames -_intrnames: - .ascii DEVICE_NAMES - .asciz "stray irq0" - .asciz "stray irq1" - .asciz "stray irq2" - .asciz "stray irq3" - .asciz "stray irq4" - .asciz "stray irq5" - .asciz "stray irq6" - .asciz "stray irq7" - .asciz "stray irq8" - .asciz "stray irq9" - .asciz "stray irq10" - .asciz "stray irq11" - .asciz "stray irq12" - .asciz "stray irq13" - .asciz "stray irq14" - .asciz "stray irq15" -_eintrnames: - - .text diff --git a/sys/amd64/isa/clock.c b/sys/amd64/isa/clock.c deleted file mode 100644 index d9bca71ad7c1..000000000000 --- a/sys/amd64/isa/clock.c +++ /dev/null @@ -1,1182 +0,0 @@ -/*- - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * William Jolitz and Don Ahn. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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. - * - * from: @(#)clock.c 7.2 (Berkeley) 5/12/91 - * $Id: clock.c,v 1.128 1998/10/23 10:46:20 phk Exp $ - */ - -/* - * Routines to handle clock hardware. - */ - -/* - * inittodr, settodr and support routines written - * by Christoph Robitschko <chmr@edvz.tu-graz.ac.at> - * - * reintroduced and updated by Chris Stenton <chris@gnome.co.uk> 8/10/94 - */ - -#include "opt_clock.h" -#include "apm.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/time.h> -#include <sys/kernel.h> -#ifndef SMP -#include <sys/lock.h> -#endif -#include <sys/sysctl.h> - -#include <machine/clock.h> -#ifdef CLK_CALIBRATION_LOOP -#include <machine/cons.h> -#endif -#include <machine/cputypes.h> -#include <machine/frame.h> -#include <machine/ipl.h> -#include <machine/limits.h> -#include <machine/md_var.h> -#if NAPM > 0 -#include <machine/apm_bios.h> -#include <i386/apm/apm_setup.h> -#endif -#ifdef APIC_IO -#include <machine/segments.h> -#endif -#if defined(SMP) || defined(APIC_IO) -#include <machine/smp.h> -#endif /* SMP || APIC_IO */ -#include <machine/specialreg.h> - -#include <i386/isa/icu.h> -#include <i386/isa/isa.h> -#include <i386/isa/rtc.h> -#include <i386/isa/timerreg.h> - -#include <sys/interrupt.h> - -#ifdef SMP -#define disable_intr() CLOCK_DISABLE_INTR() -#define enable_intr() CLOCK_ENABLE_INTR() - -#ifdef APIC_IO -#include <i386/isa/intr_machdep.h> -/* The interrupt triggered by the 8254 (timer) chip */ -int apic_8254_intr; -static u_long read_intr_count __P((int vec)); -static void setup_8254_mixed_mode __P((void)); -#endif -#endif /* SMP */ - -/* - * 32-bit time_t's can't reach leap years before 1904 or after 2036, so we - * can use a simple formula for leap years. - */ -#define LEAPYEAR(y) ((u_int)(y) % 4 == 0) -#define DAYSPERYEAR (31+28+31+30+31+30+31+31+30+31+30+31) - -#define TIMER_DIV(x) ((timer_freq + (x) / 2) / (x)) - -/* - * Time in timer cycles that it takes for microtime() to disable interrupts - * and latch the count. microtime() currently uses "cli; outb ..." so it - * normally takes less than 2 timer cycles. Add a few for cache misses. - * Add a few more to allow for latency in bogus calls to microtime() with - * interrupts already disabled. - */ -#define TIMER0_LATCH_COUNT 20 - -/* - * Maximum frequency that we are willing to allow for timer0. Must be - * low enough to guarantee that the timer interrupt handler returns - * before the next timer interrupt. - */ -#define TIMER0_MAX_FREQ 20000 - -int adjkerntz; /* local offset from GMT in seconds */ -int disable_rtc_set; /* disable resettodr() if != 0 */ -u_int idelayed; -int statclock_disable; -u_int stat_imask = SWI_CLOCK_MASK; -#ifndef TIMER_FREQ -#define TIMER_FREQ 1193182 -#endif -u_int timer_freq = TIMER_FREQ; -int timer0_max_count; -u_int tsc_freq; -int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ - -static int beeping = 0; -static u_int clk_imask = HWI_MASK | SWI_MASK; -static const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; -static u_int hardclock_max_count; -static u_int32_t i8254_lastcount; -static u_int32_t i8254_offset; -static int i8254_ticked; -/* - * XXX new_function and timer_func should not handle clockframes, but - * timer_func currently needs to hold hardclock to handle the - * timer0_state == 0 case. We should use register_intr()/unregister_intr() - * to switch between clkintr() and a slightly different timerintr(). - */ -static void (*new_function) __P((struct clockframe *frame)); -static u_int new_rate; -static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; -static u_char rtc_statusb = RTCSB_24HR | RTCSB_PINTR; -static u_int timer0_prescaler_count; - -/* Values for timerX_state: */ -#define RELEASED 0 -#define RELEASE_PENDING 1 -#define ACQUIRED 2 -#define ACQUIRE_PENDING 3 - -static u_char timer0_state; -static u_char timer2_state; -static void (*timer_func) __P((struct clockframe *frame)) = hardclock; -static u_int tsc_present; - -static unsigned i8254_get_timecount __P((struct timecounter *tc)); -static unsigned tsc_get_timecount __P((struct timecounter *tc)); -static void set_timer_freq(u_int freq, int intr_freq); - -static struct timecounter tsc_timecounter = { - tsc_get_timecount, /* get_timecount */ - 0, /* no poll_pps */ - ~0u, /* counter_mask */ - 0, /* frequency */ - "TSC" /* name */ -}; - -SYSCTL_OPAQUE(_debug, OID_AUTO, tsc_timecounter, CTLFLAG_RD, - &tsc_timecounter, sizeof(tsc_timecounter), "S,timecounter", ""); - -static struct timecounter i8254_timecounter = { - i8254_get_timecount, /* get_timecount */ - 0, /* no poll_pps */ - ~0u, /* counter_mask */ - 0, /* frequency */ - "i8254" /* name */ -}; - -SYSCTL_OPAQUE(_debug, OID_AUTO, i8254_timecounter, CTLFLAG_RD, - &i8254_timecounter, sizeof(i8254_timecounter), "S,timecounter", ""); - -static void -clkintr(struct clockframe frame) -{ - if (timecounter->tc_get_timecount == i8254_get_timecount) { - /* - * Maintain i8254_offset and related variables. Optimize - * the usual case where i8254 counter rollover has not been - * detected in i8254_get_timecount() by pretending that we - * read the counter when it rolled over. Otherwise, call - * i8254_get_timecount() to do most of the work. The - * hardware counter must be read to ensure monotonicity - * despite multiple rollovers and misbehaving hardware. - */ - (disable_intr)(); /* XXX avoid clock locking */ - if (i8254_ticked) { - i8254_get_timecount(NULL); - i8254_ticked = 0; - } else { - i8254_offset += timer0_max_count; - i8254_lastcount = 0; - } - (enable_intr)(); /* XXX avoid clock locking */ - } - timer_func(&frame); - switch (timer0_state) { - - case RELEASED: - setdelayed(); - break; - - case ACQUIRED: - if ((timer0_prescaler_count += timer0_max_count) - >= hardclock_max_count) { - timer0_prescaler_count -= hardclock_max_count; - hardclock(&frame); - setdelayed(); - } - break; - - case ACQUIRE_PENDING: - setdelayed(); - timer0_max_count = TIMER_DIV(new_rate); - disable_intr(); - outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); - outb(TIMER_CNTR0, timer0_max_count & 0xff); - outb(TIMER_CNTR0, timer0_max_count >> 8); - enable_intr(); - timer0_prescaler_count = 0; - timer_func = new_function; - timer0_state = ACQUIRED; - break; - - case RELEASE_PENDING: - if ((timer0_prescaler_count += timer0_max_count) - >= hardclock_max_count) { - timer0_prescaler_count -= hardclock_max_count; -#ifdef FIXME - /* - * XXX: This magic doesn't work, but It shouldn't be - * needed now anyway since we will not be able to - * aquire the i8254 if it is used for timecounting. - */ - /* - * See microtime.s for this magic. - */ - time.tv_usec += (27465 * timer0_prescaler_count) >> 15; - if (time.tv_usec >= 1000000) - time.tv_usec -= 1000000; -#endif - hardclock(&frame); - setdelayed(); - timer0_max_count = hardclock_max_count; - disable_intr(); - outb(TIMER_MODE, - TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); - outb(TIMER_CNTR0, timer0_max_count & 0xff); - outb(TIMER_CNTR0, timer0_max_count >> 8); - enable_intr(); - timer0_prescaler_count = 0; - timer_func = hardclock; - timer0_state = RELEASED; - } - break; - } -} - -/* - * The acquire and release functions must be called at ipl >= splclock(). - */ -int -acquire_timer0(int rate, void (*function) __P((struct clockframe *frame))) -{ - static int old_rate; - - if (rate <= 0 || rate > TIMER0_MAX_FREQ) - return (-1); - if (strcmp(timecounter->tc_name, "i8254") == 0) - return (-1); - switch (timer0_state) { - - case RELEASED: - timer0_state = ACQUIRE_PENDING; - break; - - case RELEASE_PENDING: - if (rate != old_rate) - return (-1); - /* - * The timer has been released recently, but is being - * re-acquired before the release completed. In this - * case, we simply reclaim it as if it had not been - * released at all. - */ - timer0_state = ACQUIRED; - break; - - default: - return (-1); /* busy */ - } - new_function = function; - old_rate = new_rate = rate; - return (0); -} - -int -acquire_timer2(int mode) -{ - - if (timer2_state != RELEASED) - return (-1); - timer2_state = ACQUIRED; - - /* - * This access to the timer registers is as atomic as possible - * because it is a single instruction. We could do better if we - * knew the rate. Use of splclock() limits glitches to 10-100us, - * and this is probably good enough for timer2, so we aren't as - * careful with it as with timer0. - */ - outb(TIMER_MODE, TIMER_SEL2 | (mode & 0x3f)); - - return (0); -} - -int -release_timer0() -{ - switch (timer0_state) { - - case ACQUIRED: - timer0_state = RELEASE_PENDING; - break; - - case ACQUIRE_PENDING: - /* Nothing happened yet, release quickly. */ - timer0_state = RELEASED; - break; - - default: - return (-1); - } - return (0); -} - -int -release_timer2() -{ - - if (timer2_state != ACQUIRED) - return (-1); - timer2_state = RELEASED; - outb(TIMER_MODE, TIMER_SEL2 | TIMER_SQWAVE | TIMER_16BIT); - return (0); -} - -/* - * This routine receives statistical clock interrupts from the RTC. - * As explained above, these occur at 128 interrupts per second. - * When profiling, we receive interrupts at a rate of 1024 Hz. - * - * This does not actually add as much overhead as it sounds, because - * when the statistical clock is active, the hardclock driver no longer - * needs to keep (inaccurate) statistics on its own. This decouples - * statistics gathering from scheduling interrupts. - * - * The RTC chip requires that we read status register C (RTC_INTR) - * to acknowledge an interrupt, before it will generate the next one. - * Under high interrupt load, rtcintr() can be indefinitely delayed and - * the clock can tick immediately after the read from RTC_INTR. In this - * case, the mc146818A interrupt signal will not drop for long enough - * to register with the 8259 PIC. If an interrupt is missed, the stat - * clock will halt, considerably degrading system performance. This is - * why we use 'while' rather than a more straightforward 'if' below. - * Stat clock ticks can still be lost, causing minor loss of accuracy - * in the statistics, but the stat clock will no longer stop. - */ -static void -rtcintr(struct clockframe frame) -{ - while (rtcin(RTC_INTR) & RTCIR_PERIOD) - statclock(&frame); -} - -#include "opt_ddb.h" -#ifdef DDB -#include <ddb/ddb.h> - -DB_SHOW_COMMAND(rtc, rtc) -{ - printf("%02x/%02x/%02x %02x:%02x:%02x, A = %02x, B = %02x, C = %02x\n", - rtcin(RTC_YEAR), rtcin(RTC_MONTH), rtcin(RTC_DAY), - rtcin(RTC_HRS), rtcin(RTC_MIN), rtcin(RTC_SEC), - rtcin(RTC_STATUSA), rtcin(RTC_STATUSB), rtcin(RTC_INTR)); -} -#endif /* DDB */ - -static int -getit(void) -{ - u_long ef; - int high, low; - - ef = read_eflags(); - disable_intr(); - - /* Select timer0 and latch counter value. */ - outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); - - low = inb(TIMER_CNTR0); - high = inb(TIMER_CNTR0); - - CLOCK_UNLOCK(); - write_eflags(ef); - return ((high << 8) | low); -} - -/* - * Wait "n" microseconds. - * Relies on timer 1 counting down from (timer_freq / hz) - * Note: timer had better have been programmed before this is first used! - */ -void -DELAY(int n) -{ - int delta, prev_tick, tick, ticks_left; - -#ifdef DELAYDEBUG - int getit_calls = 1; - int n1; - static int state = 0; - - if (state == 0) { - state = 1; - for (n1 = 1; n1 <= 10000000; n1 *= 10) - DELAY(n1); - state = 2; - } - if (state == 1) - printf("DELAY(%d)...", n); -#endif - /* - * Guard against the timer being uninitialized if we are called - * early for console i/o. - */ - if (timer0_max_count == 0) - set_timer_freq(timer_freq, hz); - - /* - * Read the counter first, so that the rest of the setup overhead is - * counted. Guess the initial overhead is 20 usec (on most systems it - * takes about 1.5 usec for each of the i/o's in getit(). The loop - * takes about 6 usec on a 486/33 and 13 usec on a 386/20. The - * multiplications and divisions to scale the count take a while). - */ - prev_tick = getit(); - n -= 0; /* XXX actually guess no initial overhead */ - /* - * Calculate (n * (timer_freq / 1e6)) without using floating point - * and without any avoidable overflows. - */ - if (n <= 0) - ticks_left = 0; - else if (n < 256) - /* - * Use fixed point to avoid a slow division by 1000000. - * 39099 = 1193182 * 2^15 / 10^6 rounded to nearest. - * 2^15 is the first power of 2 that gives exact results - * for n between 0 and 256. - */ - ticks_left = ((u_int)n * 39099 + (1 << 15) - 1) >> 15; - else - /* - * Don't bother using fixed point, although gcc-2.7.2 - * generates particularly poor code for the long long - * division, since even the slow way will complete long - * before the delay is up (unless we're interrupted). - */ - ticks_left = ((u_int)n * (long long)timer_freq + 999999) - / 1000000; - - while (ticks_left > 0) { - tick = getit(); -#ifdef DELAYDEBUG - ++getit_calls; -#endif - delta = prev_tick - tick; - prev_tick = tick; - if (delta < 0) { - delta += timer0_max_count; - /* - * Guard against timer0_max_count being wrong. - * This shouldn't happen in normal operation, - * but it may happen if set_timer_freq() is - * traced. - */ - if (delta < 0) - delta = 0; - } - ticks_left -= delta; - } -#ifdef DELAYDEBUG - if (state == 1) - printf(" %d calls to getit() at %d usec each\n", - getit_calls, (n + 5) / getit_calls); -#endif -} - -static void -sysbeepstop(void *chan) -{ - outb(IO_PPI, inb(IO_PPI)&0xFC); /* disable counter2 output to speaker */ - release_timer2(); - beeping = 0; -} - -int -sysbeep(int pitch, int period) -{ - int x = splclock(); - - if (acquire_timer2(TIMER_SQWAVE|TIMER_16BIT)) - if (!beeping) { - /* Something else owns it. */ - splx(x); - return (-1); /* XXX Should be EBUSY, but nobody cares anyway. */ - } - disable_intr(); - outb(TIMER_CNTR2, pitch); - outb(TIMER_CNTR2, (pitch>>8)); - enable_intr(); - if (!beeping) { - /* enable counter2 output to speaker */ - outb(IO_PPI, inb(IO_PPI) | 3); - beeping = period; - timeout(sysbeepstop, (void *)NULL, period); - } - splx(x); - return (0); -} - -/* - * RTC support routines - */ - -int -rtcin(reg) - int reg; -{ - u_char val; - - outb(IO_RTC, reg); - inb(0x84); - val = inb(IO_RTC + 1); - inb(0x84); - return (val); -} - -static __inline void -writertc(u_char reg, u_char val) -{ - inb(0x84); - outb(IO_RTC, reg); - inb(0x84); - outb(IO_RTC + 1, val); - inb(0x84); /* XXX work around wrong order in rtcin() */ -} - -static __inline int -readrtc(int port) -{ - return(bcd2bin(rtcin(port))); -} - -static u_int -calibrate_clocks(void) -{ - u_int count, prev_count, tot_count; - int sec, start_sec, timeout; - - if (bootverbose) - printf("Calibrating clock(s) ... "); - if (!(rtcin(RTC_STATUSD) & RTCSD_PWR)) - goto fail; - timeout = 100000000; - - /* Read the mc146818A seconds counter. */ - for (;;) { - if (!(rtcin(RTC_STATUSA) & RTCSA_TUP)) { - sec = rtcin(RTC_SEC); - break; - } - if (--timeout == 0) - goto fail; - } - - /* Wait for the mC146818A seconds counter to change. */ - start_sec = sec; - for (;;) { - if (!(rtcin(RTC_STATUSA) & RTCSA_TUP)) { - sec = rtcin(RTC_SEC); - if (sec != start_sec) - break; - } - if (--timeout == 0) - goto fail; - } - - /* Start keeping track of the i8254 counter. */ - prev_count = getit(); - if (prev_count == 0 || prev_count > timer0_max_count) - goto fail; - tot_count = 0; - - if (tsc_present) - wrmsr(0x10, 0LL); /* XXX 0x10 is the MSR for the TSC */ - - /* - * Wait for the mc146818A seconds counter to change. Read the i8254 - * counter for each iteration since this is convenient and only - * costs a few usec of inaccuracy. The timing of the final reads - * of the counters almost matches the timing of the initial reads, - * so the main cause of inaccuracy is the varying latency from - * inside getit() or rtcin(RTC_STATUSA) to the beginning of the - * rtcin(RTC_SEC) that returns a changed seconds count. The - * maximum inaccuracy from this cause is < 10 usec on 486's. - */ - start_sec = sec; - for (;;) { - if (!(rtcin(RTC_STATUSA) & RTCSA_TUP)) - sec = rtcin(RTC_SEC); - count = getit(); - if (count == 0 || count > timer0_max_count) - goto fail; - if (count > prev_count) - tot_count += prev_count - (count - timer0_max_count); - else - tot_count += prev_count - count; - prev_count = count; - if (sec != start_sec) - break; - if (--timeout == 0) - goto fail; - } - - /* - * Read the cpu cycle counter. The timing considerations are - * similar to those for the i8254 clock. - */ - if (tsc_present) - tsc_freq = rdtsc(); - - if (bootverbose) { - if (tsc_present) - printf("TSC clock: %u Hz, ", tsc_freq); - printf("i8254 clock: %u Hz\n", tot_count); - } - return (tot_count); - -fail: - if (bootverbose) - printf("failed, using default i8254 clock of %u Hz\n", - timer_freq); - return (timer_freq); -} - -static void -set_timer_freq(u_int freq, int intr_freq) -{ - u_long ef; - int new_timer0_max_count; - - ef = read_eflags(); - disable_intr(); - timer_freq = freq; - new_timer0_max_count = hardclock_max_count = TIMER_DIV(intr_freq); - if (new_timer0_max_count != timer0_max_count) { - timer0_max_count = new_timer0_max_count; - outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); - outb(TIMER_CNTR0, timer0_max_count & 0xff); - outb(TIMER_CNTR0, timer0_max_count >> 8); - } - CLOCK_UNLOCK(); - write_eflags(ef); -} - -/* - * Initialize 8254 timer 0 early so that it can be used in DELAY(). - * XXX initialization of other timers is unintentionally left blank. - */ -void -startrtclock() -{ - u_int delta, freq; - - if (cpu_feature & CPUID_TSC) - tsc_present = 1; - else - tsc_present = 0; - - writertc(RTC_STATUSA, rtc_statusa); - writertc(RTC_STATUSB, RTCSB_24HR); - - set_timer_freq(timer_freq, hz); - freq = calibrate_clocks(); -#ifdef CLK_CALIBRATION_LOOP - if (bootverbose) { - printf( - "Press a key on the console to abort clock calibration\n"); - while (cncheckc() == -1) - calibrate_clocks(); - } -#endif - - /* - * Use the calibrated i8254 frequency if it seems reasonable. - * Otherwise use the default, and don't use the calibrated i586 - * frequency. - */ - delta = freq > timer_freq ? freq - timer_freq : timer_freq - freq; - if (delta < timer_freq / 100) { -#ifndef CLK_USE_I8254_CALIBRATION - if (bootverbose) - printf( -"CLK_USE_I8254_CALIBRATION not specified - using default frequency\n"); - freq = timer_freq; -#endif - timer_freq = freq; - } else { - if (bootverbose) - printf( - "%d Hz differs from default of %d Hz by more than 1%%\n", - freq, timer_freq); - tsc_freq = 0; - } - - set_timer_freq(timer_freq, hz); - i8254_timecounter.tc_frequency = timer_freq; - init_timecounter(&i8254_timecounter); - -#ifndef CLK_USE_TSC_CALIBRATION - if (tsc_freq != 0) { - if (bootverbose) - printf( -"CLK_USE_TSC_CALIBRATION not specified - using old calibration method\n"); - tsc_freq = 0; - } -#endif - if (tsc_present && tsc_freq == 0) { - /* - * Calibration of the i586 clock relative to the mc146818A - * clock failed. Do a less accurate calibration relative - * to the i8254 clock. - */ - wrmsr(0x10, 0LL); /* XXX */ - DELAY(1000000); - tsc_freq = rdtsc(); -#ifdef CLK_USE_TSC_CALIBRATION - if (bootverbose) - printf("TSC clock: %u Hz (Method B)\n", tsc_freq); -#endif - } - -#if !defined(SMP) - /* - * We can not use the TSC in SMP mode, until we figure out a - * cheap (impossible), reliable and precise (yeah right!) way - * to synchronize the TSCs of all the CPUs. - * Curse Intel for leaving the counter out of the I/O APIC. - */ - -#if NAPM > 0 - /* - * We can not use the TSC if we found an APM bios. Too many - * of them lie about their ability&intention to fiddle the CPU - * clock for us to rely on this. Precise timekeeping on an - * APM'ed machine is at best a fools pursuit anyway, since - * any and all of the time spent in various SMM code can't - * be reliably accounted for. Reading the RTC is your only - * source of reliable time info. The i8254 looses too of course - * but we need to have some kind of time... - */ - if (apm_version != APMINI_CANTFIND) - return; -#endif /* NAPM > 0 */ - - if (tsc_present && tsc_freq != 0) { - tsc_timecounter.tc_frequency = tsc_freq; - init_timecounter(&tsc_timecounter); - } - -#endif /* !defined(SMP) */ -} - -/* - * Initialize the time of day register, based on the time base which is, e.g. - * from a filesystem. - */ -void -inittodr(time_t base) -{ - unsigned long sec, days; - int yd; - int year, month; - int y, m, s; - struct timespec ts; - - if (base) { - s = splclock(); - ts.tv_sec = base; - ts.tv_nsec = 0; - set_timecounter(&ts); - splx(s); - } - - /* Look if we have a RTC present and the time is valid */ - if (!(rtcin(RTC_STATUSD) & RTCSD_PWR)) - goto wrong_time; - - /* wait for time update to complete */ - /* If RTCSA_TUP is zero, we have at least 244us before next update */ - while (rtcin(RTC_STATUSA) & RTCSA_TUP); - - days = 0; -#ifdef USE_RTC_CENTURY - year = readrtc(RTC_YEAR) + readrtc(RTC_CENTURY) * 100; -#else - year = readrtc(RTC_YEAR) + 1900; - if (year < 1970) - year += 100; -#endif - if (year < 1970) - goto wrong_time; - month = readrtc(RTC_MONTH); - for (m = 1; m < month; m++) - days += daysinmonth[m-1]; - if ((month > 2) && LEAPYEAR(year)) - days ++; - days += readrtc(RTC_DAY) - 1; - yd = days; - for (y = 1970; y < year; y++) - days += DAYSPERYEAR + LEAPYEAR(y); - sec = ((( days * 24 + - readrtc(RTC_HRS)) * 60 + - readrtc(RTC_MIN)) * 60 + - readrtc(RTC_SEC)); - /* sec now contains the number of seconds, since Jan 1 1970, - in the local time zone */ - - sec += tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0); - - y = time_second - sec; - if (y <= -2 || y >= 2) { - /* badly off, adjust it */ - s = splclock(); - ts.tv_sec = sec; - ts.tv_nsec = 0; - set_timecounter(&ts); - splx(s); - } - return; - -wrong_time: - printf("Invalid time in real time clock.\n"); - printf("Check and reset the date immediately!\n"); -} - -/* - * Write system time back to RTC - */ -void -resettodr() -{ - unsigned long tm; - int y, m, s; - - if (disable_rtc_set) - return; - - s = splclock(); - tm = time_second; - splx(s); - - /* Disable RTC updates and interrupts. */ - writertc(RTC_STATUSB, RTCSB_HALT | RTCSB_24HR); - - /* Calculate local time to put in RTC */ - - tm -= tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0); - - writertc(RTC_SEC, bin2bcd(tm%60)); tm /= 60; /* Write back Seconds */ - writertc(RTC_MIN, bin2bcd(tm%60)); tm /= 60; /* Write back Minutes */ - writertc(RTC_HRS, bin2bcd(tm%24)); tm /= 24; /* Write back Hours */ - - /* We have now the days since 01-01-1970 in tm */ - writertc(RTC_WDAY, (tm+4)%7); /* Write back Weekday */ - for (y = 1970, m = DAYSPERYEAR + LEAPYEAR(y); - tm >= m; - y++, m = DAYSPERYEAR + LEAPYEAR(y)) - tm -= m; - - /* Now we have the years in y and the day-of-the-year in tm */ - writertc(RTC_YEAR, bin2bcd(y%100)); /* Write back Year */ -#ifdef USE_RTC_CENTURY - writertc(RTC_CENTURY, bin2bcd(y/100)); /* ... and Century */ -#endif - for (m = 0; ; m++) { - int ml; - - ml = daysinmonth[m]; - if (m == 1 && LEAPYEAR(y)) - ml++; - if (tm < ml) - break; - tm -= ml; - } - - writertc(RTC_MONTH, bin2bcd(m + 1)); /* Write back Month */ - writertc(RTC_DAY, bin2bcd(tm + 1)); /* Write back Month Day */ - - /* Reenable RTC updates and interrupts. */ - writertc(RTC_STATUSB, rtc_statusb); -} - - -/* - * Start both clocks running. - */ -void -cpu_initclocks() -{ - int diag; -#ifdef APIC_IO - int apic_8254_trial; -#endif /* APIC_IO */ - - if (statclock_disable) { - /* - * The stat interrupt mask is different without the - * statistics clock. Also, don't set the interrupt - * flag which would normally cause the RTC to generate - * interrupts. - */ - stat_imask = HWI_MASK | SWI_MASK; - rtc_statusb = RTCSB_24HR; - } else { - /* Setting stathz to nonzero early helps avoid races. */ - stathz = RTC_NOPROFRATE; - profhz = RTC_PROFRATE; - } - - /* Finish initializing 8253 timer 0. */ -#ifdef APIC_IO - - apic_8254_intr = isa_apic_irq(0); - apic_8254_trial = 0; - if (apic_8254_intr >= 0 ) { - if (apic_int_type(0, 0) == 3) - apic_8254_trial = 1; - } else { - /* look for ExtInt on pin 0 */ - if (apic_int_type(0, 0) == 3) { - apic_8254_intr = 0; - setup_8254_mixed_mode(); - } else - panic("APIC_IO: Cannot route 8254 interrupt to CPU"); - } - - register_intr(/* irq */ apic_8254_intr, /* XXX id */ 0, /* flags */ 0, - /* XXX */ (inthand2_t *)clkintr, &clk_imask, - /* unit */ 0); - INTREN(1 << apic_8254_intr); - -#else /* APIC_IO */ - - register_intr(/* irq */ 0, /* XXX id */ 0, /* flags */ 0, - /* XXX */ (inthand2_t *)clkintr, &clk_imask, - /* unit */ 0); - INTREN(IRQ0); - -#endif /* APIC_IO */ - - /* Initialize RTC. */ - writertc(RTC_STATUSA, rtc_statusa); - writertc(RTC_STATUSB, RTCSB_24HR); - - /* Don't bother enabling the statistics clock. */ - if (statclock_disable) - return; - diag = rtcin(RTC_DIAG); - if (diag != 0) - printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS); - -#ifdef APIC_IO - if (isa_apic_irq(8) != 8) - panic("APIC RTC != 8"); -#endif /* APIC_IO */ - - register_intr(/* irq */ 8, /* XXX id */ 1, /* flags */ 0, - /* XXX */ (inthand2_t *)rtcintr, &stat_imask, - /* unit */ 0); - -#ifdef APIC_IO - INTREN(APIC_IRQ8); -#else - INTREN(IRQ8); -#endif /* APIC_IO */ - - writertc(RTC_STATUSB, rtc_statusb); - -#ifdef APIC_IO - if (apic_8254_trial) { - - printf("APIC_IO: Testing 8254 interrupt delivery\n"); - while (read_intr_count(8) < 6) - ; /* nothing */ - if (read_intr_count(apic_8254_intr) < 3) { - /* - * The MP table is broken. - * The 8254 was not connected to the specified pin - * on the IO APIC. - * Workaround: Limited variant of mixed mode. - */ - INTRDIS(1 << apic_8254_intr); - unregister_intr(apic_8254_intr, - /* XXX */ (inthand2_t *) clkintr); - printf("APIC_IO: Broken MP table detected: " - "8254 is not connected to IO APIC int pin %d\n", - apic_8254_intr); - - apic_8254_intr = 0; - setup_8254_mixed_mode(); - register_intr(/* irq */ apic_8254_intr, /* XXX id */ 0, /* flags */ 0, - /* XXX */ (inthand2_t *)clkintr, &clk_imask, - /* unit */ 0); - INTREN(1 << apic_8254_intr); - } - - } - if (apic_8254_intr) - printf("APIC_IO: routing 8254 via pin %d\n",apic_8254_intr); - else - printf("APIC_IO: routing 8254 via 8259 on pin 0\n"); -#endif - -} - -#ifdef APIC_IO -static u_long -read_intr_count(int vec) -{ - u_long *up; - up = intr_countp[vec]; - if (up) - return *up; - return 0UL; -} - -static void -setup_8254_mixed_mode() -{ - /* - * Allow 8254 timer to INTerrupt 8259: - * re-initialize master 8259: - * reset; prog 4 bytes, single ICU, edge triggered - */ - outb(IO_ICU1, 0x13); - outb(IO_ICU1 + 1, NRSVIDT); /* start vector (unused) */ - outb(IO_ICU1 + 1, 0x00); /* ignore slave */ - outb(IO_ICU1 + 1, 0x03); /* auto EOI, 8086 */ - outb(IO_ICU1 + 1, 0xfe); /* unmask INT0 */ - - /* program IO APIC for type 3 INT on INT0 */ - if (ext_int_setup(0, 0) < 0) - panic("8254 redirect via APIC pin0 impossible!"); -} -#endif - -void -setstatclockrate(int newhz) -{ - if (newhz == RTC_PROFRATE) - rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF; - else - rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; - writertc(RTC_STATUSA, rtc_statusa); -} - -static int -sysctl_machdep_i8254_freq SYSCTL_HANDLER_ARGS -{ - int error; - u_int freq; - - /* - * Use `i8254' instead of `timer' in external names because `timer' - * is is too generic. Should use it everywhere. - */ - freq = timer_freq; - error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req); - if (error == 0 && req->newptr != NULL) { - if (timer0_state != RELEASED) - return (EBUSY); /* too much trouble to handle */ - set_timer_freq(freq, hz); - i8254_timecounter.tc_frequency = freq; - } - return (error); -} - -SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW, - 0, sizeof(u_int), sysctl_machdep_i8254_freq, "I", ""); - -static int -sysctl_machdep_tsc_freq SYSCTL_HANDLER_ARGS -{ - int error; - u_int freq; - - if (!tsc_present) - return (EOPNOTSUPP); - freq = tsc_freq; - error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req); - if (error == 0 && req->newptr != NULL) { - tsc_freq = freq; - tsc_timecounter.tc_frequency = tsc_freq; - } - return (error); -} - -SYSCTL_PROC(_machdep, OID_AUTO, tsc_freq, CTLTYPE_INT | CTLFLAG_RW, - 0, sizeof(u_int), sysctl_machdep_tsc_freq, "I", ""); - -static unsigned -i8254_get_timecount(struct timecounter *tc) -{ - u_int count; - u_long ef; - u_int high, low; - - ef = read_eflags(); - disable_intr(); - - /* Select timer0 and latch counter value. */ - outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); - - low = inb(TIMER_CNTR0); - high = inb(TIMER_CNTR0); - - count = hardclock_max_count - ((high << 8) | low); - if (count < i8254_lastcount) { - i8254_ticked = 1; - i8254_offset += hardclock_max_count; - } - - i8254_lastcount = count; - count += i8254_offset; - CLOCK_UNLOCK(); - write_eflags(ef); - return (count); -} - -static unsigned -tsc_get_timecount(struct timecounter *tc) -{ - return (rdtsc()); -} diff --git a/sys/amd64/isa/icu.h b/sys/amd64/isa/icu.h deleted file mode 100644 index cfe4dceb0873..000000000000 --- a/sys/amd64/isa/icu.h +++ /dev/null @@ -1,161 +0,0 @@ -/*- - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * William Jolitz. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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. - * - * from: @(#)icu.h 5.6 (Berkeley) 5/9/91 - * $Id: icu.h,v 1.15 1997/07/22 20:12:05 fsmp Exp $ - */ - -/* - * AT/386 Interrupt Control constants - * W. Jolitz 8/89 - */ - -#ifndef _I386_ISA_ICU_H_ -#define _I386_ISA_ICU_H_ - -#ifndef LOCORE - -#ifdef APIC_IO - -/* -#define MP_SAFE - * Note: - * Most of the SMP equivilants of the icu macros are coded - * elsewhere in an MP-safe fashion. - * In particular note that the 'imen' variable is opaque. - * DO NOT access imen directly, use INTREN()/INTRDIS(). - */ - -void INTREN __P((u_int)); -void INTRDIS __P((u_int)); -#define INTRMASK(msk,s) (msk |= (s)) -#define INTRUNMASK(msk,s) (msk &= ~(s)) - -#else /* APIC_IO */ - -/* - * Interrupt "level" mechanism variables, masks, and macros - */ -extern unsigned imen; /* interrupt mask enable */ - -#define INTREN(s) (imen &= ~(s), SET_ICUS()) -#define INTRDIS(s) (imen |= (s), SET_ICUS()) -#define INTRMASK(msk,s) (msk |= (s)) -#define INTRUNMASK(msk,s) (msk &= ~(s)) - -#if 0 -#ifdef PC98 -#define SET_ICUS() (outb(IO_ICU1 + 2, imen), outb(IU_ICU2 + 2, imen >> 8)) -#define INTRGET() ((inb(IO_ICU2) << 8 | inb(IO_ICU1)) & 0xffff) -#else /* IBM-PC */ -#define SET_ICUS() (outb(IO_ICU1 + 1, imen), outb(IU_ICU2 + 1, imen >> 8)) -#define INTRGET() ((inb(IO_ICU2) << 8 | inb(IO_ICU1)) & 0xffff) -#endif /* PC98 */ -#else -/* - * XXX - IO_ICU* are defined in isa.h, not icu.h, and nothing much bothers to - * include isa.h, while too many things include icu.h. - */ -#ifdef PC98 -#define SET_ICUS() (outb(0x02, imen), outb(0x0a, imen >> 8)) -/* XXX is this correct? */ -#define INTRGET() ((inb(0x0a) << 8 | inb(0x02)) & 0xffff) -#else -#define SET_ICUS() (outb(0x21, imen), outb(0xa1, imen >> 8)) -#define INTRGET() ((inb(0xa1) << 8 | inb(0x21)) & 0xffff) -#endif -#endif - -#endif /* APIC_IO */ - -#endif /* LOCORE */ - - -#ifdef APIC_IO -/* - * Note: The APIC uses different values for IRQxxx. - * Unfortunately many drivers use the 8259 values as indexes - * into tables, etc. The APIC equivilants are kept as APIC_IRQxxx. - * The 8259 versions have to be used in SMP for legacy operation - * of the drivers. - */ -#endif /* APIC_IO */ - -/* - * Interrupt enable bits - in normal order of priority (which we change) - */ -#define IRQ0 0x0001 /* highest priority - timer */ -#define IRQ1 0x0002 -#define IRQ_SLAVE 0x0004 -#define IRQ8 0x0100 -#define IRQ9 0x0200 -#define IRQ2 IRQ9 -#define IRQ10 0x0400 -#define IRQ11 0x0800 -#define IRQ12 0x1000 -#define IRQ13 0x2000 -#define IRQ14 0x4000 -#define IRQ15 0x8000 -#define IRQ3 0x0008 /* this is highest after rotation */ -#define IRQ4 0x0010 -#define IRQ5 0x0020 -#define IRQ6 0x0040 -#define IRQ7 0x0080 /* lowest - parallel printer */ - -#ifdef PC98 -#undef IRQ2 -#define IRQ2 0x0004 -#undef IRQ_SLAVE -#define IRQ_SLAVE 0x0080 -#endif - - -/* - * Interrupt Control offset into Interrupt descriptor table (IDT) - */ -#define ICU_OFFSET 32 /* 0-31 are processor exceptions */ - -#ifdef APIC_IO - -/* 32-47: ISA IRQ0-IRQ15, 48-55: IO APIC IRQ16-IRQ23 */ -#define ICU_LEN 24 - -#else - -#define ICU_LEN 16 /* 32-47 are ISA interrupts */ - -#endif /* APIC_IO */ - -#endif /* !_I386_ISA_ICU_H_ */ diff --git a/sys/amd64/isa/icu_ipl.S b/sys/amd64/isa/icu_ipl.S deleted file mode 100644 index 4d917254c0a0..000000000000 --- a/sys/amd64/isa/icu_ipl.S +++ /dev/null @@ -1,170 +0,0 @@ -/*- - * Copyright (c) 1989, 1990 William F. Jolitz. - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * William Jolitz. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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. - * - * $Id: icu_ipl.s,v 1.3 1997/09/02 19:40:13 fsmp Exp $ - */ - - .data - ALIGN_DATA -vec: - .long vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7 - .long vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15 - -/* interrupt mask enable (all h/w off) */ - .globl _imen -_imen: .long HWI_MASK - - -/* - * - */ - .text - SUPERALIGN_TEXT - -/* - * Interrupt priority mechanism - * -- soft splXX masks with group mechanism (cpl) - * -- h/w masks for currently active or unused interrupts (imen) - * -- ipending = active interrupts currently masked by cpl - */ - -ENTRY(splz) - /* - * The caller has restored cpl and checked that (ipending & ~cpl) - * is nonzero. We have to repeat the check since if there is an - * interrupt while we're looking, _doreti processing for the - * interrupt will handle all the unmasked pending interrupts - * because we restored early. We're repeating the calculation - * of (ipending & ~cpl) anyway so that the caller doesn't have - * to pass it, so this only costs one "jne". "bsfl %ecx,%ecx" - * is undefined when %ecx is 0 so we can't rely on the secondary - * btrl tests. - */ - movl _cpl,%eax -splz_next: - /* - * We don't need any locking here. (ipending & ~cpl) cannot grow - * while we're looking at it - any interrupt will shrink it to 0. - */ - movl %eax,%ecx - notl %ecx - andl _ipending,%ecx - jne splz_unpend - ret - - ALIGN_TEXT -splz_unpend: - bsfl %ecx,%ecx - btrl %ecx,_ipending - jnc splz_next - cmpl $NHWI,%ecx - jae splz_swi - /* - * We would prefer to call the intr handler directly here but that - * doesn't work for badly behaved handlers that want the interrupt - * frame. Also, there's a problem determining the unit number. - * We should change the interface so that the unit number is not - * determined at config time. - */ - jmp *vec(,%ecx,4) - - ALIGN_TEXT -splz_swi: - cmpl $SWI_AST,%ecx - je splz_next /* "can't happen" */ - pushl %eax - orl imasks(,%ecx,4),%eax - movl %eax,_cpl - call *_ihandlers(,%ecx,4) - popl %eax - movl %eax,_cpl - jmp splz_next - -/* - * Fake clock interrupt(s) so that they appear to come from our caller instead - * of from here, so that system profiling works. - * XXX do this more generally (for all vectors; look up the C entry point). - * XXX frame bogusness stops us from just jumping to the C entry point. - */ - ALIGN_TEXT -vec0: - popl %eax /* return address */ - pushfl - pushl $KCSEL - pushl %eax - cli - MEXITCOUNT - jmp _Xintr0 /* XXX might need _Xfastintr0 */ - -#ifndef PC98 - ALIGN_TEXT -vec8: - popl %eax - pushfl - pushl $KCSEL - pushl %eax - cli - MEXITCOUNT - jmp _Xintr8 /* XXX might need _Xfastintr8 */ -#endif /* PC98 */ - -/* - * The 'generic' vector stubs. - */ - -#define BUILD_VEC(irq_num) \ - ALIGN_TEXT ; \ -__CONCAT(vec,irq_num): ; \ - int $ICU_OFFSET + (irq_num) ; \ - ret - - BUILD_VEC(1) - BUILD_VEC(2) - BUILD_VEC(3) - BUILD_VEC(4) - BUILD_VEC(5) - BUILD_VEC(6) - BUILD_VEC(7) -#ifdef PC98 - BUILD_VEC(8) -#endif - BUILD_VEC(9) - BUILD_VEC(10) - BUILD_VEC(11) - BUILD_VEC(12) - BUILD_VEC(13) - BUILD_VEC(14) - BUILD_VEC(15) diff --git a/sys/amd64/isa/icu_ipl.s b/sys/amd64/isa/icu_ipl.s deleted file mode 100644 index 4d917254c0a0..000000000000 --- a/sys/amd64/isa/icu_ipl.s +++ /dev/null @@ -1,170 +0,0 @@ -/*- - * Copyright (c) 1989, 1990 William F. Jolitz. - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * William Jolitz. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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. - * - * $Id: icu_ipl.s,v 1.3 1997/09/02 19:40:13 fsmp Exp $ - */ - - .data - ALIGN_DATA -vec: - .long vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7 - .long vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15 - -/* interrupt mask enable (all h/w off) */ - .globl _imen -_imen: .long HWI_MASK - - -/* - * - */ - .text - SUPERALIGN_TEXT - -/* - * Interrupt priority mechanism - * -- soft splXX masks with group mechanism (cpl) - * -- h/w masks for currently active or unused interrupts (imen) - * -- ipending = active interrupts currently masked by cpl - */ - -ENTRY(splz) - /* - * The caller has restored cpl and checked that (ipending & ~cpl) - * is nonzero. We have to repeat the check since if there is an - * interrupt while we're looking, _doreti processing for the - * interrupt will handle all the unmasked pending interrupts - * because we restored early. We're repeating the calculation - * of (ipending & ~cpl) anyway so that the caller doesn't have - * to pass it, so this only costs one "jne". "bsfl %ecx,%ecx" - * is undefined when %ecx is 0 so we can't rely on the secondary - * btrl tests. - */ - movl _cpl,%eax -splz_next: - /* - * We don't need any locking here. (ipending & ~cpl) cannot grow - * while we're looking at it - any interrupt will shrink it to 0. - */ - movl %eax,%ecx - notl %ecx - andl _ipending,%ecx - jne splz_unpend - ret - - ALIGN_TEXT -splz_unpend: - bsfl %ecx,%ecx - btrl %ecx,_ipending - jnc splz_next - cmpl $NHWI,%ecx - jae splz_swi - /* - * We would prefer to call the intr handler directly here but that - * doesn't work for badly behaved handlers that want the interrupt - * frame. Also, there's a problem determining the unit number. - * We should change the interface so that the unit number is not - * determined at config time. - */ - jmp *vec(,%ecx,4) - - ALIGN_TEXT -splz_swi: - cmpl $SWI_AST,%ecx - je splz_next /* "can't happen" */ - pushl %eax - orl imasks(,%ecx,4),%eax - movl %eax,_cpl - call *_ihandlers(,%ecx,4) - popl %eax - movl %eax,_cpl - jmp splz_next - -/* - * Fake clock interrupt(s) so that they appear to come from our caller instead - * of from here, so that system profiling works. - * XXX do this more generally (for all vectors; look up the C entry point). - * XXX frame bogusness stops us from just jumping to the C entry point. - */ - ALIGN_TEXT -vec0: - popl %eax /* return address */ - pushfl - pushl $KCSEL - pushl %eax - cli - MEXITCOUNT - jmp _Xintr0 /* XXX might need _Xfastintr0 */ - -#ifndef PC98 - ALIGN_TEXT -vec8: - popl %eax - pushfl - pushl $KCSEL - pushl %eax - cli - MEXITCOUNT - jmp _Xintr8 /* XXX might need _Xfastintr8 */ -#endif /* PC98 */ - -/* - * The 'generic' vector stubs. - */ - -#define BUILD_VEC(irq_num) \ - ALIGN_TEXT ; \ -__CONCAT(vec,irq_num): ; \ - int $ICU_OFFSET + (irq_num) ; \ - ret - - BUILD_VEC(1) - BUILD_VEC(2) - BUILD_VEC(3) - BUILD_VEC(4) - BUILD_VEC(5) - BUILD_VEC(6) - BUILD_VEC(7) -#ifdef PC98 - BUILD_VEC(8) -#endif - BUILD_VEC(9) - BUILD_VEC(10) - BUILD_VEC(11) - BUILD_VEC(12) - BUILD_VEC(13) - BUILD_VEC(14) - BUILD_VEC(15) diff --git a/sys/amd64/isa/icu_vector.S b/sys/amd64/isa/icu_vector.S deleted file mode 100644 index 042614b829e2..000000000000 --- a/sys/amd64/isa/icu_vector.S +++ /dev/null @@ -1,250 +0,0 @@ -/* - * from: vector.s, 386BSD 0.1 unknown origin - * $Id: icu_vector.s,v 1.8 1998/08/11 15:08:12 bde Exp $ - */ - -/* - * modified for PC98 by Kakefuda - */ - -#ifdef PC98 -#define ICU_IMR_OFFSET 2 /* IO_ICU{1,2} + 2 */ -#else -#define ICU_IMR_OFFSET 1 /* IO_ICU{1,2} + 1 */ -#endif - -#define ICU_EOI 0x20 /* XXX - define elsewhere */ - -#define IRQ_BIT(irq_num) (1 << ((irq_num) % 8)) -#define IRQ_BYTE(irq_num) ((irq_num) >> 3) - -#ifdef AUTO_EOI_1 -#define ENABLE_ICU1 /* use auto-EOI to reduce i/o */ -#define OUTB_ICU1 -#else -#define ENABLE_ICU1 \ - movb $ICU_EOI,%al ; /* as soon as possible send EOI ... */ \ - OUTB_ICU1 /* ... to clear in service bit */ -#define OUTB_ICU1 \ - outb %al,$IO_ICU1 -#endif - -#ifdef AUTO_EOI_2 -/* - * The data sheet says no auto-EOI on slave, but it sometimes works. - */ -#define ENABLE_ICU1_AND_2 ENABLE_ICU1 -#else -#define ENABLE_ICU1_AND_2 \ - movb $ICU_EOI,%al ; /* as above */ \ - outb %al,$IO_ICU2 ; /* but do second icu first ... */ \ - OUTB_ICU1 /* ... then first icu (if !AUTO_EOI_1) */ -#endif - -/* - * Macros for interrupt interrupt entry, call to handler, and exit. - */ - -#define FAST_INTR(irq_num, vec_name, enable_icus) \ - .text ; \ - SUPERALIGN_TEXT ; \ -IDTVEC(vec_name) ; \ - pushl %eax ; /* save only call-used registers */ \ - pushl %ecx ; \ - pushl %edx ; \ - pushl %ds ; \ - MAYBE_PUSHL_ES ; \ - movl $KDSEL,%eax ; \ - movl %ax,%ds ; \ - MAYBE_MOVW_AX_ES ; \ - FAKE_MCOUNT((4+ACTUALLY_PUSHED)*4(%esp)) ; \ - pushl _intr_unit + (irq_num) * 4 ; \ - call *_intr_handler + (irq_num) * 4 ; /* do the work ASAP */ \ - enable_icus ; /* (re)enable ASAP (helps edge trigger?) */ \ - addl $4,%esp ; \ - incl _cnt+V_INTR ; /* book-keeping can wait */ \ - movl _intr_countp + (irq_num) * 4,%eax ; \ - incl (%eax) ; \ - movl _cpl,%eax ; /* are we unmasking pending HWIs or SWIs? */ \ - notl %eax ; \ - andl _ipending,%eax ; \ - jne 2f ; /* yes, maybe handle them */ \ -1: ; \ - MEXITCOUNT ; \ - MAYBE_POPL_ES ; \ - popl %ds ; \ - popl %edx ; \ - popl %ecx ; \ - popl %eax ; \ - iret ; \ -; \ - ALIGN_TEXT ; \ -2: ; \ - cmpb $3,_intr_nesting_level ; /* is there enough stack? */ \ - jae 1b ; /* no, return */ \ - movl _cpl,%eax ; \ - /* XXX next line is probably unnecessary now. */ \ - movl $HWI_MASK|SWI_MASK,_cpl ; /* limit nesting ... */ \ - incb _intr_nesting_level ; /* ... really limit it ... */ \ - sti ; /* ... to do this as early as possible */ \ - MAYBE_POPL_ES ; /* discard most of thin frame ... */ \ - popl %ecx ; /* ... original %ds ... */ \ - popl %edx ; \ - xchgl %eax,4(%esp) ; /* orig %eax; save cpl */ \ - pushal ; /* build fat frame (grrr) ... */ \ - pushl %ecx ; /* ... actually %ds ... */ \ - pushl %es ; \ - movl $KDSEL,%eax ; \ - movl %ax,%es ; \ - movl (2+8+0)*4(%esp),%ecx ; /* ... %ecx from thin frame ... */ \ - movl %ecx,(2+6)*4(%esp) ; /* ... to fat frame ... */ \ - movl (2+8+1)*4(%esp),%eax ; /* ... cpl from thin frame */ \ - pushl %eax ; \ - subl $4,%esp ; /* junk for unit number */ \ - MEXITCOUNT ; \ - jmp _doreti - -#define INTR(irq_num, vec_name, icu, enable_icus, reg) \ - .text ; \ - SUPERALIGN_TEXT ; \ -IDTVEC(vec_name) ; \ - pushl $0 ; /* dummy error code */ \ - pushl $0 ; /* dummy trap type */ \ - pushal ; \ - pushl %ds ; /* save our data and extra segments ... */ \ - pushl %es ; \ - movl $KDSEL,%eax ; /* ... and reload with kernel's own ... */ \ - movl %ax,%ds ; /* ... early for obsolete reasons */ \ - movl %ax,%es ; \ - movb _imen + IRQ_BYTE(irq_num),%al ; \ - orb $IRQ_BIT(irq_num),%al ; \ - movb %al,_imen + IRQ_BYTE(irq_num) ; \ - outb %al,$icu+ICU_IMR_OFFSET ; \ - enable_icus ; \ - movl _cpl,%eax ; \ - testb $IRQ_BIT(irq_num),%reg ; \ - jne 2f ; \ - incb _intr_nesting_level ; \ -__CONCAT(Xresume,irq_num): ; \ - FAKE_MCOUNT(12*4(%esp)) ; /* XXX late to avoid double count */ \ - incl _cnt+V_INTR ; /* tally interrupts */ \ - movl _intr_countp + (irq_num) * 4,%eax ; \ - incl (%eax) ; \ - movl _cpl,%eax ; \ - pushl %eax ; \ - pushl _intr_unit + (irq_num) * 4 ; \ - orl _intr_mask + (irq_num) * 4,%eax ; \ - movl %eax,_cpl ; \ - sti ; \ - call *_intr_handler + (irq_num) * 4 ; \ - cli ; /* must unmask _imen and icu atomically */ \ - movb _imen + IRQ_BYTE(irq_num),%al ; \ - andb $~IRQ_BIT(irq_num),%al ; \ - movb %al,_imen + IRQ_BYTE(irq_num) ; \ - outb %al,$icu+ICU_IMR_OFFSET ; \ - sti ; /* XXX _doreti repeats the cli/sti */ \ - MEXITCOUNT ; \ - /* We could usually avoid the following jmp by inlining some of */ \ - /* _doreti, but it's probably better to use less cache. */ \ - jmp _doreti ; \ -; \ - ALIGN_TEXT ; \ -2: ; \ - /* XXX skip mcounting here to avoid double count */ \ - orb $IRQ_BIT(irq_num),_ipending + IRQ_BYTE(irq_num) ; \ - popl %es ; \ - popl %ds ; \ - popal ; \ - addl $4+4,%esp ; \ - iret - -MCOUNT_LABEL(bintr) - FAST_INTR(0,fastintr0, ENABLE_ICU1) - FAST_INTR(1,fastintr1, ENABLE_ICU1) - FAST_INTR(2,fastintr2, ENABLE_ICU1) - FAST_INTR(3,fastintr3, ENABLE_ICU1) - FAST_INTR(4,fastintr4, ENABLE_ICU1) - FAST_INTR(5,fastintr5, ENABLE_ICU1) - FAST_INTR(6,fastintr6, ENABLE_ICU1) - FAST_INTR(7,fastintr7, ENABLE_ICU1) - FAST_INTR(8,fastintr8, ENABLE_ICU1_AND_2) - FAST_INTR(9,fastintr9, ENABLE_ICU1_AND_2) - FAST_INTR(10,fastintr10, ENABLE_ICU1_AND_2) - FAST_INTR(11,fastintr11, ENABLE_ICU1_AND_2) - FAST_INTR(12,fastintr12, ENABLE_ICU1_AND_2) - FAST_INTR(13,fastintr13, ENABLE_ICU1_AND_2) - FAST_INTR(14,fastintr14, ENABLE_ICU1_AND_2) - FAST_INTR(15,fastintr15, ENABLE_ICU1_AND_2) - INTR(0,intr0, IO_ICU1, ENABLE_ICU1, al) - INTR(1,intr1, IO_ICU1, ENABLE_ICU1, al) - INTR(2,intr2, IO_ICU1, ENABLE_ICU1, al) - INTR(3,intr3, IO_ICU1, ENABLE_ICU1, al) - INTR(4,intr4, IO_ICU1, ENABLE_ICU1, al) - INTR(5,intr5, IO_ICU1, ENABLE_ICU1, al) - INTR(6,intr6, IO_ICU1, ENABLE_ICU1, al) - INTR(7,intr7, IO_ICU1, ENABLE_ICU1, al) - INTR(8,intr8, IO_ICU2, ENABLE_ICU1_AND_2, ah) - INTR(9,intr9, IO_ICU2, ENABLE_ICU1_AND_2, ah) - INTR(10,intr10, IO_ICU2, ENABLE_ICU1_AND_2, ah) - INTR(11,intr11, IO_ICU2, ENABLE_ICU1_AND_2, ah) - INTR(12,intr12, IO_ICU2, ENABLE_ICU1_AND_2, ah) - INTR(13,intr13, IO_ICU2, ENABLE_ICU1_AND_2, ah) - INTR(14,intr14, IO_ICU2, ENABLE_ICU1_AND_2, ah) - INTR(15,intr15, IO_ICU2, ENABLE_ICU1_AND_2, ah) -MCOUNT_LABEL(eintr) - - .data - .globl _ihandlers -_ihandlers: /* addresses of interrupt handlers */ - /* actually resumption addresses for HWI's */ - .long Xresume0, Xresume1, Xresume2, Xresume3 - .long Xresume4, Xresume5, Xresume6, Xresume7 - .long Xresume8, Xresume9, Xresume10, Xresume11 - .long Xresume12, Xresume13, Xresume14, Xresume15 - .long _swi_null, swi_net, _swi_null, _swi_null - .long _swi_vm, _swi_null, _swi_null, _swi_null - .long _swi_null, _swi_null, _swi_null, _swi_null - .long _swi_null, _swi_null, _softclock, swi_ast - -imasks: /* masks for interrupt handlers */ - .space NHWI*4 /* padding; HWI masks are elsewhere */ - - .long SWI_TTY_MASK, SWI_NET_MASK, SWI_CAMNET_MASK, SWI_CAMBIO_MASK - .long SWI_VM_MASK, 0, 0, 0 - .long 0, 0, 0, 0 - .long 0, 0, SWI_CLOCK_MASK, SWI_AST_MASK - -/* - * Interrupt counters and names. The format of these and the label names - * must agree with what vmstat expects. The tables are indexed by device - * ids so that we don't have to move the names around as devices are - * attached. - */ -#include "vector.h" - .globl _intrcnt, _eintrcnt -_intrcnt: - .space (NR_DEVICES + ICU_LEN) * 4 -_eintrcnt: - - .globl _intrnames, _eintrnames -_intrnames: - .ascii DEVICE_NAMES - .asciz "stray irq0" - .asciz "stray irq1" - .asciz "stray irq2" - .asciz "stray irq3" - .asciz "stray irq4" - .asciz "stray irq5" - .asciz "stray irq6" - .asciz "stray irq7" - .asciz "stray irq8" - .asciz "stray irq9" - .asciz "stray irq10" - .asciz "stray irq11" - .asciz "stray irq12" - .asciz "stray irq13" - .asciz "stray irq14" - .asciz "stray irq15" -_eintrnames: - - .text diff --git a/sys/amd64/isa/icu_vector.s b/sys/amd64/isa/icu_vector.s deleted file mode 100644 index 042614b829e2..000000000000 --- a/sys/amd64/isa/icu_vector.s +++ /dev/null @@ -1,250 +0,0 @@ -/* - * from: vector.s, 386BSD 0.1 unknown origin - * $Id: icu_vector.s,v 1.8 1998/08/11 15:08:12 bde Exp $ - */ - -/* - * modified for PC98 by Kakefuda - */ - -#ifdef PC98 -#define ICU_IMR_OFFSET 2 /* IO_ICU{1,2} + 2 */ -#else -#define ICU_IMR_OFFSET 1 /* IO_ICU{1,2} + 1 */ -#endif - -#define ICU_EOI 0x20 /* XXX - define elsewhere */ - -#define IRQ_BIT(irq_num) (1 << ((irq_num) % 8)) -#define IRQ_BYTE(irq_num) ((irq_num) >> 3) - -#ifdef AUTO_EOI_1 -#define ENABLE_ICU1 /* use auto-EOI to reduce i/o */ -#define OUTB_ICU1 -#else -#define ENABLE_ICU1 \ - movb $ICU_EOI,%al ; /* as soon as possible send EOI ... */ \ - OUTB_ICU1 /* ... to clear in service bit */ -#define OUTB_ICU1 \ - outb %al,$IO_ICU1 -#endif - -#ifdef AUTO_EOI_2 -/* - * The data sheet says no auto-EOI on slave, but it sometimes works. - */ -#define ENABLE_ICU1_AND_2 ENABLE_ICU1 -#else -#define ENABLE_ICU1_AND_2 \ - movb $ICU_EOI,%al ; /* as above */ \ - outb %al,$IO_ICU2 ; /* but do second icu first ... */ \ - OUTB_ICU1 /* ... then first icu (if !AUTO_EOI_1) */ -#endif - -/* - * Macros for interrupt interrupt entry, call to handler, and exit. - */ - -#define FAST_INTR(irq_num, vec_name, enable_icus) \ - .text ; \ - SUPERALIGN_TEXT ; \ -IDTVEC(vec_name) ; \ - pushl %eax ; /* save only call-used registers */ \ - pushl %ecx ; \ - pushl %edx ; \ - pushl %ds ; \ - MAYBE_PUSHL_ES ; \ - movl $KDSEL,%eax ; \ - movl %ax,%ds ; \ - MAYBE_MOVW_AX_ES ; \ - FAKE_MCOUNT((4+ACTUALLY_PUSHED)*4(%esp)) ; \ - pushl _intr_unit + (irq_num) * 4 ; \ - call *_intr_handler + (irq_num) * 4 ; /* do the work ASAP */ \ - enable_icus ; /* (re)enable ASAP (helps edge trigger?) */ \ - addl $4,%esp ; \ - incl _cnt+V_INTR ; /* book-keeping can wait */ \ - movl _intr_countp + (irq_num) * 4,%eax ; \ - incl (%eax) ; \ - movl _cpl,%eax ; /* are we unmasking pending HWIs or SWIs? */ \ - notl %eax ; \ - andl _ipending,%eax ; \ - jne 2f ; /* yes, maybe handle them */ \ -1: ; \ - MEXITCOUNT ; \ - MAYBE_POPL_ES ; \ - popl %ds ; \ - popl %edx ; \ - popl %ecx ; \ - popl %eax ; \ - iret ; \ -; \ - ALIGN_TEXT ; \ -2: ; \ - cmpb $3,_intr_nesting_level ; /* is there enough stack? */ \ - jae 1b ; /* no, return */ \ - movl _cpl,%eax ; \ - /* XXX next line is probably unnecessary now. */ \ - movl $HWI_MASK|SWI_MASK,_cpl ; /* limit nesting ... */ \ - incb _intr_nesting_level ; /* ... really limit it ... */ \ - sti ; /* ... to do this as early as possible */ \ - MAYBE_POPL_ES ; /* discard most of thin frame ... */ \ - popl %ecx ; /* ... original %ds ... */ \ - popl %edx ; \ - xchgl %eax,4(%esp) ; /* orig %eax; save cpl */ \ - pushal ; /* build fat frame (grrr) ... */ \ - pushl %ecx ; /* ... actually %ds ... */ \ - pushl %es ; \ - movl $KDSEL,%eax ; \ - movl %ax,%es ; \ - movl (2+8+0)*4(%esp),%ecx ; /* ... %ecx from thin frame ... */ \ - movl %ecx,(2+6)*4(%esp) ; /* ... to fat frame ... */ \ - movl (2+8+1)*4(%esp),%eax ; /* ... cpl from thin frame */ \ - pushl %eax ; \ - subl $4,%esp ; /* junk for unit number */ \ - MEXITCOUNT ; \ - jmp _doreti - -#define INTR(irq_num, vec_name, icu, enable_icus, reg) \ - .text ; \ - SUPERALIGN_TEXT ; \ -IDTVEC(vec_name) ; \ - pushl $0 ; /* dummy error code */ \ - pushl $0 ; /* dummy trap type */ \ - pushal ; \ - pushl %ds ; /* save our data and extra segments ... */ \ - pushl %es ; \ - movl $KDSEL,%eax ; /* ... and reload with kernel's own ... */ \ - movl %ax,%ds ; /* ... early for obsolete reasons */ \ - movl %ax,%es ; \ - movb _imen + IRQ_BYTE(irq_num),%al ; \ - orb $IRQ_BIT(irq_num),%al ; \ - movb %al,_imen + IRQ_BYTE(irq_num) ; \ - outb %al,$icu+ICU_IMR_OFFSET ; \ - enable_icus ; \ - movl _cpl,%eax ; \ - testb $IRQ_BIT(irq_num),%reg ; \ - jne 2f ; \ - incb _intr_nesting_level ; \ -__CONCAT(Xresume,irq_num): ; \ - FAKE_MCOUNT(12*4(%esp)) ; /* XXX late to avoid double count */ \ - incl _cnt+V_INTR ; /* tally interrupts */ \ - movl _intr_countp + (irq_num) * 4,%eax ; \ - incl (%eax) ; \ - movl _cpl,%eax ; \ - pushl %eax ; \ - pushl _intr_unit + (irq_num) * 4 ; \ - orl _intr_mask + (irq_num) * 4,%eax ; \ - movl %eax,_cpl ; \ - sti ; \ - call *_intr_handler + (irq_num) * 4 ; \ - cli ; /* must unmask _imen and icu atomically */ \ - movb _imen + IRQ_BYTE(irq_num),%al ; \ - andb $~IRQ_BIT(irq_num),%al ; \ - movb %al,_imen + IRQ_BYTE(irq_num) ; \ - outb %al,$icu+ICU_IMR_OFFSET ; \ - sti ; /* XXX _doreti repeats the cli/sti */ \ - MEXITCOUNT ; \ - /* We could usually avoid the following jmp by inlining some of */ \ - /* _doreti, but it's probably better to use less cache. */ \ - jmp _doreti ; \ -; \ - ALIGN_TEXT ; \ -2: ; \ - /* XXX skip mcounting here to avoid double count */ \ - orb $IRQ_BIT(irq_num),_ipending + IRQ_BYTE(irq_num) ; \ - popl %es ; \ - popl %ds ; \ - popal ; \ - addl $4+4,%esp ; \ - iret - -MCOUNT_LABEL(bintr) - FAST_INTR(0,fastintr0, ENABLE_ICU1) - FAST_INTR(1,fastintr1, ENABLE_ICU1) - FAST_INTR(2,fastintr2, ENABLE_ICU1) - FAST_INTR(3,fastintr3, ENABLE_ICU1) - FAST_INTR(4,fastintr4, ENABLE_ICU1) - FAST_INTR(5,fastintr5, ENABLE_ICU1) - FAST_INTR(6,fastintr6, ENABLE_ICU1) - FAST_INTR(7,fastintr7, ENABLE_ICU1) - FAST_INTR(8,fastintr8, ENABLE_ICU1_AND_2) - FAST_INTR(9,fastintr9, ENABLE_ICU1_AND_2) - FAST_INTR(10,fastintr10, ENABLE_ICU1_AND_2) - FAST_INTR(11,fastintr11, ENABLE_ICU1_AND_2) - FAST_INTR(12,fastintr12, ENABLE_ICU1_AND_2) - FAST_INTR(13,fastintr13, ENABLE_ICU1_AND_2) - FAST_INTR(14,fastintr14, ENABLE_ICU1_AND_2) - FAST_INTR(15,fastintr15, ENABLE_ICU1_AND_2) - INTR(0,intr0, IO_ICU1, ENABLE_ICU1, al) - INTR(1,intr1, IO_ICU1, ENABLE_ICU1, al) - INTR(2,intr2, IO_ICU1, ENABLE_ICU1, al) - INTR(3,intr3, IO_ICU1, ENABLE_ICU1, al) - INTR(4,intr4, IO_ICU1, ENABLE_ICU1, al) - INTR(5,intr5, IO_ICU1, ENABLE_ICU1, al) - INTR(6,intr6, IO_ICU1, ENABLE_ICU1, al) - INTR(7,intr7, IO_ICU1, ENABLE_ICU1, al) - INTR(8,intr8, IO_ICU2, ENABLE_ICU1_AND_2, ah) - INTR(9,intr9, IO_ICU2, ENABLE_ICU1_AND_2, ah) - INTR(10,intr10, IO_ICU2, ENABLE_ICU1_AND_2, ah) - INTR(11,intr11, IO_ICU2, ENABLE_ICU1_AND_2, ah) - INTR(12,intr12, IO_ICU2, ENABLE_ICU1_AND_2, ah) - INTR(13,intr13, IO_ICU2, ENABLE_ICU1_AND_2, ah) - INTR(14,intr14, IO_ICU2, ENABLE_ICU1_AND_2, ah) - INTR(15,intr15, IO_ICU2, ENABLE_ICU1_AND_2, ah) -MCOUNT_LABEL(eintr) - - .data - .globl _ihandlers -_ihandlers: /* addresses of interrupt handlers */ - /* actually resumption addresses for HWI's */ - .long Xresume0, Xresume1, Xresume2, Xresume3 - .long Xresume4, Xresume5, Xresume6, Xresume7 - .long Xresume8, Xresume9, Xresume10, Xresume11 - .long Xresume12, Xresume13, Xresume14, Xresume15 - .long _swi_null, swi_net, _swi_null, _swi_null - .long _swi_vm, _swi_null, _swi_null, _swi_null - .long _swi_null, _swi_null, _swi_null, _swi_null - .long _swi_null, _swi_null, _softclock, swi_ast - -imasks: /* masks for interrupt handlers */ - .space NHWI*4 /* padding; HWI masks are elsewhere */ - - .long SWI_TTY_MASK, SWI_NET_MASK, SWI_CAMNET_MASK, SWI_CAMBIO_MASK - .long SWI_VM_MASK, 0, 0, 0 - .long 0, 0, 0, 0 - .long 0, 0, SWI_CLOCK_MASK, SWI_AST_MASK - -/* - * Interrupt counters and names. The format of these and the label names - * must agree with what vmstat expects. The tables are indexed by device - * ids so that we don't have to move the names around as devices are - * attached. - */ -#include "vector.h" - .globl _intrcnt, _eintrcnt -_intrcnt: - .space (NR_DEVICES + ICU_LEN) * 4 -_eintrcnt: - - .globl _intrnames, _eintrnames -_intrnames: - .ascii DEVICE_NAMES - .asciz "stray irq0" - .asciz "stray irq1" - .asciz "stray irq2" - .asciz "stray irq3" - .asciz "stray irq4" - .asciz "stray irq5" - .asciz "stray irq6" - .asciz "stray irq7" - .asciz "stray irq8" - .asciz "stray irq9" - .asciz "stray irq10" - .asciz "stray irq11" - .asciz "stray irq12" - .asciz "stray irq13" - .asciz "stray irq14" - .asciz "stray irq15" -_eintrnames: - - .text diff --git a/sys/amd64/isa/intr_machdep.c b/sys/amd64/isa/intr_machdep.c deleted file mode 100644 index 0254195f5ddb..000000000000 --- a/sys/amd64/isa/intr_machdep.c +++ /dev/null @@ -1,501 +0,0 @@ -/*- - * Copyright (c) 1991 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * William Jolitz. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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. - * - * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 - * $Id: intr_machdep.c,v 1.15 1998/12/04 22:54:46 archie Exp $ - */ - -#include "opt_auto_eoi.h" - -#include <sys/param.h> -#ifndef SMP -#include <machine/lock.h> -#endif -#include <sys/systm.h> -#include <sys/syslog.h> -#include <machine/ipl.h> -#include <machine/md_var.h> -#include <machine/segments.h> -#if defined(APIC_IO) -#include <machine/smp.h> -#include <machine/smptests.h> /** FAST_HI */ -#endif /* APIC_IO */ -#include <i386/isa/isa_device.h> -#ifdef PC98 -#include <pc98/pc98/pc98.h> -#include <pc98/pc98/pc98_machdep.h> -#include <pc98/pc98/epsonio.h> -#else -#include <i386/isa/isa.h> -#endif -#include <i386/isa/icu.h> -#include "vector.h" - -#include <i386/isa/intr_machdep.h> -#include <sys/interrupt.h> -#ifdef APIC_IO -#include <machine/clock.h> -#endif - -/* XXX should be in suitable include files */ -#ifdef PC98 -#define ICU_IMR_OFFSET 2 /* IO_ICU{1,2} + 2 */ -#define ICU_SLAVEID 7 -#else -#define ICU_IMR_OFFSET 1 /* IO_ICU{1,2} + 1 */ -#define ICU_SLAVEID 2 -#endif - -#ifdef APIC_IO -/* - * This is to accommodate "mixed-mode" programming for - * motherboards that don't connect the 8254 to the IO APIC. - */ -#define AUTO_EOI_1 1 -#endif - -u_long *intr_countp[ICU_LEN]; -inthand2_t *intr_handler[ICU_LEN]; -u_int intr_mask[ICU_LEN]; -static u_int* intr_mptr[ICU_LEN]; -void *intr_unit[ICU_LEN]; - -static inthand_t *fastintr[ICU_LEN] = { - &IDTVEC(fastintr0), &IDTVEC(fastintr1), - &IDTVEC(fastintr2), &IDTVEC(fastintr3), - &IDTVEC(fastintr4), &IDTVEC(fastintr5), - &IDTVEC(fastintr6), &IDTVEC(fastintr7), - &IDTVEC(fastintr8), &IDTVEC(fastintr9), - &IDTVEC(fastintr10), &IDTVEC(fastintr11), - &IDTVEC(fastintr12), &IDTVEC(fastintr13), - &IDTVEC(fastintr14), &IDTVEC(fastintr15) -#if defined(APIC_IO) - , &IDTVEC(fastintr16), &IDTVEC(fastintr17), - &IDTVEC(fastintr18), &IDTVEC(fastintr19), - &IDTVEC(fastintr20), &IDTVEC(fastintr21), - &IDTVEC(fastintr22), &IDTVEC(fastintr23) -#endif /* APIC_IO */ -}; - -static inthand_t *slowintr[ICU_LEN] = { - &IDTVEC(intr0), &IDTVEC(intr1), &IDTVEC(intr2), &IDTVEC(intr3), - &IDTVEC(intr4), &IDTVEC(intr5), &IDTVEC(intr6), &IDTVEC(intr7), - &IDTVEC(intr8), &IDTVEC(intr9), &IDTVEC(intr10), &IDTVEC(intr11), - &IDTVEC(intr12), &IDTVEC(intr13), &IDTVEC(intr14), &IDTVEC(intr15) -#if defined(APIC_IO) - , &IDTVEC(intr16), &IDTVEC(intr17), &IDTVEC(intr18), &IDTVEC(intr19), - &IDTVEC(intr20), &IDTVEC(intr21), &IDTVEC(intr22), &IDTVEC(intr23) -#endif /* APIC_IO */ -}; - -static inthand2_t isa_strayintr; - -#ifdef PC98 -#define NMI_PARITY 0x04 -#define NMI_EPARITY 0x02 -#else -#define NMI_PARITY (1 << 7) -#define NMI_IOCHAN (1 << 6) -#define ENMI_WATCHDOG (1 << 7) -#define ENMI_BUSTIMER (1 << 6) -#define ENMI_IOSTATUS (1 << 5) -#endif - -/* - * Handle a NMI, possibly a machine check. - * return true to panic system, false to ignore. - */ -int -isa_nmi(cd) - int cd; -{ -#ifdef PC98 - int port = inb(0x33); - if (epson_machine_id == 0x20) - epson_outb(0xc16, epson_inb(0xc16) | 0x1); - if (port & NMI_PARITY) { - panic("BASE RAM parity error, likely hardware failure."); - } else if (port & NMI_EPARITY) { - panic("EXTENDED RAM parity error, likely hardware failure."); - } else { - printf("\nNMI Resume ??\n"); - return(0); - } -#else /* IBM-PC */ - int isa_port = inb(0x61); - int eisa_port = inb(0x461); - - if (isa_port & NMI_PARITY) - panic("RAM parity error, likely hardware failure."); - - if (isa_port & NMI_IOCHAN) - panic("I/O channel check, likely hardware failure."); - - /* - * On a real EISA machine, this will never happen. However it can - * happen on ISA machines which implement XT style floating point - * error handling (very rare). Save them from a meaningless panic. - */ - if (eisa_port == 0xff) - return(0); - - if (eisa_port & ENMI_WATCHDOG) - panic("EISA watchdog timer expired, likely hardware failure."); - - if (eisa_port & ENMI_BUSTIMER) - panic("EISA bus timeout, likely hardware failure."); - - if (eisa_port & ENMI_IOSTATUS) - panic("EISA I/O port status error."); - - printf("\nNMI ISA %x, EISA %x\n", isa_port, eisa_port); - return(0); -#endif -} - -/* - * Fill in default interrupt table (in case of spuruious interrupt - * during configuration of kernel, setup interrupt control unit - */ -void -isa_defaultirq() -{ - int i; - - /* icu vectors */ - for (i = 0; i < ICU_LEN; i++) - icu_unset(i, (inthand2_t *)NULL); - - /* initialize 8259's */ - outb(IO_ICU1, 0x11); /* reset; program device, four bytes */ - - outb(IO_ICU1+ICU_IMR_OFFSET, NRSVIDT); /* starting at this vector index */ - outb(IO_ICU1+ICU_IMR_OFFSET, IRQ_SLAVE); /* slave on line 7 */ -#ifdef PC98 -#ifdef AUTO_EOI_1 - outb(IO_ICU1+ICU_IMR_OFFSET, 0x1f); /* (master) auto EOI, 8086 mode */ -#else - outb(IO_ICU1+ICU_IMR_OFFSET, 0x1d); /* (master) 8086 mode */ -#endif -#else /* IBM-PC */ -#ifdef AUTO_EOI_1 - outb(IO_ICU1+ICU_IMR_OFFSET, 2 | 1); /* auto EOI, 8086 mode */ -#else - outb(IO_ICU1+ICU_IMR_OFFSET, 1); /* 8086 mode */ -#endif -#endif /* PC98 */ - outb(IO_ICU1+ICU_IMR_OFFSET, 0xff); /* leave interrupts masked */ - outb(IO_ICU1, 0x0a); /* default to IRR on read */ -#ifndef PC98 - outb(IO_ICU1, 0xc0 | (3 - 1)); /* pri order 3-7, 0-2 (com2 first) */ -#endif /* !PC98 */ - - outb(IO_ICU2, 0x11); /* reset; program device, four bytes */ - outb(IO_ICU2+ICU_IMR_OFFSET, NRSVIDT+8); /* staring at this vector index */ - outb(IO_ICU2+ICU_IMR_OFFSET, ICU_SLAVEID); /* my slave id is 7 */ -#ifdef PC98 - outb(IO_ICU2+ICU_IMR_OFFSET,9); /* 8086 mode */ -#else /* IBM-PC */ -#ifdef AUTO_EOI_2 - outb(IO_ICU2+ICU_IMR_OFFSET, 2 | 1); /* auto EOI, 8086 mode */ -#else - outb(IO_ICU2+ICU_IMR_OFFSET,1); /* 8086 mode */ -#endif -#endif /* PC98 */ - outb(IO_ICU2+ICU_IMR_OFFSET, 0xff); /* leave interrupts masked */ - outb(IO_ICU2, 0x0a); /* default to IRR on read */ -} - -/* - * Caught a stray interrupt, notify - */ -static void -isa_strayintr(vcookiep) - void *vcookiep; -{ - int intr = (void **)vcookiep - &intr_unit[0]; - - /* DON'T BOTHER FOR NOW! */ - /* for some reason, we get bursts of intr #7, even if not enabled! */ - /* - * Well the reason you got bursts of intr #7 is because someone - * raised an interrupt line and dropped it before the 8259 could - * prioritize it. This is documented in the intel data book. This - * means you have BAD hardware! I have changed this so that only - * the first 5 get logged, then it quits logging them, and puts - * out a special message. rgrimes 3/25/1993 - */ - /* - * XXX TODO print a different message for #7 if it is for a - * glitch. Glitches can be distinguished from real #7's by - * testing that the in-service bit is _not_ set. The test - * must be done before sending an EOI so it can't be done if - * we are using AUTO_EOI_1. - */ - if (intrcnt[NR_DEVICES + intr] <= 5) - log(LOG_ERR, "stray irq %d\n", intr); - if (intrcnt[NR_DEVICES + intr] == 5) - log(LOG_CRIT, - "too many stray irq %d's; not logging any more\n", intr); -} - -/* - * Return a bitmap of the current interrupt requests. This is 8259-specific - * and is only suitable for use at probe time. - */ -intrmask_t -isa_irq_pending() -{ - u_char irr1; - u_char irr2; - - irr1 = inb(IO_ICU1); - irr2 = inb(IO_ICU2); - return ((irr2 << 8) | irr1); -} - -int -update_intr_masks(void) -{ - int intr, n=0; - u_int mask,*maskptr; - - for (intr=0; intr < ICU_LEN; intr ++) { -#if defined(APIC_IO) - /* no 8259 SLAVE to ignore */ -#else - if (intr==ICU_SLAVEID) continue; /* ignore 8259 SLAVE output */ -#endif /* APIC_IO */ - maskptr = intr_mptr[intr]; - if (!maskptr) continue; - *maskptr |= 1 << intr; - mask = *maskptr; - if (mask != intr_mask[intr]) { -#if 0 - printf ("intr_mask[%2d] old=%08x new=%08x ptr=%p.\n", - intr, intr_mask[intr], mask, maskptr); -#endif - intr_mask[intr]=mask; - n++; - } - - } - return (n); -} - -/* - * The find_device_id function is only required because of the way the - * device names are currently stored for reporting in systat or vmstat. - * In fact, those programs should be modified to use the sysctl interface - * to obtain a list of driver names by traversing intreclist_head[irq]. - */ -static int -find_device_id(int irq) -{ - char buf[16]; - char *cp; - int free_id, id; - - snprintf(buf, sizeof(buf), "pci irq%d", irq); - cp = intrnames; - /* default to 0, which corresponds to clk0 */ - free_id = 0; - - for (id = 0; id < NR_DEVICES; id++) { - if (strcmp(cp, buf) == 0) - return (id); - if (free_id == 0 && strcmp(cp, "pci irqnn") == 0) - free_id = id; - while (*cp++ != '\0'); - } -#if 0 - if (free_id == 0) { - /* - * All pci irq counters are in use, perhaps because config - * is old so there aren't any. Abuse the clk0 counter. - */ - printf("\tcounting shared irq%d as clk0 irq\n", irq); - } -#endif - return (free_id); -} - -void -update_intrname(int intr, int device_id) -{ - char *cp; - int id; - - if (device_id == -1) - device_id = find_device_id(intr); - - if ((u_int)device_id >= NR_DEVICES) - return; - - intr_countp[intr] = &intrcnt[device_id]; - - for (cp = intrnames, id = 0; id <= device_id; id++) - while (*cp++ != '\0') - ; - if (cp > eintrnames) - return; - if (intr < 10) { - cp[-3] = intr + '0'; - cp[-2] = ' '; - } else if (intr < 20) { - cp[-3] = '1'; - cp[-2] = intr - 10 + '0'; - } else { - cp[-3] = '2'; - cp[-2] = intr - 20 + '0'; - } -} - - -int -icu_setup(int intr, inthand2_t *handler, void *arg, u_int *maskptr, int flags) -{ -#ifdef FAST_HI - int select; /* the select register is 8 bits */ - int vector; - u_int32_t value; /* the window register is 32 bits */ -#endif /* FAST_HI */ - u_long ef; - u_int mask = (maskptr ? *maskptr : 0); - -#if defined(APIC_IO) - if ((u_int)intr >= ICU_LEN) /* no 8259 SLAVE to ignore */ -#else - if ((u_int)intr >= ICU_LEN || intr == ICU_SLAVEID) -#endif /* APIC_IO */ - if (intr_handler[intr] != isa_strayintr) - return (EBUSY); - - ef = read_eflags(); - disable_intr(); - intr_handler[intr] = handler; - intr_mptr[intr] = maskptr; - intr_mask[intr] = mask | (1 << intr); - intr_unit[intr] = arg; -#ifdef FAST_HI - if (flags & INTR_FAST) { - vector = TPR_FAST_INTS + intr; - setidt(vector, fastintr[intr], - SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); - } - else { - vector = TPR_SLOW_INTS + intr; -#ifdef APIC_INTR_REORDER -#ifdef APIC_INTR_HIGHPRI_CLOCK - /* XXX: Hack (kludge?) for more accurate clock. */ - if (intr == apic_8254_intr || intr == 8) { - vector = TPR_FAST_INTS + intr; - } -#endif -#endif - setidt(vector, slowintr[intr], - SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); - } -#ifdef APIC_INTR_REORDER - set_lapic_isrloc(intr, vector); -#endif - /* - * Reprogram the vector in the IO APIC. - */ - if (int_to_apicintpin[intr].ioapic >= 0) { - select = int_to_apicintpin[intr].redirindex; - value = io_apic_read(int_to_apicintpin[intr].ioapic, - select) & ~IOART_INTVEC; - io_apic_write(int_to_apicintpin[intr].ioapic, - select, value | vector); - } -#else - setidt(ICU_OFFSET + intr, - flags & INTR_FAST ? fastintr[intr] : slowintr[intr], - SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); -#endif /* FAST_HI */ - INTREN(1 << intr); - MPINTR_UNLOCK(); - write_eflags(ef); - return (0); -} - -void -register_imask(dvp, mask) - struct isa_device *dvp; - u_int mask; -{ - if (dvp->id_alive && dvp->id_irq) { - int intr; - - intr = ffs(dvp->id_irq) - 1; - intr_mask[intr] = mask | (1 <<intr); - } - (void) update_intr_masks(); -} - -int -icu_unset(intr, handler) - int intr; - inthand2_t *handler; -{ - u_long ef; - - if ((u_int)intr >= ICU_LEN || handler != intr_handler[intr]) - return (EINVAL); - - INTRDIS(1 << intr); - ef = read_eflags(); - disable_intr(); - intr_countp[intr] = &intrcnt[NR_DEVICES + intr]; - intr_handler[intr] = isa_strayintr; - intr_mptr[intr] = NULL; - intr_mask[intr] = HWI_MASK | SWI_MASK; - intr_unit[intr] = &intr_unit[intr]; -#ifdef FAST_HI_XXX - /* XXX how do I re-create dvp here? */ - setidt(flags & INTR_FAST ? TPR_FAST_INTS + intr : TPR_SLOW_INTS + intr, - slowintr[intr], SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); -#else /* FAST_HI */ -#ifdef APIC_INTR_REORDER - set_lapic_isrloc(intr, ICU_OFFSET + intr); -#endif - setidt(ICU_OFFSET + intr, slowintr[intr], SDT_SYS386IGT, SEL_KPL, - GSEL(GCODE_SEL, SEL_KPL)); -#endif /* FAST_HI */ - MPINTR_UNLOCK(); - write_eflags(ef); - return (0); -} diff --git a/sys/amd64/isa/intr_machdep.h b/sys/amd64/isa/intr_machdep.h deleted file mode 100644 index 7cdce87103a2..000000000000 --- a/sys/amd64/isa/intr_machdep.h +++ /dev/null @@ -1,206 +0,0 @@ -/*- - * Copyright (c) 1991 The Regents of the University of California. - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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. - * - * from: @(#)isa_device.h 7.1 (Berkeley) 5/9/91 - * $Id: intr_machdep.h,v 1.12 1998/05/31 10:53:54 bde Exp $ - */ - -#ifndef _I386_ISA_INTR_MACHDEP_H_ -#define _I386_ISA_INTR_MACHDEP_H_ - -/* - * Low level interrupt code. - */ - -#ifdef KERNEL - -#if defined(SMP) || defined(APIC_IO) -/* - * XXX FIXME: rethink location for all IPI vectors. - */ - -/* - APIC TPR priority vector levels: - - 0xff (255) +-------------+ - | | 15 (IPIs: Xspuriousint) - 0xf0 (240) +-------------+ - | | 14 - 0xe0 (224) +-------------+ - | | 13 - 0xd0 (208) +-------------+ - | | 12 - 0xc0 (192) +-------------+ - | | 11 - 0xb0 (176) +-------------+ - | | 10 (IPIs: Xcpustop) - 0xa0 (160) +-------------+ - | | 9 (IPIs: Xinvltlb) - 0x90 (144) +-------------+ - | | 8 (linux/BSD syscall, IGNORE FAST HW INTS) - 0x80 (128) +-------------+ - | | 7 (FAST_INTR 16-23) - 0x70 (112) +-------------+ - | | 6 (FAST_INTR 0-15) - 0x60 (96) +-------------+ - | | 5 (IGNORE HW INTS) - 0x50 (80) +-------------+ - | | 4 (2nd IO APIC) - 0x40 (64) +------+------+ - | | | 3 (upper APIC hardware INTs: PCI) - 0x30 (48) +------+------+ - | | 2 (start of hardware INTs: ISA) - 0x20 (32) +-------------+ - | | 1 (exceptions, traps, etc.) - 0x10 (16) +-------------+ - | | 0 (exceptions, traps, etc.) - 0x00 (0) +-------------+ - */ - -/* IDT vector base for regular (aka. slow) and fast interrupts */ -#define TPR_SLOW_INTS 0x20 -#define TPR_FAST_INTS 0x60 - -/* blocking values for local APIC Task Priority Register */ -#define TPR_BLOCK_HWI 0x4f /* hardware INTs */ -#define TPR_IGNORE_HWI 0x5f /* ignore INTs */ -#define TPR_BLOCK_FHWI 0x7f /* hardware FAST INTs */ -#define TPR_IGNORE_FHWI 0x8f /* ignore FAST INTs */ -#define TPR_BLOCK_XINVLTLB 0x9f /* */ -#define TPR_BLOCK_XCPUSTOP 0xaf /* */ -#define TPR_BLOCK_ALL 0xff /* all INTs */ - - -#ifdef TEST_TEST1 -/* put a 'fake' HWI in top of APIC prio 0x3x, 32 + 31 = 63 = 0x3f */ -#define XTEST1_OFFSET (ICU_OFFSET + 31) -#endif /** TEST_TEST1 */ - -/* TLB shootdowns */ -#define XINVLTLB_OFFSET (ICU_OFFSET + 112) - -#ifdef BETTER_CLOCK -/* inter-cpu clock handling */ -#define XCPUCHECKSTATE_OFFSET (ICU_OFFSET + 113) -#endif - -/* IPI to generate an additional software trap at the target CPU */ -#define XCPUAST_OFFSET (ICU_OFFSET + 48) - -/* IPI to signal the CPU holding the ISR lock that another IRQ has appeared */ -#define XFORWARD_IRQ_OFFSET (ICU_OFFSET + 49) - -/* IPI to signal CPUs to stop and wait for another CPU to restart them */ -#define XCPUSTOP_OFFSET (ICU_OFFSET + 128) - -/* - * Note: this vector MUST be xxxx1111, 32 + 223 = 255 = 0xff: - */ -#define XSPURIOUSINT_OFFSET (ICU_OFFSET + 223) - -#endif /* SMP || APIC_IO */ - -#ifndef LOCORE - -/* - * Type of the first (asm) part of an interrupt handler. - */ -typedef void inthand_t __P((u_int cs, u_int ef, u_int esp, u_int ss)); - -#define IDTVEC(name) __CONCAT(X,name) - -extern char eintrnames[]; /* end of intrnames[] */ -extern u_long intrcnt[]; /* counts for for each device and stray */ -extern char intrnames[]; /* string table containing device names */ -extern u_long *intr_countp[]; /* pointers into intrcnt[] */ -extern inthand2_t *intr_handler[]; /* C entry points of intr handlers */ -extern u_int intr_mask[]; /* sets of intrs masked during handling of 1 */ -extern void *intr_unit[]; /* cookies to pass to intr handlers */ - -inthand_t - IDTVEC(fastintr0), IDTVEC(fastintr1), - IDTVEC(fastintr2), IDTVEC(fastintr3), - IDTVEC(fastintr4), IDTVEC(fastintr5), - IDTVEC(fastintr6), IDTVEC(fastintr7), - IDTVEC(fastintr8), IDTVEC(fastintr9), - IDTVEC(fastintr10), IDTVEC(fastintr11), - IDTVEC(fastintr12), IDTVEC(fastintr13), - IDTVEC(fastintr14), IDTVEC(fastintr15); -inthand_t - IDTVEC(intr0), IDTVEC(intr1), IDTVEC(intr2), IDTVEC(intr3), - IDTVEC(intr4), IDTVEC(intr5), IDTVEC(intr6), IDTVEC(intr7), - IDTVEC(intr8), IDTVEC(intr9), IDTVEC(intr10), IDTVEC(intr11), - IDTVEC(intr12), IDTVEC(intr13), IDTVEC(intr14), IDTVEC(intr15); - -#if defined(SMP) || defined(APIC_IO) -inthand_t - IDTVEC(fastintr16), IDTVEC(fastintr17), - IDTVEC(fastintr18), IDTVEC(fastintr19), - IDTVEC(fastintr20), IDTVEC(fastintr21), - IDTVEC(fastintr22), IDTVEC(fastintr23); -inthand_t - IDTVEC(intr16), IDTVEC(intr17), IDTVEC(intr18), IDTVEC(intr19), - IDTVEC(intr20), IDTVEC(intr21), IDTVEC(intr22), IDTVEC(intr23); - -inthand_t - Xinvltlb, /* TLB shootdowns */ -#ifdef BETTER_CLOCK - Xcpucheckstate, /* Check cpu state */ -#endif - Xcpuast, /* Additional software trap on other cpu */ - Xforward_irq, /* Forward irq to cpu holding ISR lock */ - Xcpustop, /* CPU stops & waits for another CPU to restart it */ - Xspuriousint; /* handle APIC "spurious INTs" */ - -#ifdef TEST_TEST1 -inthand_t - Xtest1; /* 'fake' HWI at top of APIC prio 0x3x, 32+31 = 0x3f */ -#endif /** TEST_TEST1 */ -#endif /* SMP || APIC_IO */ - -struct isa_device; - -void isa_defaultirq __P((void)); -intrmask_t isa_irq_pending __P((void)); -int isa_nmi __P((int cd)); -void update_intrname __P((int intr, int device_id)); -int icu_setup __P((int intr, inthand2_t *func, void *arg, - u_int *maskptr, int flags)); -int icu_unset __P((int intr, inthand2_t *handler)); -int update_intr_masks __P((void)); -void register_imask __P((struct isa_device *dvp, u_int mask)); - -#endif /* LOCORE */ - -#endif /* KERNEL */ - -#endif /* !_I386_ISA_INTR_MACHDEP_H_ */ diff --git a/sys/amd64/isa/isa.c b/sys/amd64/isa/isa.c deleted file mode 100644 index 177024d17d6b..000000000000 --- a/sys/amd64/isa/isa.c +++ /dev/null @@ -1,1079 +0,0 @@ -/*- - * Copyright (c) 1991 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * William Jolitz. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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. - * - * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 - * $Id: isa.c,v 1.116 1998/10/22 05:58:39 bde Exp $ - */ - -/* - * code to manage AT bus - * - * 92/08/18 Frank P. MacLachlan (fpm@crash.cts.com): - * Fixed uninitialized variable problem and added code to deal - * with DMA page boundaries in isa_dmarangecheck(). Fixed word - * mode DMA count compution and reorganized DMA setup code in - * isa_dmastart() - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/buf.h> -#include <sys/malloc.h> -#include <machine/ipl.h> -#include <machine/md_var.h> -#ifdef APIC_IO -#include <machine/smp.h> -#endif /* APIC_IO */ -#include <vm/vm.h> -#include <vm/vm_param.h> -#include <vm/pmap.h> -#include <i386/isa/isa_device.h> -#include <i386/isa/intr_machdep.h> -#include <i386/isa/isa.h> -#include <i386/isa/ic/i8237.h> - -#include <sys/interrupt.h> - -#include "pnp.h" -#if NPNP > 0 -#include <i386/isa/pnp.h> -#endif - -/* -** Register definitions for DMA controller 1 (channels 0..3): -*/ -#define DMA1_CHN(c) (IO_DMA1 + 1*(2*(c))) /* addr reg for channel c */ -#define DMA1_SMSK (IO_DMA1 + 1*10) /* single mask register */ -#define DMA1_MODE (IO_DMA1 + 1*11) /* mode register */ -#define DMA1_FFC (IO_DMA1 + 1*12) /* clear first/last FF */ - -/* -** Register definitions for DMA controller 2 (channels 4..7): -*/ -#define DMA2_CHN(c) (IO_DMA2 + 2*(2*(c))) /* addr reg for channel c */ -#define DMA2_SMSK (IO_DMA2 + 2*10) /* single mask register */ -#define DMA2_MODE (IO_DMA2 + 2*11) /* mode register */ -#define DMA2_FFC (IO_DMA2 + 2*12) /* clear first/last FF */ - -static void config_isadev __P((struct isa_device *isdp, u_int *mp)); -static void config_isadev_c __P((struct isa_device *isdp, u_int *mp, - int reconfig)); -static void conflict __P((struct isa_device *dvp, struct isa_device *tmpdvp, - int item, char const *whatnot, char const *reason, - char const *format)); -static int haveseen __P((struct isa_device *dvp, struct isa_device *tmpdvp, - u_int checkbits)); -static int isa_dmarangecheck __P((caddr_t va, u_int length, int chan)); - -/* - * print a conflict message - */ -static void -conflict(dvp, tmpdvp, item, whatnot, reason, format) - struct isa_device *dvp; - struct isa_device *tmpdvp; - int item; - char const *whatnot; - char const *reason; - char const *format; -{ - printf("%s%d not %sed due to %s conflict with %s%d at ", - dvp->id_driver->name, dvp->id_unit, whatnot, reason, - tmpdvp->id_driver->name, tmpdvp->id_unit); - printf(format, item); - printf("\n"); -} - -/* - * Check to see if things are already in use, like IRQ's, I/O addresses - * and Memory addresses. - */ -static int -haveseen(dvp, tmpdvp, checkbits) - struct isa_device *dvp; - struct isa_device *tmpdvp; - u_int checkbits; -{ - /* - * Ignore all conflicts except IRQ ones if conflicts are allowed. - */ - if (dvp->id_conflicts) - checkbits &= ~(CC_DRQ | CC_IOADDR | CC_MEMADDR); - /* - * Only check against devices that have already been found. - */ - if (tmpdvp->id_alive) { - char const *whatnot; - - /* - * Check for device driver & unit conflict; just drop probing - * a device which has already probed true. This is usually - * not strictly a conflict, but rather the case of somebody - * having specified several mutually exclusive configurations - * for a single device. - */ - if (tmpdvp->id_driver == dvp->id_driver && - tmpdvp->id_unit == dvp->id_unit) { - return 1; - } - - whatnot = checkbits & CC_ATTACH ? "attach" : "prob"; - /* - * Check for I/O address conflict. We can only check the - * starting address of the device against the range of the - * device that has already been probed since we do not - * know how many I/O addresses this device uses. - */ - if (checkbits & CC_IOADDR && tmpdvp->id_alive != -1) { - if ((dvp->id_iobase >= tmpdvp->id_iobase) && - (dvp->id_iobase <= - (tmpdvp->id_iobase + tmpdvp->id_alive - 1))) { - if (!(checkbits & CC_QUIET)) - conflict(dvp, tmpdvp, dvp->id_iobase, - whatnot, "I/O address", "0x%x"); - return 1; - } - } - /* - * Check for Memory address conflict. We can check for - * range overlap, but it will not catch all cases since the - * driver may adjust the msize paramater during probe, for - * now we just check that the starting address does not - * fall within any allocated region. - * XXX could add a second check after the probe for overlap, - * since at that time we would know the full range. - * XXX KERNBASE is a hack, we should have vaddr in the table! - */ - if (checkbits & CC_MEMADDR && tmpdvp->id_maddr) { - if ((KERNBASE + dvp->id_maddr >= tmpdvp->id_maddr) && - (KERNBASE + dvp->id_maddr <= - (tmpdvp->id_maddr + tmpdvp->id_msize - 1))) { - if (!(checkbits & CC_QUIET)) - conflict(dvp, tmpdvp, - (int)dvp->id_maddr, whatnot, - "maddr", "0x%x"); - return 1; - } - } - /* - * Check for IRQ conflicts. - */ - if (checkbits & CC_IRQ && tmpdvp->id_irq) { - if (tmpdvp->id_irq == dvp->id_irq) { - if (!(checkbits & CC_QUIET)) - conflict(dvp, tmpdvp, - ffs(dvp->id_irq) - 1, whatnot, - "irq", "%d"); - return 1; - } - } - /* - * Check for DRQ conflicts. - */ - if (checkbits & CC_DRQ && tmpdvp->id_drq != -1) { - if (tmpdvp->id_drq == dvp->id_drq) { - if (!(checkbits & CC_QUIET)) - conflict(dvp, tmpdvp, dvp->id_drq, - whatnot, "drq", "%d"); - return 1; - } - } - } - return 0; -} - -#ifdef RESOURCE_CHECK -#include <sys/drvresource.h> - -static int -checkone (struct isa_device *dvp, int type, addr_t low, addr_t high, - char *resname, char *resfmt, int attaching) -{ - int result = 0; - if (bootverbose) { - if (low == high) - printf("\tcheck %s: 0x%x\n", resname, low); - else - printf("\tcheck %s: 0x%x to 0x%x\n", - resname, low, high); - } - if (resource_check(type, RESF_NONE, low, high) != NULL) { - char *whatnot = attaching ? "attach" : "prob"; - static struct isa_device dummydev; - static struct isa_driver dummydrv; - struct isa_device *tmpdvp = &dummydev; - - dummydev.id_driver = &dummydrv; - dummydev.id_unit = 0; - dummydrv.name = "pci"; - conflict(dvp, tmpdvp, low, whatnot, resname, resfmt); - result = 1; - } else if (attaching) { - if (low == high) - printf("\tregister %s: 0x%x\n", resname, low); - else - printf("\tregister %s: 0x%x to 0x%x\n", - resname, low, high); - resource_claim(dvp, type, RESF_NONE, low, high); - } - return (result); -} - -static int -check_pciconflict(struct isa_device *dvp, int checkbits) -{ - int result = 0; - int attaching = (checkbits & CC_ATTACH) != 0; - - if (checkbits & CC_MEMADDR) { - long maddr = dvp->id_maddr; - long msize = dvp->id_msize; - if (msize > 0) { - if (checkone(dvp, REST_MEM, maddr, maddr + msize - 1, - "maddr", "0x%x", attaching) != 0) { - result = 1; - attaching = 0; - } - } - } - if (checkbits & CC_IOADDR) { - unsigned iobase = dvp->id_iobase; - unsigned iosize = dvp->id_alive; - if (iosize == -1) - iosize = 1; /* XXX can't do much about this ... */ - if (iosize > 0) { - if (checkone(dvp, REST_PORT, iobase, iobase + iosize -1, - "I/O address", "0x%x", attaching) != 0) { - result = 1; - attaching = 0; - } - } - } - if (checkbits & CC_IRQ) { - int irq = ffs(dvp->id_irq) - 1; - if (irq >= 0) { - if (checkone(dvp, REST_INT, irq, irq, - "irq", "%d", attaching) != 0) { - result = 1; - attaching = 0; - } - } - } - if (checkbits & CC_DRQ) { - int drq = dvp->id_drq; - if (drq >= 0) { - if (checkone(dvp, REST_DMA, drq, drq, - "drq", "%d", attaching) != 0) { - result = 1; - attaching = 0; - } - } - } - if (result != 0) - resource_free (dvp); - return (result); -} -#endif /* RESOURCE_CHECK */ - -/* - * Search through all the isa_devtab_* tables looking for anything that - * conflicts with the current device. - */ -int -haveseen_isadev(dvp, checkbits) - struct isa_device *dvp; - u_int checkbits; -{ -#if NPNP > 0 - struct pnp_dlist_node *nod; -#endif - struct isa_device *tmpdvp; - int status = 0; - - for (tmpdvp = isa_devtab_tty; tmpdvp->id_driver; tmpdvp++) { - status |= haveseen(dvp, tmpdvp, checkbits); - if (status) - return status; - } - for (tmpdvp = isa_devtab_bio; tmpdvp->id_driver; tmpdvp++) { - status |= haveseen(dvp, tmpdvp, checkbits); - if (status) - return status; - } - for (tmpdvp = isa_devtab_net; tmpdvp->id_driver; tmpdvp++) { - status |= haveseen(dvp, tmpdvp, checkbits); - if (status) - return status; - } - for (tmpdvp = isa_devtab_cam; tmpdvp->id_driver; tmpdvp++) { - status |= haveseen(dvp, tmpdvp, checkbits); - if (status) - return status; - } - for (tmpdvp = isa_devtab_null; tmpdvp->id_driver; tmpdvp++) { - status |= haveseen(dvp, tmpdvp, checkbits); - if (status) - return status; - } -#if NPNP > 0 - for (nod = pnp_device_list; nod != NULL; nod = nod->next) - if (status |= haveseen(dvp, &(nod->dev), checkbits)) - return status; -#endif -#ifdef RESOURCE_CHECK - if (!dvp->id_conflicts) - status = check_pciconflict(dvp, checkbits); - else if (bootverbose) - printf("\tnot checking for resource conflicts ...\n"); -#endif /* RESOURCE_CHECK */ - return(status); -} - -/* - * Configure all ISA devices - */ -void -isa_configure() -{ - struct isa_device *dvp; - - printf("Probing for devices on the ISA bus:\n"); - /* First probe all the sensitive probes */ - for (dvp = isa_devtab_tty; dvp->id_driver; dvp++) - if (dvp->id_driver->sensitive_hw) - config_isadev(dvp, &tty_imask); - for (dvp = isa_devtab_bio; dvp->id_driver; dvp++) - if (dvp->id_driver->sensitive_hw) - config_isadev(dvp, &bio_imask); - for (dvp = isa_devtab_net; dvp->id_driver; dvp++) - if (dvp->id_driver->sensitive_hw) - config_isadev(dvp, &net_imask); - for (dvp = isa_devtab_cam; dvp->id_driver; dvp++) - if (dvp->id_driver->sensitive_hw) - config_isadev(dvp, &cam_imask); - for (dvp = isa_devtab_null; dvp->id_driver; dvp++) - if (dvp->id_driver->sensitive_hw) - config_isadev(dvp, (u_int *)NULL); - - /* Then all the bad ones */ - for (dvp = isa_devtab_tty; dvp->id_driver; dvp++) - if (!dvp->id_driver->sensitive_hw) - config_isadev(dvp, &tty_imask); - for (dvp = isa_devtab_bio; dvp->id_driver; dvp++) - if (!dvp->id_driver->sensitive_hw) - config_isadev(dvp, &bio_imask); - for (dvp = isa_devtab_net; dvp->id_driver; dvp++) - if (!dvp->id_driver->sensitive_hw) - config_isadev(dvp, &net_imask); - for (dvp = isa_devtab_cam; dvp->id_driver; dvp++) - if (!dvp->id_driver->sensitive_hw) - config_isadev(dvp, &cam_imask); - for (dvp = isa_devtab_null; dvp->id_driver; dvp++) - if (!dvp->id_driver->sensitive_hw) - config_isadev(dvp, (u_int *)NULL); - - bio_imask |= SWI_CLOCK_MASK; - net_imask |= SWI_NET_MASK; - tty_imask |= SWI_TTY_MASK; - -/* - * XXX we should really add the tty device to net_imask when the line is - * switched to SLIPDISC, and then remove it when it is switched away from - * SLIPDISC. No need to block out ALL ttys during a splimp when only one - * of them is running slip. - * - * XXX actually, blocking all ttys during a splimp doesn't matter so much - * with sio because the serial interrupt layer doesn't use tty_imask. Only - * non-serial ttys suffer. It's more stupid that ALL 'net's are blocked - * during spltty. - */ -#include "sl.h" -#if NSL > 0 - net_imask |= tty_imask; - tty_imask = net_imask; -#endif - - /* bio_imask |= tty_imask ; can some tty devices use buffers? */ - - if (bootverbose) - printf("imasks: bio %x, tty %x, net %x\n", - bio_imask, tty_imask, net_imask); - - /* - * Finish initializing intr_mask[]. Note that the partly - * constructed masks aren't actually used since we're at splhigh. - * For fully dynamic initialization, register_intr() and - * icu_unset() will have to adjust the masks for _all_ - * interrupts and for tty_imask, etc. - */ - for (dvp = isa_devtab_tty; dvp->id_driver; dvp++) - register_imask(dvp, tty_imask); - for (dvp = isa_devtab_bio; dvp->id_driver; dvp++) - register_imask(dvp, bio_imask); - for (dvp = isa_devtab_net; dvp->id_driver; dvp++) - register_imask(dvp, net_imask); - for (dvp = isa_devtab_cam; dvp->id_driver; dvp++) - register_imask(dvp, cam_imask); - for (dvp = isa_devtab_null; dvp->id_driver; dvp++) - register_imask(dvp, SWI_CLOCK_MASK); -} - -/* - * Configure an ISA device. - */ -static void -config_isadev(isdp, mp) - struct isa_device *isdp; - u_int *mp; -{ - config_isadev_c(isdp, mp, 0); -} - -void -reconfig_isadev(isdp, mp) - struct isa_device *isdp; - u_int *mp; -{ - config_isadev_c(isdp, mp, 1); -} - -static void -config_isadev_c(isdp, mp, reconfig) - struct isa_device *isdp; - u_int *mp; - int reconfig; -{ - u_int checkbits; - int id_alive; - int last_alive; - struct isa_driver *dp = isdp->id_driver; - - if (!isdp->id_enabled) { - if (bootverbose) - printf("%s%d: disabled, not probed.\n", dp->name, isdp->id_unit); - return; - } - checkbits = CC_DRQ | CC_IOADDR | CC_MEMADDR; - if (!reconfig && haveseen_isadev(isdp, checkbits)) - return; - if (!reconfig && isdp->id_maddr) { - isdp->id_maddr -= ISA_HOLE_START; - isdp->id_maddr += atdevbase; - } - if (reconfig) { - last_alive = isdp->id_alive; - isdp->id_reconfig = 1; - } - else { - last_alive = 0; - isdp->id_reconfig = 0; - } - id_alive = (*dp->probe)(isdp); - if (id_alive) { - /* - * Only print the I/O address range if id_alive != -1 - * Right now this is a temporary fix just for the new - * NPX code so that if it finds a 486 that can use trap - * 16 it will not report I/O addresses. - * Rod Grimes 04/26/94 - */ - if (!isdp->id_reconfig) { - printf("%s%d", dp->name, isdp->id_unit); - if (id_alive != -1) { - if (isdp->id_iobase == -1) - printf(" at"); - else { - printf(" at 0x%x", isdp->id_iobase); - if (isdp->id_iobase + id_alive - 1 != - isdp->id_iobase) { - printf("-0x%x", - isdp->id_iobase + id_alive - 1); - } - } - } - if (isdp->id_irq) - printf(" irq %d", ffs(isdp->id_irq) - 1); - if (isdp->id_drq != -1) - printf(" drq %d", isdp->id_drq); - if (isdp->id_maddr) - printf(" maddr 0x%lx", kvtop(isdp->id_maddr)); - if (isdp->id_msize) - printf(" msize %d", isdp->id_msize); - if (isdp->id_flags) - printf(" flags 0x%x", isdp->id_flags); - if (isdp->id_iobase && !(isdp->id_iobase & 0xf300)) { - printf(" on motherboard"); - } else if (isdp->id_iobase >= 0x1000 && - !(isdp->id_iobase & 0x300)) { - printf (" on eisa slot %d", - isdp->id_iobase >> 12); - } else { - printf (" on isa"); - } - printf("\n"); - /* - * Check for conflicts again. The driver may have - * changed *dvp. We should weaken the early check - * since the driver may have been able to change - * *dvp to avoid conflicts if given a chance. We - * already skip the early check for IRQs and force - * a check for IRQs in the next group of checks. - */ - checkbits |= CC_ATTACH | CC_IRQ; - if (haveseen_isadev(isdp, checkbits)) - return; - isdp->id_alive = id_alive; - } - (*dp->attach)(isdp); - if (isdp->id_irq != 0 && isdp->id_intr == NULL) - printf("%s%d: irq with no handler\n", - dp->name, isdp->id_unit); - if (isdp->id_irq != 0 && isdp->id_intr != NULL) { -#ifdef APIC_IO - /* - * Some motherboards use upper IRQs for traditional - * ISA INTerrupt sources. In particular we have - * seen the secondary IDE connected to IRQ20. - * This code detects and fixes this situation. - */ - u_int apic_mask; - int rirq; - - apic_mask = isa_apic_mask(isdp->id_irq); - if (apic_mask != isdp->id_irq) { - rirq = ffs(isdp->id_irq) - 1; - isdp->id_irq = apic_mask; - undirect_isa_irq(rirq); /* free for ISA */ - } -#endif /* APIC_IO */ - register_intr(ffs(isdp->id_irq) - 1, isdp->id_id, - isdp->id_ri_flags, isdp->id_intr, - mp, isdp->id_unit); - } - } else { - if (isdp->id_reconfig) { - (*dp->attach)(isdp); /* reconfiguration attach */ - } - if (!last_alive) { - if (!isdp->id_reconfig) { - printf("%s%d not found", - dp->name, isdp->id_unit); - if (isdp->id_iobase != -1) - printf(" at 0x%x", isdp->id_iobase); - printf("\n"); - } - } else { -#if 0 - /* This code has not been tested.... */ - if (isdp->id_irq != 0 && isdp->id_intr != NULL) { - icu_unset(ffs(isdp->id_irq) - 1, - isdp->id_intr); - if (mp) - INTRUNMASK(*mp, isdp->id_irq); - } -#else - printf ("icu_unset() not supported here ...\n"); -#endif - } - } -} - -static caddr_t dma_bouncebuf[8]; -static u_int dma_bouncebufsize[8]; -static u_int8_t dma_bounced = 0; -static u_int8_t dma_busy = 0; /* Used in isa_dmastart() */ -static u_int8_t dma_inuse = 0; /* User for acquire/release */ -static u_int8_t dma_auto_mode = 0; - -#define VALID_DMA_MASK (7) - -/* high byte of address is stored in this port for i-th dma channel */ -static int dmapageport[8] = { 0x87, 0x83, 0x81, 0x82, 0x8f, 0x8b, 0x89, 0x8a }; - -/* - * Setup a DMA channel's bounce buffer. - */ -void -isa_dmainit(chan, bouncebufsize) - int chan; - u_int bouncebufsize; -{ - void *buf; - -#ifdef DIAGNOSTIC - if (chan & ~VALID_DMA_MASK) - panic("isa_dmainit: channel out of range"); - - if (dma_bouncebuf[chan] != NULL) - panic("isa_dmainit: impossible request"); -#endif - - dma_bouncebufsize[chan] = bouncebufsize; - - /* Try malloc() first. It works better if it works. */ - buf = malloc(bouncebufsize, M_DEVBUF, M_NOWAIT); - if (buf != NULL) { - if (isa_dmarangecheck(buf, bouncebufsize, chan) == 0) { - dma_bouncebuf[chan] = buf; - return; - } - free(buf, M_DEVBUF); - } - buf = contigmalloc(bouncebufsize, M_DEVBUF, M_NOWAIT, 0ul, 0xfffffful, - 1ul, chan & 4 ? 0x20000ul : 0x10000ul); - if (buf == NULL) - printf("isa_dmainit(%d, %d) failed\n", chan, bouncebufsize); - else - dma_bouncebuf[chan] = buf; -} - -/* - * Register a DMA channel's usage. Usually called from a device driver - * in open() or during its initialization. - */ -int -isa_dma_acquire(chan) - int chan; -{ -#ifdef DIAGNOSTIC - if (chan & ~VALID_DMA_MASK) - panic("isa_dma_acquire: channel out of range"); -#endif - - if (dma_inuse & (1 << chan)) { - printf("isa_dma_acquire: channel %d already in use\n", chan); - return (EBUSY); - } - dma_inuse |= (1 << chan); - dma_auto_mode &= ~(1 << chan); - - return (0); -} - -/* - * Unregister a DMA channel's usage. Usually called from a device driver - * during close() or during its shutdown. - */ -void -isa_dma_release(chan) - int chan; -{ -#ifdef DIAGNOSTIC - if (chan & ~VALID_DMA_MASK) - panic("isa_dma_release: channel out of range"); - - if ((dma_inuse & (1 << chan)) == 0) - printf("isa_dma_release: channel %d not in use\n", chan); -#endif - - if (dma_busy & (1 << chan)) { - dma_busy &= ~(1 << chan); - /* - * XXX We should also do "dma_bounced &= (1 << chan);" - * because we are acting on behalf of isa_dmadone() which - * was not called to end the last DMA operation. This does - * not matter now, but it may in the future. - */ - } - - dma_inuse &= ~(1 << chan); - dma_auto_mode &= ~(1 << chan); -} - -/* - * isa_dmacascade(): program 8237 DMA controller channel to accept - * external dma control by a board. - */ -void -isa_dmacascade(chan) - int chan; -{ -#ifdef DIAGNOSTIC - if (chan & ~VALID_DMA_MASK) - panic("isa_dmacascade: channel out of range"); -#endif - - /* set dma channel mode, and set dma channel mode */ - if ((chan & 4) == 0) { - outb(DMA1_MODE, DMA37MD_CASCADE | chan); - outb(DMA1_SMSK, chan); - } else { - outb(DMA2_MODE, DMA37MD_CASCADE | (chan & 3)); - outb(DMA2_SMSK, chan & 3); - } -} - -/* - * isa_dmastart(): program 8237 DMA controller channel, avoid page alignment - * problems by using a bounce buffer. - */ -void -isa_dmastart(int flags, caddr_t addr, u_int nbytes, int chan) -{ - vm_offset_t phys; - int waport; - caddr_t newaddr; - -#ifdef DIAGNOSTIC - if (chan & ~VALID_DMA_MASK) - panic("isa_dmastart: channel out of range"); - - if ((chan < 4 && nbytes > (1<<16)) - || (chan >= 4 && (nbytes > (1<<17) || (u_int)addr & 1))) - panic("isa_dmastart: impossible request"); - - if ((dma_inuse & (1 << chan)) == 0) - printf("isa_dmastart: channel %d not acquired\n", chan); -#endif - -#if 0 - /* - * XXX This should be checked, but drivers like ad1848 only call - * isa_dmastart() once because they use Auto DMA mode. If we - * leave this in, drivers that do this will print this continuously. - */ - if (dma_busy & (1 << chan)) - printf("isa_dmastart: channel %d busy\n", chan); -#endif - - dma_busy |= (1 << chan); - - if (isa_dmarangecheck(addr, nbytes, chan)) { - if (dma_bouncebuf[chan] == NULL - || dma_bouncebufsize[chan] < nbytes) - panic("isa_dmastart: bad bounce buffer"); - dma_bounced |= (1 << chan); - newaddr = dma_bouncebuf[chan]; - - /* copy bounce buffer on write */ - if (!(flags & B_READ)) - bcopy(addr, newaddr, nbytes); - addr = newaddr; - } - - /* translate to physical */ - phys = pmap_extract(pmap_kernel(), (vm_offset_t)addr); - - if (flags & B_RAW) { - dma_auto_mode |= (1 << chan); - } else { - dma_auto_mode &= ~(1 << chan); - } - - if ((chan & 4) == 0) { - /* - * Program one of DMA channels 0..3. These are - * byte mode channels. - */ - /* set dma channel mode, and reset address ff */ - - /* If B_RAW flag is set, then use autoinitialise mode */ - if (flags & B_RAW) { - if (flags & B_READ) - outb(DMA1_MODE, DMA37MD_AUTO|DMA37MD_WRITE|chan); - else - outb(DMA1_MODE, DMA37MD_AUTO|DMA37MD_READ|chan); - } - else - if (flags & B_READ) - outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_WRITE|chan); - else - outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_READ|chan); - outb(DMA1_FFC, 0); - - /* send start address */ - waport = DMA1_CHN(chan); - outb(waport, phys); - outb(waport, phys>>8); - outb(dmapageport[chan], phys>>16); - - /* send count */ - outb(waport + 1, --nbytes); - outb(waport + 1, nbytes>>8); - - /* unmask channel */ - outb(DMA1_SMSK, chan); - } else { - /* - * Program one of DMA channels 4..7. These are - * word mode channels. - */ - /* set dma channel mode, and reset address ff */ - - /* If B_RAW flag is set, then use autoinitialise mode */ - if (flags & B_RAW) { - if (flags & B_READ) - outb(DMA2_MODE, DMA37MD_AUTO|DMA37MD_WRITE|(chan&3)); - else - outb(DMA2_MODE, DMA37MD_AUTO|DMA37MD_READ|(chan&3)); - } - else - if (flags & B_READ) - outb(DMA2_MODE, DMA37MD_SINGLE|DMA37MD_WRITE|(chan&3)); - else - outb(DMA2_MODE, DMA37MD_SINGLE|DMA37MD_READ|(chan&3)); - outb(DMA2_FFC, 0); - - /* send start address */ - waport = DMA2_CHN(chan - 4); - outb(waport, phys>>1); - outb(waport, phys>>9); - outb(dmapageport[chan], phys>>16); - - /* send count */ - nbytes >>= 1; - outb(waport + 2, --nbytes); - outb(waport + 2, nbytes>>8); - - /* unmask channel */ - outb(DMA2_SMSK, chan & 3); - } -} - -void -isa_dmadone(int flags, caddr_t addr, int nbytes, int chan) -{ -#ifdef DIAGNOSTIC - if (chan & ~VALID_DMA_MASK) - panic("isa_dmadone: channel out of range"); - - if ((dma_inuse & (1 << chan)) == 0) - printf("isa_dmadone: channel %d not acquired\n", chan); -#endif - - if (((dma_busy & (1 << chan)) == 0) && - (dma_auto_mode & (1 << chan)) == 0 ) - printf("isa_dmadone: channel %d not busy\n", chan); - - if ((dma_auto_mode & (1 << chan)) == 0) - outb(chan & 4 ? DMA2_SMSK : DMA1_SMSK, (chan & 3) | 4); - - if (dma_bounced & (1 << chan)) { - /* copy bounce buffer on read */ - if (flags & B_READ) - bcopy(dma_bouncebuf[chan], addr, nbytes); - - dma_bounced &= ~(1 << chan); - } - dma_busy &= ~(1 << chan); -} - -/* - * Check for problems with the address range of a DMA transfer - * (non-contiguous physical pages, outside of bus address space, - * crossing DMA page boundaries). - * Return true if special handling needed. - */ - -static int -isa_dmarangecheck(caddr_t va, u_int length, int chan) -{ - vm_offset_t phys, priorpage = 0, endva; - u_int dma_pgmsk = (chan & 4) ? ~(128*1024-1) : ~(64*1024-1); - - endva = (vm_offset_t)round_page((vm_offset_t)va + length); - for (; va < (caddr_t) endva ; va += PAGE_SIZE) { - phys = trunc_page(pmap_extract(pmap_kernel(), (vm_offset_t)va)); -#define ISARAM_END RAM_END - if (phys == 0) - panic("isa_dmacheck: no physical page present"); - if (phys >= ISARAM_END) - return (1); - if (priorpage) { - if (priorpage + PAGE_SIZE != phys) - return (1); - /* check if crossing a DMA page boundary */ - if (((u_int)priorpage ^ (u_int)phys) & dma_pgmsk) - return (1); - } - priorpage = phys; - } - return (0); -} - -/* - * Query the progress of a transfer on a DMA channel. - * - * To avoid having to interrupt a transfer in progress, we sample - * each of the high and low databytes twice, and apply the following - * logic to determine the correct count. - * - * Reads are performed with interrupts disabled, thus it is to be - * expected that the time between reads is very small. At most - * one rollover in the low count byte can be expected within the - * four reads that are performed. - * - * There are three gaps in which a rollover can occur : - * - * - read low1 - * gap1 - * - read high1 - * gap2 - * - read low2 - * gap3 - * - read high2 - * - * If a rollover occurs in gap1 or gap2, the low2 value will be - * greater than the low1 value. In this case, low2 and high2 are a - * corresponding pair. - * - * In any other case, low1 and high1 can be considered to be correct. - * - * The function returns the number of bytes remaining in the transfer, - * or -1 if the channel requested is not active. - * - */ -int -isa_dmastatus(int chan) -{ - u_long cnt = 0; - int ffport, waport; - u_long low1, high1, low2, high2; - - /* channel active? */ - if ((dma_inuse & (1 << chan)) == 0) { - printf("isa_dmastatus: channel %d not active\n", chan); - return(-1); - } - /* channel busy? */ - - if (((dma_busy & (1 << chan)) == 0) && - (dma_auto_mode & (1 << chan)) == 0 ) { - printf("chan %d not busy\n", chan); - return -2 ; - } - if (chan < 4) { /* low DMA controller */ - ffport = DMA1_FFC; - waport = DMA1_CHN(chan) + 1; - } else { /* high DMA controller */ - ffport = DMA2_FFC; - waport = DMA2_CHN(chan - 4) + 2; - } - - disable_intr(); /* no interrupts Mr Jones! */ - outb(ffport, 0); /* clear register LSB flipflop */ - low1 = inb(waport); - high1 = inb(waport); - outb(ffport, 0); /* clear again */ - low2 = inb(waport); - high2 = inb(waport); - enable_intr(); /* enable interrupts again */ - - /* - * Now decide if a wrap has tried to skew our results. - * Note that after TC, the count will read 0xffff, while we want - * to return zero, so we add and then mask to compensate. - */ - if (low1 >= low2) { - cnt = (low1 + (high1 << 8) + 1) & 0xffff; - } else { - cnt = (low2 + (high2 << 8) + 1) & 0xffff; - } - - if (chan >= 4) /* high channels move words */ - cnt *= 2; - return(cnt); -} - -/* - * Stop a DMA transfer currently in progress. - */ -int -isa_dmastop(int chan) -{ - if ((dma_inuse & (1 << chan)) == 0) - printf("isa_dmastop: channel %d not acquired\n", chan); - - if (((dma_busy & (1 << chan)) == 0) && - ((dma_auto_mode & (1 << chan)) == 0)) { - printf("chan %d not busy\n", chan); - return -2 ; - } - - if ((chan & 4) == 0) { - outb(DMA1_SMSK, (chan & 3) | 4 /* disable mask */); - } else { - outb(DMA2_SMSK, (chan & 3) | 4 /* disable mask */); - } - return(isa_dmastatus(chan)); -} - -/* - * Find the highest priority enabled display device. Since we can't - * distinguish display devices from ttys, depend on display devices - * being sensitive and before sensitive non-display devices (if any) - * in isa_devtab_tty. - * - * XXX we should add capability flags IAMDISPLAY and ISUPPORTCONSOLES. - */ -struct isa_device * -find_display() -{ - struct isa_device *dvp; - - for (dvp = isa_devtab_tty; dvp->id_driver != NULL; dvp++) - if (dvp->id_driver->sensitive_hw && dvp->id_enabled) - return (dvp); - return (NULL); -} - -/* - * find an ISA device in a given isa_devtab_* table, given - * the table to search, the expected id_driver entry, and the unit number. - * - * this function is defined in isa_device.h, and this location is debatable; - * i put it there because it's useless w/o, and directly operates on - * the other stuff in that file. - * - */ - -struct isa_device * -find_isadev(table, driverp, unit) - struct isa_device *table; - struct isa_driver *driverp; - int unit; -{ - if (driverp == NULL) /* sanity check */ - return (NULL); - - while ((table->id_driver != driverp) || (table->id_unit != unit)) { - if (table->id_driver == 0) - return NULL; - - table++; - } - - return (table); -} diff --git a/sys/amd64/isa/isa.h b/sys/amd64/isa/isa.h deleted file mode 100644 index ea25f20604ee..000000000000 --- a/sys/amd64/isa/isa.h +++ /dev/null @@ -1,200 +0,0 @@ -/*- - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * William Jolitz. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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. - * - * from: @(#)isa.h 5.7 (Berkeley) 5/9/91 - * $Id: isa.h,v 1.21 1997/02/22 09:36:41 peter Exp $ - */ - -#ifdef PC98 -#error isa.h is included from PC-9801 source -#endif - -#ifndef _I386_ISA_ISA_H_ -#define _I386_ISA_ISA_H_ - -/* BEWARE: Included in both assembler and C code */ - -/* - * ISA Bus conventions - */ - -/* - * Input / Output Port Assignments - */ -#ifndef IO_ISABEGIN -#define IO_ISABEGIN 0x000 /* 0x000 - Beginning of I/O Registers */ - - /* CPU Board */ -#define IO_DMA1 0x000 /* 8237A DMA Controller #1 */ -#define IO_ICU1 0x020 /* 8259A Interrupt Controller #1 */ -#define IO_PMP1 0x026 /* 82347 Power Management Peripheral */ -#define IO_TIMER1 0x040 /* 8253 Timer #1 */ -#define IO_TIMER2 0x048 /* 8253 Timer #2 */ -#define IO_KBD 0x060 /* 8042 Keyboard */ -#define IO_PPI 0x061 /* Programmable Peripheral Interface */ -#define IO_RTC 0x070 /* RTC */ -#define IO_NMI IO_RTC /* NMI Control */ -#define IO_DMAPG 0x080 /* DMA Page Registers */ -#define IO_ICU2 0x0A0 /* 8259A Interrupt Controller #2 */ -#define IO_DMA2 0x0C0 /* 8237A DMA Controller #2 */ -#define IO_NPX 0x0F0 /* Numeric Coprocessor */ - - /* Cards */ - /* 0x100 - 0x16F Open */ - -#define IO_WD2 0x170 /* Secondary Fixed Disk Controller */ - -#define IO_PMP2 0x178 /* 82347 Power Management Peripheral */ - - /* 0x17A - 0x1EF Open */ - -#define IO_WD1 0x1F0 /* Primary Fixed Disk Controller */ -#define IO_GAME 0x201 /* Game Controller */ - - /* 0x202 - 0x22A Open */ - -#define IO_ASC2 0x22B /* AmiScan addr.grp. 2 */ - - /* 0x230 - 0x26A Open */ - -#define IO_ASC3 0x26B /* AmiScan addr.grp. 3 */ -#define IO_GSC1 0x270 /* -- 0x27B! GeniScan GS-4500 addr.grp. 1 */ -#define IO_LPT2 0x278 /* Parallel Port #2 */ - - /* 0x280 - 0x2AA Open */ - -#define IO_ASC4 0x2AB /* AmiScan addr.grp. 4 */ - - /* 0x2B0 - 0x2DF Open */ - -#define IO_GSC2 0x2E0 /* GeniScan GS-4500 addr.grp. 2 */ -#define IO_COM4 0x2E8 /* COM4 i/o address */ -#define IO_ASC5 0x2EB /* AmiScan addr.grp. 5 */ - - /* 0x2F0 - 0x2F7 Open */ - -#define IO_COM2 0x2F8 /* COM2 i/o address */ - - /* 0x300 - 0x32A Open */ - -#define IO_ASC6 0x32B /* AmiScan addr.grp. 6 */ -#define IO_AHA0 0x330 /* adaptec 1542 default addr. */ -#define IO_BT0 0x330 /* bustek 742a default addr. */ -#define IO_UHA0 0x330 /* ultrastore 14f default addr. */ -#define IO_AHA1 0x334 /* adaptec 1542 default addr. */ -#define IO_BT1 0x334 /* bustek 742a default addr. */ - - /* 0x340 - 0x36A Open */ - -#define IO_ASC7 0x36B /* AmiScan addr.grp. 7 */ -#define IO_GSC3 0x370 /* GeniScan GS-4500 addr.grp. 3 */ -#define IO_FD2 0x370 /* secondary base i/o address */ -#define IO_LPT1 0x378 /* Parallel Port #1 */ - - /* 0x380 - 0x3AA Open */ - -#define IO_ASC8 0x3AB /* AmiScan addr.grp. 8 */ -#define IO_MDA 0x3B0 /* Monochome Adapter */ -#define IO_LPT3 0x3BC /* Monochome Adapter Printer Port */ -#define IO_VGA 0x3C0 /* E/VGA Ports */ -#define IO_CGA 0x3D0 /* CGA Ports */ -#define IO_GSC4 0x3E0 /* GeniScan GS-4500 addr.grp. 4 */ -#define IO_COM3 0x3E8 /* COM3 i/o address */ -#define IO_ASC1 0x3EB /* AmiScan addr.grp. 1 */ -#define IO_FD1 0x3F0 /* primary base i/o address */ -#define IO_COM1 0x3F8 /* COM1 i/o address */ - -#define IO_ISAEND 0x3FF /* End (actually Max) of I/O Regs */ -#endif /* !IO_ISABEGIN */ - -/* - * Input / Output Port Sizes - these are from several sources, and tend - * to be the larger of what was found. - */ -#ifndef IO_ISASIZES -#define IO_ISASIZES - -#define IO_ASCSIZE 5 /* AmiScan GI1904-based hand scanner */ -#define IO_CGASIZE 12 /* CGA controllers */ -#define IO_COMSIZE 8 /* 8250, 16x50 com controllers */ -#define IO_DMASIZE 16 /* 8237 DMA controllers */ -#define IO_DPGSIZE 32 /* 74LS612 DMA page registers */ -#define IO_EISASIZE 256 /* EISA controllers */ -#define IO_FDCSIZE 8 /* Nec765 floppy controllers */ -#define IO_GAMSIZE 16 /* AT compatible game controllers */ -#define IO_GSCSIZE 8 /* GeniScan GS-4500G hand scanner */ -#define IO_ICUSIZE 16 /* 8259A interrupt controllers */ -#define IO_KBDSIZE 16 /* 8042 Keyboard controllers */ -#define IO_LPTSIZE 8 /* LPT controllers, some use only 4 */ -#define IO_MDASIZE 12 /* Monochrome display controllers */ -#define IO_NPXSIZE 16 /* 80387/80487 NPX registers */ -#define IO_PMPSIZE 2 /* 82347 power management peripheral */ -#define IO_PSMSIZE 5 /* 8042 Keyboard controllers */ -#define IO_RTCSIZE 16 /* CMOS real time clock, NMI control */ -#define IO_TMRSIZE 16 /* 8253 programmable timers */ -#define IO_VGASIZE 16 /* VGA controllers */ -#define IO_WDCSIZE 8 /* WD compatible disk controllers */ - -#endif /* !IO_ISASIZES */ - -/* - * Input / Output Memory Physical Addresses - */ -#ifndef IOM_BEGIN -#define IOM_BEGIN 0x0A0000 /* Start of I/O Memory "hole" */ -#define IOM_END 0x100000 /* End of I/O Memory "hole" */ -#define IOM_SIZE (IOM_END - IOM_BEGIN) -#endif /* !IOM_BEGIN */ - -/* - * RAM Physical Address Space (ignoring the above mentioned "hole") - */ -#ifndef RAM_BEGIN -#define RAM_BEGIN 0x0000000 /* Start of RAM Memory */ -#define RAM_END 0x1000000 /* End of RAM Memory */ -#define RAM_SIZE (RAM_END - RAM_BEGIN) -#endif /* !RAM_BEGIN */ - -/* - * Oddball Physical Memory Addresses - */ -#ifndef COMPAQ_RAMRELOC -#define COMPAQ_RAMRELOC 0x80C00000 /* Compaq RAM relocation/diag */ -#define COMPAQ_RAMSETUP 0x80C00002 /* Compaq RAM setup */ -#define WEITEK_FPU 0xC0000000 /* WTL 2167 */ -#define CYRIX_EMC 0xC0000000 /* Cyrix EMC */ -#endif /* !COMPAQ_RAMRELOC */ - -#endif /* !_I386_ISA_ISA_H_ */ diff --git a/sys/amd64/isa/nmi.c b/sys/amd64/isa/nmi.c deleted file mode 100644 index 0254195f5ddb..000000000000 --- a/sys/amd64/isa/nmi.c +++ /dev/null @@ -1,501 +0,0 @@ -/*- - * Copyright (c) 1991 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * William Jolitz. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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. - * - * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 - * $Id: intr_machdep.c,v 1.15 1998/12/04 22:54:46 archie Exp $ - */ - -#include "opt_auto_eoi.h" - -#include <sys/param.h> -#ifndef SMP -#include <machine/lock.h> -#endif -#include <sys/systm.h> -#include <sys/syslog.h> -#include <machine/ipl.h> -#include <machine/md_var.h> -#include <machine/segments.h> -#if defined(APIC_IO) -#include <machine/smp.h> -#include <machine/smptests.h> /** FAST_HI */ -#endif /* APIC_IO */ -#include <i386/isa/isa_device.h> -#ifdef PC98 -#include <pc98/pc98/pc98.h> -#include <pc98/pc98/pc98_machdep.h> -#include <pc98/pc98/epsonio.h> -#else -#include <i386/isa/isa.h> -#endif -#include <i386/isa/icu.h> -#include "vector.h" - -#include <i386/isa/intr_machdep.h> -#include <sys/interrupt.h> -#ifdef APIC_IO -#include <machine/clock.h> -#endif - -/* XXX should be in suitable include files */ -#ifdef PC98 -#define ICU_IMR_OFFSET 2 /* IO_ICU{1,2} + 2 */ -#define ICU_SLAVEID 7 -#else -#define ICU_IMR_OFFSET 1 /* IO_ICU{1,2} + 1 */ -#define ICU_SLAVEID 2 -#endif - -#ifdef APIC_IO -/* - * This is to accommodate "mixed-mode" programming for - * motherboards that don't connect the 8254 to the IO APIC. - */ -#define AUTO_EOI_1 1 -#endif - -u_long *intr_countp[ICU_LEN]; -inthand2_t *intr_handler[ICU_LEN]; -u_int intr_mask[ICU_LEN]; -static u_int* intr_mptr[ICU_LEN]; -void *intr_unit[ICU_LEN]; - -static inthand_t *fastintr[ICU_LEN] = { - &IDTVEC(fastintr0), &IDTVEC(fastintr1), - &IDTVEC(fastintr2), &IDTVEC(fastintr3), - &IDTVEC(fastintr4), &IDTVEC(fastintr5), - &IDTVEC(fastintr6), &IDTVEC(fastintr7), - &IDTVEC(fastintr8), &IDTVEC(fastintr9), - &IDTVEC(fastintr10), &IDTVEC(fastintr11), - &IDTVEC(fastintr12), &IDTVEC(fastintr13), - &IDTVEC(fastintr14), &IDTVEC(fastintr15) -#if defined(APIC_IO) - , &IDTVEC(fastintr16), &IDTVEC(fastintr17), - &IDTVEC(fastintr18), &IDTVEC(fastintr19), - &IDTVEC(fastintr20), &IDTVEC(fastintr21), - &IDTVEC(fastintr22), &IDTVEC(fastintr23) -#endif /* APIC_IO */ -}; - -static inthand_t *slowintr[ICU_LEN] = { - &IDTVEC(intr0), &IDTVEC(intr1), &IDTVEC(intr2), &IDTVEC(intr3), - &IDTVEC(intr4), &IDTVEC(intr5), &IDTVEC(intr6), &IDTVEC(intr7), - &IDTVEC(intr8), &IDTVEC(intr9), &IDTVEC(intr10), &IDTVEC(intr11), - &IDTVEC(intr12), &IDTVEC(intr13), &IDTVEC(intr14), &IDTVEC(intr15) -#if defined(APIC_IO) - , &IDTVEC(intr16), &IDTVEC(intr17), &IDTVEC(intr18), &IDTVEC(intr19), - &IDTVEC(intr20), &IDTVEC(intr21), &IDTVEC(intr22), &IDTVEC(intr23) -#endif /* APIC_IO */ -}; - -static inthand2_t isa_strayintr; - -#ifdef PC98 -#define NMI_PARITY 0x04 -#define NMI_EPARITY 0x02 -#else -#define NMI_PARITY (1 << 7) -#define NMI_IOCHAN (1 << 6) -#define ENMI_WATCHDOG (1 << 7) -#define ENMI_BUSTIMER (1 << 6) -#define ENMI_IOSTATUS (1 << 5) -#endif - -/* - * Handle a NMI, possibly a machine check. - * return true to panic system, false to ignore. - */ -int -isa_nmi(cd) - int cd; -{ -#ifdef PC98 - int port = inb(0x33); - if (epson_machine_id == 0x20) - epson_outb(0xc16, epson_inb(0xc16) | 0x1); - if (port & NMI_PARITY) { - panic("BASE RAM parity error, likely hardware failure."); - } else if (port & NMI_EPARITY) { - panic("EXTENDED RAM parity error, likely hardware failure."); - } else { - printf("\nNMI Resume ??\n"); - return(0); - } -#else /* IBM-PC */ - int isa_port = inb(0x61); - int eisa_port = inb(0x461); - - if (isa_port & NMI_PARITY) - panic("RAM parity error, likely hardware failure."); - - if (isa_port & NMI_IOCHAN) - panic("I/O channel check, likely hardware failure."); - - /* - * On a real EISA machine, this will never happen. However it can - * happen on ISA machines which implement XT style floating point - * error handling (very rare). Save them from a meaningless panic. - */ - if (eisa_port == 0xff) - return(0); - - if (eisa_port & ENMI_WATCHDOG) - panic("EISA watchdog timer expired, likely hardware failure."); - - if (eisa_port & ENMI_BUSTIMER) - panic("EISA bus timeout, likely hardware failure."); - - if (eisa_port & ENMI_IOSTATUS) - panic("EISA I/O port status error."); - - printf("\nNMI ISA %x, EISA %x\n", isa_port, eisa_port); - return(0); -#endif -} - -/* - * Fill in default interrupt table (in case of spuruious interrupt - * during configuration of kernel, setup interrupt control unit - */ -void -isa_defaultirq() -{ - int i; - - /* icu vectors */ - for (i = 0; i < ICU_LEN; i++) - icu_unset(i, (inthand2_t *)NULL); - - /* initialize 8259's */ - outb(IO_ICU1, 0x11); /* reset; program device, four bytes */ - - outb(IO_ICU1+ICU_IMR_OFFSET, NRSVIDT); /* starting at this vector index */ - outb(IO_ICU1+ICU_IMR_OFFSET, IRQ_SLAVE); /* slave on line 7 */ -#ifdef PC98 -#ifdef AUTO_EOI_1 - outb(IO_ICU1+ICU_IMR_OFFSET, 0x1f); /* (master) auto EOI, 8086 mode */ -#else - outb(IO_ICU1+ICU_IMR_OFFSET, 0x1d); /* (master) 8086 mode */ -#endif -#else /* IBM-PC */ -#ifdef AUTO_EOI_1 - outb(IO_ICU1+ICU_IMR_OFFSET, 2 | 1); /* auto EOI, 8086 mode */ -#else - outb(IO_ICU1+ICU_IMR_OFFSET, 1); /* 8086 mode */ -#endif -#endif /* PC98 */ - outb(IO_ICU1+ICU_IMR_OFFSET, 0xff); /* leave interrupts masked */ - outb(IO_ICU1, 0x0a); /* default to IRR on read */ -#ifndef PC98 - outb(IO_ICU1, 0xc0 | (3 - 1)); /* pri order 3-7, 0-2 (com2 first) */ -#endif /* !PC98 */ - - outb(IO_ICU2, 0x11); /* reset; program device, four bytes */ - outb(IO_ICU2+ICU_IMR_OFFSET, NRSVIDT+8); /* staring at this vector index */ - outb(IO_ICU2+ICU_IMR_OFFSET, ICU_SLAVEID); /* my slave id is 7 */ -#ifdef PC98 - outb(IO_ICU2+ICU_IMR_OFFSET,9); /* 8086 mode */ -#else /* IBM-PC */ -#ifdef AUTO_EOI_2 - outb(IO_ICU2+ICU_IMR_OFFSET, 2 | 1); /* auto EOI, 8086 mode */ -#else - outb(IO_ICU2+ICU_IMR_OFFSET,1); /* 8086 mode */ -#endif -#endif /* PC98 */ - outb(IO_ICU2+ICU_IMR_OFFSET, 0xff); /* leave interrupts masked */ - outb(IO_ICU2, 0x0a); /* default to IRR on read */ -} - -/* - * Caught a stray interrupt, notify - */ -static void -isa_strayintr(vcookiep) - void *vcookiep; -{ - int intr = (void **)vcookiep - &intr_unit[0]; - - /* DON'T BOTHER FOR NOW! */ - /* for some reason, we get bursts of intr #7, even if not enabled! */ - /* - * Well the reason you got bursts of intr #7 is because someone - * raised an interrupt line and dropped it before the 8259 could - * prioritize it. This is documented in the intel data book. This - * means you have BAD hardware! I have changed this so that only - * the first 5 get logged, then it quits logging them, and puts - * out a special message. rgrimes 3/25/1993 - */ - /* - * XXX TODO print a different message for #7 if it is for a - * glitch. Glitches can be distinguished from real #7's by - * testing that the in-service bit is _not_ set. The test - * must be done before sending an EOI so it can't be done if - * we are using AUTO_EOI_1. - */ - if (intrcnt[NR_DEVICES + intr] <= 5) - log(LOG_ERR, "stray irq %d\n", intr); - if (intrcnt[NR_DEVICES + intr] == 5) - log(LOG_CRIT, - "too many stray irq %d's; not logging any more\n", intr); -} - -/* - * Return a bitmap of the current interrupt requests. This is 8259-specific - * and is only suitable for use at probe time. - */ -intrmask_t -isa_irq_pending() -{ - u_char irr1; - u_char irr2; - - irr1 = inb(IO_ICU1); - irr2 = inb(IO_ICU2); - return ((irr2 << 8) | irr1); -} - -int -update_intr_masks(void) -{ - int intr, n=0; - u_int mask,*maskptr; - - for (intr=0; intr < ICU_LEN; intr ++) { -#if defined(APIC_IO) - /* no 8259 SLAVE to ignore */ -#else - if (intr==ICU_SLAVEID) continue; /* ignore 8259 SLAVE output */ -#endif /* APIC_IO */ - maskptr = intr_mptr[intr]; - if (!maskptr) continue; - *maskptr |= 1 << intr; - mask = *maskptr; - if (mask != intr_mask[intr]) { -#if 0 - printf ("intr_mask[%2d] old=%08x new=%08x ptr=%p.\n", - intr, intr_mask[intr], mask, maskptr); -#endif - intr_mask[intr]=mask; - n++; - } - - } - return (n); -} - -/* - * The find_device_id function is only required because of the way the - * device names are currently stored for reporting in systat or vmstat. - * In fact, those programs should be modified to use the sysctl interface - * to obtain a list of driver names by traversing intreclist_head[irq]. - */ -static int -find_device_id(int irq) -{ - char buf[16]; - char *cp; - int free_id, id; - - snprintf(buf, sizeof(buf), "pci irq%d", irq); - cp = intrnames; - /* default to 0, which corresponds to clk0 */ - free_id = 0; - - for (id = 0; id < NR_DEVICES; id++) { - if (strcmp(cp, buf) == 0) - return (id); - if (free_id == 0 && strcmp(cp, "pci irqnn") == 0) - free_id = id; - while (*cp++ != '\0'); - } -#if 0 - if (free_id == 0) { - /* - * All pci irq counters are in use, perhaps because config - * is old so there aren't any. Abuse the clk0 counter. - */ - printf("\tcounting shared irq%d as clk0 irq\n", irq); - } -#endif - return (free_id); -} - -void -update_intrname(int intr, int device_id) -{ - char *cp; - int id; - - if (device_id == -1) - device_id = find_device_id(intr); - - if ((u_int)device_id >= NR_DEVICES) - return; - - intr_countp[intr] = &intrcnt[device_id]; - - for (cp = intrnames, id = 0; id <= device_id; id++) - while (*cp++ != '\0') - ; - if (cp > eintrnames) - return; - if (intr < 10) { - cp[-3] = intr + '0'; - cp[-2] = ' '; - } else if (intr < 20) { - cp[-3] = '1'; - cp[-2] = intr - 10 + '0'; - } else { - cp[-3] = '2'; - cp[-2] = intr - 20 + '0'; - } -} - - -int -icu_setup(int intr, inthand2_t *handler, void *arg, u_int *maskptr, int flags) -{ -#ifdef FAST_HI - int select; /* the select register is 8 bits */ - int vector; - u_int32_t value; /* the window register is 32 bits */ -#endif /* FAST_HI */ - u_long ef; - u_int mask = (maskptr ? *maskptr : 0); - -#if defined(APIC_IO) - if ((u_int)intr >= ICU_LEN) /* no 8259 SLAVE to ignore */ -#else - if ((u_int)intr >= ICU_LEN || intr == ICU_SLAVEID) -#endif /* APIC_IO */ - if (intr_handler[intr] != isa_strayintr) - return (EBUSY); - - ef = read_eflags(); - disable_intr(); - intr_handler[intr] = handler; - intr_mptr[intr] = maskptr; - intr_mask[intr] = mask | (1 << intr); - intr_unit[intr] = arg; -#ifdef FAST_HI - if (flags & INTR_FAST) { - vector = TPR_FAST_INTS + intr; - setidt(vector, fastintr[intr], - SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); - } - else { - vector = TPR_SLOW_INTS + intr; -#ifdef APIC_INTR_REORDER -#ifdef APIC_INTR_HIGHPRI_CLOCK - /* XXX: Hack (kludge?) for more accurate clock. */ - if (intr == apic_8254_intr || intr == 8) { - vector = TPR_FAST_INTS + intr; - } -#endif -#endif - setidt(vector, slowintr[intr], - SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); - } -#ifdef APIC_INTR_REORDER - set_lapic_isrloc(intr, vector); -#endif - /* - * Reprogram the vector in the IO APIC. - */ - if (int_to_apicintpin[intr].ioapic >= 0) { - select = int_to_apicintpin[intr].redirindex; - value = io_apic_read(int_to_apicintpin[intr].ioapic, - select) & ~IOART_INTVEC; - io_apic_write(int_to_apicintpin[intr].ioapic, - select, value | vector); - } -#else - setidt(ICU_OFFSET + intr, - flags & INTR_FAST ? fastintr[intr] : slowintr[intr], - SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); -#endif /* FAST_HI */ - INTREN(1 << intr); - MPINTR_UNLOCK(); - write_eflags(ef); - return (0); -} - -void -register_imask(dvp, mask) - struct isa_device *dvp; - u_int mask; -{ - if (dvp->id_alive && dvp->id_irq) { - int intr; - - intr = ffs(dvp->id_irq) - 1; - intr_mask[intr] = mask | (1 <<intr); - } - (void) update_intr_masks(); -} - -int -icu_unset(intr, handler) - int intr; - inthand2_t *handler; -{ - u_long ef; - - if ((u_int)intr >= ICU_LEN || handler != intr_handler[intr]) - return (EINVAL); - - INTRDIS(1 << intr); - ef = read_eflags(); - disable_intr(); - intr_countp[intr] = &intrcnt[NR_DEVICES + intr]; - intr_handler[intr] = isa_strayintr; - intr_mptr[intr] = NULL; - intr_mask[intr] = HWI_MASK | SWI_MASK; - intr_unit[intr] = &intr_unit[intr]; -#ifdef FAST_HI_XXX - /* XXX how do I re-create dvp here? */ - setidt(flags & INTR_FAST ? TPR_FAST_INTS + intr : TPR_SLOW_INTS + intr, - slowintr[intr], SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); -#else /* FAST_HI */ -#ifdef APIC_INTR_REORDER - set_lapic_isrloc(intr, ICU_OFFSET + intr); -#endif - setidt(ICU_OFFSET + intr, slowintr[intr], SDT_SYS386IGT, SEL_KPL, - GSEL(GCODE_SEL, SEL_KPL)); -#endif /* FAST_HI */ - MPINTR_UNLOCK(); - write_eflags(ef); - return (0); -} diff --git a/sys/amd64/isa/npx.c b/sys/amd64/isa/npx.c deleted file mode 100644 index 6bb4e0fa4d17..000000000000 --- a/sys/amd64/isa/npx.c +++ /dev/null @@ -1,687 +0,0 @@ -/*- - * Copyright (c) 1990 William Jolitz. - * Copyright (c) 1991 The Regents of the University of California. - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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. - * - * from: @(#)npx.c 7.2 (Berkeley) 5/12/91 - * $Id: npx.c,v 1.64 1998/12/14 19:16:17 bde Exp $ - */ - -#include "npx.h" -#if NNPX > 0 - -#include "opt_debug_npx.h" -#include "opt_math_emulate.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/sysctl.h> -#include <sys/proc.h> -#ifdef NPX_DEBUG -#include <sys/syslog.h> -#endif -#include <sys/signalvar.h> - -#ifndef SMP -#include <machine/asmacros.h> -#endif -#include <machine/cputypes.h> -#include <machine/frame.h> -#include <machine/ipl.h> -#include <machine/md_var.h> -#include <machine/pcb.h> -#include <machine/psl.h> -#ifndef SMP -#include <machine/clock.h> -#endif -#include <machine/specialreg.h> -#include <machine/segments.h> - -#ifndef SMP -#include <i386/isa/icu.h> -#include <i386/isa/intr_machdep.h> -#include <i386/isa/isa.h> -#endif -#include <i386/isa/isa_device.h> - -/* - * 387 and 287 Numeric Coprocessor Extension (NPX) Driver. - */ - -/* Configuration flags. */ -#define NPX_DISABLE_I586_OPTIMIZED_BCOPY (1 << 0) -#define NPX_DISABLE_I586_OPTIMIZED_BZERO (1 << 1) -#define NPX_DISABLE_I586_OPTIMIZED_COPYIO (1 << 2) - -/* XXX - should be in header file. */ -ointhand2_t npxintr; - -#ifdef __GNUC__ - -#define fldcw(addr) __asm("fldcw %0" : : "m" (*(addr))) -#define fnclex() __asm("fnclex") -#define fninit() __asm("fninit") -#define fnop() __asm("fnop") -#define fnsave(addr) __asm __volatile("fnsave %0" : "=m" (*(addr))) -#define fnstcw(addr) __asm __volatile("fnstcw %0" : "=m" (*(addr))) -#define fnstsw(addr) __asm __volatile("fnstsw %0" : "=m" (*(addr))) -#define fp_divide_by_0() __asm("fldz; fld1; fdiv %st,%st(1); fnop") -#define frstor(addr) __asm("frstor %0" : : "m" (*(addr))) -#define start_emulating() __asm("smsw %%ax; orb %0,%%al; lmsw %%ax" \ - : : "n" (CR0_TS) : "ax") -#define stop_emulating() __asm("clts") - -#else /* not __GNUC__ */ - -void fldcw __P((caddr_t addr)); -void fnclex __P((void)); -void fninit __P((void)); -void fnop __P((void)); -void fnsave __P((caddr_t addr)); -void fnstcw __P((caddr_t addr)); -void fnstsw __P((caddr_t addr)); -void fp_divide_by_0 __P((void)); -void frstor __P((caddr_t addr)); -void start_emulating __P((void)); -void stop_emulating __P((void)); - -#endif /* __GNUC__ */ - -typedef u_char bool_t; - -static int npxattach __P((struct isa_device *dvp)); -static int npxprobe __P((struct isa_device *dvp)); -static int npxprobe1 __P((struct isa_device *dvp)); -static long timezero __P((const char *funcname, - void (*func)(void *buf, size_t len))); - -struct isa_driver npxdriver = { - npxprobe, npxattach, "npx", -}; - -int hw_float; /* XXX currently just alias for npx_exists */ - -SYSCTL_INT(_hw,HW_FLOATINGPT, floatingpoint, - CTLFLAG_RD, &hw_float, 0, - "Floatingpoint instructions executed in hardware"); - -#ifndef SMP -static u_int npx0_imask = SWI_CLOCK_MASK; -static struct gate_descriptor npx_idt_probeintr; -static int npx_intrno; -static volatile u_int npx_intrs_while_probing; -static volatile u_int npx_traps_while_probing; -#endif - -static bool_t npx_ex16; -static bool_t npx_exists; -static bool_t npx_irq13; - -#ifndef SMP -/* - * Special interrupt handlers. Someday intr0-intr15 will be used to count - * interrupts. We'll still need a special exception 16 handler. The busy - * latch stuff in probeintr() can be moved to npxprobe(). - */ -inthand_t probeintr; -__asm(" \n\ - .text \n\ - .p2align 2,0x90 \n\ -" __XSTRING(CNAME(probeintr)) ": \n\ - ss \n\ - incl " __XSTRING(CNAME(npx_intrs_while_probing)) " \n\ - pushl %eax \n\ - movb $0x20,%al # EOI (asm in strings loses cpp features) \n\ - outb %al,$0xa0 # IO_ICU2 \n\ - outb %al,$0x20 # IO_ICU1 \n\ - movb $0,%al \n\ - outb %al,$0xf0 # clear BUSY# latch \n\ - popl %eax \n\ - iret \n\ -"); - -inthand_t probetrap; -__asm(" \n\ - .text \n\ - .p2align 2,0x90 \n\ -" __XSTRING(CNAME(probetrap)) ": \n\ - ss \n\ - incl " __XSTRING(CNAME(npx_traps_while_probing)) " \n\ - fnclex \n\ - iret \n\ -"); -#endif /* SMP */ - -/* - * Probe routine. Initialize cr0 to give correct behaviour for [f]wait - * whether the device exists or not (XXX should be elsewhere). Set flags - * to tell npxattach() what to do. Modify device struct if npx doesn't - * need to use interrupts. Return 1 if device exists. - */ -static int -npxprobe(dvp) - struct isa_device *dvp; -{ -#ifdef SMP - - return npxprobe1(dvp); - -#else /* SMP */ - - int result; - u_long save_eflags; - u_char save_icu1_mask; - u_char save_icu2_mask; - struct gate_descriptor save_idt_npxintr; - struct gate_descriptor save_idt_npxtrap; - /* - * This routine is now just a wrapper for npxprobe1(), to install - * special npx interrupt and trap handlers, to enable npx interrupts - * and to disable other interrupts. Someday isa_configure() will - * install suitable handlers and run with interrupts enabled so we - * won't need to do so much here. - */ - npx_intrno = NRSVIDT + ffs(dvp->id_irq) - 1; - save_eflags = read_eflags(); - disable_intr(); - save_icu1_mask = inb(IO_ICU1 + 1); - save_icu2_mask = inb(IO_ICU2 + 1); - save_idt_npxintr = idt[npx_intrno]; - save_idt_npxtrap = idt[16]; - outb(IO_ICU1 + 1, ~(IRQ_SLAVE | dvp->id_irq)); - outb(IO_ICU2 + 1, ~(dvp->id_irq >> 8)); - setidt(16, probetrap, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); - setidt(npx_intrno, probeintr, SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); - npx_idt_probeintr = idt[npx_intrno]; - enable_intr(); - result = npxprobe1(dvp); - disable_intr(); - outb(IO_ICU1 + 1, save_icu1_mask); - outb(IO_ICU2 + 1, save_icu2_mask); - idt[npx_intrno] = save_idt_npxintr; - idt[16] = save_idt_npxtrap; - write_eflags(save_eflags); - return (result); - -#endif /* SMP */ -} - -static int -npxprobe1(dvp) - struct isa_device *dvp; -{ -#ifndef SMP - u_short control; - u_short status; -#endif - - /* - * Partially reset the coprocessor, if any. Some BIOS's don't reset - * it after a warm boot. - */ - outb(0xf1, 0); /* full reset on some systems, NOP on others */ - outb(0xf0, 0); /* clear BUSY# latch */ - /* - * Prepare to trap all ESC (i.e., NPX) instructions and all WAIT - * instructions. We must set the CR0_MP bit and use the CR0_TS - * bit to control the trap, because setting the CR0_EM bit does - * not cause WAIT instructions to trap. It's important to trap - * WAIT instructions - otherwise the "wait" variants of no-wait - * control instructions would degenerate to the "no-wait" variants - * after FP context switches but work correctly otherwise. It's - * particularly important to trap WAITs when there is no NPX - - * otherwise the "wait" variants would always degenerate. - * - * Try setting CR0_NE to get correct error reporting on 486DX's. - * Setting it should fail or do nothing on lesser processors. - */ - load_cr0(rcr0() | CR0_MP | CR0_NE); - /* - * But don't trap while we're probing. - */ - stop_emulating(); - /* - * Finish resetting the coprocessor, if any. If there is an error - * pending, then we may get a bogus IRQ13, but probeintr() will handle - * it OK. Bogus halts have never been observed, but we enabled - * IRQ13 and cleared the BUSY# latch early to handle them anyway. - */ - fninit(); - -#ifdef SMP - - /* - * Exception 16 MUST work for SMP. - */ - npx_irq13 = 0; - npx_ex16 = hw_float = npx_exists = 1; - dvp->id_irq = 0; /* zap the interrupt */ - /* - * special return value to flag that we do not - * actually use any I/O registers - */ - return (-1); - -#else /* SMP */ - - /* - * Don't use fwait here because it might hang. - * Don't use fnop here because it usually hangs if there is no FPU. - */ - DELAY(1000); /* wait for any IRQ13 */ -#ifdef DIAGNOSTIC - if (npx_intrs_while_probing != 0) - printf("fninit caused %u bogus npx interrupt(s)\n", - npx_intrs_while_probing); - if (npx_traps_while_probing != 0) - printf("fninit caused %u bogus npx trap(s)\n", - npx_traps_while_probing); -#endif - /* - * Check for a status of mostly zero. - */ - status = 0x5a5a; - fnstsw(&status); - if ((status & 0xb8ff) == 0) { - /* - * Good, now check for a proper control word. - */ - control = 0x5a5a; - fnstcw(&control); - if ((control & 0x1f3f) == 0x033f) { - hw_float = npx_exists = 1; - /* - * We have an npx, now divide by 0 to see if exception - * 16 works. - */ - control &= ~(1 << 2); /* enable divide by 0 trap */ - fldcw(&control); - npx_traps_while_probing = npx_intrs_while_probing = 0; - fp_divide_by_0(); - if (npx_traps_while_probing != 0) { - /* - * Good, exception 16 works. - */ - npx_ex16 = 1; - dvp->id_irq = 0; /* zap the interrupt */ - /* - * special return value to flag that we do not - * actually use any I/O registers - */ - return (-1); - } - if (npx_intrs_while_probing != 0) { - /* - * Bad, we are stuck with IRQ13. - */ - npx_irq13 = 1; - /* - * npxattach would be too late to set npx0_imask. - */ - npx0_imask |= dvp->id_irq; - return (IO_NPXSIZE); - } - /* - * Worse, even IRQ13 is broken. Use emulator. - */ - } - } - /* - * Probe failed, but we want to get to npxattach to initialize the - * emulator and say that it has been installed. XXX handle devices - * that aren't really devices better. - */ - dvp->id_irq = 0; - /* - * special return value to flag that we do not - * actually use any I/O registers - */ - return (-1); - -#endif /* SMP */ -} - -/* - * Attach routine - announce which it is, and wire into system - */ -int -npxattach(dvp) - struct isa_device *dvp; -{ - dvp->id_ointr = npxintr; - - /* The caller has printed "irq 13" for the npx_irq13 case. */ - if (!npx_irq13) { - printf("npx%d: ", dvp->id_unit); - if (npx_ex16) - printf("INT 16 interface\n"); -#if defined(MATH_EMULATE) || defined(GPL_MATH_EMULATE) - else if (npx_exists) { - printf("error reporting broken; using 387 emulator\n"); - hw_float = npx_exists = 0; - } else - printf("387 emulator\n"); -#else - else - printf("no 387 emulator in kernel!\n"); -#endif - } - npxinit(__INITIAL_NPXCW__); - -#ifdef I586_CPU - if (cpu_class == CPUCLASS_586 && npx_ex16 && - timezero("i586_bzero()", i586_bzero) < - timezero("bzero()", bzero) * 4 / 5) { - if (!(dvp->id_flags & NPX_DISABLE_I586_OPTIMIZED_BCOPY)) { - bcopy_vector = i586_bcopy; - ovbcopy_vector = i586_bcopy; - } - if (!(dvp->id_flags & NPX_DISABLE_I586_OPTIMIZED_BZERO)) - bzero = i586_bzero; - if (!(dvp->id_flags & NPX_DISABLE_I586_OPTIMIZED_COPYIO)) { - copyin_vector = i586_copyin; - copyout_vector = i586_copyout; - } - } -#endif - - return (1); /* XXX unused */ -} - -/* - * Initialize floating point unit. - */ -void -npxinit(control) - u_short control; -{ - struct save87 dummy; - - if (!npx_exists) - return; - /* - * fninit has the same h/w bugs as fnsave. Use the detoxified - * fnsave to throw away any junk in the fpu. npxsave() initializes - * the fpu and sets npxproc = NULL as important side effects. - */ - npxsave(&dummy); - stop_emulating(); - fldcw(&control); - if (curpcb != NULL) - fnsave(&curpcb->pcb_savefpu); - start_emulating(); -} - -/* - * Free coprocessor (if we have it). - */ -void -npxexit(p) - struct proc *p; -{ - - if (p == npxproc) - npxsave(&curpcb->pcb_savefpu); -#ifdef NPX_DEBUG - if (npx_exists) { - u_int masked_exceptions; - - masked_exceptions = curpcb->pcb_savefpu.sv_env.en_cw - & curpcb->pcb_savefpu.sv_env.en_sw & 0x7f; - /* - * Log exceptions that would have trapped with the old - * control word (overflow, divide by 0, and invalid operand). - */ - if (masked_exceptions & 0x0d) - log(LOG_ERR, - "pid %d (%s) exited with masked floating point exceptions 0x%02x\n", - p->p_pid, p->p_comm, masked_exceptions); - } -#endif -} - -/* - * Preserve the FP status word, clear FP exceptions, then generate a SIGFPE. - * - * Clearing exceptions is necessary mainly to avoid IRQ13 bugs. We now - * depend on longjmp() restoring a usable state. Restoring the state - * or examining it might fail if we didn't clear exceptions. - * - * XXX there is no standard way to tell SIGFPE handlers about the error - * state. The old interface: - * - * void handler(int sig, int code, struct sigcontext *scp); - * - * is broken because it is non-ANSI and because the FP state is not in - * struct sigcontext. - * - * XXX the FP state is not preserved across signal handlers. So signal - * handlers cannot afford to do FP unless they preserve the state or - * longjmp() out. Both preserving the state and longjmp()ing may be - * destroyed by IRQ13 bugs. Clearing FP exceptions is not an acceptable - * solution for signals other than SIGFPE. - */ -void -npxintr(unit) - int unit; -{ - int code; - struct intrframe *frame; - - if (npxproc == NULL || !npx_exists) { - printf("npxintr: npxproc = %p, curproc = %p, npx_exists = %d\n", - npxproc, curproc, npx_exists); - panic("npxintr from nowhere"); - } - if (npxproc != curproc) { - printf("npxintr: npxproc = %p, curproc = %p, npx_exists = %d\n", - npxproc, curproc, npx_exists); - panic("npxintr from non-current process"); - } - - outb(0xf0, 0); - fnstsw(&curpcb->pcb_savefpu.sv_ex_sw); - fnclex(); - - /* - * Pass exception to process. - */ - frame = (struct intrframe *)&unit; /* XXX */ - if ((ISPL(frame->if_cs) == SEL_UPL) || (frame->if_eflags & PSL_VM)) { - /* - * Interrupt is essentially a trap, so we can afford to call - * the SIGFPE handler (if any) as soon as the interrupt - * returns. - * - * XXX little or nothing is gained from this, and plenty is - * lost - the interrupt frame has to contain the trap frame - * (this is otherwise only necessary for the rescheduling trap - * in doreti, and the frame for that could easily be set up - * just before it is used). - */ - curproc->p_md.md_regs = (struct trapframe *)&frame->if_es; -#ifdef notyet - /* - * Encode the appropriate code for detailed information on - * this exception. - */ - code = XXX_ENCODE(curpcb->pcb_savefpu.sv_ex_sw); -#else - code = 0; /* XXX */ -#endif - trapsignal(curproc, SIGFPE, code); - } else { - /* - * Nested interrupt. These losers occur when: - * o an IRQ13 is bogusly generated at a bogus time, e.g.: - * o immediately after an fnsave or frstor of an - * error state. - * o a couple of 386 instructions after - * "fstpl _memvar" causes a stack overflow. - * These are especially nasty when combined with a - * trace trap. - * o an IRQ13 occurs at the same time as another higher- - * priority interrupt. - * - * Treat them like a true async interrupt. - */ - psignal(curproc, SIGFPE); - } -} - -/* - * Implement device not available (DNA) exception - * - * It would be better to switch FP context here (if curproc != npxproc) - * and not necessarily for every context switch, but it is too hard to - * access foreign pcb's. - */ -int -npxdna() -{ - if (!npx_exists) - return (0); - if (npxproc != NULL) { - printf("npxdna: npxproc = %p, curproc = %p\n", - npxproc, curproc); - panic("npxdna"); - } - stop_emulating(); - /* - * Record new context early in case frstor causes an IRQ13. - */ - npxproc = curproc; - curpcb->pcb_savefpu.sv_ex_sw = 0; - /* - * The following frstor may cause an IRQ13 when the state being - * restored has a pending error. The error will appear to have been - * triggered by the current (npx) user instruction even when that - * instruction is a no-wait instruction that should not trigger an - * error (e.g., fnclex). On at least one 486 system all of the - * no-wait instructions are broken the same as frstor, so our - * treatment does not amplify the breakage. On at least one - * 386/Cyrix 387 system, fnclex works correctly while frstor and - * fnsave are broken, so our treatment breaks fnclex if it is the - * first FPU instruction after a context switch. - */ - frstor(&curpcb->pcb_savefpu); - - return (1); -} - -/* - * Wrapper for fnsave instruction to handle h/w bugs. If there is an error - * pending, then fnsave generates a bogus IRQ13 on some systems. Force - * any IRQ13 to be handled immediately, and then ignore it. This routine is - * often called at splhigh so it must not use many system services. In - * particular, it's much easier to install a special handler than to - * guarantee that it's safe to use npxintr() and its supporting code. - */ -void -npxsave(addr) - struct save87 *addr; -{ -#ifdef SMP - - stop_emulating(); - fnsave(addr); - /* fnop(); */ - start_emulating(); - npxproc = NULL; - -#else /* SMP */ - - u_char icu1_mask; - u_char icu2_mask; - u_char old_icu1_mask; - u_char old_icu2_mask; - struct gate_descriptor save_idt_npxintr; - - disable_intr(); - old_icu1_mask = inb(IO_ICU1 + 1); - old_icu2_mask = inb(IO_ICU2 + 1); - save_idt_npxintr = idt[npx_intrno]; - outb(IO_ICU1 + 1, old_icu1_mask & ~(IRQ_SLAVE | npx0_imask)); - outb(IO_ICU2 + 1, old_icu2_mask & ~(npx0_imask >> 8)); - idt[npx_intrno] = npx_idt_probeintr; - enable_intr(); - stop_emulating(); - fnsave(addr); - fnop(); - start_emulating(); - npxproc = NULL; - disable_intr(); - icu1_mask = inb(IO_ICU1 + 1); /* masks may have changed */ - icu2_mask = inb(IO_ICU2 + 1); - outb(IO_ICU1 + 1, - (icu1_mask & ~npx0_imask) | (old_icu1_mask & npx0_imask)); - outb(IO_ICU2 + 1, - (icu2_mask & ~(npx0_imask >> 8)) - | (old_icu2_mask & (npx0_imask >> 8))); - idt[npx_intrno] = save_idt_npxintr; - enable_intr(); /* back to usual state */ - -#endif /* SMP */ -} - -#ifdef I586_CPU -static long -timezero(funcname, func) - const char *funcname; - void (*func) __P((void *buf, size_t len)); - -{ - void *buf; -#define BUFSIZE 1000000 - long usec; - struct timeval finish, start; - - buf = malloc(BUFSIZE, M_TEMP, M_NOWAIT); - if (buf == NULL) - return (BUFSIZE); - microtime(&start); - (*func)(buf, BUFSIZE); - microtime(&finish); - usec = 1000000 * (finish.tv_sec - start.tv_sec) + - finish.tv_usec - start.tv_usec; - if (usec <= 0) - usec = 1; - if (bootverbose) - printf("%s bandwidth = %ld bytes/sec\n", - funcname, (long)(BUFSIZE * (int64_t)1000000 / usec)); - free(buf, M_TEMP); - return (usec); -} -#endif /* I586_CPU */ - -#endif /* NNPX > 0 */ diff --git a/sys/amd64/isa/timerreg.h b/sys/amd64/isa/timerreg.h deleted file mode 100644 index ff27bacc24a4..000000000000 --- a/sys/amd64/isa/timerreg.h +++ /dev/null @@ -1,110 +0,0 @@ -/*- - * Copyright (c) 1993 The Regents of the University of California. - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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. - * - * from: Header: timerreg.h,v 1.2 93/02/28 15:08:58 mccanne Exp - * $Id$ - */ - -/* - * - * Register definitions for the Intel 8253 Programmable Interval Timer. - * - * This chip has three independent 16-bit down counters that can be - * read on the fly. There are three mode registers and three countdown - * registers. The countdown registers are addressed directly, via the - * first three I/O ports. The three mode registers are accessed via - * the fourth I/O port, with two bits in the mode byte indicating the - * register. (Why are hardware interfaces always so braindead?). - * - * To write a value into the countdown register, the mode register - * is first programmed with a command indicating the which byte of - * the two byte register is to be modified. The three possibilities - * are load msb (TMR_MR_MSB), load lsb (TMR_MR_LSB), or load lsb then - * msb (TMR_MR_BOTH). - * - * To read the current value ("on the fly") from the countdown register, - * you write a "latch" command into the mode register, then read the stable - * value from the corresponding I/O port. For example, you write - * TMR_MR_LATCH into the corresponding mode register. Presumably, - * after doing this, a write operation to the I/O port would result - * in undefined behavior (but hopefully not fry the chip). - * Reading in this manner has no side effects. - * - * [IBM-PC] - * The outputs of the three timers are connected as follows: - * - * timer 0 -> irq 0 - * timer 1 -> dma chan 0 (for dram refresh) - * timer 2 -> speaker (via keyboard controller) - * - * Timer 0 is used to call hardclock. - * Timer 2 is used to generate console beeps. - * - * [PC-9801] - * The outputs of the three timers are connected as follows: - * - * timer 0 -> irq 0 - * timer 1 -> speaker (via keyboard controller) - * timer 2 -> RS232C - * - * Timer 0 is used to call hardclock. - * Timer 1 is used to generate console beeps. - */ - -/* - * Macros for specifying values to be written into a mode register. - */ -#define TIMER_CNTR0 (IO_TIMER1 + 0) /* timer 0 counter port */ -#ifdef PC98 -#define TIMER_CNTR1 0x3fdb /* timer 1 counter port */ -#define TIMER_CNTR2 (IO_TIMER1 + 4) /* timer 2 counter port */ -#define TIMER_MODE (IO_TIMER1 + 6) /* timer mode port */ -#else -#define TIMER_CNTR1 (IO_TIMER1 + 1) /* timer 1 counter port */ -#define TIMER_CNTR2 (IO_TIMER1 + 2) /* timer 2 counter port */ -#define TIMER_MODE (IO_TIMER1 + 3) /* timer mode port */ -#endif -#define TIMER_SEL0 0x00 /* select counter 0 */ -#define TIMER_SEL1 0x40 /* select counter 1 */ -#define TIMER_SEL2 0x80 /* select counter 2 */ -#define TIMER_INTTC 0x00 /* mode 0, intr on terminal cnt */ -#define TIMER_ONESHOT 0x02 /* mode 1, one shot */ -#define TIMER_RATEGEN 0x04 /* mode 2, rate generator */ -#define TIMER_SQWAVE 0x06 /* mode 3, square wave */ -#define TIMER_SWSTROBE 0x08 /* mode 4, s/w triggered strobe */ -#define TIMER_HWSTROBE 0x0a /* mode 5, h/w triggered strobe */ -#define TIMER_LATCH 0x00 /* latch counter for reading */ -#define TIMER_LSB 0x10 /* r/w counter LSB */ -#define TIMER_MSB 0x20 /* r/w counter MSB */ -#define TIMER_16BIT 0x30 /* r/w counter 16 bits, LSB first */ -#define TIMER_BCD 0x01 /* count in BCD */ - diff --git a/sys/amd64/isa/vector.S b/sys/amd64/isa/vector.S deleted file mode 100644 index 1fc56685f3eb..000000000000 --- a/sys/amd64/isa/vector.S +++ /dev/null @@ -1,95 +0,0 @@ -/* - * from: vector.s, 386BSD 0.1 unknown origin - * $Id: vector.s,v 1.2 1997/05/24 17:05:26 smp Exp smp $ - */ - -/* - * modified for PC98 by Kakefuda - */ - -#include "opt_auto_eoi.h" - -#include <i386/isa/icu.h> -#ifdef PC98 -#include <pc98/pc98/pc98.h> -#else -#include <i386/isa/isa.h> -#endif - -#ifdef FAST_INTR_HANDLER_USES_ES -#define ACTUALLY_PUSHED 1 -#define MAYBE_MOVW_AX_ES movl %ax,%es -#define MAYBE_POPL_ES popl %es -#define MAYBE_PUSHL_ES pushl %es -#else -/* - * We can usually skip loading %es for fastintr handlers. %es should - * only be used for string instructions, and fastintr handlers shouldn't - * do anything slow enough to justify using a string instruction. - */ -#define ACTUALLY_PUSHED 0 -#define MAYBE_MOVW_AX_ES -#define MAYBE_POPL_ES -#define MAYBE_PUSHL_ES -#endif - - .data - ALIGN_DATA - - .globl _intr_nesting_level -_intr_nesting_level: - .byte 0 - .space 3 - - .text - -/* - * Macros for interrupt interrupt entry, call to handler, and exit. - * - * XXX - the interrupt frame is set up to look like a trap frame. This is - * usually a waste of time. The only interrupt handlers that want a frame - * are the clock handler (it wants a clock frame), the npx handler (it's - * easier to do right all in assembler). The interrupt return routine - * needs a trap frame for rare AST's (it could easily convert the frame). - * The direct costs of setting up a trap frame are two pushl's (error - * code and trap number), an addl to get rid of these, and pushing and - * popping the call-saved regs %esi, %edi and %ebp twice, The indirect - * costs are making the driver interface nonuniform so unpending of - * interrupts is more complicated and slower (call_driver(unit) would - * be easier than ensuring an interrupt frame for all handlers. Finally, - * there are some struct copies in the npx handler and maybe in the clock - * handler that could be avoided by working more with pointers to frames - * instead of frames. - * - * XXX - should we do a cld on every system entry to avoid the requirement - * for scattered cld's? - * - * Coding notes for *.s: - * - * If possible, avoid operations that involve an operand size override. - * Word-sized operations might be smaller, but the operand size override - * makes them slower on on 486's and no faster on 386's unless perhaps - * the instruction pipeline is depleted. E.g., - * - * Use movl to seg regs instead of the equivalent but more descriptive - * movw - gas generates an irelevant (slower) operand size override. - * - * Use movl to ordinary regs in preference to movw and especially - * in preference to movz[bw]l. Use unsigned (long) variables with the - * top bits clear instead of unsigned short variables to provide more - * opportunities for movl. - * - * If possible, use byte-sized operations. They are smaller and no slower. - * - * Use (%reg) instead of 0(%reg) - gas generates larger code for the latter. - * - * If the interrupt frame is made more flexible, INTR can push %eax first - * and decide the ipending case with less overhead, e.g., by avoiding - * loading segregs. - */ - -#ifdef APIC_IO -#include "i386/isa/apic_vector.s" -#else -#include "i386/isa/icu_vector.s" -#endif /* APIC_IO */ diff --git a/sys/amd64/isa/vector.s b/sys/amd64/isa/vector.s deleted file mode 100644 index 1fc56685f3eb..000000000000 --- a/sys/amd64/isa/vector.s +++ /dev/null @@ -1,95 +0,0 @@ -/* - * from: vector.s, 386BSD 0.1 unknown origin - * $Id: vector.s,v 1.2 1997/05/24 17:05:26 smp Exp smp $ - */ - -/* - * modified for PC98 by Kakefuda - */ - -#include "opt_auto_eoi.h" - -#include <i386/isa/icu.h> -#ifdef PC98 -#include <pc98/pc98/pc98.h> -#else -#include <i386/isa/isa.h> -#endif - -#ifdef FAST_INTR_HANDLER_USES_ES -#define ACTUALLY_PUSHED 1 -#define MAYBE_MOVW_AX_ES movl %ax,%es -#define MAYBE_POPL_ES popl %es -#define MAYBE_PUSHL_ES pushl %es -#else -/* - * We can usually skip loading %es for fastintr handlers. %es should - * only be used for string instructions, and fastintr handlers shouldn't - * do anything slow enough to justify using a string instruction. - */ -#define ACTUALLY_PUSHED 0 -#define MAYBE_MOVW_AX_ES -#define MAYBE_POPL_ES -#define MAYBE_PUSHL_ES -#endif - - .data - ALIGN_DATA - - .globl _intr_nesting_level -_intr_nesting_level: - .byte 0 - .space 3 - - .text - -/* - * Macros for interrupt interrupt entry, call to handler, and exit. - * - * XXX - the interrupt frame is set up to look like a trap frame. This is - * usually a waste of time. The only interrupt handlers that want a frame - * are the clock handler (it wants a clock frame), the npx handler (it's - * easier to do right all in assembler). The interrupt return routine - * needs a trap frame for rare AST's (it could easily convert the frame). - * The direct costs of setting up a trap frame are two pushl's (error - * code and trap number), an addl to get rid of these, and pushing and - * popping the call-saved regs %esi, %edi and %ebp twice, The indirect - * costs are making the driver interface nonuniform so unpending of - * interrupts is more complicated and slower (call_driver(unit) would - * be easier than ensuring an interrupt frame for all handlers. Finally, - * there are some struct copies in the npx handler and maybe in the clock - * handler that could be avoided by working more with pointers to frames - * instead of frames. - * - * XXX - should we do a cld on every system entry to avoid the requirement - * for scattered cld's? - * - * Coding notes for *.s: - * - * If possible, avoid operations that involve an operand size override. - * Word-sized operations might be smaller, but the operand size override - * makes them slower on on 486's and no faster on 386's unless perhaps - * the instruction pipeline is depleted. E.g., - * - * Use movl to seg regs instead of the equivalent but more descriptive - * movw - gas generates an irelevant (slower) operand size override. - * - * Use movl to ordinary regs in preference to movw and especially - * in preference to movz[bw]l. Use unsigned (long) variables with the - * top bits clear instead of unsigned short variables to provide more - * opportunities for movl. - * - * If possible, use byte-sized operations. They are smaller and no slower. - * - * Use (%reg) instead of 0(%reg) - gas generates larger code for the latter. - * - * If the interrupt frame is made more flexible, INTR can push %eax first - * and decide the ipending case with less overhead, e.g., by avoiding - * loading segregs. - */ - -#ifdef APIC_IO -#include "i386/isa/apic_vector.s" -#else -#include "i386/isa/icu_vector.s" -#endif /* APIC_IO */ |