updates from Rick Macklem for maxine.
authorRalph Campbell <ralph@ucbvax.Berkeley.EDU>
Mon, 16 Nov 1992 08:30:35 +0000 (00:30 -0800)
committerRalph Campbell <ralph@ucbvax.Berkeley.EDU>
Mon, 16 Nov 1992 08:30:35 +0000 (00:30 -0800)
SCCS-vsn: sys/pmax/pmax/clock.c 7.6
SCCS-vsn: sys/pmax/pmax/autoconf.c 7.6
SCCS-vsn: sys/pmax/pmax/conf.c 7.5
SCCS-vsn: sys/pmax/pmax/cons.c 7.5
SCCS-vsn: sys/pmax/pmax/machdep.c 7.12
SCCS-vsn: sys/pmax/pmax/trap.c 7.11
SCCS-vsn: sys/pmax/pmax/locore.s 7.11
SCCS-vsn: sys/pmax/pmax/turbochannel.h 7.2

usr/src/sys/pmax/pmax/autoconf.c
usr/src/sys/pmax/pmax/clock.c
usr/src/sys/pmax/pmax/conf.c
usr/src/sys/pmax/pmax/cons.c
usr/src/sys/pmax/pmax/locore.s
usr/src/sys/pmax/pmax/machdep.c
usr/src/sys/pmax/pmax/trap.c
usr/src/sys/pmax/pmax/turbochannel.h

index 69a0d83..ab37c7d 100644 (file)
@@ -11,7 +11,7 @@
  *
  * from: Utah $Hdr: autoconf.c 1.31 91/01/21$
  *
  *
  * from: Utah $Hdr: autoconf.c 1.31 91/01/21$
  *
- *     @(#)autoconf.c  7.5 (Berkeley) %G%
+ *     @(#)autoconf.c  7.6 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -33,6 +33,8 @@
 
 #include <machine/cpu.h>
 #include <pmax/dev/device.h>
 
 #include <machine/cpu.h>
 #include <pmax/dev/device.h>
+#include <pmax/pmax/pmaxtype.h>
+#include <pmax/pmax/turbochannel.h>
 
 /*
  * The following several variables are related to
 
 /*
  * The following several variables are related to
@@ -42,6 +44,8 @@
 int    cold = 1;       /* if 1, still working on cold-start */
 int    dkn;            /* number of iostat dk numbers assigned so far */
 int    cpuspeed = 30;  /* approx # instr per usec. */
 int    cold = 1;       /* if 1, still working on cold-start */
 int    dkn;            /* number of iostat dk numbers assigned so far */
 int    cpuspeed = 30;  /* approx # instr per usec. */
+extern int pmax_boardtype;
+extern tc_option_t tc_slot_info[TC_MAX_LOGICAL_SLOTS];
 
 /*
  * Determine mass storage and memory configuration for a machine.
 
 /*
  * Determine mass storage and memory configuration for a machine.
@@ -53,11 +57,19 @@ configure()
        register struct pmax_ctlr *cp;
        register struct scsi_device *dp;
        register struct driver *drp;
        register struct pmax_ctlr *cp;
        register struct scsi_device *dp;
        register struct driver *drp;
-#ifdef DS5000
        register int i;
        register int i;
-#endif
 
        /* print what type of CPU and FPU we have */
 
        /* print what type of CPU and FPU we have */
+
+       /*
+        * for some reason the Pmax has an R2000 cpu with an implementation
+        * level of 2 and DEC's R3000s are level 2 as well?
+        */
+       if (pmax_boardtype == DS_PMAX) {
+               cpu.cpu.cp_imp = MIPS_R2000;
+               fpu.cpu.cp_imp = MIPS_R2010;
+       }
+
        switch (cpu.cpu.cp_imp) {
        case MIPS_R2000:
                printf("cpu0 (MIPS R2000 revision %d.%d)\n",
        switch (cpu.cpu.cp_imp) {
        case MIPS_R2000:
                printf("cpu0 (MIPS R2000 revision %d.%d)\n",
@@ -103,28 +115,35 @@ configure()
 
        /* probe and initialize controllers */
        for (cp = pmax_cinit; drp = cp->pmax_driver; cp++) {
 
        /* probe and initialize controllers */
        for (cp = pmax_cinit; drp = cp->pmax_driver; cp++) {
-#ifdef DS3100
-               if (!(*drp->d_init)(cp))
-                       continue;
-#endif
+               switch (pmax_boardtype) {
+               case DS_PMAX:
+                       if (cp->pmax_addr == (char *)QUES)
+                               continue;
+                       if (!(*drp->d_init)(cp))
+                               continue;
+                       break;
 #ifdef DS5000
 #ifdef DS5000
-               /*
-                * If the device is still in an unknown slot,
-                * then it was not found by tc_find_all_options().
-                */
-               if (cp->pmax_addr == (char *)QUES)
-                       continue;
-               if (!(*drp->d_init)(cp))
-                       continue;
-               if (drp->d_intr && (i = cp->pmax_pri) >= 0) {
-                       if (intr_tab[i].func)
-                               printf("%s: slot %d already in use\n",
-                                       drp->d_name, i);
-                       intr_tab[i].func = drp->d_intr;
-                       intr_tab[i].unit = cp->pmax_unit;
-                       tc_enable_interrupt(i, 1);
-               }
-#endif
+               case DS_3MAX:
+               case DS_3MIN:
+               case DS_MAXINE:
+                       /*
+                        * If the device is still in an unknown slot,
+                        * then it was not found by tc_find_all_options().
+                        */
+                       if (cp->pmax_addr == (char *)QUES)
+                               continue;
+                       if (!(*drp->d_init)(cp))
+                               continue;
+                       if (drp->d_intr && (i = cp->pmax_pri) >= 0) {
+                               if (tc_slot_info[i].intr)
+                                       printf("%s: slot %d already in use\n",
+                                               drp->d_name, i);
+                               tc_slot_info[i].intr = drp->d_intr;
+                               tc_slot_info[i].unit = cp->pmax_unit;
+                       }
+                       break;
+#endif /* DS5000 */
+               };
 
                cp->pmax_alive = 1;
 
 
                cp->pmax_alive = 1;
 
index a7b3ecc..7810123 100644 (file)
@@ -11,7 +11,7 @@
  *
  * from: Utah $Hdr: clock.c 1.18 91/01/21$
  *
  *
  * from: Utah $Hdr: clock.c 1.18 91/01/21$
  *
- *     @(#)clock.c     7.5 (Berkeley) %G%
+ *     @(#)clock.c     7.6 (Berkeley) %G%
  */
 
 #include <sys/param.h>
  */
 
 #include <sys/param.h>
@@ -33,6 +33,8 @@
  * Resettodr restores the time of day hardware after a time change.
  */
 
  * Resettodr restores the time of day hardware after a time change.
  */
 
+volatile struct chiptime *Mach_clock_addr;
+
 /*
  * Start the real-time and statistics clocks. Leave stathz 0 since there
  * are no other timers available.
 /*
  * Start the real-time and statistics clocks. Leave stathz 0 since there
  * are no other timers available.
@@ -45,7 +47,7 @@ cpu_initclocks()
        tick = 15625;           /* number of micro-seconds between interrupts */
        hz = 1000000 / 15625;   /* 64 Hz */
        tickadj = 240000 / (60000000 / 15625);
        tick = 15625;           /* number of micro-seconds between interrupts */
        hz = 1000000 / 15625;   /* 64 Hz */
        tickadj = 240000 / (60000000 / 15625);
-       c = (volatile struct chiptime *)MACH_CLOCK_ADDR;
+       c = Mach_clock_addr;
        c->rega = REGA_TIME_BASE | SELECTED_RATE;
        c->regb = REGB_PER_INT_ENA | REGB_DATA_MODE | REGB_HOURS_FORMAT;
 }
        c->rega = REGA_TIME_BASE | SELECTED_RATE;
        c->regb = REGB_PER_INT_ENA | REGB_DATA_MODE | REGB_HOURS_FORMAT;
 }
@@ -92,7 +94,7 @@ inittodr(base)
        } else
                badbase = 0;
 
        } else
                badbase = 0;
 
-       c = (volatile struct chiptime *)MACH_CLOCK_ADDR;
+       c = Mach_clock_addr;
        /* don't read clock registers while they are being updated */
        s = splclock();
        while ((c->rega & REGA_UIP) == 1)
        /* don't read clock registers while they are being updated */
        s = splclock();
        while ((c->rega & REGA_UIP) == 1)
@@ -185,7 +187,7 @@ resettodr()
        min = t / 60;
        sec = t % 60;
 
        min = t / 60;
        sec = t % 60;
 
-       c = (volatile struct chiptime *)MACH_CLOCK_ADDR;
+       c = Mach_clock_addr;
        s = splclock();
        t = c->regb;
        c->regb = t | REGB_SET_TIME;
        s = splclock();
        t = c->regb;
        c->regb = t | REGB_SET_TIME;
index 502eb77..fbe4217 100644 (file)
@@ -7,7 +7,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)conf.c      7.4 (Berkeley) %G%
+ *     @(#)conf.c      7.5 (Berkeley) %G%
  */
 
 #include <sys/param.h>
  */
 
 #include <sys/param.h>
@@ -113,6 +113,13 @@ int        nblkdev = sizeof (bdevsw) / sizeof (bdevsw[0]);
        (dev_type_reset((*))) nullop, dev_tty_init(c,n), ttselect, \
        (dev_type_map((*))) enodev, 0 }
 
        (dev_type_reset((*))) nullop, dev_tty_init(c,n), ttselect, \
        (dev_type_map((*))) enodev, 0 }
 
+/* open, close, read, write, ioctl, select -- XXX should be a tty */
+#define        cdev_cn_init(c,n) { \
+       dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
+       dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) nullop, \
+       (dev_type_reset((*))) nullop, 0, dev_init(c,n,select), \
+       (dev_type_map((*))) enodev, 0 }
+
 #define        cdev_notdef() { \
        (dev_type_open((*))) enodev, (dev_type_close((*))) enodev, \
        (dev_type_read((*))) enodev, (dev_type_write((*))) enodev, \
 #define        cdev_notdef() { \
        (dev_type_open((*))) enodev, (dev_type_close((*))) enodev, \
        (dev_type_read((*))) enodev, (dev_type_write((*))) enodev, \
@@ -122,13 +129,7 @@ int        nblkdev = sizeof (bdevsw) / sizeof (bdevsw[0]);
 
 cdev_decl(no);                 /* dummy declarations */
 
 
 cdev_decl(no);                 /* dummy declarations */
 
-cdev_decl(dc);
-/* open, close, read, write, ioctl, select -- XXX should be a tty */
-#define        cdev_dc_init(c,n) { \
-       dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
-       dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) nullop, \
-       (dev_type_reset((*))) nullop, 0, ttselect, \
-       (dev_type_map((*))) enodev, 0 }
+cdev_decl(cn);         /* console interface */
 
 cdev_decl(ctty);
 /* open, read, write, ioctl, select -- XXX should be a tty */
 
 cdev_decl(ctty);
 /* open, read, write, ioctl, select -- XXX should be a tty */
@@ -218,9 +219,21 @@ cdev_decl(bpf);
 #include "cfb.h"
 cdev_decl(cfb);
 
 #include "cfb.h"
 cdev_decl(cfb);
 
+#include "xcfb.h"
+cdev_decl(xcfb);
+
+#include "dtop.h"
+cdev_decl(dtop);
+
+#include "scc.h"
+cdev_decl(scc);
+
+#include "dc.h"
+cdev_decl(dc);
+
 struct cdevsw  cdevsw[] =
 {
 struct cdevsw  cdevsw[] =
 {
-       cdev_dc_init(1,dc),             /* 0: virtual console */
+       cdev_cn_init(1,cn),             /* 0: virtual console */
        cdev_ctty_init(1,ctty),         /* 1: controlling terminal */
        cdev_mm_init(1,mm),             /* 2: /dev/{null,mem,kmem,...} */
        cdev_swap_init(1,sw),           /* 3: /dev/drum (swap pseudo-device) */
        cdev_ctty_init(1,ctty),         /* 1: controlling terminal */
        cdev_mm_init(1,mm),             /* 2: /dev/{null,mem,kmem,...} */
        cdev_swap_init(1,sw),           /* 3: /dev/drum (swap pseudo-device) */
@@ -234,6 +247,10 @@ struct cdevsw      cdevsw[] =
        cdev_vn_init(NVN,vn),           /* 11: vnode disk */
        cdev_bpf_init(NBPFILTER,bpf),   /* 12: berkeley packet filter */
        cdev_pm_init(NCFB,cfb),         /* 13: color frame buffer */
        cdev_vn_init(NVN,vn),           /* 11: vnode disk */
        cdev_bpf_init(NBPFILTER,bpf),   /* 12: berkeley packet filter */
        cdev_pm_init(NCFB,cfb),         /* 13: color frame buffer */
+       cdev_pm_init(NXCFB,xcfb),       /* 14: maxine color frame buffer */
+       cdev_tty_init(NDTOP,dtop),      /* 15: desktop bus interface */
+       cdev_tty_init(NDC,dc),          /* 16: dc7085 serial interface */
+       cdev_tty_init(NSCC,scc),        /* 17: scc 82530 serial interface */
 };
 
 int    nchrdev = sizeof (cdevsw) / sizeof (cdevsw[0]);
 };
 
 int    nchrdev = sizeof (cdevsw) / sizeof (cdevsw[0]);
