* Copyright (c) 1991 The Regents of the University of California.
* This code is derived from software contributed to Berkeley by
* %sccs.include.redist.c%
* @(#)isa.c 7.5 (Berkeley) %G%
#include <machine/segments.h>
#include <i386/isa/isa_device.h>
#include <i386/isa/icu.h>
* Configure all ISA devices
for (dvp
= isa_devtab_bio
; config_isadev(dvp
,&biomask
); dvp
++);
for (dvp
= isa_devtab_tty
; config_isadev(dvp
,&ttymask
); dvp
++);
for (dvp
= isa_devtab_net
; config_isadev(dvp
,&netmask
); dvp
++);
for (dvp
= isa_devtab_null
; config_isadev(dvp
,0); dvp
++);
* The problem is... if netmask == 0, then the loopback
* code can do some really ugly things.
* workaround for this: if netmask == 0, set it to 0x8000, which
* is the value used by splsoftclock. this is nasty, but it
* should work until this interrupt system goes away. -- cgd
netmask
= 0x8000; /* same as for softclock. XXX */
/* biomask |= ttymask ; can some tty devices use buffers? */
printf("biomask %x ttymask %x netmask %x\n", biomask
, ttymask
, netmask
);
* Configure an ISA device.
if (dp
= isdp
->id_driver
) {
isdp
->id_maddr
-= 0xa0000;
isdp
->id_maddr
+= atdevbase
;
isdp
->id_alive
= (*dp
->probe
)(isdp
);
printf("%s%d", dp
->name
, isdp
->id_unit
);
printf(" at 0x%x ", isdp
->id_iobase
);
intrno
= ffs(isdp
->id_irq
)-1;
printf("irq %d ", intrno
);
if(mp
)INTRMASK(*mp
,isdp
->id_irq
);
setidt(ICU_OFFSET
+intrno
, isdp
->id_intr
,
if (isdp
->id_drq
!= -1) printf("drq %d ", isdp
->id_drq
);
#define IDTVEC(name) __CONCAT(X,name)
/* default interrupt vector table */
extern 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
);
* Fill in default interrupt table (in case of spuruious interrupt
* during configuration of kernel, setup interrupt control unit
setidt(32, &IDTVEC(intr0
), SDT_SYS386IGT
, SEL_KPL
);
setidt(33, &IDTVEC(intr1
), SDT_SYS386IGT
, SEL_KPL
);
setidt(34, &IDTVEC(intr2
), SDT_SYS386IGT
, SEL_KPL
);
setidt(35, &IDTVEC(intr3
), SDT_SYS386IGT
, SEL_KPL
);
setidt(36, &IDTVEC(intr4
), SDT_SYS386IGT
, SEL_KPL
);
setidt(37, &IDTVEC(intr5
), SDT_SYS386IGT
, SEL_KPL
);
setidt(38, &IDTVEC(intr6
), SDT_SYS386IGT
, SEL_KPL
);
setidt(39, &IDTVEC(intr7
), SDT_SYS386IGT
, SEL_KPL
);
setidt(40, &IDTVEC(intr8
), SDT_SYS386IGT
, SEL_KPL
);
setidt(41, &IDTVEC(intr9
), SDT_SYS386IGT
, SEL_KPL
);
setidt(42, &IDTVEC(intr10
), SDT_SYS386IGT
, SEL_KPL
);
setidt(43, &IDTVEC(intr11
), SDT_SYS386IGT
, SEL_KPL
);
setidt(44, &IDTVEC(intr12
), SDT_SYS386IGT
, SEL_KPL
);
setidt(45, &IDTVEC(intr13
), SDT_SYS386IGT
, SEL_KPL
);
setidt(46, &IDTVEC(intr14
), SDT_SYS386IGT
, SEL_KPL
);
setidt(47, &IDTVEC(intr15
), SDT_SYS386IGT
, SEL_KPL
);
/* stuff needed for virtual to physical calculations */
struct buf
*dma_bounce
[8];
if (x
>= KERNBASE
) return 1;
/****************************************************************************/
/* set up DMA read/write operation and virtual address addr for nbytes */
/****************************************************************************/
at_dma(read
,addr
,nbytes
, chan
)
if (kernel_space(addr
)) raw
= 0;
if (dma_bounce
[chan
] == 0)
dma_bounce
[chan
] = geteblk(MAXDMASZ
);
bounce
= dma_bounce
[chan
]->b_un
.b_addr
;
/* copy bounce buffer on write */
if (raw
&& !read
) bcopy(addr
,bounce
,nbytes
);
/* Set read/write bytes */
outb(0xC,0x46); outb(0xB,0x46);
outb(0xC,0x4A); outb(0xB,0x4A);
if (raw
) phys
= (unsigned long) bounce
;
/* translate to physical */
phys
= pmap_extract(kernel_pmap
, (vm_offset_t
)phys
);
outb(0x4,(phys
>>8) & 0xFF);
outb(0x81,(phys
>>16) & 0xFF);
outb(0x5,(nbytes
>>8) & 0xFF);
* Handle a NMI, possibly a machine check.
* return true to panic system, false to ignore.
log(LOG_CRIT
, "\nNMI port 61 %x, port 70 %x\n", inb(0x61), inb(0x70));
* Caught a stray interrupt, notify
/* for some reason, we get bursts of intr #7, even if not enabled! */
log(LOG_ERR
,"ISA strayintr %d", ffs(d
)-1);