home *** CD-ROM | disk | FTP | other *** search
- #include "drc.h"
- #if NDRC > 0
- /*
- * Cidmac Robot FIFO driver
- *
- * After doing a successful open on this device, the user process
- * must fill in the "drcROBOT" structure (in drc.h) and "write"
- * it to this device. The structure includes Read buffer, count,
- * write buffer (the count is the first word) and the address of
- * a user interrupt routine which gets executed on a Dr11-c interrupt
- * after the buffer is read from the Dr11-c and placed directly
- * in user memory. After executing the user routine, the data in
- * the output buffer is written back to the Dr11-c. Doing ANY syscalls
- * from the user interrupt routine IS PROHIBITED!!! and will crash
- * the system with a "CHM? ERROR". Also the user interrupt routine
- * has full R/W access to kernel memory and any traps, aborts, or
- * other faults will result in a system crash. Care should be
- * taken not to write to any address with bit 31 set (80XXXXXX)
- * since this is the kernel. (The stack is here though, so don't
- * put very much stuff there). No syscalls are used to R/W this
- * device once the initial write is done since they are too slow.
- * The kernel interrupt routine handles it all from previously
- * specified parameters.
- * On any Dr11-c error, a uprintf() is issued to the controlling
- * tty and the console and the user process is sent a SIGHUP signal
- * since there is no means of returning an error.
- *
- * Warning: This driver needs the file close code in sys1.c/exit()
- * moved up before the code to release memory. Also many unorthodox
- * things are used here to gain speed for a realtime environment
- * like running a user routine in kernel mode on the intstk and
- * skipping protection, etc, etc. Anybody who uses this driver
- * must be checked out in ROOT privelidges and system startup/
- * shutdown/realtime procedures. This driver must take an interrupt
- * every 7 milliseconds (1/2 tick) and let the user routine run for
- * 5 milliseconds. This must be used in a single user enivornment.
- * Also any process with this device open, must NOT FORK(), VFORK(),
- * EXEC(), or do anything with raw I/O or which expands the data or
- * stack regions (like break() or growing the stack). Also the "open"
- * of this driver must be followed by a "write(fd, &drcROBOT, sizeof drcROBOT)"
- * to load initial parameters (should have used ioctl instead).
- * None of the parameters is checked (except for the write being done)
- * for validity. Failure to heed the warnings will result in system
- * crashes. Good luck.
- * --ghg 1/14/82.
- *
- * added minor device number for stanford arm 30 Oct 84 BUCK
- */
- int drcdebug = 0;
-
- #include "../h/param.h"
- #include "../h/systm.h"
- #include "../h/tty.h"
- #include "../h/pte.h"
- #include "../h/map.h"
- #include "../h/buf.h"
- #include "../h/ubareg.h"
- #include "../h/ubavar.h"
- #include "../h/conf.h"
- #include "../h/mtpr.h"
- #include "../h/dir.h"
- #include "../h/user.h"
- #include "../h/proc.h"
-
- #include "../h/drc.h"
-
- #define PUMA
- #ifdef PUMA
- #define ROBOT 0 /* minor device of Puma robot */
- #endif
-
- #ifdef STAN
- #define ROBOT 1 /* minor device of Stanford robot */
- #endif
-
- #define DRC_DELAY 50000 /* spin loop timeout */
-
- #define DRC_CSR0 010000 /* bit 0 (to user dev) */
- #define DRC_CSR1 020000 /* bit 1 (to user dev) */
- #define DRC_INT 01 /* INTER other cpu */
- #define DRC_IEA 0100 /* INTER Enable A */
- #define DRC_REQA 040000 /* REQ A line from user dev */
- #define DRC_REQB 0100000 /* REQ B line from user dev */
- #define FIFO_EMPTY 0200
-
-
- struct drc_softc {
- int sc_openf;
- struct tty *sc_ttyp;
- int sc_nice;
- struct proc *sc_procp; /* proc with this dev open */
- caddr_t sc_rbuf; /* read buffer address */
- int sc_rcount; /* byte count */
- caddr_t sc_wbuf; /* write buffer address */
- int sc_P0BR; /* This proc's P0BR, P0LR, P1BR, P1LR */
- int sc_P0LR;
- int sc_P1BR;
- int sc_P1LR;
- int sc_setup; /* nz of setup complete */
- int (*sc_routine)();/* address of user interrupt routine */
- int (*sc_routine2)();/* address of user interrupt routine2 */
- int sc_vslocked; /* number of bytes locked down */
- } drc_softc[NDRC];
-
- struct drcdevice {
- u_short drccsr;
- u_short drcbuf;
- };
-
- int drcprobe(), drcattach(), drcintr();
- struct uba_device *drcdinfo[NDRC];
- u_short drcstd[] = { 0 };
- struct uba_driver drcdriver =
- { drcprobe, 0, drcattach, 0, drcstd, "drc", drcdinfo };
-
- #define DRCUNIT(dev) (minor(dev))
-
- drcprobe(reg)
- caddr_t reg;
- {
- register int br, cvec;
- register struct drcdevice *drcaddr = (struct drcdevice *)reg;
-
- /*
- drcaddr->drccsr = DRC_IEA|DRC_IEB;
- DELAY(10000);
- drcaddr->drccsr = 0;
- */
- br = 0x16;
- cvec = 0140;
- }
-
- /*ARGSUSED*/
- drcattach(ui)
- register struct uba_device *ui;
- {
-
- }
-
- drcopen(dev)
- dev_t dev;
- {
- register struct drc_softc *sc;
- register struct uba_device *ui;
- register struct drcdevice *drcaddr;
- register i, junk;
-
- if (DRCUNIT(dev) >= NDRC || (ui = drcdinfo[DRCUNIT(dev)]) == 0 ||
- ui->ui_alive == 0 || (sc = &drc_softc[DRCUNIT(dev)])->sc_openf) {
- u.u_error = ENXIO;
- return;
- }
- drcaddr = (struct drcdevice *)ui->ui_addr;
- sc->sc_procp = u.u_procp; /* used for signals later */
- sc->sc_ttyp = u.u_ttyp; /* controlling terminal for error mes */
- sc->sc_nice = u.u_procp->p_nice;
- u.u_procp->p_nice = 1;
- sc->sc_openf = 1;
- sc->sc_setup = 0;
- sc->sc_vslocked = 0;
- drcaddr->drccsr = 0;
- /*
- * Suck the FIFO dry first... Give up after 1024 since
- * it will be a hardware problem.
- */
- i = 0;
- while ((drcaddr->drccsr & FIFO_EMPTY) == 0) {
- junk = drcaddr->drcbuf;
- if (i++ > 1024) {
- uprintf("Robot FIFO hung full -- hardware problems\n");
- drcclose(dev);
- u.u_error = EIO;
- break;
- }
- }
- }
-
- drcclose(dev)
- dev_t dev;
- {
- register struct drc_softc *sc = &drc_softc[DRCUNIT(dev)];
- register struct drcdevice *drcaddr =
- (struct drcdevice *)drcdinfo[DRCUNIT(dev)]->ui_addr;
-
-
- drcaddr->drccsr = 0;
- sc->sc_setup = 0;
- if (sc->sc_vslocked)
- vsunlock(0, sc->sc_vslocked);
- u.u_procp->p_flag &= ~SLOCK;
- sc->sc_procp = (struct proc *) 0;
- sc->sc_ttyp = (struct tty *) 0;
- u.u_procp->p_nice = sc->sc_nice;
- drc_softc[DRCUNIT(dev)].sc_openf = 0;
- }
-
- drcread(dev)
- {
-
- u.u_error = ENXIO;
- }
-
- /*
- * For now, the write routine just inits the sc struct from
- * a user supplied drcrobot...
- */
- drcwrite(dev)
- dev_t dev;
- {
- register struct drc_softc *sc = &drc_softc[DRCUNIT(dev)];
- register struct drcdevice *drcaddr =
- (struct drcdevice *)drcdinfo[DRCUNIT(dev)]->ui_addr;
- struct drcROBOT drcROBOT;
-
- if (copyin(u.u_base, &drcROBOT, sizeof (struct drcROBOT))) {
- u.u_error = EFAULT;
- return;
- }
- sc->sc_routine = drcROBOT.R_routine;
- sc->sc_routine2 = drcROBOT.R_routine2;
- sc->sc_rbuf = drcROBOT.R_rbuf;
- sc->sc_wbuf = drcROBOT.R_wbuf;
-
- /*
- * Lock down all the pages in text + data region
- */
-
-
- sc->sc_vslocked = ctob(u.u_tsize + u.u_dsize);
- if(drcdebug)
- printf("locking down %d bytes\n", sc->sc_vslocked);
- vslock(0, sc->sc_vslocked);
- u.u_procp->p_flag |= SLOCK; /* lock in core */
- sc->sc_P0BR = mfpr(P0BR);
- sc->sc_P0LR = mfpr(P0LR);
- sc->sc_P1BR = mfpr(P1BR);
- sc->sc_P1LR = mfpr(P1LR);
- sc->sc_setup = 1;
- drcaddr->drccsr = DRC_IEA;
-
- u.u_base += sizeof (struct drcROBOT);
- u.u_count -= sizeof (struct drcROBOT);
-
- }
-
- drcintr(dev)
- dev_t dev;
- {
- int c;
- register struct drc_softc *sc = &drc_softc[DRCUNIT(dev)];
- register struct drcdevice *drcaddr =
- (struct drcdevice *)drcdinfo[DRCUNIT(dev)]->ui_addr;
- register count;
- register short *fp = (short *)&drcaddr->drcbuf;
- register short *sp = (short *)sc->sc_rbuf;
- int oldP0BR, oldP0LR, oldP1BR, oldP1LR;
-
-
- if(drcdebug)
- printf("I%d\n",dev);
-
- spl7();
- /*
- * Save current user-page table pointer
- * and switch to user (P0,P1 region) page
- * table mapping for the process running
- * the robot, run his signal routine, and switch
- * back P0BR and P0LR to this proc.
- * This is playing with FIRE !!
- * THIS IS VAX-11/780 MACHINE DEPENDENT !!!!
- * ("Kentucky" process switch)
- */
- oldP0BR = mfpr(P0BR);
- oldP0LR = mfpr(P0LR);
- oldP1BR = mfpr(P1BR);
- oldP1LR = mfpr(P1LR);
- mtpr(P0BR, sc->sc_P0BR);
- mtpr(P0LR, sc->sc_P0LR);
- mtpr(P1BR, sc->sc_P1BR);
- mtpr(P0BR, sc->sc_P0BR);
- mtpr(TBIA, 0); /* Invalidate translation buffer */
- if (drcaddr->drccsr&FIFO_EMPTY) { /* spur intr */
- uprintf("Spur Robot interrupt\n");
- sc->sc_setup = 0; /* blow him away */
- goto out;
- }
- if (sc->sc_routine) {
- count = (int) (short) *fp;
- if (count < 0 || count > 63) {
- int i, junk;
-
- uprintf("Bad robot count: 0%o\n", count);
- while ((drcaddr->drccsr & FIFO_EMPTY) == 0) {
- junk = drcaddr->drcbuf;
- if (i++ > 1024) {
- uprintf("Robot FIFO hung full -- hardware problems\n");
- sc->sc_setup = 0;/* blow him away */
- goto out;
- }
- }
- sc->sc_setup = 0; /* blow him away */
- goto out;
- }
- *sp++ = count;
- while (count--)
- *sp++ = *fp; /* suck it all out */
-
- if ((drcaddr->drccsr & FIFO_EMPTY) == 0) {
- uprintf("drcintr: FIFO not empty\n");
- sc->sc_setup = 0; /* blow him away */
- }
- (*sc->sc_routine)();
- sp = (short *) sc->sc_wbuf;
- *fp = count = *sp++;
- while (count--)
- *fp = *sp++;
- if (sc->sc_routine2)
- (*sc->sc_routine2)();
- } else
- uprintf("No user interrupt routine\n");
- out:
- mtpr(P0BR, oldP0BR);
- mtpr(P0LR, oldP0LR);
- mtpr(P1BR, oldP1BR);
- mtpr(P1LR, oldP1LR);
- mtpr(TBIA, 0);
- if (!sc->sc_setup) {
- drcaddr->drccsr = 0; /* Clear IENB */
- if (sc->sc_procp)
- psignal(sc->sc_procp, SIGHUP); /* blow him away */
- }
- }
-
- drcreset()
- {
- }
-
- drcioctl()
- {
- }
-
- #ifdef notdef
- drchung(dev, s, interrupt)
- register dev_t dev;
- register char *s;
- int interrupt;
- {
- register struct drc_softc *sc = &drc_softc[DRCUNIT(dev)];
- register struct drcdevice *drcaddr =
- (struct drcdevice *)drcdinfo[DRCUNIT(dev)]->ui_addr;
- register pri;
- struct tty *savettyp;
-
- interrupt = 1; /* for now */
- if (interrupt) {
- pri = spl7();
- savettyp = u.u_ttyp;
- u.u_ttyp = sc->sc_ttyp;
- }
- uprintf("DR11C Hung, Csr: 0%o, Ob: 0%o, Ib: 0%o %s\n",
- drcaddr->drccsr, drcaddr->drcobuf, drcaddr->drcibuf, s);
-
- if (interrupt) {
- u.u_ttyp = savettyp;
- sc->sc_setup = 0; /* abort this device */
- splx(pri);
- } else {
- u.u_error = EIO;
- }
-
- printf("DR11C Hung, Csr: 0%o, Ob: 0%o, Ib: 0%o %s\n",
- drcaddr->drccsr, drcaddr->drcobuf, drcaddr->drcibuf, s);
-
- }
- #endif
-
- #endif
-