index b352f14..4a47223 100644 (file)
@@ -11,7 +11,7 @@
  *
  * from: Utah $Hdr: cons.c 1.1 90/07/09$
  *
  *
  * from: Utah $Hdr: cons.c 1.1 90/07/09$
  *
- *     @(#)cons.c      7.4 (Berkeley) %G%
+ *     @(#)cons.c      7.5 (Berkeley) %G%
  */
 
 #include <sys/param.h>
  */
 
 #include <sys/param.h>
 #include <sys/file.h>
 #include <sys/conf.h>
 
 #include <sys/file.h>
 #include <sys/conf.h>
 
-#include <machine/machMon.h>
+#include <pmax/stand/dec_prom.h>
 
 /*
 
 /*
- * Console output may be redirected to another tty
- * (e.g. a window); if so, constty will point to the current
- * virtual console.
+ * Console I/O is redirected to the appropriate device, either a screen and
+ * keyboard or a serial port.
  */
  */
-struct tty *constty;           /* virtual console output device */
+#include <pmax/pmax/cons.h>
+
+struct consdev cn_tab = {
+       1,
+       1,
+       NODEV,
+       (struct pmax_fb *)0,
+       (int (*)())0,
+       (int (*)())0,
+       (void (*)())0,
+       (struct tty *)0,
+};
+
+cnopen(dev, flag, mode, p)
+       dev_t dev;
+       int flag, mode;
+       struct proc *p;
+{
+       if (cn_tab.cn_dev == NODEV)
+               return (0);
+       dev = cn_tab.cn_dev;
+       return ((*cdevsw[major(dev)].d_open)(dev, flag, mode, p));
+}
+cnclose(dev, flag, mode, p)
+       dev_t dev;
+       int flag, mode;
+       struct proc *p;
+{
+       if (cn_tab.cn_dev == NODEV)
+               return (0);
+       dev = cn_tab.cn_dev;
+       return ((*cdevsw[major(dev)].d_close)(dev, flag, mode, p));
+}
+cnread(dev, uio, flag)
+       dev_t dev;
+       struct uio *uio;
+{
+       if (cn_tab.cn_dev == NODEV)
+               return (0);
+       dev = cn_tab.cn_dev;
+       return ((*cdevsw[major(dev)].d_read)(dev, uio, flag));
+}
+cnwrite(dev, uio, flag)
+       dev_t dev;
+       struct uio *uio;
+{
+       if (cn_tab.cn_dev == NODEV)
+               return (0);
+       dev = cn_tab.cn_dev;
+       return ((*cdevsw[major(dev)].d_write)(dev, uio, flag));
+}
+cnioctl(dev, cmd, data, flag, p)
+       dev_t dev;
+       caddr_t data;
+       struct proc *p;
+{
+       int error;
+
+       if (cn_tab.cn_dev == NODEV)
+               return (0);
+       dev = cn_tab.cn_dev;
+       return ((*cdevsw[major(dev)].d_ioctl)(dev, cmd, data, flag, p));
+}
+
+/*ARGSUSED*/
+cnselect(dev, rw, p)
+       dev_t dev;
+       int rw;
+       struct proc *p;
+{
+       if (cn_tab.cn_dev == NODEV)
+               return (1);
+       return (ttselect(cn_tab.cn_dev, rw, p));
+}
 
 /*
  * Get character from console.
  */
 cngetc()
 {
 
 /*
  * Get character from console.
  */
 cngetc()
 {
-       int (*f)();
-#include "dc.h"
-#if NDC > 0
-#include <machine/dc7085cons.h>
-#include <pmax/dev/pdma.h>
-       extern struct pdma dcpdma[];
 
        /* check to be sure device has been initialized */
 
        /* check to be sure device has been initialized */
-       if (dcpdma[0].p_addr)
-               return (dcKBDGetc());
-       f = (int (*)())MACH_MON_GETCHAR;
-       return (*f)();
-#else
-       f = (int (*)())MACH_MON_GETCHAR;
-       return (*f)();
-#endif
+       if (cn_tab.cn_dev == NODEV || cn_tab.cn_disabled)
+               return ((*callv->getchar)());
+       return ((*cn_tab.cn_getc)(cn_tab.cn_dev));
 }
 
 /*
 }
 
 /*
@@ -61,20 +126,15 @@ cngetc()
 cnputc(c)
        register int c;
 {
 cnputc(c)
        register int c;
 {
-#include "pm.h"
-#if NPM > 0
-       pmPutc(c);
-#else
-#include "cfb.h"
-#if NCFB > 0
-       cfbPutc(c);
-#else
        int s;
        int s;
-       void (*f)() = (void (*)())MACH_MON_PUTCHAR;
 
 
-       s = splhigh();
-       (*f)(c);
-       splx(s);
-#endif
-#endif
+       if (cn_tab.cn_dev == NODEV || cn_tab.cn_disabled) {
+               s = splhigh();
+               (*callv->printf)("%c", c);
+               splx(s);
+       } else if (c) {
+               if (c == '\n')
+                       (*cn_tab.cn_putc)(cn_tab.cn_dev, '\r');
+               (*cn_tab.cn_putc)(cn_tab.cn_dev, c);
+       }
 }
 }
index 0243cfc..6c16042 100644 (file)
@@ -22,7 +22,7 @@
  * from: $Header: /sprite/src/kernel/vm/ds3100.md/vmPmaxAsm.s,
  *     v 1.1 89/07/10 14:27:41 nelson Exp $ SPRITE (DECWRL)
  *
  * from: $Header: /sprite/src/kernel/vm/ds3100.md/vmPmaxAsm.s,
  *     v 1.1 89/07/10 14:27:41 nelson Exp $ SPRITE (DECWRL)
  *
- *     @(#)locore.s    7.10 (Berkeley) %G%
+ *     @(#)locore.s    7.11 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -2902,6 +2902,50 @@ LEAF(MachFlushICache)
        .set    reorder
 END(MachFlushICache)
 
        .set    reorder
 END(MachFlushICache)
 
+/*----------------------------------------------------------------------------
+ *
+ * MachFlushDCache --
+ *
+ *     void MachFlushDCache(addr, len)
+ *             vm_offset_t addr, len;
+ *
+ *     Flush data cache for range of addr to addr + len - 1.
+ *     The address can be any valid address so long as no TLB misses occur.
+ *     (Be sure to use cached K0SEG kernel addresses)
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     The contents of the cache is flushed.
+ *
+ *----------------------------------------------------------------------------
+ */
+LEAF(MachFlushDCache)
+       .set    noreorder
+       mfc0    t0, MACH_COP_0_STATUS_REG       # Save SR
+       mtc0    zero, MACH_COP_0_STATUS_REG     # Disable interrupts.
+
+       la      v1, 1f
+       or      v1, MACH_UNCACHED_MEMORY_ADDR   # Run uncached.
+       j       v1
+       nop
+1:
+       bc0f    1b                              # make sure stores are complete
+       li      v1, MACH_SR_ISOL_CACHES
+       mtc0    v1, MACH_COP_0_STATUS_REG
+       nop
+       addu    a1, a1, a0                      # compute ending address
+1:
+       addu    a0, a0, 4
+       bne     a0, a1, 1b
+       sb      zero, -4(a0)
+
+       mtc0    t0, MACH_COP_0_STATUS_REG       # enable interrupts
+       j       ra                              # return and run cached
+       nop
+       .set    reorder
+END(MachFlushDCache)
+
 #ifdef KADB
 /*
  * Read a long and return it.
 #ifdef KADB
 /*
  * Read a long and return it.
index 24f130b..d5bc25e 100644 (file)
@@ -10,7 +10,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)machdep.c   7.11 (Berkeley) %G%
+ *     @(#)machdep.c   7.12 (Berkeley) %G%
  */
 
 /* from: Utah $Hdr: machdep.c 1.63 91/04/24$ */
  */
 
 /* from: Utah $Hdr: machdep.c 1.63 91/04/24$ */
 #include <machine/cpu.h>
 #include <machine/reg.h>
 #include <machine/psl.h>
 #include <machine/cpu.h>
 #include <machine/reg.h>
 #include <machine/psl.h>
-#include <machine/machMon.h>
 #include <machine/pte.h>
 #include <machine/pte.h>
+#include <machine/dc7085cons.h>
+
+#include <pmax/stand/dec_prom.h>
 
 #include <pmax/dev/device.h>
 
 #include <pmax/dev/device.h>
+#include <pmax/dev/sccreg.h>
 
 #include <pmax/pmax/clockreg.h>
 
 #include <pmax/pmax/clockreg.h>
+#include <pmax/pmax/kn01.h>
+#include <pmax/pmax/kn02.h>
+#include <pmax/pmax/kmin.h>
+#include <pmax/pmax/maxine.h>
+#include <pmax/pmax/asic.h>
+#include <pmax/pmax/turbochannel.h>
+#include <pmax/pmax/pmaxtype.h>
+#include <pmax/pmax/cons.h>
+
+#include <pm.h>
+#include <cfb.h>
+#include <mfb.h>
+#include <xcfb.h>
+#include <dc.h>
+#include <dtop.h>
+#include <scc.h>
+#include <le.h>
+
+#if NDC > 0
+extern int dcGetc(), dcparam();
+extern void dcPutc();
+#endif
+#if NDTOP > 0
+extern int dtopKBDGetc();
+#endif
+#if NSCC > 0
+extern int sccGetc(), sccparam();
+extern void sccPutc();
+#endif
+extern int KBDGetc();
+extern void fbPutc();
+extern struct consdev cn_tab;
+
+/* Will scan from max to min, inclusive */
+static int tc_max_slot = KN02_TC_MAX;
+static int tc_min_slot = KN02_TC_MIN;
+
 
 vm_map_t buffer_map;
 
 
 vm_map_t buffer_map;
 
@@ -59,16 +99,44 @@ int nswbuf = 0;
 #ifdef NBUF
 int    nbuf = NBUF;
 #else
 #ifdef NBUF
 int    nbuf = NBUF;
 #else
-int    nbuf = 0;
+int    nbuf = 1024;
 #endif
 #ifdef BUFPAGES
 int    bufpages = BUFPAGES;
 #else
 #endif
 #ifdef BUFPAGES
 int    bufpages = BUFPAGES;
 #else
-int    bufpages = 0;
+int    bufpages = 1024;
 #endif
 #endif
-int    msgbufmapped;           /* set when safe to use msgbuf */
+int    msgbufmapped = 0;       /* set when safe to use msgbuf */
 int    maxmem;                 /* max memory per process */
 int    physmem;                /* max supported memory, changes to actual */
 int    maxmem;                 /* max memory per process */
 int    physmem;                /* max supported memory, changes to actual */
+int    pmax_boardtype;         /* Mother board type */
+u_long le_iomem;               /* 128K for lance chip via. ASIC */
+const  struct callback *callv; /* pointer to PROM entry points */
+
+void   (*tc_enable_interrupt)();
+extern int (*pmax_hardware_intr)();
+void   pmax_slot_hand_fill();
+int    kn02_intr(), kmin_intr(), xine_intr(), pmax_intr();
+extern int Mach_spl0(), Mach_spl1(), Mach_spl2(), Mach_spl3(), splhigh();
+int    (*Mach_splnet)() = splhigh;
+int    (*Mach_splbio)() = splhigh;
+int    (*Mach_splimp)() = splhigh;
+int    (*Mach_spltty)() = splhigh;
+int    (*Mach_splclock)() = splhigh;
+int    (*Mach_splstatclock)() = splhigh;
+void   (*tc_slot_hand_fill)();
+extern volatile struct chiptime *Mach_clock_addr;
+u_long kmin_tc3_imask, xine_tc3_imask;
+tc_option_t tc_slot_info[TC_MAX_LOGICAL_SLOTS];
+static void asic_init();
+extern void RemconsInit();
+#ifdef DS5000
+void   kn02_enable_intr(), kn02_slot_hand_fill(),
+       kmin_enable_intr(), kmin_slot_hand_fill(),
+       xine_enable_intr(), xine_slot_hand_fill(),
+       tc_find_all_options();
+#endif /* DS5000 */
+
 /*
  * safepri is a safe priority for sleep to set for a spin-wait
  * during autoconfiguration or after a panic.
 /*
  * safepri is a safe priority for sleep to set for a spin-wait
  * during autoconfiguration or after a panic.
@@ -83,9 +151,11 @@ struct      proc nullproc;          /* for use by swtch_exit() */
  * Process arguments passed to us by the prom monitor.
  * Return the first page address following the system.
  */
  * Process arguments passed to us by the prom monitor.
  * Return the first page address following the system.
  */
-mach_init(argc, argv)
+mach_init(argc, argv, code, cv)
        int argc;
        char *argv[];
        int argc;
        char *argv[];
+       u_int code;
+       const struct callback *cv;
 {
        register char *cp;
        register int i;
 {
        register char *cp;
        register int i;
@@ -103,13 +173,11 @@ mach_init(argc, argv)
        v = (caddr_t)pmax_round_page(end);
        bzero(edata, v - edata);
 
        v = (caddr_t)pmax_round_page(end);
        bzero(edata, v - edata);
 
-#ifdef DS5000
        /* check for direct boot from DS5000 PROM */
        if (argc > 0 && strcmp(argv[0], "boot") == 0) {
                argc--;
                argv++;
        }
        /* check for direct boot from DS5000 PROM */
        if (argc > 0 && strcmp(argv[0], "boot") == 0) {
                argc--;
                argv++;
        }
-#endif
 
        /* look at argv[0] and compute bootdev */
        makebootdev(argv[0]);
 
        /* look at argv[0] and compute bootdev */
        makebootdev(argv[0]);
@@ -212,47 +280,65 @@ mach_init(argc, argv)
        /*
         * Determine what model of computer we are running on.
         */
        /*
         * Determine what model of computer we are running on.
         */
-       {
-               char *(*f)() = (char *(*)())MACH_MON_GETENV2;
-
-               if (cp = (*f)("systype"))
+       if (code == DEC_PROM_MAGIC) {
+               callv = cv;
+               i = (*cv->getsysid)();
+               cp = "";
+       } else {
+               callv = &callvec;
+               if (cp = (*callv->getenv)("systype"))
                        i = atoi(cp);
                        i = atoi(cp);
-               else
+               else {
                        cp = "";
                        cp = "";
-
-               /* check for MIPS based platform */
-               if (((i >> 24) & 0xFF) != 0x82) {
-                       printf("Unknown System type '%s'\n", cp);
-                       boot(RB_HALT | RB_NOSYNC);
+                       i = 0;
                }
        }
                }
        }
+       /* check for MIPS based platform */
+       if (((i >> 24) & 0xFF) != 0x82) {
+               printf("Unknown System type '%s'\n", cp);
+               boot(RB_HALT | RB_NOSYNC);
+       }
 
        /* check what model platform we are running on */
 
        /* check what model platform we are running on */
-       switch ((i >> 16) & 0xFF) {
-#ifdef DS3100
-       case 1: /* DS3100 Pmax */
+       pmax_boardtype = ((i >> 16) & 0xff);
+       switch (pmax_boardtype) {
+       case DS_PMAX:   /* DS3100 Pmax */
                /*
                /*
-                * Find out how much memory is available.
+                * Set up interrupt handling and I/O addresses.
                 */
                 */
-               physmem = btoc(v - KERNBASE);
-               cp = (char *)MACH_PHYS_TO_UNCACHED(physmem << PGSHIFT);
-               while (cp < (char *)MACH_MAX_MEM_ADDR) {
-                       if (badaddr(cp, 4))
-                               break;
-                       cp += NBPG;
-                       physmem++;
-               }
+               pmax_hardware_intr = pmax_intr;
+               Mach_splnet = Mach_spl1;
+               Mach_splbio = Mach_spl0;
+               Mach_splimp = Mach_spl1;
+               Mach_spltty = Mach_spl2;
+               Mach_splclock = Mach_spl3;
+               Mach_splstatclock = Mach_spl3;
+               Mach_clock_addr = (volatile struct chiptime *)
+                       MACH_PHYS_TO_UNCACHED(KN01_SYS_CLOCK);
+               pmax_slot_hand_fill();
                break;
                break;
-#endif
 
 #ifdef DS5000
 
 #ifdef DS5000
-       case 2: /* DS5000 3max */
-           {
-               extern void tc_find_all_options();
+       case DS_3MAX:   /* DS5000/200 3max */
+               {
+               volatile int *csr_addr =
+                       (volatile int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CSR);
 
                /* disable all TURBOchannel interrupts */
 
                /* disable all TURBOchannel interrupts */
-               i = *(volatile int *)MACH_SYS_CSR_ADDR;
-               *(volatile int *)MACH_SYS_CSR_ADDR = i & ~(MACH_CSR_MBZ | 0xFF);
+               i = *csr_addr;
+               *csr_addr = i & ~(KN02_CSR_WRESERVED | 0xFF);
+
+               tc_slot_hand_fill = kn02_slot_hand_fill;
+               pmax_hardware_intr = kn02_intr;
+               tc_enable_interrupt = kn02_enable_intr;
+               Mach_splnet = Mach_spl0;
+               Mach_splbio = Mach_spl0;
+               Mach_splimp = Mach_spl0;
+               Mach_spltty = Mach_spl0;
+               Mach_splclock = Mach_spl1;
+               Mach_splstatclock = Mach_spl1;
+               Mach_clock_addr = (volatile struct chiptime *)
+                       MACH_PHYS_TO_UNCACHED(KN02_SYS_CLOCK);
 
                /*
                 * Probe the TURBOchannel to see what controllers are present.
 
                /*
                 * Probe the TURBOchannel to see what controllers are present.
@@ -260,41 +346,115 @@ mach_init(argc, argv)
                tc_find_all_options();
 
                /* clear any memory errors from probes */
                tc_find_all_options();
 
                /* clear any memory errors from probes */
-               *(unsigned *)MACH_ERROR_ADDR = 0;
+               *(unsigned *)MACH_PHYS_TO_UNCACHED(KN02_SYS_ERRADR) = 0;
+               }
+               break;
+
+       case DS_3MIN:   /* DS5000/1xx 3min */
+               tc_max_slot = KMIN_TC_MAX;
+               tc_min_slot = KMIN_TC_MIN;
+               tc_slot_hand_fill = kmin_slot_hand_fill;
+               pmax_hardware_intr = kmin_intr;
+               tc_enable_interrupt = kmin_enable_intr;
 
                /*
 
                /*
-                * Find out how much memory is available.
+                * Since all the motherboard interrupts come through the
+                * I/O ASIC, it has to be turned off for all the spls and
+                * since we don't know what kinds of devices are in the
+                * turbochannel option slots, just splhigh().
                 */
                 */
-               physmem = btoc(v - KERNBASE);
-               cp = (char *)MACH_PHYS_TO_UNCACHED(physmem << PGSHIFT);
-               while (cp < (char *)MACH_MAX_MEM_ADDR) {
-                       if (badaddr(cp, 4))
-                               break;
-                       *(int *)cp = 0xa5a5a5a5;
-                       /*
-                        * Data will persist on the bus if we read it right
-                        * away. Have to be tricky here.
-                        */
-                       ((int *)cp)[4] = 0x5a5a5a5a;
-                       MachEmptyWriteBuffer();
-                       if (*(int *)cp != 0xa5a5a5a5)
-                               break;
-                       cp += NBPG;
-                       physmem++;
-               }
+               Mach_splnet = splhigh;
+               Mach_splbio = splhigh;
+               Mach_splimp = splhigh;
+               Mach_spltty = splhigh;
+               Mach_splclock = splhigh;
+               Mach_splstatclock = splhigh;
+               Mach_clock_addr = (volatile struct chiptime *)
+                       MACH_PHYS_TO_UNCACHED(KMIN_SYS_CLOCK);
+
+               /*
+                * Probe the TURBOchannel to see what controllers are present.
+                */
+               tc_find_all_options();
+
+               /*
+                * Initialize interrupts.
+                */
+               *(u_int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_IMSK) = KMIN_IM0;
+               *(u_int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_INTR) = 0;
+               /* clear any memory errors from probes */
+               *(unsigned *)MACH_PHYS_TO_UNCACHED(KMIN_REG_TIMEOUT) = 0;
+               break;
+
+       case DS_MAXINE: /* DS5000/xx maxine */
+               tc_max_slot = XINE_TC_MAX;
+               tc_min_slot = XINE_TC_MIN;
+               tc_slot_hand_fill = xine_slot_hand_fill;
+               pmax_hardware_intr = xine_intr;
+               tc_enable_interrupt = xine_enable_intr;
+               Mach_splnet = Mach_spl3;
+               Mach_splbio = Mach_spl3;
+               Mach_splimp = Mach_spl3;
+               Mach_spltty = Mach_spl3;
+               Mach_splclock = Mach_spl1;
+               Mach_splstatclock = Mach_spl1;
+               Mach_clock_addr = (volatile struct chiptime *)
+                       MACH_PHYS_TO_UNCACHED(XINE_SYS_CLOCK);
+
+               /*
+                * Probe the TURBOchannel to see what controllers are present.
+                */
+               tc_find_all_options();
+
+               /*
+                * Initialize interrupts.
+                */
+               *(u_int *)MACH_PHYS_TO_UNCACHED(XINE_REG_IMSK) = XINE_IM0;
+               *(u_int *)MACH_PHYS_TO_UNCACHED(XINE_REG_INTR) = 0;
+               /* clear any memory errors from probes */
+               *(unsigned *)MACH_PHYS_TO_UNCACHED(XINE_REG_TIMEOUT) = 0;
                break;
                break;
-           }
-#endif DS5000
+#endif /* DS5000 */
 
 
-       case 5: /* DS5800 Isis */
-       case 6: /* DS5400 MIPSfair */
        default:
                printf("kernel not configured for systype 0x%x\n", i);
                boot(RB_HALT | RB_NOSYNC);
        }
 
        default:
                printf("kernel not configured for systype 0x%x\n", i);
                boot(RB_HALT | RB_NOSYNC);
        }
 
+       /*
+        * Find out how much memory is available.
+        */
+       physmem = btoc(v - KERNBASE);
+       cp = (char *)MACH_PHYS_TO_UNCACHED(physmem << PGSHIFT);
+       while (cp < (char *)MACH_MAX_MEM_ADDR) {
+               if (badaddr(cp, 4))
+                       break;
+               *(int *)cp = 0xa5a5a5a5;
+               /*
+                * Data will persist on the bus if we read it right
+                * away. Have to be tricky here.
+                */
+               ((int *)cp)[4] = 0x5a5a5a5a;
+               MachEmptyWriteBuffer();
+               if (*(int *)cp != 0xa5a5a5a5)
+                       break;
+               cp += NBPG;
+               physmem++;
+       }
+
        maxmem = physmem;
 
        maxmem = physmem;
 
+#if NLE > 0
+       /*
+        * Grab 128K at the top of physical memory for the lance chip
+        * on machines where it does dma through the I/O ASIC.
+        */
+       if (pmax_boardtype == DS_3MIN || pmax_boardtype == DS_MAXINE) {
+               maxmem -= btoc(128 * 1024);
+               le_iomem = (maxmem << PGSHIFT);
+       }
+#endif /* NLE */
+
        /*
         * Initialize error message buffer (at end of core).
         */
        /*
         * Initialize error message buffer (at end of core).
         */
@@ -366,31 +526,164 @@ mach_init(argc, argv)
  * Console initialization: called early on from main,
  * before vm init or startup.  Do enough configuration
  * to choose and initialize a console.
  * Console initialization: called early on from main,
  * before vm init or startup.  Do enough configuration
  * to choose and initialize a console.
- * XXX need something better here.
  */
 consinit()
 {
  */
 consinit()
 {
+       register int kbd, crt;
+       register char *oscon;
 
 
-#include "pm.h"
-#if NPM > 0
-       if (pminit())
-               return;
-#endif
+       /*
+        * First get the "osconsole" environment variable.
+        */
+       oscon = (*callv->getenv)("osconsole");
+       crt = kbd = -1;
+       if (oscon && *oscon >= '0' && *oscon <= '9') {
+               kbd = *oscon - '0';
+               cn_tab.cn_screen = 0;
+               while (*++oscon) {
+                       if (*oscon == ',')
+                               cn_tab.cn_screen = 1;
+                       else if (cn_tab.cn_screen &&
+                           *oscon >= '0' && *oscon <= '9') {
+                               crt = kbd;
+                               kbd = *oscon - '0';
+                               break;
+                       }
+               }
+       }
+       if (pmax_boardtype == DS_PMAX && kbd == 1)
+               cn_tab.cn_screen = 1;
 
 
-#include "cfb.h"
-#if NCFB > 0
-       {
-               register struct pmax_ctlr *cp;
-               register struct driver *drp;
+       /*
+        * First try the keyboard/crt cases then fall through to the
+        * remote serial lines.
+        */
+       if (cn_tab.cn_screen) {
+           switch (pmax_boardtype) {
+           case DS_PMAX:
+#if NDC > 0 && NPM > 0
+               if (pminit()) {
+                       cn_tab.cn_dev = makedev(DCDEV, DCKBD_PORT);
+                       cn_tab.cn_getc = KBDGetc;
+                       cn_tab.cn_kbdgetc = dcGetc;
+                       cn_tab.cn_putc = fbPutc;
+                       cn_tab.cn_disabled = 0;
+                       return;
+               }
+#endif /* NDC and NPM */
+               goto remcons;
+
+           case DS_MAXINE:
+#if NDTOP > 0
+               if (kbd == 3) {
+                       cn_tab.cn_dev = makedev(DTOPDEV, 0);
+                       cn_tab.cn_getc = dtopKBDGetc;
+                       cn_tab.cn_putc = fbPutc;
+               } else
+#endif /* NDTOP */
+                       goto remcons;
+#if NXCFB > 0
+               if (crt == 3 && xcfbinit()) {
+                       cn_tab.cn_disabled = 0;
+                       return;
+               }
+#endif /* XCFB */
+               break;
 
 
-               for (cp = pmax_cinit; drp = cp->pmax_driver; cp++) {
-                       if (strcmp(drp->d_name, "cfb"))
-                               continue;
-                       if (cfb_init(cp))
-                               return;
+           case DS_3MAX:
+#if NDC > 0
+               if (kbd == 7) {
+                       cn_tab.cn_dev = makedev(DCDEV, DCKBD_PORT);
+                       cn_tab.cn_getc = KBDGetc;
+                       cn_tab.cn_kbdgetc = dcGetc;
+                       cn_tab.cn_putc = fbPutc;
+               } else
+#endif /* NDC */
+                       goto remcons;
+               break;
+
+           case DS_3MIN:
+#if NSCC > 0
+               if (kbd == 3) {
+                       cn_tab.cn_dev = makedev(SCCDEV, SCCKBD_PORT);
+                       cn_tab.cn_getc = KBDGetc;
+                       cn_tab.cn_kbdgetc = sccGetc;
+                       cn_tab.cn_putc = fbPutc;
+               } else
+#endif /* NSCC */
+                       goto remcons;
+               break;
+
+           default:
+               goto remcons;
+           };
+
+           /*
+            * Check for a suitable turbochannel frame buffer.
+            */
+           if (tc_slot_info[crt].driver_name) {
+#if NMFB > 0
+               if (strcmp(tc_slot_info[crt].driver_name, "mfb") == 0 &&
+                   mfbinit(tc_slot_info[crt].k1seg_address)) {
+                       cn_tab.cn_disabled = 0;
+                       return;
+               }
+#endif /* NMFB */
+#if NCFB > 0
+               if (strcmp(tc_slot_info[crt].driver_name, "cfb") == 0 &&
+                   cfbinit(tc_slot_info[crt].k1seg_address)) {
+                       cn_tab.cn_disabled = 0;
+                       return;
                }
                }
+#endif /* NCFB */
+               printf("crt: %s not supported as console device\n",
+                       tc_slot_info[crt].driver_name);
+           } else
+               printf("No crt console device in slot %d\n", crt);
        }
        }
-#endif
+remcons:
+       /*
+        * Configure a serial port as a remote console.
+        */
+       cn_tab.cn_screen = 0;
+       switch (pmax_boardtype) {
+       case DS_PMAX:
+#if NDC > 0
+               if (kbd == 4)
+                       cn_tab.cn_dev = makedev(DCDEV, DCCOMM_PORT);
+               else
+                       cn_tab.cn_dev = makedev(DCDEV, DCPRINTER_PORT);
+               cn_tab.cn_getc = dcGetc;
+               cn_tab.cn_putc = dcPutc;
+#endif /* NDC */
+               break;
+
+       case DS_3MAX:
+#if NDC > 0
+               cn_tab.cn_dev = makedev(DCDEV, DCPRINTER_PORT);
+               cn_tab.cn_getc = dcGetc;
+               cn_tab.cn_putc = dcPutc;
+#endif /* NDC */
+               break;
+
+       case DS_3MIN:
+#if NSCC > 0
+               cn_tab.cn_dev = makedev(SCCDEV, SCCCOMM3_PORT);
+               cn_tab.cn_getc = sccGetc;
+               cn_tab.cn_putc = sccPutc;
+#endif /* NSCC */
+               break;
+
+       case DS_MAXINE:
+#if NSCC > 0
+               cn_tab.cn_dev = makedev(SCCDEV, SCCCOMM2_PORT);
+               cn_tab.cn_getc = sccGetc;
+               cn_tab.cn_putc = sccPutc;
+#endif /* NSCC */
+               break;
+       };
+       if (cn_tab.cn_dev == NODEV)
+               printf("Can't configure console!\n");
 }
 
 /*
 }
 
 /*
@@ -758,17 +1051,24 @@ boot(howto)
                resettodr();
        }
        (void) splhigh();               /* extreme priority */
                resettodr();
        }
        (void) splhigh();               /* extreme priority */
-       if (howto & RB_HALT) {
-               void (*f)() = (void (*)())MACH_MON_REINIT;
+       if (callv != &callvec) {
+               if (howto & RB_HALT)
+                       (*callv->rex)('h');
+               else {
+                       if (howto & RB_DUMP)
+                               dumpsys();
+                       (*callv->rex)('b');
+               }
+       } else if (howto & RB_HALT) {
+               volatile void (*f)() = (volatile void (*)())DEC_PROM_REINIT;
 
                (*f)(); /* jump back to prom monitor */
        } else {
 
                (*f)(); /* jump back to prom monitor */
        } else {
-               void (*f)() = (void (*)())MACH_MON_AUTOBOOT;
+               volatile void (*f)() = (volatile void (*)())DEC_PROM_AUTOBOOT;
 
                if (howto & RB_DUMP)
                        dumpsys();
                (*f)(); /* jump back to prom monitor and do 'auto' cmd */
 
                if (howto & RB_DUMP)
                        dumpsys();
                (*f)(); /* jump back to prom monitor and do 'auto' cmd */
-               /*NOTREACHED*/
        }
        /*NOTREACHED*/
 }
        }
        /*NOTREACHED*/
 }
@@ -882,7 +1182,7 @@ initcpu()
        int i;
 
        /* disable clock interrupts (until startrtclock()) */
        int i;
 
        /* disable clock interrupts (until startrtclock()) */
-       c = (volatile struct chiptime *)MACH_CLOCK_ADDR;
+       c = Mach_clock_addr;
        c->regb = REGB_DATA_MODE | REGB_HOURS_FORMAT;
        i = c->regc;
        spl0();         /* safe to turn interrupts on now */
        c->regb = REGB_DATA_MODE | REGB_HOURS_FORMAT;
        i = c->regc;
        spl0();         /* safe to turn interrupts on now */
@@ -927,7 +1227,6 @@ atoi(s)
                        break;
                default:
                        base = 8;
                        break;
                default:
                        base = 8;
-                       break;
                }
        }
 
                }
        }
 
