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

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