home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / C / ROBOT01.ZIP / RCCL075 < prev    next >
Encoding:
Text File  |  1987-03-02  |  11.8 KB  |  468 lines

  1. #include "drc.h"
  2. #if NDRC > 0
  3. /*
  4.  *  Cidmac Robot  DR11C 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.  */
  48. int drcdebug = 0;
  49.  
  50. #include "../h/param.h"
  51. #include "../h/systm.h"
  52. #include "../h/tty.h"
  53. #include "../h/pte.h"
  54. #include "../h/map.h"
  55. #include "../h/buf.h"
  56. #include "../h/ubareg.h"
  57. #include "../h/ubavar.h"
  58. #include "../h/conf.h"
  59. #include "../h/mtpr.h"
  60. #include "../h/dir.h"
  61. #include "../h/user.h"
  62. #include "../h/proc.h"
  63.  
  64. #include "../h/drc.h"
  65.  
  66. #define    ROBOT        0    /* minor device of robot project */
  67. #define    DRC_DELAY    50000    /* spin loop timeout */
  68.  
  69. #define    DRC_CSR0    01    /* CSR bit 0 (to user dev) */
  70. #define    DRC_CSR1    02    /* CSR bit 1 (to user dev) */
  71. #define    DRC_IEB        040    /* INTER Enable B */
  72. #define    DRC_IEA        0100    /* INTER Enable A */
  73. #define    DRC_REQA    0200    /* REQ A line from user dev */
  74. #define    DRC_REQB    0100000    /* REQ B line from user dev */
  75.  
  76.  
  77. struct drc_softc {
  78.     int    sc_openf;
  79.     struct    tty *sc_ttyp;
  80.     int    sc_nice;
  81.     struct    proc *sc_procp;    /* proc with this dev open */
  82.     caddr_t    sc_rbuf;    /* read buffer address */
  83.     int    sc_rcount;    /* byte count */
  84.     caddr_t    sc_wbuf;    /* write buffer address */
  85.     int    sc_P0BR;    /* This proc's P0BR, P0LR, P1BR, P1LR */
  86.     int    sc_P0LR;
  87.     int    sc_P1BR;
  88.     int    sc_P1LR;
  89.     int    sc_setup;    /* nz of setup complete */
  90.     int    (*sc_routine)();/* address of user interrupt routine */
  91.     int    (*sc_routine2)();/* address of user interrupt routine2 */
  92.     int    sc_vslocked;    /* number of bytes locked down */
  93. } drc_softc[NDRC];
  94.  
  95. struct drcdevice {
  96.     u_short    drccsr;
  97.     u_short    drcobuf;
  98.     u_short    drcibuf;
  99. };
  100.  
  101. int    drcprobe(), drcattach(), drcintr();
  102. struct    uba_device *drcdinfo[NDRC];
  103. u_short    drcstd[] = { 0 };
  104. struct    uba_driver drcdriver =
  105.     { drcprobe, 0, drcattach, 0, drcstd, "drc", drcdinfo };
  106.  
  107. #define    DRCUNIT(dev)    (minor(dev))
  108.  
  109. drcprobe(reg)
  110.     caddr_t reg;
  111. {
  112.     register int br, cvec;
  113.     register struct drcdevice *drcaddr = (struct drcdevice *)reg;
  114.  
  115. /*
  116.     drcaddr->drccsr = DRC_IEA|DRC_IEB;
  117.     DELAY(10000);
  118.     drcaddr->drccsr = 0;
  119. */
  120.     br = 0x16;
  121.     cvec = 0310;
  122.     if (((int)reg & 077) == 070)
  123.         cvec = 0300;    /* VOMIT */
  124. }
  125.  
  126. /*ARGSUSED*/
  127. drcattach(ui)
  128.     register struct uba_device *ui;
  129. {
  130.  
  131. }
  132.  
  133. drcopen(dev)
  134.     dev_t dev;
  135. {
  136.     register struct drc_softc *sc;
  137.     register struct uba_device *ui;
  138.     register struct drcdevice *drcaddr;
  139.  
  140.     if (DRCUNIT(dev) >= NDRC || (ui = drcdinfo[DRCUNIT(dev)]) == 0 ||
  141.         ui->ui_alive == 0 || (sc = &drc_softc[DRCUNIT(dev)])->sc_openf) {
  142.         u.u_error = ENXIO;
  143.         return;
  144.     }
  145.     drcaddr = (struct drcdevice *)ui->ui_addr;
  146.     sc->sc_procp = u.u_procp;    /* used for signals later */
  147.     sc->sc_ttyp = u.u_ttyp;        /* controlling terminal for error mes */
  148.     sc->sc_nice = u.u_procp->p_nice;
  149.     u.u_procp->p_nice = 1;
  150.     sc->sc_openf = 1;
  151.     sc->sc_setup = 0;
  152.     sc->sc_vslocked = 0;
  153.     drcaddr->drccsr = 0;
  154. }
  155.  
  156. drcclose(dev)
  157.     dev_t dev;
  158. {
  159.     register struct drc_softc *sc = &drc_softc[DRCUNIT(dev)];
  160.     register struct drcdevice *drcaddr =
  161.         (struct drcdevice *)drcdinfo[DRCUNIT(dev)]->ui_addr;
  162.  
  163.     
  164.     drcaddr->drccsr = 0;
  165.     sc->sc_setup = 0;
  166.     if (sc->sc_vslocked)
  167.         vsunlock(0, sc->sc_vslocked);
  168.     u.u_procp->p_flag &= ~SLOCK;
  169.     sc->sc_procp = (struct proc *) 0;
  170.     sc->sc_ttyp = (struct tty *) 0;
  171.     u.u_procp->p_nice = sc->sc_nice;
  172.     drc_softc[DRCUNIT(dev)].sc_openf = 0;
  173. }
  174.  
  175. drcread(dev)
  176. {
  177.  
  178.     u.u_error = ENXIO;
  179. }
  180.  
  181. /*
  182.  * For now, the write routine just inits the sc struct from
  183.  * a user supplied drcrobot...
  184.  */
  185. drcwrite(dev)
  186.     dev_t dev;
  187. {
  188.     register struct drc_softc *sc = &drc_softc[DRCUNIT(dev)];
  189.     register struct drcdevice *drcaddr =
  190.         (struct drcdevice *)drcdinfo[DRCUNIT(dev)]->ui_addr;
  191.     struct drcROBOT drcROBOT;
  192.  
  193.     if (copyin(u.u_base, &drcROBOT, sizeof (struct drcROBOT))) {
  194.         u.u_error = EFAULT;
  195.         return;
  196.     }
  197.     sc->sc_routine = drcROBOT.R_routine;
  198.     sc->sc_routine2 = drcROBOT.R_routine2;
  199.     sc->sc_rbuf = drcROBOT.R_rbuf;
  200.     sc->sc_rcount = drcROBOT.R_rcount;
  201.     sc->sc_wbuf = drcROBOT.R_wbuf;
  202.  
  203.     /*
  204.      * Lock down all the pages in text + data region
  205.      */
  206.  
  207.  
  208.     sc->sc_vslocked = ctob(u.u_tsize + u.u_dsize);
  209. if(drcdebug)
  210. printf("locking down %d bytes\n", sc->sc_vslocked);
  211.     vslock(0, sc->sc_vslocked);
  212.     u.u_procp->p_flag |= SLOCK;    /* lock in core */
  213.     sc->sc_P0BR = mfpr(P0BR);
  214.     sc->sc_P0LR = mfpr(P0LR);
  215.     sc->sc_P1BR = mfpr(P1BR);
  216.     sc->sc_P1LR = mfpr(P1LR);
  217.     sc->sc_setup = 1;
  218.     drcaddr->drccsr = DRC_IEA|DRC_IEB;
  219.  
  220.     u.u_base += sizeof (struct drcROBOT);
  221.     u.u_count -= sizeof (struct drcROBOT);
  222.  
  223. }
  224. drcWRITE(dev)
  225.     dev_t dev;
  226. {
  227.     register struct drc_softc *sc = &drc_softc[DRCUNIT(dev)];
  228.     register struct drcdevice *drcaddr =
  229.         (struct drcdevice *)drcdinfo[DRCUNIT(dev)]->ui_addr;
  230.     register short *sp = (short *)sc->sc_wbuf;
  231.     register count = *sp++ / sizeof (short);
  232.     int c;
  233.  
  234.     switch (DRCUNIT(dev)) {
  235.  
  236.     case ROBOT:
  237.  
  238.         while (count--) {
  239.             drcaddr->drcobuf = *sp++;
  240.             drcaddr->drccsr = DRC_CSR0;
  241.             c = DRC_DELAY;
  242.             while ((drcaddr->drccsr & DRC_REQA) == 0) {
  243.                 if (--c == 0) {
  244.                     drchung(dev,"SET REQA (write)",0);
  245.                     goto out;
  246.                 }
  247.             }
  248.             drcaddr->drccsr = 0;
  249.             c = DRC_DELAY;
  250.             while (drcaddr->drccsr & DRC_REQA) {
  251.                 if (--c == 0) {
  252.                     drchung(dev,"CLR REQA (write)",0);
  253.                     goto out;
  254.                 }
  255.             }
  256.                 
  257.         }
  258.         /*
  259.          * Indicate end of transfer
  260.          */
  261.  
  262.         c = DRC_DELAY;
  263. if (drcdebug)
  264. uprintf("write done\n");
  265.         drcaddr->drccsr = DRC_CSR0 | DRC_CSR1;
  266.         while ((drcaddr->drccsr & DRC_REQB) == 0) {
  267.             if (--c == 0) {
  268.                 drchung(dev,"SET REQB (write)",0);
  269.                 goto out;
  270.             }
  271.         }
  272.         drcaddr->drccsr = 0;
  273.         c = DRC_DELAY;
  274.         while (drcaddr->drccsr & DRC_REQB) {
  275.             if (--c == 0) {
  276.                 drchung(dev,"CLR REQB (write)",0);
  277.                 goto out;
  278.             }
  279.         }
  280.         break;
  281.  
  282.     default:
  283.         /* this is ineffecient and sucks */
  284. if (drcdebug)
  285. uprintf("default case\n");
  286.         break;
  287.  
  288.     }
  289. out:  ;
  290. }
  291.  
  292. drcREAD(dev)
  293.     register dev_t dev;
  294. {
  295.     register struct drc_softc *sc = &drc_softc[DRCUNIT(dev)];
  296.     register struct drcdevice *drcaddr =
  297.         (struct drcdevice *)drcdinfo[DRCUNIT(dev)]->ui_addr;
  298.     register short *sp = (short *)sc->sc_rbuf;
  299.     register count = sc->sc_rcount;
  300.     int c;
  301.  
  302.     switch (DRCUNIT(dev)) {
  303.  
  304.     case ROBOT:
  305.  
  306.         count /= sizeof (short);
  307.         count++;
  308.         while (count--) {
  309.             c = DRC_DELAY;
  310.             while ((drcaddr->drccsr & (DRC_REQA|DRC_REQB)) == 0) {
  311.                 if (--c == 0) {
  312.                     drchung(dev,"SET REQA (read)",0);
  313.                     goto out;
  314.                 }
  315.             }
  316.             if (drcaddr->drccsr & DRC_REQB) {
  317. if (drcdebug)
  318. uprintf("read EOF\n");
  319.                 /*
  320.                  * End of transfer
  321.                  */
  322.                 drcaddr->drccsr = DRC_CSR1;
  323.                 c = DRC_DELAY;
  324.                 while (drcaddr->drccsr & DRC_REQB) {
  325.                     if (--c == 0) {
  326.                         drchung(dev,"CLR REQB (read)",0);
  327.                         goto out;
  328.                     }
  329.                 }
  330.                 drcaddr->drccsr = 0;
  331.                 return;
  332.                 /* all done */
  333.  
  334.             }
  335.             *sp++  = drcaddr->drcibuf;
  336.             drcaddr->drccsr = DRC_CSR0;
  337.             c = DRC_DELAY;
  338.             while (drcaddr->drccsr & DRC_REQA) {
  339.                 if (--c == 0) {
  340.                     drchung(dev,"SET REQA (read)",0);
  341.                     goto out;
  342.                 }
  343.             }
  344.             drcaddr->drccsr = 0;
  345.         }
  346.         break;
  347.  
  348.     default:
  349. if (drcdebug)
  350. uprintf("default case2\n");
  351.         break;
  352.  
  353.     }
  354. out:  ;
  355.     drcaddr->drccsr = 0;
  356. }
  357.  
  358. drcintr(dev)
  359.     dev_t dev;
  360. {
  361.     int c;
  362.     register struct drc_softc *sc = &drc_softc[DRCUNIT(dev)];
  363.     register struct drcdevice *drcaddr =
  364.         (struct drcdevice *)drcdinfo[DRCUNIT(dev)]->ui_addr;
  365.     register s;
  366.     int oldP0BR, oldP0LR, oldP1BR, oldP1LR;
  367.  
  368.  
  369. if(drcdebug)
  370. printf("I%d\n",dev);
  371.     
  372.     drcaddr->drccsr = DRC_CSR1;
  373.     c = DRC_DELAY;
  374.     while (drcaddr->drccsr & DRC_REQB) {
  375.         if (--c == 0) {
  376.             drchung(dev, "CLR REQB (interrupt)",1);
  377.         }
  378.     }
  379.     drcaddr->drccsr = 0;
  380.     if (!sc->sc_setup) {
  381.         drchung(dev, "Driver not properly setup", 1);
  382.         return;
  383.     }
  384.     s = spl7();
  385.     /*
  386.      * Save current user-page table pointer
  387.      * and switch to user (P0,P1 region) page
  388.      * table mapping for the process running
  389.      * the robot, run his signal routine, and switch
  390.      * back P0BR and P0LR to this proc.
  391.      * This is playing with FIRE !!
  392.      * THIS IS VAX-11/780 MACHINE DEPENDENT !!!!
  393.      * ("Kentucky" process switch)
  394.      */
  395.     oldP0BR = mfpr(P0BR);
  396.     oldP0LR = mfpr(P0LR);
  397.     oldP1BR = mfpr(P1BR);
  398.     oldP1LR = mfpr(P1LR);
  399.     mtpr(P0BR, sc->sc_P0BR);
  400.     mtpr(P0LR, sc->sc_P0LR);
  401.     mtpr(P1BR, sc->sc_P1BR);
  402.     mtpr(P0BR, sc->sc_P0BR);
  403.     mtpr(TBIA, 0);    /* Invalidate translation buffer */
  404.     if (sc->sc_routine) {
  405.         drcREAD(dev);
  406.         (*sc->sc_routine)();
  407.         drcWRITE(dev);
  408.         if (sc->sc_routine2)
  409.             (*sc->sc_routine2)();
  410.         drcaddr->drccsr = DRC_IEA|DRC_IEB;
  411.     } else
  412.         uprintf("No user interrupt routine\n");
  413.     mtpr(P0BR, oldP0BR);
  414.     mtpr(P0LR, oldP0LR);
  415.     mtpr(P1BR, oldP1BR);
  416.     mtpr(P1LR, oldP1LR);
  417.     mtpr(TBIA, 0);
  418.     splx(s);
  419.     if (!sc->sc_setup) {
  420.         drcaddr->drccsr = 0;    /* Clear IENB */
  421.         if (sc->sc_procp)
  422.             psignal(sc->sc_procp, SIGHUP);    /* blow him away */
  423.     }
  424. }
  425.  
  426. drcreset()
  427. {
  428. }
  429.  
  430. drcioctl()
  431. {
  432. }
  433.  
  434. drchung(dev, s, interrupt)
  435. register dev_t dev;
  436. register char *s;
  437. int interrupt;
  438. {
  439.     register struct drc_softc *sc = &drc_softc[DRCUNIT(dev)];
  440.     register struct drcdevice *drcaddr =
  441.         (struct drcdevice *)drcdinfo[DRCUNIT(dev)]->ui_addr;
  442.     register pri;
  443.     struct tty *savettyp;
  444.  
  445.     interrupt = 1; /* for now */
  446.     if (interrupt) {
  447.         pri = spl7();
  448.         savettyp = u.u_ttyp;
  449.         u.u_ttyp = sc->sc_ttyp;
  450.     }
  451.     uprintf("DR11C Hung, Csr: 0%o, Ob: 0%o, Ib: 0%o %s\n",
  452.         drcaddr->drccsr, drcaddr->drcobuf, drcaddr->drcibuf, s);
  453.     
  454.     if (interrupt) {
  455.         u.u_ttyp = savettyp;
  456.         sc->sc_setup = 0;    /* abort this device */
  457.         splx(pri);
  458.     } else {
  459.         u.u_error = EIO;
  460.     }
  461.  
  462.     printf("DR11C Hung, Csr: 0%o, Ob: 0%o, Ib: 0%o %s\n",
  463.         drcaddr->drccsr, drcaddr->drcobuf, drcaddr->drcibuf, s);
  464.  
  465. }
  466.  
  467. #endif
  468.