@@ -951,6 +1250,44 @@ out:
        return val;     
 }
 
        return val;     
 }
 
+/*
+ * Fill in the pmax addresses by hand.
+ */
+static struct pmax_address {
+       char    *pmax_name;
+       char    *pmax_addr;
+       int     pmax_pri;
+} pmax_addresses[] = {
+       { "pm", (char *)MACH_PHYS_TO_CACHED(KN01_PHYS_FBUF_START),      3 },
+       { "dc", (char *)MACH_PHYS_TO_UNCACHED(KN01_SYS_DZ),             2 },
+       { "le", (char *)MACH_PHYS_TO_UNCACHED(KN01_SYS_LANCE),          1 },
+       { "sii",(char *)MACH_PHYS_TO_UNCACHED(KN01_SYS_SII),            0 },
+       { (char *)0, },
+};
+
+void
+pmax_slot_hand_fill()
+{
+       register struct pmax_ctlr *cp;
+       register struct driver *drp;
+       register struct pmax_address *pmap;
+
+       /*
+        * Find the device driver entry and fill in the address.
+        */
+       for (cp = pmax_cinit; drp = cp->pmax_driver; cp++) {
+               for (pmap = pmax_addresses; pmap->pmax_name; pmap++) {
+                       if (strcmp(drp->d_name, pmap->pmax_name))
+                               continue;
+                       if (cp->pmax_addr == (char *)QUES) {
+                               cp->pmax_addr = pmap->pmax_addr;
+                               cp->pmax_pri = pmap->pmax_pri;
+                               continue;
+                       }
+               }
+       }
+}
+
 #ifdef DS5000
 /* 
  * Mach Operating System
 #ifdef DS5000
 /* 
  * Mach Operating System
@@ -978,7 +1315,6 @@ out:
  * rights to redistribute these changes.
  */
 
  * rights to redistribute these changes.
  */
 
