1994-10-26 08:45:48 +00:00

367 lines
8.8 KiB
C

/* $NetBSD: via.c,v 1.10 1994/10/26 08:47:20 cgd Exp $ */
/*-
* Copyright (C) 1993 Allen K. Briggs, Chris P. Caputo,
* Michael L. Finch, Bradley A. Grantham, and
* Lawrence A. Kesteloot
* 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 Alice Group.
* 4. The names of the Alice Group or any of its members may not be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE ALICE GROUP ``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 ALICE GROUP 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.
*
*/
/*
* This code handles both the VIA and RBV functionality.
*/
#include <sys/param.h>
#include <machine/cpu.h>
#include <machine/frame.h>
#include "via.h"
#include <sys/kernel.h>
static int scsi_drq_intr(void), scsi_irq_intr(void);
long via1_noint(), via2_noint();
long adb_intr(), rtclock_intr(), profclock();
long nubus_intr();
int slot_noint();
int VIA2 = 1; /* default for II, IIx, IIcx, SE/30. */
long via1_spent[2][7]={
{0,0,0,0,0,0,0},
{0,0,0,0,0,0,0},
};
long (*via1itab[7])()={
via1_noint,
via1_noint,
adb_intr,
via1_noint,
via1_noint,
via1_noint,
rtclock_intr,
}; /* VIA1 interrupt handler table */
long (*via2itab[7])()={
(long (*)()) scsi_drq_intr,
nubus_intr,
via2_noint,
(long (*)()) scsi_irq_intr,
via2_noint, /* snd_intr */
via2_noint, /* via2t2_intr */
via2_noint,
}; /* VIA2 interrupt handler table */
static int via_inited=0;
int mac68k_trip_debugger=0;
/* nubus slot interrupt routines */
int (*slotitab[6])() = {
slot_noint,
slot_noint,
slot_noint,
slot_noint,
slot_noint,
slot_noint
};
int slotutab[6];
void VIA_initialize()
{
/* Sanity. */
if(via_inited){printf("WARNING: Initializing VIA's again.\n");return;}
/* Initialize VIA1 */
/* set all timers to 0 */
via_reg(VIA1, vT1L) = 0;
via_reg(VIA1, vT1LH) = 0;
via_reg(VIA1, vT1C) = 0;
via_reg(VIA1, vT1CH) = 0;
via_reg(VIA1, vT2C) = 0;
via_reg(VIA1, vT2CH) = 0;
#if not_on_all_machines_ugh
/* program direction and data for VIA #1 */
via_reg(VIA1, vBufA) = 0x01;
via_reg(VIA1, vDirA) = 0x3f;
via_reg(VIA1, vBufB) = 0x07;
via_reg(VIA1, vDirB) = 0x87;
#endif
/* disable all interrupts */
via_reg(VIA1, vIFR) = 0x7f;
via_reg(VIA1, vIER) = 0x7f;
/* enable specific interrupts */
/* via_reg(VIA1, vIER) = (VIA1_INTS & (~(V1IF_T1))) | 0x80; */
via_reg(VIA1, vIER) = V1IF_ADBRDY | 0x80;
/* turn off timer latch */
via_reg(VIA1, vACR) &= 0x3f;
if(VIA2 == VIA2OFF){
/* Initialize VIA2 */
via_reg(VIA2, vT1L) = 0;
via_reg(VIA2, vT1LH) = 0;
via_reg(VIA2, vT1C) = 0;
via_reg(VIA2, vT1CH) = 0;
via_reg(VIA2, vT2C) = 0;
via_reg(VIA2, vT2CH) = 0;
/* turn off timer latch */
via_reg(VIA2, vACR) &= 0x3f;
#if not_on_all_machines_ugh
/* program direction and data for VIA #2 */
via_reg(VIA2, vBufA) = via_reg(VIA2, vBufA);
via_reg(VIA2, vDirA) = 0xc0;
via_reg(VIA2, vBufB) = 0x05;
via_reg(VIA2, vDirB) = 0x80;
#endif
/* unlock nubus */
via_reg(VIA2, vPCR) = 0x06;
via_reg(VIA2, vBufB) |= 0x02;
via_reg(VIA2, vDirB) |= 0x02;
#ifdef never
/* disable all interrupts */
via_reg(VIA2, vIER) = 0x7f;
via_reg(VIA2, vIFR) = 0x7f;
/* enable specific interrupts */
switch(machineid){ /* Argh! setmachdep()! */
case MACH_MACPB140:
case MACH_MACPB170:
/* below, we will keep track of interrupts. */
via_reg(VIA2, vIER) = 0xff /*VIA2_INTS | 0x80 | V1IF_ADBRDY*/;
break;
default:
via_reg(VIA2, vIER) = VIA2_INTS | 0x80;
break;
}
#endif
}else{ /* RBV */
/* I'm sure that I'll find something to put in here
someday. -- BG */
/* enable specific interrupts */
/* via_reg(VIA2, rIER) = RBV_INTS | 0x80; */
}
via_inited=1;
}
void via1_intr(struct frame *fp)
{
static intpend = 0;
register unsigned char intbits, enbbits;
register unsigned char bitnum, bitmsk;
struct timeval before, after;
intbits = via_reg(VIA1, vIFR); /* get interrupts pending */
intbits &= via_reg(VIA1, vIER); /* only care about enabled ones */
intbits &= ~ intpend; /* to stop recursion */
bitmsk = 1;
bitnum = 0;
mac68k_trip_debugger = 0;
while(bitnum < 7){
if(intbits & bitmsk){
intpend |= bitmsk; /* don't process this twice */
before = time;
via1itab[bitnum](bitnum); /* run interrupt handler */
after = time;
via1_spent[0][bitnum] += (after.tv_sec - before.tv_sec) *
1000000;
if(after.tv_usec < before.tv_usec)
via1_spent[0][bitnum] -= before.tv_usec - after.tv_usec;
else
via1_spent[0][bitnum] += after.tv_usec - before.tv_usec;
via1_spent[1][bitnum]++;
intpend &= ~bitmsk; /* fix previous pending */
via_reg(VIA1, vIFR) = bitmsk;
/* turn off interrupt pending. */
}
bitnum++;
bitmsk <<= 1;
}
#ifdef DDB
if (mac68k_trip_debugger) Debugger();
#endif
}
void via2_intr(struct frame *fp)
{
static intpend = 0;
register unsigned char intbits, enbbits;
register char bitnum, bitmsk;
if(VIA2 == VIA2OFF){
intbits = via_reg(VIA2, vIFR); /* get interrupts pending */
/* if(via_inited)printf("via2 %02x\n", intbits); */
intbits &= via_reg(VIA2, vIER); /* only care about enabled ones */
}else{/* assume RBV */
intbits = via_reg(VIA2, rIFR); /* get interrupts pending */
/* if(via_inited)printf("rbv %02x\n", intbits); */
intbits &= via_reg(VIA2, rIER); /* only care about enabled ones */
}
intbits &= ~ intpend; /* to stop recursion */
bitmsk = 1;
bitnum = 0;
while(bitnum < 7){
if(intbits & bitmsk){
intpend |= bitmsk; /* don't process this twice */
via2itab[bitnum](bitnum); /* run interrupt handler */
intpend &= ~bitmsk; /* fix previous pending */
if(VIA2 == VIA2OFF)
via_reg(VIA2, vIFR) = bitmsk;
else /* Assume RBV */
via_reg(VIA2, rIFR) = bitmsk;
/* turn off interrupt pending. */
}
bitnum++;
bitmsk <<= 1;
}
if (intpend) printf("via2_intr(): intpend at end 0x%x.\n", intpend);
}
long via1_noint(int bitnum)
{
/* printf("via1_noint(%d)\n", bitnum); */
return 1;
}
long via2_noint(int bitnum)
{
/* printf("via2_noint(%d)\n", bitnum); */
return 1;
}
int add_nubus_intr(addr, func, unit)
int addr;
int (*func)();
int unit;
{
int s = splhigh();
int slot;
slot = nubus_addr_to_slot(addr);
if (slot < 0) return 0;
slotitab[slot-9] = func;
slotutab[slot-9] = unit;
via_reg(VIA2, vIER) = /*VIA2_INTS |*/ V2IF_SLOTINT | 0x80;
splx(s);
return 1;
}
long nubus_intr()
{
int i, mask;
if ((~(via_reg(VIA2, vBufA) & 0x3f)) == 0x02)
printf("slot a nu-bus intr\n");
do {
mask = 1;
for (i = 0; i < 6; i++) {
if ((via_reg(VIA2, vBufA) & mask) == 0)
(*slotitab[i])(slotutab[i], i+9);
mask <<= 1;
}
} while ((via_reg(VIA2, vBufA) & 0x3f) != 0x3f);
return 1;
}
static char zero = 0;
int slot_noint(int unit, int slot)
{
/*
printf("slot_noint() slot %x\n", slot);
*/
((char *)(0xf0000000 | ((long)slot << 24)))[0xa0000] = zero;
return 1;
}
void via_shutdown()
{
if(VIA2 == VIA2OFF){
via_reg(VIA2, vDirB) |= 0x04; /* Set write for bit 2/
via_reg(VIA2, vBufB) &= ~0x04; /* Shut down */
}else if(VIA2 == RBVOFF){
via_reg(VIA2, rBufB) &= ~0x04;
}
}
int rbv_vidstatus(void)
{
int montype;
montype = via_reg(VIA2, rMonitor) & RBVMonitorMask;
if(montype == RBVMonIDNone)
montype = RBVMonIDOff;
ddprintf("Monitor type: %d\n", montype);
return(0);
return(montype);
}
static int
scsi_irq_intr(void)
{
if (mac68k_machine.scsi96) {
if (ncr53c96_irq_intr()) return 1;
}
if (mac68k_machine.scsi80) {
if (ncr5380_irq_intr()) return 1;
}
return 0;
}
static int
scsi_drq_intr(void)
{
if (mac68k_machine.scsi96) {
if (ncr53c96_drq_intr()) return 1;
}
if (mac68k_machine.scsi80) {
if (ncr5380_drq_intr()) return 1;
}
return 0;
}