diff options
Diffstat (limited to 'sys/arch/mvme88k/dev')
-rw-r--r-- | sys/arch/mvme88k/dev/bugtty.c | 490 | ||||
-rw-r--r-- | sys/arch/mvme88k/dev/clock.c | 109 | ||||
-rw-r--r-- | sys/arch/mvme88k/dev/m88k/bugio.c | 108 | ||||
-rw-r--r-- | sys/arch/mvme88k/dev/mb.c | 87 | ||||
-rw-r--r-- | sys/arch/mvme88k/dev/pcc2.c | 253 | ||||
-rw-r--r-- | sys/arch/mvme88k/dev/pcctwo.c | 252 |
6 files changed, 1299 insertions, 0 deletions
diff --git a/sys/arch/mvme88k/dev/bugtty.c b/sys/arch/mvme88k/dev/bugtty.c new file mode 100644 index 00000000000..48f668a3102 --- /dev/null +++ b/sys/arch/mvme88k/dev/bugtty.c @@ -0,0 +1,490 @@ +/* $NetBSD$ */ + +/* + * Copyright (c) 1995 Dale Rahn. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Dale Rahn. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/ioctl.h> +#include <sys/device.h> +#include <sys/tty.h> +#include <sys/proc.h> +#include <sys/conf.h> +#include <sys/uio.h> +#include <sys/queue.h> +#include <dev/cons.h> + +#include <machine/autoconf.h> +#include <machine/cpu.h> + +#include "bugtty.h" + +int bugttymatch __P((struct device *parent, void *self, void *aux)); +void bugttyattach __P((struct device *parent, struct device *self, void *aux)); + +struct cfdriver bugttycd = { + NULL, "bugtty", bugttymatch, bugttyattach, + DV_TTY, sizeof(struct device) +}; + +/* prototypes */ +int bugttycnprobe __P((struct consdev *cp)); +int bugttycninit __P((struct consdev *cp)); +int bugttycngetc __P((dev_t dev)); +int bugttycnputc __P((dev_t dev, char c)); + +int bugttyopen __P((dev_t dev, int flag, int mode, struct proc *p)); +int bugttyclose __P((dev_t dev, int flag, int mode, struct proc *p)); +int bugttyread __P((dev_t dev, struct uio *uio, int flag)); +int bugttywrite __P((dev_t dev, struct uio *uio, int flag)); +int bugttyioctl __P((dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)); +int bugttystop __P((struct tty *tp, int flag)); + +#define DIALOUT(x) ((x) & 0x80) +#define SWFLAGS(dev) (bugttyswflags | (DIALOUT(dev) ? TIOCFLAG_SOFTCAR : 0)) + +#define BUGBUF 80 +char bugtty_ibuffer[BUGBUF+1]; +volatile char *pinchar = bugtty_ibuffer; +char bug_obuffer[BUGBUF+1]; + +#define bugtty_tty bugttytty +struct tty *bugtty_tty[NBUGTTY]; +int needprom = 1; + +int +bugttymatch(parent, self, aux) + struct device *parent; + void *self; + void *aux; +{ + extern int needprom; + + if (needprom == 0) + return (0); + return (1); +} + +void +bugttyattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + printf("\n"); +} + +#define BUGTTYUNIT(x) ((x) & (0x7f)) +void bugttyoutput __P((struct tty *tp)); + +int bugttydefaultrate = TTYDEF_SPEED; +int bugttyswflags; + +int +bugttymctl(dev, bits, how) + dev_t dev; + int bits, how; +{ + static int settings = TIOCM_DTR | TIOCM_RTS | + TIOCM_CTS | TIOCM_CD | TIOCM_DSR; + int s; + + /*printf("mctl: dev %x, bits %x, how %x,",dev, bits, how);*/ + + /* settings are currently ignored */ + s = spltty(); + switch (how) { + case DMSET: + break; + case DMBIC: + break; + case DMBIS: + break; + case DMGET: + break; + } + (void)splx(s); + + bits = 0; + /* proper defaults? */ + bits |= TIOCM_DTR; + bits |= TIOCM_RTS; + bits |= TIOCM_CTS; + bits |= TIOCM_CD; + /* bits |= TIOCM_RI; */ + bits |= TIOCM_DSR; + + /* printf("retbits %x\n", bits); */ + return (bits); +} + +int +bugttyopen(dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + int s, unit = BUGTTYUNIT(dev); + struct tty *tp; + extern int needprom; + + if (needprom == 0) + return (ENODEV); + + s = spltty(); + if (bugtty_tty[unit]) { + tp = bugtty_tty[unit]; + } else { + tp = bugtty_tty[unit] = ttymalloc(); + } + tp->t_oproc = bugttyoutput; + tp->t_param = NULL; + tp->t_dev = dev; + + if ((tp->t_state & TS_ISOPEN) == 0) { + tp->t_state |= TS_WOPEN; + ttychars(tp); + if (tp->t_ispeed == 0) { + /* + * only when cleared do we reset to defaults. + */ + tp->t_iflag = TTYDEF_IFLAG; + tp->t_oflag = TTYDEF_OFLAG; + tp->t_cflag = TTYDEF_CFLAG; + tp->t_lflag = TTYDEF_LFLAG; + tp->t_ispeed = tp->t_ospeed = bugttydefaultrate; + } + /* bugtty does not have carrier */ + tp->t_cflag |= CLOCAL; + /* + * do these all the time + */ + if (bugttyswflags & TIOCFLAG_CLOCAL) + tp->t_cflag |= CLOCAL; + if (bugttyswflags & TIOCFLAG_CRTSCTS) + tp->t_cflag |= CRTSCTS; + if (bugttyswflags & TIOCFLAG_MDMBUF) + tp->t_cflag |= MDMBUF; + bugttyparam(tp, &tp->t_termios); + ttsetwater(tp); + + (void)bugttymctl(dev, TIOCM_DTR | TIOCM_RTS, DMSET); + /* + if ((SWFLAGS(dev) & TIOCFLAG_SOFTCAR) || + (bugttymctl(dev, 0, DMGET) & TIOCM_CD)) + tp->t_state |= TS_CARR_ON; + else + tp->t_state &= ~TS_CARR_ON; + */ + tp->t_state |= TS_CARR_ON; + } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) { + splx(s); + return (EBUSY); + } + + /* + * if NONBLOCK requested, ignore carrier + */ +/* + if (flag & O_NONBLOCK) + goto done; +*/ + + splx(s); + /* + * Reset the tty pointer, as there could have been a dialout + * use of the tty with a dialin open waiting. + */ + tp->t_dev = dev; + return ((*linesw[tp->t_line].l_open)(dev, tp)); +} + +int +bugttyparam() +{ + return (0); +} + +void +bugttyoutput(tp) + struct tty *tp; +{ + int cc, s, unit, cnt ; + + /* only supports one unit */ + + if ((tp->t_state & TS_ISOPEN) == 0) + return; + + s = spltty(); + cc = tp->t_outq.c_cc; + while (cc > 0) { + cnt = min(BUGBUF, cc); + cnt = q_to_b(&tp->t_outq, bug_obuffer, cnt); + bugoutstr(bug_obuffer, &bug_obuffer[cnt]); + cc -= cnt; + } + splx(s); +} + +int +bugttyclose(dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + int unit = BUGTTYUNIT(dev); + struct tty *tp = bugtty_tty[unit]; + + (*linesw[tp->t_line].l_close)(tp, flag); + + ttyclose(tp); +#if 0 + bugtty_tty[unit] = NULL; +#endif + return (0); +} + +int +bugttyread(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ + struct tty *tp; + + if ((tp = bugtty_tty[BUGTTYUNIT(dev)]) == NULL) + return (ENXIO); + return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); +} + +#if 1 +/* only to be called at splclk() */ +bugtty_chkinput() +{ + struct tty *tp; + + tp = bugtty_tty[0]; /* Kinda ugly hack */ + if (tp == NULL ) + return; + + if (buginstat()) { + while (buginstat()) { + u_char c = buginchr() & 0xff; + (*linesw[tp->t_line].l_rint)(c, tp); + } + /* + wakeup(tp); + */ + } +} +#endif + +int +bugttywrite(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ +#if 0 + /* bypass tty output routines. */ + int i, cnt, s; + int oldoff; + + s = spltty(); + oldoff = uio->uio_offset; + do { + uiomove(bug_obuffer, BUGBUF, uio); + bugoutstr(bug_obuffer, &bug_obuffer[uio->uio_offset - oldoff]); + oldoff = uio->uio_offset; + } while (uio->uio_resid != 0); + splx(s); + + return (0); +#else + struct tty *tp; + if((tp = bugtty_tty[BUGTTYUNIT(dev)]) == NULL) + return (ENXIO); + return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); +#endif +} + +int +bugttyioctl(dev, cmd, data, flag, p) + dev_t dev; + int cmd; + caddr_t data; + int flag; + struct proc *p; +{ + int unit = BUGTTYUNIT(dev); + struct tty *tp = bugtty_tty[unit]; + int error; + + if (!tp) + return (ENXIO); + + error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); + if (error >= 0) + return (error); + + error = ttioctl(tp, cmd, data, flag, p); + if (error >= 0) + return (error); + + switch (cmd) { + case TIOCSBRK: + /* */ + break; + + case TIOCCBRK: + /* */ + break; + + case TIOCSDTR: + (void) bugttymctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIS); + break; + + case TIOCCDTR: + (void) bugttymctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIC); + break; + + case TIOCMSET: + (void) bugttymctl(dev, *(int *) data, DMSET); + break; + + case TIOCMBIS: + (void) bugttymctl(dev, *(int *) data, DMBIS); + break; + + case TIOCMBIC: + (void) bugttymctl(dev, *(int *) data, DMBIC); + break; + + case TIOCMGET: + *(int *)data = bugttymctl(dev, 0, DMGET); + break; + case TIOCGFLAGS: + *(int *)data = SWFLAGS(dev); + break; + case TIOCSFLAGS: + error = suser(p->p_ucred, &p->p_acflag); + if (error != 0) + return (EPERM); + + bugttyswflags = *(int *)data; + bugttyswflags &= /* only allow valid flags */ + (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | TIOCFLAG_CRTSCTS); + break; + default: + return (ENOTTY); + } + + return (0); +} + +int +bugttystop(tp, flag) + struct tty *tp; + int flag; +{ + int s; + + s = spltty(); + if (tp->t_state & TS_BUSY) { + if ((tp->t_state & TS_TTSTOP) == 0) + tp->t_state |= TS_FLUSH; + } + splx(s); + return (0); +} + +/* + * bugtty is the last possible choice for a console device. + */ +int +bugttycnprobe(cp) + struct consdev *cp; +{ + int maj; + extern int needprom; + + if (needprom == 0) { + cp->cn_pri = CN_DEAD; + return (0); + } + +#if 0 + switch (cputyp) { + case CPU_147: + case CPU_162: + cp->cn_pri = CN_NORMAL; + return (0); + default: + break; + } +#else + cp->cn_pri = CN_NORMAL; + return (0); +#endif /* 0 */ + + /* locate the major number */ + for (maj = 0; maj < nchrdev; maj++) + if (cdevsw[maj].d_open == bugttyopen) + break; + + cp->cn_dev = makedev(maj, 0); + cp->cn_pri = CN_NORMAL; + + return (1); +} + +int +bugttycninit(cp) + struct consdev *cp; +{ +} + +int +bugttycngetc(dev) + dev_t dev; +{ + return (buginchr()); +} + +int +bugttycnputc(dev, c) + dev_t dev; + char c; +{ + if (c == '\n') + bugoutchr('\r'); + bugoutchr(c); +} diff --git a/sys/arch/mvme88k/dev/clock.c b/sys/arch/mvme88k/dev/clock.c new file mode 100644 index 00000000000..77b458f2526 --- /dev/null +++ b/sys/arch/mvme88k/dev/clock.c @@ -0,0 +1,109 @@ + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/device.h> +#include <machine/board.h> +#include <machine/bug.h> +#include <machine/pcctworeg.h> + +extern u_int *pcc_io_base; +extern const u_int timer_reload; +void setstatclockrate (int hzrate) +{ +} + +resettodr() +{ +} + +int +hexdectodec(unsigned char n) +{ + + return(((n>>4)&0x0F)*10 + (n&0x0F)); +} + +#define STARTOFTIME 1970 +#define FEBRUARY 2 +#define leapyear(year) (((year)%4==0) && ((year)%100) != 0 || ((year)%400) == 0) +#define days_in_year(year) (leapyear((year)) ? 366 : 365) +#define days_in_month(a) (month_days[(a) - 1]) + +static int month_days[12] = { + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +}; + + +inittodr(time_t base) +{ + struct bugrtc rtc; + u_long sec, min, hour, day, month, year; + u_long i, tmp, timebuf; + + /* ignore suggested time, use realtime clock via bug */ + bugrtcrd(&rtc); + sec = hexdectodec(rtc.s); + min = hexdectodec(rtc.m); + hour = hexdectodec(rtc.H); + day = hexdectodec(rtc.D); + month = hexdectodec(rtc.M); + year = hexdectodec(rtc.Y) + 1900; + + tmp = 0; + for (i = STARTOFTIME; i < year; i++) { + tmp += days_in_year(i); + } + for (i = 1; i < month; i++) { + tmp += days_in_month(i); + } + if (leapyear(year) && month > FEBRUARY) { + tmp++; + } + printf("date yy mm dd hh mm.ss:%02d %02d %02d %02d %02d.%02d:", + year,month,day,hour,min, sec); + tmp += (day -1); + timebuf = (((tmp * 24 + hour) * 60 + min) * 60 + sec); + printf(" epochsec %d\n",timebuf); + time.tv_sec = timebuf; + time.tv_usec = 0; +} + +clkread() +{ +} + +cpu_initclocks() +{ +#if 0 + u_int *io_base; + io_base = 0xfffe1000; /* should really be return of virtmem alloc */ + /* + io_base = pcc_io_base; + */ + /* timer 2 setup */ + PCC_TIMER2_PRE(io_base) = timer_reload; + PCC_TIMER2_CTR(io_base) = 0x7; + PCC_TIMER2_ICR(io_base) = 0x8e; +#endif +} + +/* + * Clock interrupts. + */ +int +clockintr(cap) + void *cap; +{ +#if 0 + volatile register unsigned char icr; + /* clear clock interrupt */ + asm ("ld.b %0,%1" : "=r" (icr) : "" (TIMER2ICR)); + icr |= ICLR; + asm ("st.b %0,%1" : "=r" (icr) : "" (TIMER2ICR)); + + /* read the limit register to clear the interrupt */ +#endif /* 0 */ + hardclock((struct clockframe *)cap); + + return (1); +} diff --git a/sys/arch/mvme88k/dev/m88k/bugio.c b/sys/arch/mvme88k/dev/m88k/bugio.c new file mode 100644 index 00000000000..932614a29d5 --- /dev/null +++ b/sys/arch/mvme88k/dev/m88k/bugio.c @@ -0,0 +1,108 @@ +#include <machine/bugio.h> + +#define INCHR "0x0000" +#define INSTAT "0x0001" +#define INLN "0x0002" +#define READSTR "0x0003" +#define READLN "0x0004" +#define DSKRD "0x0010" +#define DSKWR "0x0011" +#define DSKCFIG "0x0012" +#define OUTCHR "0x0020" +#define OUTSTR "0x0021" +#define PCRLF "0x0026" +#define TMDISP "0x0042" +#define DELAY "0x0043" +#define RTC_DSP "0x0052" +#define RTC_RD "0x0053" +#define RETURN "0x0063" +#define BRD_ID "0x0070" +#define BUGTRAP "0x01F0" + +char +buginchr(void) +{ + register int cc asm("r2"); + asm("or r9,r0," INCHR); + asm("tb0 0,r0,0x1F0"); + /*asm("or %0,r0,r2" : "=r" (cc) : );*/ + return ((char)cc & 0xFF); +} + +/* return 1 if not empty else 0 */ + +buginstat(void) +{ + int ret; + asm("or r9,r0," INSTAT); + asm("tb0 0,r0,0x1F0"); + asm("or %0,r0,r2" : "=r" (ret) : ); + return (ret & 0x40 ? 1 : 0); +} + +bugoutchr(unsigned char c) +{ + unsigned char cc; + + if ((cc = c) == '\n') { + bugpcrlf(); + return; + } + asm("or r2,r0,%0" : : "r" (cc)); + asm("or r9,r0," OUTCHR); + asm("tb0 0,r0,0x1F0"); +} + +bugoutstr(char *s, char *se) +{ + asm("or r9,r0," OUTSTR); + asm("tb0 0,r0,0x1F0"); +} + +bugpcrlf(void) +{ + asm("or r9,r0," PCRLF); + asm("tb0 0,r0,0x1F0"); +} +/* return 0 on success */ + +bugdskrd(struct bugdisk_io *arg) +{ + int ret; + asm("or r9,r0, " DSKRD); + asm("tb0 0,r0,0x1F0"); + asm("or %0,r0,r2" : "=r" (ret) : ); + return ((ret&0x4) == 0x4 ? 1 : 0); +} + +/* return 0 on success */ + +bugdskwr(struct bugdisk_io *arg) +{ + int ret; + asm("or r9,r0, " DSKWR); + asm("tb0 0,r0,0x1F0"); + asm("or %0,r0,r2" : "=r" (ret) : ); + return ((ret&0x4) == 0x4 ? 1 : 0); +} + +bugrtcrd(struct bugrtc *rtc) +{ + asm("or r9,r0, " RTC_RD); + asm("tb0 0,r0,0x1F0"); +} + +bugreturn(void) +{ + asm("or r9,r0, " RETURN); + asm("tb0 0,r0,0x1F0"); +} + +bugbrdid(struct bugbrdid *id) +{ + struct bugbrdid *ptr; + asm("or r9,r0, " BRD_ID); + asm("tb0 0,r0,0x1F0"); + asm("or %0,r0,r2" : "=r" (ptr) : ); + bcopy(ptr, id, sizeof(struct bugbrdid)); +} diff --git a/sys/arch/mvme88k/dev/mb.c b/sys/arch/mvme88k/dev/mb.c new file mode 100644 index 00000000000..2cf934de61f --- /dev/null +++ b/sys/arch/mvme88k/dev/mb.c @@ -0,0 +1,87 @@ +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/reboot.h> +#include <sys/conf.h> +#include <sys/device.h> +#include <sys/disklabel.h> +#include <machine/cpu.h> + +void mbattach __P((struct device *, struct device *, void *)); +int mbprint __P((void *, char *)); +int mbmatch __P((struct device *, struct cfdata *, void *)); +int submatch( struct device *parent, struct cfdata *self, void *aux); + +/* + * mainbus driver + */ +struct cfdriver mainbuscd = { + NULL, "mainbus", mbmatch, mbattach, + DV_DULL, sizeof(struct device), NULL, 0 +}; + +int +mbmatch(pdp, cfp, auxp) + struct device *pdp; + struct cfdata *cfp; + void *auxp; +{ + if (cfp->cf_unit > 0) + return(0); + /* + * We are always here + */ + return(1); +} +/* + * "find" all the things that should be there. + */ +void +mbattach(pdp, dp, auxp) + struct device *pdp, *dp; + void *auxp; +{ + struct cfdata *cf; + extern int machineid; + + /* nothing to do for this bus */ + printf (" machine type %x\n", machineid); + + if ((cf = config_search(submatch, dp, auxp)) != NULL) { + return; + } + +} + +mbprint(auxp, pnp) + void *auxp; + char *pnp; +{ + if (pnp) + printf("%s at %s", (char *)auxp, pnp); + return(UNCONF); +} + +int +submatch(parent, self, aux) + struct device *parent; + struct cfdata *self; + void *aux; +{ + if (!(*self->cf_driver->cd_match)(parent, self, NULL)) { + /* + * STOLEN - BE CAREFUL + * If we don't do this, isa_configure() will repeatedly try to + * probe devices that weren't found. But we need to be careful + * to do it only for the ISA bus, or we would cause things like + * `com0 at ast? slave ?' to not probe on the second ast. + */ + if (!parent) + self->cf_fstate = FSTATE_FOUND; + + return 0; + } + + config_attach(parent, self, NULL, mbprint); + + return 1; +} diff --git a/sys/arch/mvme88k/dev/pcc2.c b/sys/arch/mvme88k/dev/pcc2.c new file mode 100644 index 00000000000..c78cbb24a81 --- /dev/null +++ b/sys/arch/mvme88k/dev/pcc2.c @@ -0,0 +1,253 @@ +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <machine/cpu.h> +#include <machine/pcc2.h> + +int m1x7pccprobe(struct device *parent, struct cfdata *self, void *aux); +void m1x7pccattach(struct device *parent, struct device *self, void *aux); + +int abort_handler(); +extern void abort_intrv(); +extern void pcc_intrv(); +extern int intrh_debug; +extern int machineid; +extern void badtrap(); +extern int submatch( struct device *parent, struct cfdata *self, void *aux); +/* static */ u_int *pcc_io_base; +static u_int *pcc_vector_base; + +static void abort_setup(); +void timer2_intr(); + +struct pcctwosoftc { + struct device sc_dev; + caddr_t sc_vaddr; + caddr_t sc_paddr; + struct pcctworeg *sc_pcc2; +}; + +void pcctwoattach __P((struct device *, struct device *, void *)); +int pcctwoprobe __P((struct device *, void *, void *)); +int pcctwoabort __P((struct frame *)); + +struct cfdriver pcctwocd = { + NULL, "pcctwo", pcctwomatch, pcctwoattach, + DV_DULL, sizeof(struct pcctwosoftc), 0 +}; + +struct pcctworeg *sys_pcc2 = NULL; + +int +pcctwomatch(struct device *parent, struct cfdata *self, void *aux) +{ +#if defined(__m88k__) + if (machineid == 0x187) { + return 1; + } +#endif + return 0; +} + +void +pcctwoattach(struct device *parent, struct device *self, void *aux) +{ + struct cfdata *cf; + volatile char *ibvr; /* Interrupt Base Vector Register */ + u_int ibv; /* Interrupt Base Vector, offset from vbr */ + u_int *iv; /* interupt vector */ + int i; + u_int vector_base; + + /* attach memory mapped io space */ + /* map 0xfffe1000 - 0xfffe102f, 0xfffe2800 */ + /* ppc_io_base = mmio(0xfffe1000, 1800, PG_RW|PG_CI); */ + pcc_io_base = 0xfffe1000; /* should really be return of virtmem alloc */ + /* set PCC vector base */ + ibv = PCC_IBVR(pcc_io_base) & 0xf0; + ibvr = &PCC_IBVR(pcc_io_base); + printf("pcc:ibvr %x *ibvr %x ibv %x\n",ibvr,*ibvr, ibv); + pcc_vector_base = (u_int *)ibv; + asm volatile ("movec vbr,%0": "=d" (vector_base)); + printf("pcc:vector_base %x\n",vector_base); + /* register "standard interupt handlers */ + + abort_setup(); + iv = (u_int *)(vector_base + (ibv * 4)); +printf("iv %x\n",iv); + for (i = 0; i <= SOFT2_VECTOR; i++) { + iv[i] = (u_int)pcc_intrv; + } + /* + timer2_setup(); + */ + iv = (u_int *)(vector_base + (ibv + TICK2_VECTOR) * 4); + *iv = (u_int)&pcc_intrv; + +#ifdef DEBUG + if (intrh_debug) + pr_intrh(); +#endif + if ((cf = config_search(submatch, self, aux)) != NULL) { + return; + } + return ; +} +asm (" .text"); +asm (" .global _pcc_intrv"); +asm ("_pcc_intrv:"); +asm (" link a6,#0"); +asm (" movml a0/a1/d0/d1,sp@-"); +asm (" movel a6,a0"); +asm (" addql #4,a0"); +asm (" movel a0,sp@-"); +asm (" jbsr _pcc_handler"); +asm (" addql #4,sp"); +asm (" movml sp@+,a0/a1/d0/d1"); +asm (" unlk a6"); +asm (" jra rei"); + +asm (" .global _abort_intrv"); +asm ("_abort_intrv:"); +asm (" movml a0/a1/d0/d1,sp@-"); +asm (" jbsr _abort_handler"); +asm (" movml sp@+,a0/a1/d0/d1"); +asm (" jra rei"); +/* asm (" .previous"); */ + +void *m147le_arg; +void +pcc_handler(struct exception_frame *except) +{ + u_int vector; + int handled = 0; + +#if 0 + printf("except %x\n",except); + printf("sr %x\n",except->sr); + printf("pc %x\n",except->pc); + printf("type %x\n",except->type); +#endif + vector = except->vo; +/* printf("vector %x\n",vector); */ + vector = (vector/4 - (u_int)pcc_vector_base); +/* printf("vector %x\n",vector); */ + + switch (vector) { + case AC_FAIL_VECTOR: + printf("ac_fail vector\n"); + break; + case BERR_VECTOR: + printf("berr vector\n"); + printf("pcc_handler:invalid vector %x\n",vector); + break; + case ABORT_VECTOR: + printf("abort vector\n"); + abort_handler(); + handled = 1; + break; + case SERIAL_VECTOR: + printf("serial vector\n"); + PCC_SERIAL_ICR(0xfffe1000) = 0; + break; + case LANCE_VECTOR: + leintr(m147le_arg); + handled = 1; + break; + case SCSIPORT_VECTOR: + printf("scsiport vector\n"); + m147sc_scintr(); + break; + case SCSIDMA_VECTOR: + printf("scsidma vector\n"); + m147sc_dmaintr(); + break; + case PRINTER_VECTOR: + printf("printer vector\n"); + break; + case TICK1_VECTOR: + printf("tick1 vector\n"); + printf("pcc_handler:invalid vector %x\n",vector); + break; + case TICK2_VECTOR: + timer2_intr(except); + handled = 1; + break; + case SOFT1_VECTOR: + printf("soft1 vector\n"); + break; + case SOFT2_VECTOR: + printf("soft2 vector\n"); + break; + default: + printf("pcc_handler:invalid vector %x\n",vector); + } + + if (handled == 0) { + printf("except %x\n",except); + printf("sr %x\n",except->sr); + printf("pc %x\n",except->pc); + printf("type %x\n",except->type); + } +} + + +int +abort_handler() +{ + printf("aicr = 0x%x\n",PCC_ABRT_ICR(pcc_io_base)); + PCC_ABRT_ICR(pcc_io_base) = 0x88; + printf("aicr = 0x%x\n",PCC_ABRT_ICR(pcc_io_base)); + Debugger(); + return 0; +} +static void abort_setup() +{ + printf("PCC_ABRT_ICR %x\n",&PCC_ABRT_ICR(pcc_io_base)); + printf("aicr = 0x%x\n",PCC_ABRT_ICR(pcc_io_base)); + PCC_ABRT_ICR(pcc_io_base) = 0x88; + printf("aicr = 0x%x\n",PCC_ABRT_ICR(pcc_io_base)); +} + +/* timer2 (clock) driver */ + +/*const u_int timer_reload = 0; /* .4096 sec ? */ +/* const u_int timer_reload = 62870; 1/60 sec ? */ +const u_int timer_reload = 63936; /* 1/100 sec ? */ + +#if 0 +void +timer2_setup() +{ + u_int *io_base; + pcc_io_base = 0xfffe1000; /* should really be return of virtmem alloc */ + io_base = pcc_io_base; + printf("pcc_io_base %x io_base %x\n",pcc_io_base, io_base); + printf("PCC_TIMER2_PRE %x\n",&PCC_TIMER2_PRE(io_base)); + printf("PCC_TIMER2_CTR %x\n",&PCC_TIMER2_CTR(io_base)); + printf("PCC_TIMER2_ICR %x\n",&PCC_TIMER2_ICR(io_base)); + PCC_TIMER2_PRE(io_base) = timer_reload; + PCC_TIMER2_CTR(io_base) = 0x7; + PCC_TIMER2_ICR(io_base) = 0x8e; +} +#endif +void +timer2_intr(struct exception_frame *except) +{ + u_int *io_base; + pcc_io_base = 0xfffe1000; /* should really be return of virtmem alloc */ + io_base = pcc_io_base; + + if (0x80 && PCC_TIMER2_ICR(io_base)) { + PCC_TIMER2_ICR(io_base) = 0x8e; + /* hardclock(); */ + hardclock(except); + + } else { + printf("timer2_intr: vector called without interrupt\n"); + } + /* REALLY UGLY HACK */ + bugtty_chkinput(); + + return; +} diff --git a/sys/arch/mvme88k/dev/pcctwo.c b/sys/arch/mvme88k/dev/pcctwo.c new file mode 100644 index 00000000000..be4fc02be6a --- /dev/null +++ b/sys/arch/mvme88k/dev/pcctwo.c @@ -0,0 +1,252 @@ +/* $NetBSD$ */ + +/* + * Copyright (c) 1995 Theo de Raadt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Theo de Raadt + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * VME16x PCC2 chip + */ +#include <sys/param.h> +#include <sys/conf.h> +#include <sys/ioctl.h> +#include <sys/proc.h> +#include <sys/user.h> +#include <sys/tty.h> +#include <sys/uio.h> +#include <sys/callout.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/syslog.h> +#include <sys/fcntl.h> +#include <sys/device.h> +#include <machine/cpu.h> +#include <machine/autoconf.h> +#include <dev/cons.h> +#include <mvme68k/mvme68k/isr.h> + +#include <mvme68k/dev/pcctworeg.h> + +struct pcctwosoftc { + struct device sc_dev; + caddr_t sc_vaddr; + caddr_t sc_paddr; + struct pcctworeg *sc_pcc2; + struct intrhand sc_nmiih; +}; + +void pcctwoattach __P((struct device *, struct device *, void *)); +int pcctwomatch __P((struct device *, void *, void *)); +int pcctwoabort __P((struct frame *)); + +struct cfdriver pcctwocd = { + NULL, "pcctwo", pcctwomatch, pcctwoattach, + DV_DULL, sizeof(struct pcctwosoftc), 0 +}; + +struct pcctworeg *sys_pcc2 = NULL; + +struct intrhand *pcctwointrs[PCC2_NVEC]; + +int +pcctwomatch(parent, vcf, args) + struct device *parent; + void *vcf, *args; +{ + struct cfdata *cf = vcf; + struct confargs *ca = args; + struct pcctworeg *pcc2; + + /* the PCC2 only exists on MVME16x's except the 162, right? */ + if (cputyp == CPU_162 || cputyp == CPU_147) + return (0); + pcc2 = (struct pcctworeg *)(IIOV(ca->ca_paddr) + PCC2_PCC2CHIP_OFF); + if (badbaddr(pcc2)) + return (0); + if (pcc2->pcc2_chipid != PCC2_CHIPID) + return (0); + return (1); +} + +int +pcctwo_print(args, bus) + void *args; + char *bus; +{ + struct confargs *ca = args; + + printf(" offset 0x%x", ca->ca_offset); + if (ca->ca_ipl > 0) + printf(" ipl %d", ca->ca_ipl); + return (UNCONF); +} + +int +pcctwo_scan(parent, child, args) + struct device *parent; + void *child, *args; +{ + struct cfdata *cf = child; + struct pcctwosoftc *sc = (struct pcctwosoftc *)parent; + struct confargs *ca = args; + struct confargs oca; + + if (parent->dv_cfdata->cf_driver->cd_indirect) { + printf(" indirect devices not supported\n"); + return 0; + } + + bzero(&oca, sizeof oca); + oca.ca_paddr = sc->sc_paddr + cf->cf_loc[0]; + if (ISIIOVA(sc->sc_vaddr + cf->cf_loc[0])) + oca.ca_vaddr = sc->sc_vaddr + cf->cf_loc[0]; + else + oca.ca_vaddr = (caddr_t)-1; + oca.ca_offset = cf->cf_loc[0]; + oca.ca_ipl = cf->cf_loc[1]; + oca.ca_bustype = BUS_PCCTWO; + oca.ca_master = (void *)sc->sc_pcc2; + oca.ca_name = cf->cf_driver->cd_name; + if ((*cf->cf_driver->cd_match)(parent, cf, &oca) == 0) + return (0); + config_attach(parent, cf, &oca, pcctwo_print); + return (1); +} + +void +pcctwoattach(parent, self, args) + struct device *parent, *self; + void *args; +{ + struct confargs *ca = args; + struct pcctwosoftc *sc = (struct pcctwosoftc *)self; + extern u_long vectab[], pcctwotrap; + int i; + + if (sys_pcc2) + panic("pcc2 already attached!"); + + /* + * since we know ourself to land in intiobase land, + * we must adjust our address + */ + sc->sc_paddr = ca->ca_paddr; + sc->sc_vaddr = (caddr_t)IIOV(sc->sc_paddr); + sc->sc_pcc2 = (struct pcctworeg *)(sc->sc_vaddr + PCC2_PCC2CHIP_OFF); + sys_pcc2 = sc->sc_pcc2; + + printf(": rev %d\n", sc->sc_pcc2->pcc2_chiprev); + + /* + * make the PCCTWO interrupt range point to the pcc2 trap routine. + */ + for (i = 0; i < PCC2_NVEC; i++) { + vectab[PCC2_VECBASE+i] = (u_long)&pcctwotrap; + } + + sc->sc_pcc2->pcc2_genctl |= PCC2_GENCTL_IEN; /* global irq enable */ + + sys_pcc2->pcc2_gpioirq = PCC2_GPIO_PLTY | PCC2_IRQ_IEN | 0x7;/*lvl7*/ + sys_pcc2->pcc2_gpio = 0; /* do not turn on CR_O or CR_OE */ + sc->sc_nmiih.ih_fn = pcctwoabort; + sc->sc_nmiih.ih_arg = 0; + sc->sc_nmiih.ih_lvl = 7; + sc->sc_nmiih.ih_wantframe = 1; + /*sc->sc_mc->mc_abort .... enable at ipl 7 */ + pcctwointr_establish(PCC2V_GPIO, &sc->sc_nmiih); + + sc->sc_pcc2->pcc2_vecbase = PCC2_VECBASE; + config_search(pcctwo_scan, self, args); +} + +#ifndef PCCTWOINTR_ASM +/* + * pcctwointr: called from locore with the PC and evec from the trap frame. + */ +int +pcctwointr(pc, evec, frame) + int pc; + int evec; + void *frame; +{ + int vec = (evec & 0xfff) >> 2; /* XXX should be m68k macro? */ + extern u_long intrcnt[]; /* XXX from locore */ + struct intrhand *ih; + int r; + + vec = vec & 0xf; + if (vec >= PCC2_NVEC) + goto bail; + + cnt.v_intr++; + for (ih = pcctwointrs[vec]; ih; ih = ih->ih_next) { + if (ih->ih_wantframe) + r = (*ih->ih_fn)(frame); + else + r = (*ih->ih_fn)(ih->ih_arg); + if (r > 0) + return; + } +bail: + return (straytrap(pc, evec)); +} +#endif /* !PCCTWOINTR_ASM */ + +/* + * pcctwointr_establish: establish pcctwo interrupt + */ +int +pcctwointr_establish(vec, ih) + int vec; + struct intrhand *ih; +{ + if (vec >= PCC2_NVEC) { + printf("pcctwo: illegal vector: 0x%x\n", vec); + panic("pcctwointr_establish"); + } + + /* XXX should attach at tail */ + ih->ih_next = pcctwointrs[vec]; + pcctwointrs[vec] = ih; +} +int +pcctwoabort(frame) + struct frame *frame; +{ +#ifdef REALLY_CARE_ABOUT_DEBOUNCE + /* wait for it to debounce */ + while (sys_pcc2->pcc2_abortirq & PCC2_ABORT_ABS) + ; +#endif + + sys_pcc2->pcc2_gpioirq = sys_pcc2->pcc2_gpioirq | PCC2_IRQ_ICLR; + + nmihand(frame); + return (1); +} |