-#include <pmax/pmax/turbochannel.h>
 
 /*
  * Driver map: associates a device driver to an option type.
 
 /*
  * Driver map: associates a device driver to an option type.
@@ -989,114 +1325,218 @@ struct drivers_map {
        char    module_name[TC_ROM_LLEN];       /* from ROM, literally! */
        char    *driver_name;                   /* in bus_??_init[] tables */
 } tc_drivers_map[] = {
        char    module_name[TC_ROM_LLEN];       /* from ROM, literally! */
        char    *driver_name;                   /* in bus_??_init[] tables */
 } tc_drivers_map[] = {
-       { "KN02    ",   "dc"},          /* system board, serial I/O */
+       { "KN02    ",   "dc"},          /* (*) 3max system board (with DC) */
        { "PMAD-AA ",   "le"},          /* Ether */
        { "PMAZ-AA ",   "asc"},         /* SCSI */
        { "PMAD-AA ",   "le"},          /* Ether */
        { "PMAZ-AA ",   "asc"},         /* SCSI */
+       { "PMAG-AA ",   "mfb"},         /* Mono Frame Buffer */
        { "PMAG-BA ",   "cfb"},         /* Color Frame Buffer */
        { "PMAG-CA ",   "ga"},          /* 2D graphic board */
        { "PMAG-DA ",   "gq"},          /* 3D graphic board (LM) */
        { "PMAG-FA ",   "gq"},          /* 3D graphic board (HE) */
        { "PMAG-BA ",   "cfb"},         /* Color Frame Buffer */
        { "PMAG-CA ",   "ga"},          /* 2D graphic board */
        { "PMAG-DA ",   "gq"},          /* 3D graphic board (LM) */
        { "PMAG-FA ",   "gq"},          /* 3D graphic board (HE) */
-
+       { "PMAG-DV ",   "xcfb"},        /* (*) maxine Color Frame Buffer */
+       { "Z8530   ",   "scc"},         /* (*) 3min/maxine serial lines */
+       { "ASIC    ",   "asic"},        /* (*) 3min/maxine DMA controller */
+       { "XINE-FDC",   "fdc"},         /* (*) maxine floppy controller */
+       { "DTOP    ",   "dtop"},        /* (*) maxine desktop bus */
+       { "AMD79c30",   "isdn"},        /* (*) maxine ISDN chip */
+       { "XINE-FRC",   "frc"},         /* (*) maxine free-running counter */
        { "", 0}                        /* list end */
 };
 
        { "", 0}                        /* list end */
 };
 
+/*
+ * Identify an option on the TC.  Looks at the mandatory
+ * info in the option's ROM and checks it.
+ */
 #ifdef DEBUG
 int tc_verbose = 0;
 #endif
 
 #ifdef DEBUG
 int tc_verbose = 0;
 #endif
 
+static int
+tc_identify_option( addr, slot, complain)
+       tc_rommap_t     *addr;
+       tc_option_t     *slot;
+       int             complain;
+{
+       register int    i;
+       unsigned char   width;
+       char            firmwr[TC_ROM_LLEN+1], vendor[TC_ROM_LLEN+1],
+                       module[TC_ROM_LLEN+1], host_type[TC_ROM_SLEN+1];
+
+       /*
+        * We do not really use the 'width' info, but take advantage
+        * of the restriction that the spec impose on the portion
+        * of the ROM that maps between +0x3e0 and +0x470, which
+        * is the only piece we need to look at.
+        */
+       width = addr->rom_width.value;
+       switch (width) {
+       case 1:
+       case 2:
+       case 4:
+               break;
+
+       default:
+#ifdef DEBUG
+               if (tc_verbose && complain)
+                       printf("%s (x%x) at x%x\n", "Invalid ROM width",
+                              width, addr);
+#endif
+               return (0);
+       }
+
+       if (addr->rom_stride.value != 4) {
+#ifdef DEBUG
+               if (tc_verbose && complain)
+                       printf("%s (x%x) at x%x\n", "Invalid ROM stride",
+                              addr->rom_stride.value, addr);
+#endif
+               return (0);
+       }
+
+       if ((addr->test_data[0] != 0x55) ||
+           (addr->test_data[4] != 0x00) ||
+           (addr->test_data[8] != 0xaa) ||
+           (addr->test_data[12] != 0xff)) {
+#ifdef DEBUG
+               if (tc_verbose && complain)
+                       printf("%s x%x\n", "Test pattern failed, option at",
+                              addr);
+#endif
+               return (0);
+       }
+
+       for (i = 0; i < TC_ROM_LLEN; i++) {
+               firmwr[i] = addr->firmware_rev[i].value;
+               vendor[i] = addr->vendor_name[i].value;
+               module[i] = addr->module_name[i].value;
+               if (i >= TC_ROM_SLEN)
+                       continue;
+               host_type[i] = addr->host_firmware_type[i].value;
+       }
+       firmwr[TC_ROM_LLEN] = vendor[TC_ROM_LLEN] =
+       module[TC_ROM_LLEN] = host_type[TC_ROM_SLEN] = '\0';
+
+#ifdef DEBUG
+       if (tc_verbose)
+               printf("%s %s '%s' at x%x\n %s %s %s '%s'\n %s %d %s %d %s\n",
+               "Found a", vendor, module, addr,
+               "Firmware rev.", firmwr,
+               "diagnostics for a", host_type,
+               "ROM size is", addr->rom_size.value << 3,
+               "Kbytes, uses", addr->slot_size.value, "TC slot(s)");
+#endif
+
+       bcopy(module, slot->module_name, TC_ROM_LLEN);
+       bcopy(vendor,  slot->module_id, TC_ROM_LLEN);
+       bcopy(firmwr, &slot->module_id[TC_ROM_LLEN], TC_ROM_LLEN);
+       slot->slot_size = addr->slot_size.value;
+       slot->rom_width = width;
+
+       return (1);
+}
+
 /*
 /*
- * TURBOchannel autoconf procedure. Finds in one sweep what is
+ * TURBOchannel autoconf procedure.  Finds in one sweep what is
  * hanging on the bus and fills in the tc_slot_info array.
  * This is only the first part of the autoconf scheme, at this
  * hanging on the bus and fills in the tc_slot_info array.
  * This is only the first part of the autoconf scheme, at this
- * time we are basically only looking for a graphics board and
- * serial port to use as system console (all workstations).
- *
- * XXX Someday make number of slots dynamic too.
+ * time we are basically only looking for a graphics board to
+ * use as system console (all workstations).
  */
 
  */
 
