home *** CD-ROM | disk | FTP | other *** search
/ Between Heaven & Hell 2 / BetweenHeavenHell.cdr / 500 / 471 / rccl133 < prev    next >
Text File  |  1987-03-02  |  10KB  |  376 lines

  1. #if NDRC > 0
  2. /*
  3.  *  Cidmac Robot  FIFO driver
  4.  *
  5.  *  After doing a successful open on this device, the user process
  6.  *  must fill in the "drcROBOT" structure (in drc.h) and "write"
  7.  *  it to this device. The structure includes Read buffer, count,
  8.  *  write buffer (the count is the first word) and the address of
  9.  *  a user interrupt routine which gets executed on a Dr11-c interrupt
  10.  *  after the buffer is read from the Dr11-c and placed directly
  11.  *  in user memory. After executing the user routine, the data in
  12.  *  the output buffer is written back to the Dr11-c. Doing ANY syscalls
  13.  *  from the user interrupt routine IS PROHIBITED!!! and will crash
  14.  *  the system with a "CHM? ERROR".  Also the user interrupt routine
  15.  *  has full R/W access to kernel memory and any traps, aborts, or
  16.  *  other faults will result in a system crash.  Care should be
  17.  *  taken not to write to any address with bit 31 set (80XXXXXX)
  18.  *  since this is the kernel. (The stack is here though, so don't
  19.  *  put very much stuff there). No syscalls are used to R/W this
  20.  *  device once the initial write is done since they are too slow.
  21.  *  The kernel interrupt routine handles it all from previously
  22.  *  specified parameters.
  23.  *  On any Dr11-c error, a uprintf() is issued to the controlling
  24.  *  tty and the console and the user process is sent a SIGHUP signal
  25.  *  since there is no means of returning an error.
  26.  *
  27.  *  Warning: This driver needs the file close code in sys1.c/exit()
  28.  *  moved up before the code to release memory.  Also many unorthodox
  29.  *  things are used here to gain speed for a realtime environment
  30.  *  like running a user routine in kernel mode on the intstk and
  31.  *  skipping protection, etc, etc.  Anybody who uses this driver
  32.  *  must be checked out in ROOT privelidges and system startup/
  33.  *  shutdown/realtime procedures.  This driver must take an interrupt
  34.  *  every 7 milliseconds (1/2 tick) and let the user routine run for
  35.  *  5 milliseconds.  This must be used in a single user enivornment.
  36.  *  Also any process with this device open, must NOT FORK(), VFORK(),
  37.  *  EXEC(), or do anything with raw I/O or which expands the data or
  38.  *  stack regions (like break() or growing the stack). Also the "open"
  39.  *  of this driver must be followed by a "write(fd, &drcROBOT, sizeof drcROBOT)"
  40.  *  to load initial parameters (should have used ioctl instead).
  41.  *  None of the parameters is checked (except for the write being done)
  42.  *  for validity.  Failure to heed the warnings will result in system
  43.  *  crashes.  Good luck.
  44.  *  --ghg 1/14/82.
  45.  *
  46.  *    added minor device number for stanford arm 30 Oct 84 BUCK
  47.  */
  48. int drcdebug = 0;
  49.  
  50. #include <sys/param.h>
  51. #include <sys/systm.h>
  52. #include <sys/tty.h>
  53. #include <vax/pte.h>
  54. #include <h/map.h>
  55. #include <h/buf.h>
  56. #include <vaxuba/ubareg.h>
  57. #include <vaxuba/ubavar.h>
  58. #include <h/conf.h>
  59. #include <vax/mtpr.h>
  60. #include <h/dir.h>
  61. #include <h/user.h>
  62. #include <h/proc.h>
  63. #include "drc.h"
  64.  
  65. #define PUMA
  66. #ifdef PUMA
  67. #define    ROBOT        0    /* minor device of Puma robot */
  68. #endif
  69.  
  70. #ifdef STAN
  71. #define    ROBOT        1    /* minor device of Stanford robot */
  72. #endif
  73.  
  74. #define    DRC_DELAY    50000    /* spin loop timeout */
  75.  
  76. #define    DRC_CSR0    010000    /* bit 0 (to user dev) */
  77. #define    DRC_CSR1    020000    /* bit 1 (to user dev) */
  78. #define    DRC_INT        01    /* INTER other cpu */
  79. #define    DRC_IEA        0100    /* INTER Enable A */
  80. #define    DRC_REQA    040000    /* REQ A line from user dev */
  81. #define    DRC_REQB    0100000    /* REQ B line from user dev */
  82. #define    FIFO_EMPTY    0200
  83.  
  84.  
  85. struct drc_softc {
  86.     int    sc_openf;
  87.     struct    tty *sc_ttyp;
  88.     int    sc_nice;
  89.     struct    proc *sc_procp;    /* proc with this dev open */
  90.     caddr_t    sc_rbuf;    /* read buffer address */
  91.     int    sc_rcount;    /* byte count */
  92.     caddr_t    sc_wbuf;    /* write buffer address */
  93.     int    sc_P0BR;    /* This proc's P0BR, P0LR, P1BR, P1LR */
  94.     int    sc_P0LR;
  95.     int    sc_P1BR;
  96.     int    sc_P1LR;
  97.     int    sc_setup;    /* nz of setup complete */
  98.     int    (*sc_routine)();/* address of user interrupt routine */
  99.     int    (*sc_routine2)();/* address of user interrupt routine2 */
  100.     int    sc_vslocked;    /* number of bytes locked down */
  101. } drc_softc[NDRC];
  102.  
  103. struct drcdevice {
  104.     u_short    drccsr;
  105.     u_short    drcbuf;
  106. };
  107.  
  108. int    drcprobe(), drcattach(), drcintr();
  109. struct    uba_device *drcdinfo[NDRC];
  110. u_short    drcstd[] = { 0 };
  111. struct    uba_driver drcdriver =
  112.     { drcprobe, 0, drcattach, 0, drcstd, "drc", drcdinfo };
  113.  
  114. #define    DRCUNIT(dev)    (minor(dev))
  115.  
  116. drcprobe(reg)
  117.     caddr_t reg;
  118. {
  119.     register int br, cvec;
  120.     register struct drcdevice *drcaddr = (struct drcdevice *)reg;
  121.  
  122. /*
  123.     drcaddr->drccsr = DRC_IEA|DRC_IEB;
  124.     DELAY(10000);
  125.     drcaddr->drccsr = 0;
  126. */
  127.     br = 0x16;
  128.     cvec = 0140;
  129. }
  130.  
  131. /*ARGSUSED*/
  132. drcattach(ui)
  133.     register struct uba_device *ui;
  134. {
  135.  
  136. }
  137.  
  138. drcopen(dev)
  139.     dev_t dev;
  140. {
  141.     register struct drc_softc *sc;
  142.     register struct uba_device *ui;
  143.     register struct drcdevice *drcaddr;
  144.     register i, junk;
  145.  
  146.     if (DRCUNIT(dev) >= NDRC || (ui = drcdinfo[DRCUNIT(dev)]) == 0 ||
  147.         ui->ui_alive == 0 || (sc = &drc_softc[DRCUNIT(dev)])->sc_openf) {
  148.         u.u_error = ENXIO;
  149.         return;
  150.     }
  151.     drcaddr = (struct drcdevice *)ui->ui_addr;
  152.     sc->sc_procp = u.u_procp;    /* used for signals later */
  153.     sc->sc_ttyp = u.u_ttyp;        /* controlling terminal for error mes */
  154.     sc->sc_nice = u.u_procp->p_nice;
  155.     u.u_procp->p_nice = 1;
  156.     sc->sc_openf = 1;
  157.     sc->sc_setup = 0;
  158.     sc->sc_vslocked = 0;
  159.     drcaddr->drccsr = 0;
  160.     /*
  161.      * Suck the FIFO dry first... Give up after 1024 since
  162.      * it will be a hardware problem.
  163.      */
  164.     i = 0;
  165.     while ((drcaddr->drccsr & FIFO_EMPTY) == 0) {
  166.         junk = drcaddr->drcbuf;
  167.         if (i++ > 1024) {
  168.             uprintf("Robot FIFO hung full -- hardware problems\n");
  169.             drcclose(dev);
  170.             u.u_error = EIO;
  171.             break;
  172.         }
  173.     }
  174. }
  175.  
  176. drcclose(dev)
  177.     dev_t dev;
  178. {
  179.     register struct drc_softc *sc = &drc_softc[DRCUNIT(dev)];
  180.     register struct drcdevice *drcaddr =
  181.         (struct drcdevice *)drcdinfo[DRCUNIT(dev)]->ui_addr;
  182.  
  183.     
  184.     drcaddr->drccsr = 0;
  185.     sc->sc_setup = 0;
  186.     if (sc->sc_vslocked)
  187.         vsunlock(0, sc->sc_vslocked);
  188.     u.u_procp->p_flag &= ~SLOCK;
  189.     sc->sc_procp = (struct proc *) 0;
  190.     sc->sc_ttyp = (struct tty *) 0;
  191.     u.u_procp->p_nice = sc->sc_nice;
  192.     drc_softc[DRCUNIT(dev)].sc_openf = 0;
  193. }
  194.  
  195. drcread(dev)
  196. {
  197.  
  198.     u.u_error = ENXIO;
  199. }
  200.  
  201. /*
  202.  * For now, the write routine just inits the sc struct from
  203.  * a user supplied drcrobot...
  204.  */
  205. drcwrite(dev)
  206.     dev_t dev;
  207. {
  208.     register struct drc_softc *sc = &drc_softc[DRCUNIT(dev)];
  209.     register struct drcdevice *drcaddr =
  210.         (struct drcdevice *)drcdinfo[DRCUNIT(dev)]->ui_addr;
  211.     struct drcROBOT drcROBOT;
  212.  
  213.     if (copyin(u.u_base, &drcROBOT, sizeof (struct drcROBOT))) {
  214.         u.u_error = EFAULT;
  215.         return;
  216.     }
  217.     sc->sc_routine = drcROBOT.R_routine;
  218.     sc->sc_routine2 = drcROBOT.R_routine2;
  219.     sc->sc_rbuf = drcROBOT.R_rbuf;
  220.     sc->sc_wbuf = drcROBOT.R_wbuf;
  221.  
  222.     /*
  223.      * Lock down all the pages in text + data region
  224.      */
  225.  
  226.  
  227.     sc->sc_vslocked = ctob(u.u_tsize + u.u_dsize);
  228. if(drcdebug)
  229. printf("locking down %d bytes\n", sc->sc_vslocked);
  230.     vslock(0, sc->sc_vslocked);
  231.     u.u_procp->p_flag |= SLOCK;    /* lock in core */
  232.     sc->sc_P0BR = mfpr(P0BR);
  233.     sc->sc_P0LR = mfpr(P0LR);
  234.     sc->sc_P1BR = mfpr(P1BR);
  235.     sc->sc_P1LR = mfpr(P1LR);
  236.     sc->sc_setup = 1;
  237.     drcaddr->drccsr = DRC_IEA;
  238.  
  239.     u.u_base += sizeof (struct drcROBOT);
  240.     u.u_count -= sizeof (struct drcROBOT);
  241.  
  242. }
  243.  
  244. drcintr(dev)
  245.     dev_t dev;
  246. {
  247.     int c;
  248.     register struct drc_softc *sc = &drc_softc[DRCUNIT(dev)];
  249.     register struct drcdevice *drcaddr =
  250.         (struct drcdevice *)drcdinfo[DRCUNIT(dev)]->ui_addr;
  251.     register count;
  252.     register short *fp = (short *)&drcaddr->drcbuf;
  253.     register short *sp = (short *)sc->sc_rbuf;
  254.     int oldP0BR, oldP0LR, oldP1BR, oldP1LR;
  255.  
  256.  
  257. if(drcdebug)
  258. printf("I%d\n",dev);
  259.     
  260.     spl7();
  261.     /*
  262.      * Save current user-page table pointer
  263.      * and switch to user (P0,P1 region) page
  264.      * table mapping for the process running
  265.      * the robot, run his signal routine, and switch
  266.      * back P0BR and P0LR to this proc.
  267.      * This is playing with FIRE !!
  268.      * THIS IS VAX-11/780 MACHINE DEPENDENT !!!!
  269.      * ("Kentucky" process switch)
  270.      */
  271.     oldP0BR = mfpr(P0BR);
  272.     oldP0LR = mfpr(P0LR);
  273.     oldP1BR = mfpr(P1BR);
  274.     oldP1LR = mfpr(P1LR);
  275.     mtpr(P0BR, sc->sc_P0BR);
  276.     mtpr(P0LR, sc->sc_P0LR);
  277.     mtpr(P1BR, sc->sc_P1BR);
  278.     mtpr(P0BR, sc->sc_P0BR);
  279.     mtpr(TBIA, 0);    /* Invalidate translation buffer */
  280.     if (drcaddr->drccsr&FIFO_EMPTY) {    /* spur intr */
  281.         uprintf("Spur Robot interrupt\n");
  282.         sc->sc_setup = 0;    /* blow him away */
  283.         goto out;
  284.     }
  285.     if (sc->sc_routine) {
  286.         count = (int) (short) *fp;
  287.         if (count < 0 || count > 63) {
  288.             int i, junk;
  289.  
  290.             uprintf("Bad robot count: 0%o\n", count);
  291.             while ((drcaddr->drccsr & FIFO_EMPTY) == 0) {
  292.                 junk = drcaddr->drcbuf;
  293.                 if (i++ > 1024) {
  294.                     uprintf("Robot FIFO hung full -- hardware problems\n");
  295.                     sc->sc_setup = 0;/* blow him away */
  296.                     goto out;
  297.                 }
  298.             }
  299.             sc->sc_setup = 0;    /* blow him away */
  300.             goto out;
  301.         }
  302.         *sp++ = count;
  303.         while (count--)
  304.             *sp++  = *fp;    /* suck it all out */
  305.  
  306.         if ((drcaddr->drccsr & FIFO_EMPTY) == 0) {
  307.             uprintf("drcintr: FIFO not empty\n");
  308.             sc->sc_setup = 0;    /* blow him away */
  309.         }
  310.         (*sc->sc_routine)();
  311.         sp = (short *) sc->sc_wbuf;
  312.         *fp = count = *sp++;
  313.         while (count--)
  314.             *fp = *sp++;
  315.         if (sc->sc_routine2)
  316.             (*sc->sc_routine2)();
  317.     } else
  318.         uprintf("No user interrupt routine\n");
  319. out:
  320.     mtpr(P0BR, oldP0BR);
  321.     mtpr(P0LR, oldP0LR);
  322.     mtpr(P1BR, oldP1BR);
  323.     mtpr(P1LR, oldP1LR);
  324.     mtpr(TBIA, 0);
  325.     if (!sc->sc_setup) {
  326.         drcaddr->drccsr = 0;    /* Clear IENB */
  327.         if (sc->sc_procp)
  328.             psignal(sc->sc_procp, SIGHUP);    /* blow him away */
  329.     }
  330. }
  331.  
  332. drcreset()
  333. {
  334. }
  335.  
  336. drcioctl()
  337. {
  338. }
  339.  
  340. #ifdef notdef
  341. drchung(dev, s, interrupt)
  342. register dev_t dev;
  343. register char *s;
  344. int interrupt;
  345. {
  346.     register struct drc_softc *sc = &drc_softc[DRCUNIT(dev)];
  347.     register struct drcdevice *drcaddr =
  348.         (struct drcdevice *)drcdinfo[DRCUNIT(dev)]->ui_addr;
  349.     register pri;
  350.     struct tty *savettyp;
  351.  
  352.     interrupt = 1; /* for now */
  353.     if (interrupt) {
  354.         pri = spl7();
  355.         savettyp = u.u_ttyp;
  356.         u.u_ttyp = sc->sc_ttyp;
  357.     }
  358.     uprintf("DR11C Hung, Csr: 0%o, Ob: 0%o, Ib: 0%o %s\n",
  359.         drcaddr->drccsr, drcaddr->drcobuf, drcaddr->drcibuf, s);
  360.     
  361.     if (interrupt) {
  362.         u.u_ttyp = savettyp;
  363.         sc->sc_setup = 0;    /* abort this device */
  364.         splx(pri);
  365.     } else {
  366.         u.u_error = EIO;
  367.     }
  368.  
  369.     printf("DR11C Hung, Csr: 0%o, Ob: 0%o, Ib: 0%o %s\n",
  370.         drcaddr->drccsr, drcaddr->drcobuf, drcaddr->drcibuf, s);
  371.  
  372. }
  373. #endif
  374.  
  375. #endif
  376.