-#define KN02_TC_NSLOTS 8
-
-tc_option_t    tc_slot_info[KN02_TC_NSLOTS];
-
-caddr_t        tc_slot_virt_addr[] = {
-       (caddr_t)0xbe000000,    /* TURBOchannel, slot 0 */
-       (caddr_t)0xbe400000,    /* TURBOchannel, slot 1 */
-       (caddr_t)0xbe800000,    /* TURBOchannel, slot 2 */
-       (caddr_t)0xbec00000,    /* TURBOchannel, slot 3 */
-       (caddr_t)0xbf000000,    /* TURBOchannel, slot 4 */
-       (caddr_t)0xbf400000,    /* TURBOchannel, slot 5 */
-       (caddr_t)0xbf800000,    /* TURBOchannel, slot 6 */
-/*     (caddr_t)0xbfc00000,       TURBOchannel, slot 7 */
+unsigned int   tc_slot_phys_base [TC_MAX_SLOTS] = {
+       /* use 3max for default values */
+       KN02_PHYS_TC_0_START, KN02_PHYS_TC_1_START,
+       KN02_PHYS_TC_2_START, KN02_PHYS_TC_3_START,
+       KN02_PHYS_TC_4_START, KN02_PHYS_TC_5_START,
+       KN02_PHYS_TC_6_START, KN02_PHYS_TC_7_START
 };
 
 void
 tc_find_all_options()
 {
        register int i;
 };
 
 void
 tc_find_all_options()
 {
        register int i;
-       caddr_t addr;
+       u_long addr;
+       int found;
        register tc_option_t *sl;
        register tc_option_t *sl;
-       register struct drivers_map *map;
+       struct drivers_map *map;
        register struct pmax_ctlr *cp;
        register struct driver *drp;
 
        /*
        register struct pmax_ctlr *cp;
        register struct driver *drp;
 
        /*
-        * Look for all controllers on the bus.
+        * Take a look at the bus
         */
         */
-       i = sizeof(tc_slot_virt_addr) / sizeof(tc_slot_virt_addr[0]) - 1;
-       while (i >= 0) {
-               addr = tc_slot_virt_addr[i];
-               if (tc_probe_slot(addr, &tc_slot_info[i])) {
+       bzero(tc_slot_info, sizeof(tc_slot_info));
+       for (i = tc_max_slot; i >= tc_min_slot;) {
+               addr = MACH_PHYS_TO_UNCACHED(tc_slot_phys_base[i]);
+               found = tc_probe_slot(addr, &tc_slot_info[i]);
+
+               if (found) {
                        /*
                         * Found a slot, make a note of it 
                         */
                        tc_slot_info[i].present = 1;
                        /*
                         * Found a slot, make a note of it 
                         */
                        tc_slot_info[i].present = 1;
-                       tc_slot_info[i].module_address = addr;
+                       tc_slot_info[i].k1seg_address = addr;
                }
 
                i -= tc_slot_info[i].slot_size;
        }
 
        /*
                }
 
                i -= tc_slot_info[i].slot_size;
        }
 
        /*
-        * Now for each slot found, see if we have a device driver that
-        * handles it.
+        * Some slots (e.g. the system slot on 3max) might require
+        * hand-filling.  If so, do it now. 
         */
         */
-       for (i = 0, sl = tc_slot_info; i < KN02_TC_NSLOTS; i++, sl++) {
+       if (tc_slot_hand_fill)
+               (*tc_slot_hand_fill) (tc_slot_info);
+
+       /*
+        * Now for each alive slot see if we have a device driver that
+        * handles it.  This is done in "priority order", meaning that
+        * always present devices are at higher slot numbers on all
+        * current TC machines, and option slots are at lowest numbers.
+        */
+       for (i = TC_MAX_LOGICAL_SLOTS - 1; i >= 0; i--) {
+               sl = &tc_slot_info[i];
                if (!sl->present)
                        continue;
                if (!sl->present)
                        continue;
-               /*
-                * Look for mapping between the module name and
-                * the device driver name.
-                */
+               found = FALSE;
                for (map = tc_drivers_map; map->driver_name; map++) {
                        if (bcmp(sl->module_name, map->module_name, TC_ROM_LLEN))
                                continue;
                for (map = tc_drivers_map; map->driver_name; map++) {
                        if (bcmp(sl->module_name, map->module_name, TC_ROM_LLEN))
                                continue;
-                       goto fnd_map;
+                       sl->driver_name = map->driver_name;
+                       found = TRUE;
+                       break;
+               }
+               if (!found) {
+                       printf("%s %s %s\n", "Cannot associate a device driver to",
+                              sl->module_name, ". Will (try to) ignore it.");
+                       sl->present = 0;
+                       continue;
                }
                }
-#ifdef DEBUG
-               if (tc_verbose)
-                       printf("Cannot associate a device driver to %s\n",
-                               sl->module_name);
-#endif
-               sl->present = 0;
-               continue;
 
                /*
                 * Find the device driver entry and fill in the address.
                 */
 
                /*
                 * Find the device driver entry and fill in the address.
                 */
-       fnd_map:
                for (cp = pmax_cinit; drp = cp->pmax_driver; cp++) {
                        if (strcmp(drp->d_name, map->driver_name))
                                continue;
                        if (cp->pmax_addr == (char *)QUES) {
                for (cp = pmax_cinit; drp = cp->pmax_driver; cp++) {
                        if (strcmp(drp->d_name, map->driver_name))
                                continue;
                        if (cp->pmax_addr == (char *)QUES) {
-                               cp->pmax_addr = sl->module_address;
+                               cp->pmax_addr = (char *)sl->k1seg_address;
                                cp->pmax_pri = i;
                                cp->pmax_pri = i;
+                               /*
+                                * Only enable interrupts if there is an
+                                * interrupt handler for it. (e.g., PMAG-BA 
+                                * can't disable the vertical retrace interrupt
+                                * and we might want to ignore it).
+                                */
+                               if (drp->d_intr)
+                                       (*tc_enable_interrupt)(i, 1);
                                continue;
                        }
                                continue;
                        }
-                       if (cp->pmax_addr != sl->module_address) {
+                       if (cp->pmax_addr != (char *)sl->k1seg_address) {
                                cp->pmax_addr = (char *)QUES;
                                printf("%s: device not at configued address (expected at %x, found at %x)\n",
                                        drp->d_name,
                                cp->pmax_addr = (char *)QUES;
                                printf("%s: device not at configued address (expected at %x, found at %x)\n",
                                        drp->d_name,
-                                       cp->pmax_addr, sl->module_address);
+                                       cp->pmax_addr, sl->k1seg_address);
                        }
                }
        }
                        }
                }
        }
@@ -1134,111 +1574,316 @@ tc_probe_slot(addr, slot)
 }
 
 /*
 }
 
 /*
- * Identify an option on the TURBOchannel.  Looks at the mandatory
- * info in the option's ROM and checks it.
+ * Enable/Disable interrupts for a TURBOchannel slot.
  */
  */
-int
-tc_identify_option(addr, slot, complain)
-       tc_rommap_t *addr;
-       tc_option_t *slot;
-       int complain;
+void
+kn02_enable_intr(slotno, on)
+       register int slotno;
+       int on;
 {
 {
-       register int i;
-       unsigned char width;
-       char firmwr[TC_ROM_LLEN+1];
-       char vendor[TC_ROM_LLEN+1];
-       char module[TC_ROM_LLEN+1];
-       char host_type[TC_ROM_SLEN+1];
+       register volatile int *p_csr =
+               (volatile int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CSR);
+       int csr;
+       int s;
 
 
-       /*
-        * We do not really use the 'width' info, but take advantage
-        * of the restriction that the spec impose on the portion
-        * of the ROM that maps between +0x3e0 and +0x470, which
-        * is the only piece we need to look at.
-        */
-       width = addr->rom_width.value;
-       switch (width) {
+       slotno = 1 << (slotno + KN02_CSR_IOINTEN_SHIFT);
+       s = Mach_spl0();
+       csr = *p_csr & ~(KN02_CSR_WRESERVED | 0xFF);
+       if (on)
+               *p_csr = csr | slotno;
+       else
+               *p_csr = csr & ~slotno;
+       splx(s);
+}
+
+/*
+ *     Object:
+ *             kmin_enable_intr                EXPORTED function
+ *
+ *     Enable/Disable interrupts from a TURBOchannel slot.
+ *
+ *     We pretend we actually have 8 slots even if we really have
+ *     only 4: TCslots 0-2 maps to slots 0-2, TCslot3 maps to
+ *     slots 3-7 (see kmin_slot_hand_fill).
+ */
+void
+kmin_enable_intr(slotno, on)
+       register unsigned int slotno;
+       int on;
+{
+       register unsigned mask;
+
+       switch (slotno) {
+       case 0:
        case 1:
        case 2:
        case 1:
        case 2:
-       case 4:
+               return;
+       case KMIN_SCSI_SLOT:
+               mask = (KMIN_INTR_SCSI | KMIN_INTR_SCSI_PTR_LOAD |
+                       KMIN_INTR_SCSI_OVRUN | KMIN_INTR_SCSI_READ_E);
+               break;
+       case KMIN_LANCE_SLOT:
+               mask = KMIN_INTR_LANCE;
+               break;
+       case KMIN_SCC0_SLOT:
+               mask = KMIN_INTR_SCC_0;
+               break;
+       case KMIN_SCC1_SLOT:
+               mask = KMIN_INTR_SCC_1;
+               break;
+       case KMIN_ASIC_SLOT:
+               mask = KMIN_INTR_ASIC;
                break;
                break;
-
        default:
        default:
-               if (complain)
-                       printf("Invalid ROM width (0x%x) at x%x\n",
-                              width, addr);
-               return (0);
-       }
-
-       if (addr->rom_stride.value != 4) {
-               if (complain)
-                       printf("Invalid ROM stride (0x%x) at x%x\n",
-                              addr->rom_stride.value, addr);
-               return (0);
+               return;
        }
        }
+       if (on)
+               kmin_tc3_imask |= mask;
+       else
+               kmin_tc3_imask &= ~mask;
+}
 
 
-       if (addr->test_data[0] != 0x55 ||
-           addr->test_data[4] != 0x00 ||
-           addr->test_data[8] != 0xaa ||
-           addr->test_data[12] != 0xff) {
-               if (complain)
-                       printf("Test pattern failed, option at x%x\n",
-                              addr);
-               return (0);
-       }
+/*
+ *     Object:
+ *             xine_enable_intr                EXPORTED function
+ *
+ *     Enable/Disable interrupts from a TURBOchannel slot.
+ *
+ *     We pretend we actually have 11 slots even if we really have
+ *     only 3: TCslots 0-1 maps to slots 0-1, TCslot 2 is used for
+ *     the system (TCslot3), TCslot3 maps to slots 3-10
+ *     (see xine_slot_hand_fill).
+ *     Note that all these interrupts come in via the IMR.
+ */
+void
+xine_enable_intr(slotno, on)
+       register unsigned int slotno;
+       int on;
+{
+       register unsigned mask;
 
 
-       for (i = 0; i < TC_ROM_LLEN; i++) {
-               firmwr[i] = addr->firmware_rev[i].value;
-               vendor[i] = addr->vendor_name[i].value;
-               module[i] = addr->module_name[i].value;
-               if (i >= TC_ROM_SLEN)
-                       continue;
-               host_type[i] = addr->host_firmware_type[i].value;
+       switch (slotno) {
+       case 0:                 /* a real slot, but  */
+               mask = XINE_INTR_TC_0;
+               break;
+       case 1:                 /* a real slot, but */
+               mask = XINE_INTR_TC_1;
+               break;
+       case XINE_FLOPPY_SLOT:
+               mask = XINE_INTR_FLOPPY;
+               break;
+       case XINE_SCSI_SLOT:
+               mask = (XINE_INTR_SCSI | XINE_INTR_SCSI_PTR_LOAD |
+                       XINE_INTR_SCSI_OVRUN | XINE_INTR_SCSI_READ_E);
+               break;
+       case XINE_LANCE_SLOT:
+               mask = XINE_INTR_LANCE;
+               break;
+       case XINE_SCC0_SLOT:
+               mask = XINE_INTR_SCC_0;
+               break;
+       case XINE_DTOP_SLOT:
+               mask = XINE_INTR_DTOP_RX;
+               break;
+       case XINE_ISDN_SLOT:
+               mask = XINE_INTR_ISDN;
+               break;
+       case XINE_ASIC_SLOT:
+               mask = XINE_INTR_ASIC;
+               break;
+       default:
+               return;/* ignore */
        }
        }
+       if (on)
+               xine_tc3_imask |= mask;
+       else
+               xine_tc3_imask &= ~mask;
+}
 
 
-#ifdef DEBUG
-       if (tc_verbose) {
-               firmwr[TC_ROM_LLEN] = '\0';
-               vendor[TC_ROM_LLEN] = '\0';
-               module[TC_ROM_LLEN] = '\0';
-               host_type[TC_ROM_SLEN] = '\0';
-               printf("%s %s '%s' at x%x\n %s %s %s '%s'\n %s %d %s %d %s\n",
-                      "Found a", vendor, module, addr,
-                      "Firmware rev.", firmwr,
-                      "diagnostics for a", host_type,
-                      "ROM size is", addr->rom_size.value << 3,
-                      "Kbytes, uses", addr->slot_size.value, "TC slot(s)");
-       }
+/*
+ *     Object:
+ *             kn02_slot_hand_fill             EXPORTED function
+ *
+ *     Fill in by hand the info for TC slots that are non-standard.
+ *     This is basically just the system slot on a 3max, it does not
+ *     look to me like it follows the TC rules although some of the
+ *     required info is indeed there.
+ *
+ */
+void
+kn02_slot_hand_fill(slot)
+       tc_option_t *slot;
+{
+       slot[7].present = 1;
+       slot[7].slot_size = 1;
+       slot[7].rom_width = 1;
+#if unsafe
+       bcopy(0xbffc0410, slot[7].module_name, TC_ROM_LLEN+1);
 #endif
 #endif
+       bcopy("KN02    ", slot[7].module_name, TC_ROM_LLEN+1);
+       bcopy("DEC xxxx", slot[7].module_id, TC_ROM_LLEN+1);
+       slot[7].k1seg_address = MACH_PHYS_TO_UNCACHED(KN02_SYS_DZ);
+}
 
 
-       bcopy(module, slot->module_name, TC_ROM_LLEN);
-       bcopy(vendor, slot->module_id, TC_ROM_LLEN);
-       bcopy(firmwr, &slot->module_id[TC_ROM_LLEN], TC_ROM_LLEN);
-       slot->slot_size = addr->slot_size.value;
-       slot->rom_width = width;
+/*
+ *     Object:
+ *             kmin_slot_hand_fill             EXPORTED function
+ *
+ *     Fill in by hand the info for TC slots that are non-standard.
+ *     This is the system slot on a 3min, which we think of as a
+ *     set of non-regular size TC slots.
+ *
+ */
+void
+kmin_slot_hand_fill(slot)
+       tc_option_t *slot;
+{
+       register int i;
 
 
-       return (1);
+       for (i = KMIN_SCSI_SLOT; i < KMIN_ASIC_SLOT+1; i++) {
+               slot[i].present = 1;
+               slot[i].slot_size = 1;
+               slot[i].rom_width = 1;
+               slot[i].unit = 0;
+               bcopy("DEC KMIN", slot[i].module_id, TC_ROM_LLEN+1);
+       }
+
+       /* scsi */
+       bcopy("PMAZ-AA ", slot[KMIN_SCSI_SLOT].module_name, TC_ROM_LLEN+1);
+       slot[KMIN_SCSI_SLOT].k1seg_address =
+               MACH_PHYS_TO_UNCACHED(KMIN_SYS_SCSI);
+
+       /* lance */
+       bcopy("PMAD-AA ", slot[KMIN_LANCE_SLOT].module_name, TC_ROM_LLEN+1);
+       slot[KMIN_LANCE_SLOT].k1seg_address = 0;
+
+       /* scc */
+       bcopy("Z8530   ", slot[KMIN_SCC0_SLOT].module_name, TC_ROM_LLEN+1);
+       slot[KMIN_SCC0_SLOT].k1seg_address =
+               MACH_PHYS_TO_UNCACHED(KMIN_SYS_SCC_0);
+
+       slot[KMIN_SCC1_SLOT].unit = 1;
+       bcopy("Z8530   ", slot[KMIN_SCC1_SLOT].module_name, TC_ROM_LLEN+1);
+       slot[KMIN_SCC1_SLOT].k1seg_address =
+               MACH_PHYS_TO_UNCACHED(KMIN_SYS_SCC_1);
+
+       /* asic */
+       bcopy("ASIC    ", slot[KMIN_ASIC_SLOT].module_name, TC_ROM_LLEN+1);
+       slot[KMIN_ASIC_SLOT].k1seg_address =
+               MACH_PHYS_TO_UNCACHED(KMIN_SYS_ASIC);
+       asic_init(TRUE);
 }
 
 /*
 }
 
 /*
- * Enable/Disable interrupts for a TURBOchannel slot.
+ *     Object:
+ *             xine_slot_hand_fill             EXPORTED function
+ *
+ *     Fill in by hand the info for TC slots that are non-standard.
+ *     This is the system slot on a 3min, which we think of as a
+ *     set of non-regular size TC slots.
+ *
  */
  */
-tc_enable_interrupt(slotno, on)
-       register int slotno;
-       int on;
+void
+xine_slot_hand_fill(slot)
+       tc_option_t *slot;
 {
 {
-       register volatile int *p_csr = (volatile int *)MACH_SYS_CSR_ADDR;
-       int csr;
-       int s;
+       register int i;
 
 
-       slotno = 1 << (slotno + MACH_CSR_IOINTEN_SHIFT);
-       s = Mach_spl0();
-       csr = *p_csr & ~(MACH_CSR_MBZ | 0xFF);
-       if (on)
-               *p_csr = csr | slotno;
-       else
-               *p_csr = csr & ~slotno;
-       splx(s);
+       for (i = XINE_FLOPPY_SLOT; i < XINE_FRC_SLOT+1; i++) {
+               slot[i].present = 1;
+               slot[i].slot_size = 1;
+               slot[i].rom_width = 1;
+               slot[i].unit = 0;
+               bcopy("DEC XINE", slot[i].module_id, TC_ROM_LLEN+1);
+       }
+
+       /* floppy */
+       bcopy("XINE-FDC", slot[XINE_FLOPPY_SLOT].module_name, TC_ROM_LLEN+1);
+       slot[XINE_FLOPPY_SLOT].k1seg_address =
+               MACH_PHYS_TO_UNCACHED(XINE_SYS_FLOPPY);
+
+       /* scsi */
+       bcopy("PMAZ-AA ", slot[XINE_SCSI_SLOT].module_name, TC_ROM_LLEN+1);
+       slot[XINE_SCSI_SLOT].k1seg_address =
+               MACH_PHYS_TO_UNCACHED(XINE_SYS_SCSI);
+
+       /* lance */
+       bcopy("PMAD-AA ", slot[XINE_LANCE_SLOT].module_name, TC_ROM_LLEN+1);
+       slot[XINE_LANCE_SLOT].k1seg_address =
+               MACH_PHYS_TO_UNCACHED(XINE_SYS_LANCE);
+
+       /* scc */
+       bcopy("Z8530   ", slot[XINE_SCC0_SLOT].module_name, TC_ROM_LLEN+1);
+       slot[XINE_SCC0_SLOT].k1seg_address =
+               MACH_PHYS_TO_UNCACHED(XINE_SYS_SCC_0);
+
+       /* Desktop */
+       bcopy("DTOP    ", slot[XINE_DTOP_SLOT].module_name, TC_ROM_LLEN+1);
+       slot[XINE_DTOP_SLOT].k1seg_address =
+               MACH_PHYS_TO_UNCACHED(XINE_SYS_DTOP+0x20000); /* why? */
+
+       /* ISDN */
+       bcopy("AMD79c30", slot[XINE_ISDN_SLOT].module_name, TC_ROM_LLEN+1);
+       slot[XINE_ISDN_SLOT].k1seg_address =
+               MACH_PHYS_TO_UNCACHED(XINE_SYS_ISDN);
+
+       /* Video */
+       bcopy("PMAG-DV ", slot[XINE_CFB_SLOT].module_name, TC_ROM_LLEN+1);
+       slot[XINE_CFB_SLOT].k1seg_address =
+               MACH_PHYS_TO_CACHED(XINE_PHYS_CFB_START);
+
+       /* asic */
+       bcopy("ASIC    ", slot[XINE_ASIC_SLOT].module_name, TC_ROM_LLEN+1);
+       slot[XINE_ASIC_SLOT].k1seg_address =
+               MACH_PHYS_TO_UNCACHED(XINE_SYS_ASIC);
+
+       /* free-running counter (high resolution mapped time) */
+       bcopy("XINE-FRC", slot[XINE_FRC_SLOT].module_name, TC_ROM_LLEN+1);
+       slot[XINE_FRC_SLOT].k1seg_address =
+               MACH_PHYS_TO_UNCACHED(XINE_REG_FCTR);
+       asic_init(FALSE);
 }
 
 }
 
+/*
+ * Initialize the I/O asic
+ */
+static void
+asic_init(isa_3min)
+       int isa_3min;
+{
+       volatile u_int *ssr, *decoder;
+
+       /* These are common between 3min and maxine */
+       decoder = (volatile u_int *)
+               MACH_PHYS_TO_UNCACHED(KMIN_REG_LANCE_DECODE);
+       *decoder = KMIN_LANCE_CONFIG;
+#ifdef notdef
+       decoder = (volatile u_int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_SCSI_DECODE);
+       *decoder = KMIN_SCSI_CONFIG;
+       decoder = (volatile u_int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_SCC0_DECODE);
+       *decoder = KMIN_SCC0_CONFIG;
+
+       ssr = (volatile u_int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_CSR);
+
+       if (isa_3min) {
+               decoder = (volatile u_int *)
+                       MACH_PHYS_TO_UNCACHED(KMIN_REG_SCC1_DECODE);
+               *decoder = KMIN_SCC1_CONFIG;
+
+               /* take all chips out of reset now */
+               *ssr = 0x00000f00;
+
+       } else {
+               decoder = (volatile u_int *)
+                       MACH_PHYS_TO_UNCACHED(XINE_REG_DTOP_DECODE);
+               *decoder = XINE_DTOP_CONFIG;
+               decoder = (volatile u_int *)
+                       MACH_PHYS_TO_UNCACHED(XINE_REG_FLOPPY_DECODE);
+               *decoder = XINE_FLOPPY_CONFIG;
+
+               /* take all chips out of reset now */
+               *ssr = 0x00001fc1;
+       }
+#endif
+}
 #endif /* DS5000 */
 #endif /* DS5000 */
index f09e821..71984d8 100644 (file)
@@ -11,7 +11,7 @@
  *
  * from: Utah $Hdr: trap.c 1.32 91/04/06$
  *
  *
  * from: Utah $Hdr: trap.c 1.32 91/04/06$
  *
- *     @(#)trap.c      7.10 (Berkeley) %G%
+ *     @(#)trap.c      7.11 (Berkeley) %G%
  */
 
 #include <sys/param.h>
  */
 
 #include <sys/param.h>
 #include <machine/cpu.h>
 #include <machine/pte.h>
 #include <machine/mips_opcode.h>
 #include <machine/cpu.h>
 #include <machine/pte.h>
 #include <machine/mips_opcode.h>
-#include <pmax/pmax/clockreg.h>
 
 #include <vm/vm.h>
 #include <vm/vm_kern.h>
 #include <vm/vm_page.h>
 
 
 #include <vm/vm.h>
 #include <vm/vm_kern.h>
 #include <vm/vm_page.h>
 
+#include <pmax/pmax/clockreg.h>
+#include <pmax/pmax/kn01.h>
+#include <pmax/pmax/kn02.h>
+#include <pmax/pmax/kmin.h>
+#include <pmax/pmax/maxine.h>
+#include <pmax/pmax/asic.h>
+#include <pmax/pmax/turbochannel.h>
+
+#include <asc.h>
+#include <sii.h>
+#include <le.h>
+#include <dc.h>
+
 /*
  * This is a kludge to allow X windows to work.
  */
 /*
  * This is a kludge to allow X windows to work.
  */
@@ -60,7 +72,6 @@ extern void MachKernIntr();
 extern void MachUserIntr();
 extern void MachTLBModException();
 extern void MachTLBMissException();
 extern void MachUserIntr();
 extern void MachTLBModException();
 extern void MachTLBMissException();
-static void MemErrorInterrupt();
 extern unsigned MachEmulateBranch();
 
 void (*machExceptionTable[])() = {
 extern unsigned MachEmulateBranch();
 
 void (*machExceptionTable[])() = {
@@ -135,6 +146,14 @@ struct trapdebug {         /* trap history buffer for debugging */
 } trapdebug[TRAPSIZE], *trp = trapdebug;
 #endif
 
 } trapdebug[TRAPSIZE], *trp = trapdebug;
 #endif
 
+static void pmax_errintr();
+static void kn02_errintr(), kn02ba_errintr();
+static unsigned kn02ba_recover_erradr();
+extern tc_option_t tc_slot_info[TC_MAX_LOGICAL_SLOTS];
+extern u_long kmin_tc3_imask, xine_tc3_imask;
+int (*pmax_hardware_intr)() = (int (*)())0;
+extern volatile struct chiptime *Mach_clock_addr;
+
 /*
  * Handle an exception.
  * Called from MachKernGenException() or MachUserGenException()
 /*
  * Handle an exception.
  * Called from MachKernGenException() or MachUserGenException()
@@ -710,12 +729,6 @@ out:
        return (pc);
 }
 
        return (pc);
 }
 
-#ifdef DS5000
-struct intr_tab intr_tab[8];
-#endif
-
-int    temp;           /* XXX ULTRIX compiler bug with -O */
-
 /*
  * Handle an interrupt.
  * Called from MachKernIntr() or MachUserIntr()
 /*
  * Handle an interrupt.
  * Called from MachKernIntr() or MachUserIntr()
@@ -742,46 +755,118 @@ interrupt(statusReg, causeReg, pc)
 
        cnt.v_intr++;
        mask = causeReg & statusReg;    /* pending interrupts & enable mask */
 
        cnt.v_intr++;
        mask = causeReg & statusReg;    /* pending interrupts & enable mask */
-#ifdef DS3100
+       if (pmax_hardware_intr)
+               splx((*pmax_hardware_intr)(mask, pc, statusReg, causeReg));
+       if (mask & MACH_INT_MASK_5) {
+               if (!USERMODE(statusReg)) {
+#ifdef DEBUG
+                       trapDump("fpintr");
+#else
+                       printf("FPU interrupt: PC %x CR %x SR %x\n",
+                               pc, causeReg, statusReg);
+#endif
+               } else
+                       MachFPInterrupt(statusReg, causeReg, pc);
+       }
+       if (mask & MACH_SOFT_INT_MASK_0) {
+               clearsoftclock();
+               cnt.v_soft++;
+               softclock();
+       }
+       /* process network interrupt if we trapped or will very soon */
+       if ((mask & MACH_SOFT_INT_MASK_1) ||
+           netisr && (statusReg & MACH_SOFT_INT_MASK_1)) {
+               clearsoftnet();
+               cnt.v_soft++;
+#ifdef INET
+               if (netisr & (1 << NETISR_ARP)) {
+                       netisr &= ~(1 << NETISR_ARP);
+                       arpintr();
+               }
+               if (netisr & (1 << NETISR_IP)) {
+                       netisr &= ~(1 << NETISR_IP);
+                       ipintr();
+               }
+#endif
+#ifdef NS
+               if (netisr & (1 << NETISR_NS)) {
+                       netisr &= ~(1 << NETISR_NS);
+                       nsintr();
+               }
+#endif
+#ifdef ISO
+               if (netisr & (1 << NETISR_ISO)) {
+                       netisr &= ~(1 << NETISR_ISO);
+                       clnlintr();
+               }
+#endif
+       }
+}
+
+/*
+ * Handle pmax (DECstation 2100/3100) interrupts.
+ */
+pmax_intr(mask, pc, statusReg, causeReg)
+       unsigned mask;
+       unsigned pc;
+       unsigned statusReg;
+       unsigned causeReg;
+{
+       register volatile struct chiptime *c = Mach_clock_addr;
+       struct clockframe cf;
+       int temp;
+
        /* handle clock interrupts ASAP */
        if (mask & MACH_INT_MASK_3) {
        /* handle clock interrupts ASAP */
        if (mask & MACH_INT_MASK_3) {
-               register volatile struct chiptime *c =
-                       (volatile struct chiptime *)MACH_CLOCK_ADDR;
-
                temp = c->regc; /* XXX clear interrupt bits */
                cf.pc = pc;
                cf.sr = statusReg;
                hardclock(&cf);
                causeReg &= ~MACH_INT_MASK_3;   /* reenable clock interrupts */
                temp = c->regc; /* XXX clear interrupt bits */
                cf.pc = pc;
                cf.sr = statusReg;
                hardclock(&cf);
                causeReg &= ~MACH_INT_MASK_3;   /* reenable clock interrupts */
+               splx(MACH_INT_MASK_3 | MACH_SR_INT_ENA_CUR);
        }
        }
-       /*
-        * Enable hardware interrupts which were enabled but not pending.
-        * We only respond to software interrupts when returning to spl0.
-        */
-       splx((statusReg & ~causeReg & MACH_HARD_INT_MASK) |
-               MACH_SR_INT_ENA_CUR);
+#if NSII > 0
        if (mask & MACH_INT_MASK_0)
                siiintr(0);
        if (mask & MACH_INT_MASK_0)
                siiintr(0);
+#endif
+#if NLE > 0
        if (mask & MACH_INT_MASK_1)
                leintr(0);
        if (mask & MACH_INT_MASK_1)
                leintr(0);
+#endif
+#if NDC > 0
        if (mask & MACH_INT_MASK_2)
                dcintr(0);
        if (mask & MACH_INT_MASK_2)
                dcintr(0);
+#endif
        if (mask & MACH_INT_MASK_4)
        if (mask & MACH_INT_MASK_4)
-               MemErrorInterrupt();
-#endif /* DS3100 */
-#ifdef DS5000
+               pmax_errintr();
+       return ((statusReg & ~causeReg & MACH_HARD_INT_MASK) |
+               MACH_SR_INT_ENA_CUR);
+}
+
+/*
+ * Handle hardware interrupts for the KN02. (DECstation 5000/200)
+ * Returns spl value.
+ */
+kn02_intr(mask, pc, statusReg, causeReg)
+       unsigned mask;
+       unsigned pc;
+       unsigned statusReg;
+       unsigned causeReg;
+{
+       register unsigned i, m;
+       register volatile struct chiptime *c = Mach_clock_addr;
+       register unsigned csr;
+       int temp;
+       struct clockframe cf;
+       static int warned = 0;
+
        /* handle clock interrupts ASAP */
        if (mask & MACH_INT_MASK_1) {
        /* handle clock interrupts ASAP */
        if (mask & MACH_INT_MASK_1) {
-               register volatile struct chiptime *c =
-                       (volatile struct chiptime *)MACH_CLOCK_ADDR;
-               register unsigned csr;
-               static int warned = 0;
-
-               csr = *(unsigned *)MACH_SYS_CSR_ADDR;
-               if ((csr & MACH_CSR_PSWARN) && !warned) {
+               csr = *(unsigned *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CSR);
+               if ((csr & KN02_CSR_PSWARN) && !warned) {
                        warned = 1;
                        printf("WARNING: power supply is overheating!\n");
                        warned = 1;
                        printf("WARNING: power supply is overheating!\n");
-               } else if (warned && !(csr & MACH_CSR_PSWARN)) {
+               } else if (warned && !(csr & KN02_CSR_PSWARN)) {
                        warned = 0;
                        printf("WARNING: power supply is OK again\n");
                }
                        warned = 0;
                        printf("WARNING: power supply is OK again\n");
                }
@@ -790,94 +875,228 @@ interrupt(statusReg, causeReg, pc)
                cf.pc = pc;
                cf.sr = statusReg;
                hardclock(&cf);
                cf.pc = pc;
                cf.sr = statusReg;
                hardclock(&cf);
-               causeReg &= ~MACH_INT_MASK_1;   /* reenable clock interrupts */
+
+               /* Re-enable clock interrupts */
+               causeReg &= ~MACH_INT_MASK_1;
+               splx(MACH_INT_MASK_1 | MACH_SR_INT_ENA_CUR);
        }
        if (mask & MACH_INT_MASK_0) {
        }
        if (mask & MACH_INT_MASK_0) {
-               register unsigned csr;
-               register unsigned i, m;
 
 
-               csr = *(unsigned *)MACH_SYS_CSR_ADDR;
-               m = csr & (csr >> MACH_CSR_IOINTEN_SHIFT) & MACH_CSR_IOINT_MASK;
+               csr = *(unsigned *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CSR);
+               m = csr & (csr >> KN02_CSR_IOINTEN_SHIFT) & KN02_CSR_IOINT;
 #if 0
 #if 0
-               *(unsigned *)MACH_SYS_CSR_ADDR =
-                       (csr & ~(MACH_CSR_MBZ | 0xFF)) |
-                       (m << MACH_CSR_IOINTEN_SHIFT);
+               *(unsigned *)MACHPHYS_TO_UNCACHED(KN02_SYS_CSR) =
+                       (csr & ~(KN02_CSR_WRESERVED | 0xFF)) |
+                       (m << KN02_CSR_IOINTEN_SHIFT);
 #endif
 #endif
-               /*
-                * Enable hardware interrupts which were enabled but not
-                * pending. We only respond to software interrupts when
-                * returning to spl0.
-                */
-               splx((statusReg & ~causeReg & MACH_HARD_INT_MASK) |
-                       MACH_SR_INT_ENA_CUR);
                for (i = 0; m; i++, m >>= 1) {
                        if (!(m & 1))
                                continue;
                for (i = 0; m; i++, m >>= 1) {
                        if (!(m & 1))
                                continue;
-                       if (intr_tab[i].func)
-                               (*intr_tab[i].func)(intr_tab[i].unit);
+                       if (tc_slot_info[i].intr)
+                               (*tc_slot_info[i].intr)(tc_slot_info[i].unit);
                        else
                                printf("spurious interrupt %d\n", i);
                }
 #if 0
                        else
                                printf("spurious interrupt %d\n", i);
                }
 #if 0
-               *(unsigned *)MACH_SYS_CSR_ADDR =
-                       csr & ~(MACH_CSR_MBZ | 0xFF);
+               *(unsigned *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CSR) =
+                       csr & ~(KN02_CSR_WRESERVED | 0xFF);
 #endif
 #endif
-       } else {
-               /*
-                * Enable hardware interrupts which were enabled but not
-                * pending. We only respond to software interrupts when
-                * returning to spl0.
-                */
-               splx((statusReg & ~causeReg & MACH_HARD_INT_MASK) |
-                       MACH_SR_INT_ENA_CUR);
        }
        if (mask & MACH_INT_MASK_3)
        }
        if (mask & MACH_INT_MASK_3)
-               MemErrorInterrupt();
-#endif /* DS5000 */
-       if (mask & MACH_INT_MASK_5) {
-               if (!USERMODE(statusReg)) {
-#ifdef DEBUG
-                       trapDump("fpintr");
-#else
-                       printf("FPU interrupt: PC %x CR %x SR %x\n",
-                               pc, causeReg, statusReg);
+               kn02_errintr();
+       return ((statusReg & ~causeReg & MACH_HARD_INT_MASK) |
+               MACH_SR_INT_ENA_CUR);
+}
+
+/*
+ * 3min hardware interrupts. (DECstation 5000/1xx)
+ */
+kmin_intr(mask, pc, statusReg, causeReg)
+       unsigned mask;
+       unsigned pc;
+       unsigned statusReg;
+       unsigned causeReg;
+{
+       register u_int intr;
+       register volatile struct chiptime *c = Mach_clock_addr;
+       volatile u_int *imaskp =
+               (volatile u_int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_IMSK);
+       volatile u_int *intrp =
+               (volatile u_int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_INTR);
+       unsigned int old_mask;
+       struct clockframe cf;
+       int temp;
+       static int user_warned = 0;
+
+       old_mask = *imaskp & kmin_tc3_imask;
+       *imaskp = old_mask;
+
+       if (mask & MACH_INT_MASK_3) {
+               intr = *intrp;
+               /* masked interrupts are still observable */
+               intr &= old_mask;
+       
+               if (intr & KMIN_INTR_SCSI_PTR_LOAD) {
+                       *intrp &= ~KMIN_INTR_SCSI_PTR_LOAD;
+#if NASC > 0
+                       asc_dma_intr();
 #endif
 #endif
-               } else
-                       MachFPInterrupt(statusReg, causeReg, pc);
-       }
-       if (mask & MACH_SOFT_INT_MASK_0) {
-               clearsoftclock();
-               cnt.v_soft++;
-               softclock();
-       }
-       /* process network interrupt if we trapped or will very soon */
-       if ((mask & MACH_SOFT_INT_MASK_1) ||
-           netisr && (statusReg & MACH_SOFT_INT_MASK_1)) {
-               clearsoftnet();
-               cnt.v_soft++;
-#ifdef INET
-               if (netisr & (1 << NETISR_ARP)) {
-                       netisr &= ~(1 << NETISR_ARP);
-                       arpintr();
                }
                }
-               if (netisr & (1 << NETISR_IP)) {
-                       netisr &= ~(1 << NETISR_IP);
-                       ipintr();
+       
+               if (intr & (KMIN_INTR_SCSI_OVRUN | KMIN_INTR_SCSI_READ_E))
+                       *intrp &= ~(KMIN_INTR_SCSI_OVRUN | KMIN_INTR_SCSI_READ_E);
+
+               if (intr & KMIN_INTR_LANCE_READ_E)
+                       *intrp &= ~KMIN_INTR_LANCE_READ_E;
+
+               if (intr & KMIN_INTR_TIMEOUT)
+                       kn02ba_errintr();
+       
+               if (intr & KMIN_INTR_CLOCK) {
+                       temp = c->regc; /* XXX clear interrupt bits */
+                       cf.pc = pc;
+                       cf.sr = statusReg;
+                       hardclock(&cf);
                }
                }
-#endif
-#ifdef NS
-               if (netisr & (1 << NETISR_NS)) {
-                       netisr &= ~(1 << NETISR_NS);
-                       nsintr();
+       
+               if ((intr & KMIN_INTR_SCC_0) &&
+                       tc_slot_info[KMIN_SCC0_SLOT].intr)
+                       (*(tc_slot_info[KMIN_SCC0_SLOT].intr))
+                       (tc_slot_info[KMIN_SCC0_SLOT].unit);
+       
+               if ((intr & KMIN_INTR_SCC_1) &&
+                       tc_slot_info[KMIN_SCC1_SLOT].intr)
+                       (*(tc_slot_info[KMIN_SCC1_SLOT].intr))
+                       (tc_slot_info[KMIN_SCC1_SLOT].unit);
+       
+               if ((intr & KMIN_INTR_SCSI) &&
+                       tc_slot_info[KMIN_SCSI_SLOT].intr)
+                       (*(tc_slot_info[KMIN_SCSI_SLOT].intr))
+                       (tc_slot_info[KMIN_SCSI_SLOT].unit);
+       
+               if ((intr & KMIN_INTR_LANCE) &&
+                       tc_slot_info[KMIN_LANCE_SLOT].intr)
+                       (*(tc_slot_info[KMIN_LANCE_SLOT].intr))
+                       (tc_slot_info[KMIN_LANCE_SLOT].unit);
+       
+               if (user_warned && ((intr & KMIN_INTR_PSWARN) == 0)) {
+                       *imaskp = 0;
+                       printf("%s\n", "Power supply ok now.");
+                       user_warned = 0;
                }
                }
-#endif
-#ifdef ISO
-               if (netisr & (1 << NETISR_ISO)) {
-                       netisr &= ~(1 << NETISR_ISO);
-                       clnlintr();
+               if ((intr & KMIN_INTR_PSWARN) && (user_warned < 3)) {
+                       *imaskp = 0;
+                       user_warned++;
+                       printf("%s\n", "Power supply overheating");
                }
                }
+       }
+       if ((mask & MACH_INT_MASK_0) && tc_slot_info[0].intr)
+               (*tc_slot_info[0].intr)(tc_slot_info[0].unit);
+       if ((mask & MACH_INT_MASK_1) && tc_slot_info[1].intr)
+               (*tc_slot_info[1].intr)(tc_slot_info[1].unit);
+       if ((mask & MACH_INT_MASK_2) && tc_slot_info[2].intr)
+               (*tc_slot_info[2].intr)(tc_slot_info[2].unit);
+       return ((statusReg & ~causeReg & MACH_HARD_INT_MASK) |
+               MACH_SR_INT_ENA_CUR);
+}
+
+/*
+ * Maxine hardwark interrupts. (Personal DECstation 5000/xx)
+ */
+xine_intr(mask, pc, statusReg, causeReg)
+       unsigned mask;
+       unsigned pc;
+       unsigned statusReg;
+       unsigned causeReg;
+{
+       register u_int intr;
+       register volatile struct chiptime *c = Mach_clock_addr;
+       volatile u_int *imaskp = (volatile u_int *)
+               MACH_PHYS_TO_UNCACHED(XINE_REG_IMSK);
+       volatile u_int *intrp = (volatile u_int *)
+               MACH_PHYS_TO_UNCACHED(XINE_REG_INTR);
+       u_int old_mask;
+       struct clockframe cf;
+       int temp;
+static int clkticks = 0;
+
+       old_mask = *imaskp & xine_tc3_imask;
+       *imaskp = old_mask;
+
+       /* handle clock interrupts ASAP */
+       if (mask & MACH_INT_MASK_1) {
+               temp = c->regc; /* XXX clear interrupt bits */
+               cf.pc = pc;
+               cf.sr = statusReg;
+               hardclock(&cf);
+if ((++clkticks % 10000) == 0) printf("TICKKEYY TICKEY!\n");
+               causeReg &= ~MACH_INT_MASK_1;
+               /* reenable clock interrupts */
+               splx(MACH_INT_MASK_1 | MACH_SR_INT_ENA_CUR);
+       }
+       if (mask & MACH_INT_MASK_3) {
+               intr = *intrp;
+               /* masked interrupts are still observable */
+               intr &= old_mask;
+
+               if (intr & XINE_INTR_SCSI_PTR_LOAD) {
+                       *intrp &= ~XINE_INTR_SCSI_PTR_LOAD;
+#if NASC > 0
+                       asc_dma_intr();
 #endif
 #endif
+               }
+       
+               if (intr & (XINE_INTR_SCSI_OVRUN | XINE_INTR_SCSI_READ_E))
+                       *intrp &= ~(XINE_INTR_SCSI_OVRUN | XINE_INTR_SCSI_READ_E);
+
+               if (intr & XINE_INTR_LANCE_READ_E)
+                       *intrp &= ~XINE_INTR_LANCE_READ_E;
+
+               if ((intr & XINE_INTR_FLOPPY) &&
+                       tc_slot_info[XINE_FLOPPY_SLOT].intr)
+                       (*(tc_slot_info[XINE_FLOPPY_SLOT].intr))
+                       (tc_slot_info[XINE_FLOPPY_SLOT].unit);
+       
+               if ((intr & XINE_INTR_TC_0) &&
+                       tc_slot_info[0].intr)
+                       (*(tc_slot_info[0].intr))
+                       (tc_slot_info[0].unit);
+       
+               if ((intr & XINE_INTR_ISDN) &&
+                       tc_slot_info[XINE_ISDN_SLOT].intr)
+                       (*(tc_slot_info[XINE_ISDN_SLOT].intr))
+                       (tc_slot_info[XINE_ISDN_SLOT].unit);
+       
+               if ((intr & XINE_INTR_SCSI) &&
+                       tc_slot_info[XINE_SCSI_SLOT].intr)
+                       (*(tc_slot_info[XINE_SCSI_SLOT].intr))
+                       (tc_slot_info[XINE_SCSI_SLOT].unit);
+       
+               if ((intr & XINE_INTR_LANCE) &&
+                       tc_slot_info[XINE_LANCE_SLOT].intr)
+                       (*(tc_slot_info[XINE_LANCE_SLOT].intr))
+                       (tc_slot_info[XINE_LANCE_SLOT].unit);
+       
+               if ((intr & XINE_INTR_SCC_0) &&
+                       tc_slot_info[XINE_SCC0_SLOT].intr)
+                       (*(tc_slot_info[XINE_SCC0_SLOT].intr))
+                       (tc_slot_info[XINE_SCC0_SLOT].unit);
+       
+               if ((intr & XINE_INTR_TC_1) &&
+                       tc_slot_info[1].intr)
+                       (*(tc_slot_info[1].intr))
+                       (tc_slot_info[1].unit);
+       
+               if ((intr & XINE_INTR_DTOP_RX) &&
+                       tc_slot_info[XINE_DTOP_SLOT].intr)
+                       (*(tc_slot_info[XINE_DTOP_SLOT].intr))
+                       (tc_slot_info[XINE_DTOP_SLOT].unit);
+       
        }
        }
+       if (mask & MACH_INT_MASK_2)
+               kn02ba_errintr();
+       return ((statusReg & ~causeReg & MACH_HARD_INT_MASK) |
+               MACH_SR_INT_ENA_CUR);
 }
 
 /*
 }
 
 /*
@@ -1001,7 +1220,10 @@ vmUserUnmap()
 /*
  *----------------------------------------------------------------------
  *
 /*
  *----------------------------------------------------------------------
  *
- * MemErrorInterrupt --
+ * MemErrorInterrupts --
+ *   pmax_errintr - for the DS2100/DS3100
+ *   kn02_errintr - for the DS5000/200
+ *   kn02ba_errintr - for the DS5000/1xx and DS5000/xx
  *
  *     Handler an interrupt for the control register.
  *
  *
  *     Handler an interrupt for the control register.
  *
@@ -1014,26 +1236,67 @@ vmUserUnmap()
  *----------------------------------------------------------------------
  */
 static void
  *----------------------------------------------------------------------
  */
 static void
-MemErrorInterrupt()
+pmax_errintr()
 {
 {
-#ifdef DS3100
-       volatile u_short *sysCSRPtr = (u_short *)MACH_SYS_CSR_ADDR;
+       volatile u_short *sysCSRPtr =
+               (u_short *)MACH_PHYS_TO_UNCACHED(KN01_SYS_CSR);
        u_short csr;
 
        csr = *sysCSRPtr;
 
        u_short csr;
 
        csr = *sysCSRPtr;
 
-       if (csr & MACH_CSR_MEM_ERR) {
+       if (csr & KN01_CSR_MERR) {
                printf("Memory error at 0x%x\n",
                printf("Memory error at 0x%x\n",
-                       *(unsigned *)MACH_WRITE_ERROR_ADDR);
+                       *(unsigned *)MACH_PHYS_TO_UNCACHED(KN01_SYS_ERRADR));
                panic("Mem error interrupt");
        }
                panic("Mem error interrupt");
        }
-       *sysCSRPtr = (csr & ~MACH_CSR_MBZ) | 0xff;
-#endif /* DS3100 */
-#ifdef DS5000
-       printf("erradr %x\n", *(unsigned *)MACH_ERROR_ADDR);
-       *(unsigned *)MACH_ERROR_ADDR = 0;
+       *sysCSRPtr = (csr & ~KN01_CSR_MBZ) | 0xff;
+}
+
+static void
+kn02_errintr()
+{
+
+       printf("erradr %x\n", *(unsigned *)MACH_PHYS_TO_UNCACHED(KN02_SYS_ERRADR));
+       *(unsigned *)MACH_PHYS_TO_UNCACHED(KN02_SYS_ERRADR) = 0;
        MachEmptyWriteBuffer();
        MachEmptyWriteBuffer();
-#endif /* DS5000 */
+}
+
+static void
+kn02ba_errintr()
+{
+       register int mer, adr, siz;
+       static int errintr_cnt = 0;
+
+       siz = *(volatile int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_MSR);
+       mer = *(volatile int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_MER);
+       adr = *(volatile int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_AER);
+
+       /* clear interrupt bit */
+       *(unsigned int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_TIMEOUT) = 0;
+
+       errintr_cnt++;
+       printf("(%d)%s%x [%x %x %x]\n", errintr_cnt,
+              "Bad memory chip at phys ",
+              kn02ba_recover_erradr(adr, mer),
+              mer, siz, adr);
+}
+
+static unsigned
+kn02ba_recover_erradr(phys, mer)
+       register unsigned phys, mer;
+{
+       /* phys holds bits 28:2, mer knows which byte */
+       switch (mer & KMIN_MER_LASTBYTE) {
+       case KMIN_LASTB31:
+               mer = 3; break;
+       case KMIN_LASTB23:
+               mer = 2; break;
+       case KMIN_LASTB15:
+               mer = 1; break;
+       case KMIN_LASTB07:
+               mer = 0; break;
+       }
+       return ((phys & KMIN_AER_ADDR_MASK) | mer);
 }
 
 /*
 }
 
 /*
index 7633e0d..f9254c6 100644 (file)
@@ -8,7 +8,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)turbochannel.h      7.1 (Berkeley) %G%
+ *     @(#)turbochannel.h      7.2 (Berkeley) %G%
  */
 
 /* 
  */
 
 /* 
  *     Definitions for the TURBOchannel BUS.
  */
 
  *     Definitions for the TURBOchannel BUS.
  */
 
+/*
+ * Max conceivable number of slots on the TC
+ */
+#define        TC_MAX_SLOTS            8
+#define        TC_MAX_LOGICAL_SLOTS    12
+
 /*
  * Address map specifications for any TC option
  * These are offset from the option's base address
 /*
  * Address map specifications for any TC option
  * These are offset from the option's base address
@@ -86,9 +92,12 @@ typedef struct {
        u_char  present;                        /* and do we handle it */
        u_char  slot_size;                      /* how many TC slots */
        u_char  rom_width;                      /* bytewide or.. */
        u_char  present;                        /* and do we handle it */
        u_char  slot_size;                      /* how many TC slots */
        u_char  rom_width;                      /* bytewide or.. */
+       u_char  unit;                           /* Device unit number */
        char    module_name[TC_ROM_LLEN+1];     /* ROM name */
        char    module_id[TC_ROM_LLEN * 2+1];   /* vendor and rev */
        char    module_name[TC_ROM_LLEN+1];     /* ROM name */
        char    module_id[TC_ROM_LLEN * 2+1];   /* vendor and rev */
-       caddr_t module_address;                 /* TC starting address */
+       u_long          k1seg_address;          /* TC starting address */
+       char            *driver_name;           /* software name */
+       void            (*intr)();              /* interrupt routine */
 } tc_option_t;
 
 
 } tc_option_t;