home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Distributions / ucb / 2.9-derivatives / 2.9-pro350 / sys-dev / ra.c < prev    next >
Encoding:
C/C++ Source or Header  |  1985-02-26  |  16.4 KB  |  747 lines

  1. #include "ra.h"
  2. #if NRA > 0
  3. /*
  4.  * Ms disk driver for UDA50/RDQX1 controllers.
  5.  * Notes: The macro SWAPW(a) interchanges the words of a long. This is
  6.  * necessary since the controllers expect the low order word of a long
  7.  * to be first. Ok for a vax, but not for the pdp11. The type "shorts"
  8.  * is also used to simplify reference to the 32 bit fields for the
  9.  * controller that require the low order word first.
  10.  * This driver has not been tested on a UDA50, but should work since
  11.  * it was written using UDA50 doc. It works fine with the RQDX1 on the
  12.  * Qbus. The only area that may be a problem is with the UNIBUS_MAP, but
  13.  * I think the code is Ok.
  14.  *
  15.  * Restrictions:
  16.  *    Unit numbers must be less than 8.
  17.  *
  18.  * TO DO:
  19.  *    write dump code
  20.  */
  21. #include <sys/param.h>
  22. #include <sys/systm.h>
  23. #include <sys/buf.h>
  24. #include <sys/conf.h>
  25. #include <sys/dir.h>
  26. #include <sys/user.h>
  27. #ifndef INTRLVE
  28. #include <sys/inline.h>
  29. #endif
  30. #include <sys/map.h>
  31. #include <sys/vm.h>
  32.  
  33. /* This value is adequate for the RQDX1 but should be increased to 4 or
  34.  * 5 for the UDA50. This is because the credit limit is 4 for the RQDX1
  35.  * and about 22 for the current UDA50 rev.
  36.  * Note: changing the number of packets is only for performance enhancement.
  37.  */
  38. #define    NRSPL2    2        /* log2 number of response packets */
  39. #define    NCMDL2    2        /* log2 number of command packets */
  40. #define    NRSP    (1<<NRSPL2)
  41. #define    NCMD    (1<<NCMDL2)
  42. #include <sys/rareg.h>
  43.  
  44. /* This should probably be in seg.h */
  45. #ifdef    KERN_NONSEP
  46. #ifndef       ENABLE34
  47. #define          KDSA0    ((u_short *) 0172340)
  48. #else
  49. #define       KDSA0    ((u_short *) 0163700)
  50. #endif
  51. #else
  52. #ifndef    ENABLE34
  53. #define          KDSA0    ((u_short *) 0172360)
  54. #else
  55. #define       KDSA0    ((u_short *) 0163760)
  56. #endif
  57. #endif
  58.  
  59. struct ra_softc {
  60.     short    sc_state;    /* state of controller */
  61.     short    sc_mapped;    /* Unibus map allocated for ra struct? */
  62.     short    sc_ivec;    /* interrupt vector address */
  63.     short    sc_credits;    /* transfer credits */
  64.     short    sc_lastcmd;    /* pointer into command ring */
  65.     short    sc_lastrsp;    /* pointer into response ring */
  66.     short    sc_onlin;    /* flags for drives online */
  67. } ra_softc;
  68.  
  69. /*
  70.  * Controller states
  71.  */
  72. #define    S_IDLE    0        /* hasn't been initialized */
  73. #define    S_STEP1    1        /* doing step 1 init */
  74. #define    S_STEP2    2        /* doing step 2 init */
  75. #define    S_STEP3    3        /* doing step 3 init */
  76. #define    S_SCHAR    4        /* doing "set controller characteristics" */
  77. #define    S_RUN    5        /* running */
  78.  
  79. struct ra {
  80.     struct raca    ra_ca;        /* communications area */
  81.     struct ms    ra_rsp[NRSP];    /* response packets */
  82.     struct ms    ra_cmd[NCMD];    /* command packets */
  83. } ra;
  84.  
  85. int    raerr = 0;            /* causes hex dump of packets */
  86.  
  87. daddr_t    radsize[NRA];            /* disk size, from ONLINE end packet */
  88. struct    ms *ragetcp();
  89. extern struct size ra_sizes[];
  90. extern struct radevice *RAADDR;
  91.  
  92. #ifdef UCB_DBUFS
  93. struct    buf rrabuf[NRA];
  94. #else
  95. struct    buf rrabuf;
  96. #endif
  97. struct    buf ratab;
  98. struct    buf rautab[NRA];
  99. struct    buf rawtab;            /* I/O wait queue, per controller */
  100. struct    buf ramap;
  101.  
  102. #define    b_qsize        b_resid        /* queue size per drive, in rautab */
  103.  
  104. void raroot()
  105. {
  106.     raattach(RAADDR, 0);
  107. }
  108.  
  109. raattach(addr, unit)
  110. struct radevice *addr;
  111. {
  112.     if (unit == 0) {
  113.         RAADDR = addr;
  114.         return(1);
  115.     }
  116.     return(0);
  117. }
  118.  
  119. /*
  120.  * Open an RA.  Initialize the device and
  121.  * set the unit online.
  122.  */
  123. raopen(dev)
  124.     dev_t dev;
  125. {
  126.     register int unit;
  127.     register struct ra_softc *sc;
  128.  
  129.     unit = minor(dev) >> 3;
  130.     if (unit >= NRA || (RAADDR == (struct radevice *)NULL)) {
  131.         u.u_error = ENXIO;
  132.         return;
  133.     }
  134.     sc = &ra_softc;
  135.     (void) _spl4();
  136.     if (sc->sc_state != S_RUN) {
  137.         if (sc->sc_state == S_IDLE)
  138.             rainit();
  139.         /* wait for initialization to complete */
  140.         sleep((caddr_t)sc, PZERO+1);
  141.         if (sc->sc_state != S_RUN) {
  142.             u.u_error = EIO;
  143.             return;
  144.         }
  145.     }
  146.     /* If the unit is not ONLINE, do it */
  147.     if ((sc->sc_onlin & (1<<unit)) == 0) {
  148.         int i;
  149.         struct buf *dp;
  150.         struct ms *mp;
  151.         dp = &rautab[unit];
  152.         if ((sc->sc_credits < 2) || ((mp = ragetcp()) == NULL)) {
  153.             u.u_error = EIO;
  154.             return;
  155.         }
  156.         sc->sc_credits--;
  157.         mp->ms_opcode = M_OP_ONLIN;
  158.         mp->ms_unit = unit;
  159.         dp->b_active = 2;
  160.         ratab.b_active++;
  161.         mp->ms_dscptr->high |= RA_OWN|RA_INT;
  162.         i = RAADDR->raip;
  163.         sleep((caddr_t)sc, PZERO+1);
  164.         if ((sc->sc_onlin & (1<<unit)) == 0||sc->sc_state != S_RUN) {
  165.             u.u_error = EIO;
  166.             return;
  167.         }
  168.     }
  169.     (void) _spl0();
  170. }
  171.  
  172. /*
  173.  * Initialize an RA.  Set up UB mapping registers,
  174.  * initialize data structures, and start hardware
  175.  * initialization sequence.
  176.  */
  177. rainit()
  178. {
  179.     register struct ra_softc *sc;
  180.     register struct ra *rap;
  181.  
  182.     sc = &ra_softc;
  183.     sc->sc_ivec = RA_IVEC;
  184.     ratab.b_active++;
  185.     rap = &ra;
  186.     /* Get physical addr. of comm. area and map to Unibus Virtual as
  187.      * required. This is only done once after boot.
  188.      */
  189.     if (sc->sc_mapped == 0) {
  190.         long addr;
  191.         /* Convert Kernel virtual to physical. Not too sure if this
  192.          * code is OK for an ENABLE34.
  193.          * Currently essentially a noop for 2.9 since kernel virtual
  194.          * equals physical data addresses, but just in case this
  195.          * changes?
  196.          */
  197.         addr = (long) KDSA0[(((unsigned)rap)>>13)&07];
  198.         addr <<= 6;
  199.         addr += (long) (((unsigned) rap) & 017777);
  200.         ramap.b_un.b_addr = loint(addr);
  201.         ramap.b_xmem = hiint(addr);
  202. #ifdef UNIBUS_MAP
  203.         /* Map physical to Unibus virtual via. mapalloc() as req. */
  204.         ramap.b_flags = B_PHYS;
  205.         ramap.b_bcount = (sizeof)ra;
  206.         mapalloc(&ramap);
  207. #endif
  208.         sc->sc_mapped = 1;
  209.     }
  210.  
  211.     /*
  212.      * Start the hardware initialization sequence.
  213.      */
  214.     RAADDR->raip = 0;        /* start initialization */
  215.     while ((RAADDR->rasa & RA_STEP1) == 0)
  216.         ;
  217.     RAADDR->rasa = RA_ERR|(NCMDL2<<11)|(NRSPL2<<8)|RA_IE|(sc->sc_ivec/4);
  218.     /*
  219.      * Initialization continues in interrupt routine.
  220.      */
  221.     sc->sc_state = S_STEP1;
  222.     sc->sc_credits = 0;
  223. }
  224.  
  225. rastrategy(bp)
  226.     register struct buf *bp;
  227. {
  228.     register struct buf *dp;
  229.     register int unit;
  230.     int xunit = minor(bp->b_dev) & 07;
  231.     daddr_t sz, maxsz;
  232.  
  233.     sz = (bp->b_bcount+511) >> 9;
  234.     unit = dkunit(bp);
  235.     if (unit >= NRA)
  236.         goto bad;
  237.     if ((maxsz = ra_sizes[xunit].nblocks) < 0)
  238.         maxsz = radsize[unit] - ra_sizes[xunit].cyloff*RA_CYL;
  239.     if (bp->b_blkno < 0 || dkblock(bp)+sz > maxsz)
  240.         goto bad;
  241.     dp = &rautab[unit];
  242.     (void) _spl4();
  243.     /*
  244.      * Link the buffer onto the drive queue
  245.      */
  246.     if (dp->b_actf == 0)
  247.         dp->b_actf = bp;
  248.     else
  249.         dp->b_actl->av_forw = bp;
  250.     dp->b_actl = bp;
  251.     bp->av_forw = 0;
  252.     /*
  253.      * Link the drive onto the controller queue
  254.      */
  255.     if (dp->b_active == 0) {
  256.         dp->b_forw = NULL;
  257.         if (ratab.b_actf == NULL)
  258.             ratab.b_actf = dp;
  259.         else
  260.             ratab.b_actl->b_forw = dp;
  261.         ratab.b_actl = dp;
  262.         dp->b_active = 1;
  263.     }
  264.     if (ratab.b_active == 0) {
  265.         (void) rastart();
  266.     }
  267.     (void) _spl0();
  268.     return;
  269.  
  270. bad:
  271.     bp->b_error = EINVAL;
  272.     bp->b_flags |= B_ERROR;
  273.     iodone(bp);
  274.     return;
  275. }
  276.  
  277. rastart()
  278. {
  279.     register struct buf *bp, *dp;
  280.     register struct ms *mp;
  281.     register struct ra_softc *sc;
  282.     int i;
  283.  
  284.     sc = &ra_softc;
  285.     
  286. loop:
  287.     if ((dp = ratab.b_actf) == NULL) {
  288.         ratab.b_active = 0;
  289.         return (0);
  290.     }
  291.     if ((bp = dp->b_actf) == NULL) {
  292.         /*
  293.          * No more requests for this drive, remove
  294.          * from controller queue and look at next drive.
  295.          * We know we're at the head of the controller queue.
  296.          */
  297.         dp->b_active = 0;
  298.         ratab.b_actf = dp->b_forw;
  299.         goto loop;
  300.     }
  301.     ratab.b_active++;
  302.     if ((RAADDR->rasa&RA_ERR) || sc->sc_state != S_RUN) {
  303.         harderr(bp, "ra");
  304.         printf("rasa %o stat %d\n", RAADDR->rasa, sc->sc_state);
  305.         rainit();
  306.         /* SHOULD REQUEUE OUTSTANDING REQUESTS */
  307.         return (0);
  308.     }
  309.     /*
  310.      * If no credits, can't issue any commands
  311.      * until some outstanding commands complete.
  312.      */
  313.     if (sc->sc_credits < 2)
  314.         return (0);
  315.     if ((mp = ragetcp()) == NULL)
  316.         return (0);
  317.     sc->sc_credits--;    /* committed to issuing a command */
  318.     /* If drive not ONLINE, issue an online com. */
  319.     if ((sc->sc_onlin & (1<<dkunit(bp))) == 0) {
  320.         mp->ms_opcode = M_OP_ONLIN;
  321.         mp->ms_unit = dkunit(bp);
  322.         dp->b_active = 2;
  323.         ratab.b_actf = dp->b_forw;    /* remove from controller q */
  324.         mp->ms_dscptr->high |= RA_OWN|RA_INT;
  325.         i = RAADDR->raip;
  326.         goto loop;
  327.     }
  328. #ifdef UNIBUS_MAP
  329.     mapalloc(bp);
  330. #endif
  331.     mp->ms_cmdref.low = (u_short)bp;    /* pointer to get back */
  332.     mp->ms_opcode = bp->b_flags&B_READ ? M_OP_READ : M_OP_WRITE;
  333.     mp->ms_unit = dkunit(bp);
  334.     mp->ms_lbn = SWAPW(dkblock(bp)+ra_sizes[minor(bp->b_dev)&7].cyloff*RA_CYL);
  335.     mp->ms_bytecnt = SWAPW(bp->b_bcount);
  336.     mp->ms_buffer.high = bp->b_xmem;
  337.     mp->ms_buffer.low = bp->b_un.b_addr;
  338.     mp->ms_dscptr->high |= RA_OWN|RA_INT;
  339.     i = RAADDR->raip;        /* initiate polling */
  340. #ifdef RA_DKN
  341.     dk_busy |= 1<<RA_DKN;
  342.     dp->b_qsize++;
  343.     dk_xfer[RA_DKN]++;
  344. #endif
  345.  
  346.     /*
  347.      * Move drive to the end of the controller queue
  348.      */
  349.     if (dp->b_forw != NULL) {
  350.         ratab.b_actf = dp->b_forw;
  351.         ratab.b_actl->b_forw = dp;
  352.         ratab.b_actl = dp;
  353.         dp->b_forw = NULL;
  354.     }
  355.     /*
  356.      * Move buffer to I/O wait queue
  357.      */
  358.     dp->b_actf = bp->av_forw;
  359.     dp = &rawtab;
  360.     bp->av_forw = dp;
  361.     bp->av_back = dp->av_back;
  362.     dp->av_back->av_forw = bp;
  363.     dp->av_back = bp;
  364.     goto loop;
  365. }
  366.  
  367. /*
  368.  * RA interrupt routine.
  369.  */
  370. raintr()
  371. {
  372.     struct buf *bp;
  373.     register int i;
  374.     register struct ra_softc *sc = &ra_softc;
  375.     register struct ra *rap = &ra;
  376.     struct ms *mp;
  377.     long addr, uvaddr();
  378.  
  379.     switch (sc->sc_state) {
  380.     case S_IDLE:
  381.         printf("ra0: randm intr\n");
  382.         return;
  383.  
  384.     case S_STEP1:
  385. #define    STEP1MASK    0174377
  386. #define    STEP1GOOD    (RA_STEP2|RA_IE|(NCMDL2<<3)|NRSPL2)
  387.         if ((RAADDR->rasa&STEP1MASK) != STEP1GOOD) {
  388.             sc->sc_state = S_IDLE;
  389.             wakeup((caddr_t)sc);
  390.             return;
  391.         }
  392.         addr = uvaddr(&ra.ra_ca.ca_ringbase);
  393.         RAADDR->rasa = loint(addr);
  394.         sc->sc_state = S_STEP2;
  395.         return;
  396.  
  397.     case S_STEP2:
  398. #define    STEP2MASK    0174377
  399. #define    STEP2GOOD    (RA_STEP3|RA_IE|(sc->sc_ivec/4))
  400.         if ((RAADDR->rasa&STEP2MASK) != STEP2GOOD) {
  401.             sc->sc_state = S_IDLE;
  402.             wakeup((caddr_t)sc);
  403.             return;
  404.         }
  405.         RAADDR->rasa = hiint(addr);
  406.         sc->sc_state = S_STEP3;
  407.         return;
  408.  
  409.     case S_STEP3:
  410. #define    STEP3MASK    0174000
  411. #define    STEP3GOOD    RA_STEP4
  412.         if ((RAADDR->rasa&STEP3MASK) != STEP3GOOD) {
  413.             sc->sc_state = S_IDLE;
  414.             wakeup((caddr_t)sc);
  415.             return;
  416.         }
  417.         RAADDR->rasa = RA_GO;
  418.         sc->sc_state = S_SCHAR;
  419.  
  420.         /*
  421.          * Initialize the data structures.
  422.          */
  423.         for (i = 0; i < NRSP; i++) {
  424.             addr = uvaddr(&rap->ra_rsp[i].ms_cmdref);
  425.             rap->ra_ca.ca_rspdsc[i].low = loint(addr);
  426.             rap->ra_ca.ca_rspdsc[i].high = RA_OWN|RA_INT|
  427.                 hiint(addr);
  428.             rap->ra_rsp[i].ms_dscptr = &rap->ra_ca.ca_rspdsc[i];
  429.             rap->ra_rsp[i].ms_header.ra_msglen = sizeof (struct ms);
  430.         }
  431.         for (i = 0; i < NCMD; i++) {
  432.             addr = uvaddr(&rap->ra_cmd[i].ms_cmdref);
  433.             rap->ra_ca.ca_cmddsc[i].low = loint(addr);
  434.             rap->ra_ca.ca_cmddsc[i].high = RA_INT|
  435.                 hiint(addr);
  436.             rap->ra_cmd[i].ms_dscptr = &rap->ra_ca.ca_cmddsc[i];
  437.             rap->ra_cmd[i].ms_header.ra_msglen = sizeof (struct ms);
  438.         }
  439.         bp = &rawtab;
  440.         bp->av_forw = bp->av_back = bp;
  441.         sc->sc_lastcmd = 0;
  442.         sc->sc_lastrsp = 0;
  443.         if ((mp = ragetcp()) == NULL) {
  444.             sc->sc_state = S_IDLE;
  445.             wakeup((caddr_t)sc);
  446.             return;
  447.         }
  448.         mp->ms_opcode = M_OP_STCON;
  449.         mp->ms_cntflgs = M_CF_ATTN|M_CF_MISC|M_CF_THIS;
  450.         mp->ms_dscptr->high |= RA_OWN|RA_INT;
  451.         i = RAADDR->raip;    /* initiate polling */
  452.         return;
  453.  
  454.     case S_SCHAR:
  455.     case S_RUN:
  456.         break;
  457.  
  458.     default:
  459.         printf("ra0: intr in stat %d\n",
  460.             sc->sc_state);
  461.         return;
  462.     }
  463.  
  464.     if (RAADDR->rasa&RA_ERR) {
  465.         printf("ra0: fatal err (%o)\n", RAADDR->rasa);
  466.         RAADDR->raip = 0;
  467.         wakeup((caddr_t)sc);
  468.     }
  469.  
  470.     /*
  471.      * Check for response ring transition.
  472.      */
  473.     if (rap->ra_ca.ca_rspint) {
  474.         rap->ra_ca.ca_rspint = 0;
  475.         for (i = sc->sc_lastrsp;; i++) {
  476.             i %= NRSP;
  477.             if (rap->ra_ca.ca_rspdsc[i].high&RA_OWN)
  478.                 break;
  479.             rarsp(rap, sc, i);
  480.             rap->ra_ca.ca_rspdsc[i].high |= RA_OWN;
  481.         }
  482.         sc->sc_lastrsp = i;
  483.     }
  484.  
  485.     /*
  486.      * Check for command ring transition.
  487.      */
  488.     if (rap->ra_ca.ca_cmdint) {
  489.         rap->ra_ca.ca_cmdint = 0;
  490.     }
  491.     (void) rastart();
  492. }
  493.  
  494. /*
  495.  * Process a response packet
  496.  */
  497. rarsp(ra, sc, i)
  498.     register struct ra *ra;
  499.     register struct ra_softc *sc;
  500.     int i;
  501. {
  502.     register struct ms *mp;
  503.     struct buf *dp, *bp;
  504.     int st;
  505.  
  506.     mp = &ra->ra_rsp[i];
  507.     mp->ms_header.ra_msglen = sizeof (struct ms);
  508.     sc->sc_credits += mp->ms_header.ra_credits & 0xf;
  509.     if ((mp->ms_header.ra_credits & 0xf0) > 0x10)
  510.         return;
  511.     /*
  512.      * If it's an error log message (datagram),
  513.      * pass it on for more extensive processing.
  514.      */
  515.     if ((mp->ms_header.ra_credits & 0xf0) == 0x10) {
  516.         raerror((struct ml *)mp);
  517.         return;
  518.     }
  519.     if (mp->ms_unit >= 8)
  520.         return;
  521.     st = mp->ms_status&M_ST_MASK;
  522.     switch ((mp->ms_opcode)&0377) {
  523.     case M_OP_STCON|M_OP_END:
  524.         if (st == M_ST_SUCC)
  525.             sc->sc_state = S_RUN;
  526.         else
  527.             sc->sc_state = S_IDLE;
  528.         ratab.b_active = 0;
  529.         wakeup((caddr_t)sc);
  530.         break;
  531.  
  532.     case M_OP_ONLIN|M_OP_END:
  533.         /*
  534.          * Link the drive onto the controller queue
  535.          */
  536.         dp = &rautab[mp->ms_unit];
  537.         dp->b_forw = NULL;
  538.         if (ratab.b_actf == NULL)
  539.             ratab.b_actf = dp;
  540.         else
  541.             ratab.b_actl->b_forw = dp;
  542.         ratab.b_actl = dp;
  543.         if (st == M_ST_SUCC) {
  544.             sc->sc_onlin |= (1<<mp->ms_unit);
  545.             radsize[mp->ms_unit] = (((long)(mp->ms_unt2))<<16)|
  546.                 (((long)(mp->ms_unt1))&0xffff);
  547.         } else {
  548.             harderr(dp->b_actf, "ra");
  549.             printf("OFFLINE\n");
  550.             while (bp = dp->b_actf) {
  551.                 dp->b_actf = bp->av_forw;
  552.                 bp->b_flags |= B_ERROR;
  553.                 iodone(bp);
  554.             }
  555.         }
  556.         dp->b_active = 1;
  557.         wakeup((caddr_t)sc);
  558.         break;
  559.  
  560.     case M_OP_AVATN:
  561.         sc->sc_onlin &= ~(1<<mp->ms_unit);
  562.         break;
  563.  
  564.     case M_OP_READ|M_OP_END:
  565.     case M_OP_WRITE|M_OP_END:
  566.         bp = (struct buf *)mp->ms_cmdref.low;
  567.         /*
  568.          * Unlink buffer from I/O wait queue.
  569.          */
  570.         bp->av_back->av_forw = bp->av_forw;
  571.         bp->av_forw->av_back = bp->av_back;
  572.         dp = &rautab[mp->ms_unit];
  573. #ifdef RA_DKN
  574.         if (--dp->b_qsize == 0) {
  575.             dk_busy &= ~(1<<RA_DKN);
  576.         }
  577. #endif RA_DKN
  578.         if (st == M_ST_OFFLN || st == M_ST_AVLBL) {
  579.             sc->sc_onlin &= ~(1<<mp->ms_unit);
  580.             /*
  581.              * Link the buffer onto the front of the drive queue
  582.              */
  583.             if ((bp->av_forw = dp->b_actf) == 0)
  584.                 dp->b_actl = bp;
  585.             dp->b_actf = bp;
  586.             /*
  587.              * Link the drive onto the controller queue
  588.              */
  589.             if (dp->b_active == 0) {
  590.                 dp->b_forw = NULL;
  591.                 if (ratab.b_actf == NULL)
  592.                     ratab.b_actf = dp;
  593.                 else
  594.                     ratab.b_actl->b_forw = dp;
  595.                 ratab.b_actl = dp;
  596.                 dp->b_active = 1;
  597.             }
  598.             return;
  599.         }
  600.         if (st != M_ST_SUCC) {
  601.             harderr(bp, "ra");
  602.             printf("stat %o\n", mp->ms_status);
  603.             bp->b_flags |= B_ERROR;
  604.         }
  605.         bp->b_resid = bp->b_bcount - ((u_short)SWAPW(mp->ms_bytecnt));
  606.         iodone(bp);
  607.         break;
  608.  
  609.     case M_OP_GTUNT|M_OP_END:
  610.         break;
  611.  
  612.     default:
  613.         printf("ra: unknown pckt\n");
  614.     }
  615. }
  616.  
  617.  
  618. /*
  619.  * Process an error log message
  620.  *
  621.  * For now, just log the error on the console.
  622.  * Only minimal decoding is done, only "useful"
  623.  * information is printed.  Eventually should
  624.  * send message to an error logger.
  625.  */
  626. raerror(mp)
  627.     register struct ml *mp;
  628. {
  629.     printf("ra0: %s err, ",
  630.         mp->ml_flags&(M_LF_SUCC|M_LF_CONT) ? "soft" : "hard");
  631.     switch (mp->ml_format&0377) {
  632.     case M_FM_CNTERR:
  633.         printf("cntrl err ev 0%o\n", mp->ml_event);
  634.         break;
  635.  
  636.     case M_FM_BUSADDR:
  637.         printf("mem err ev 0%o, addr 0%O\n",
  638.             mp->ml_event, SWAPW(mp->ml_busaddr));
  639.         break;
  640.  
  641.     case M_FM_DISKTRN:
  642.         printf("dsk xfer err unit %d, grp 0x%x, hdr 0x%X\n",
  643.             mp->ml_unit, mp->ml_group, SWAPW(mp->ml_hdr));
  644.         break;
  645.  
  646.     case M_FM_SDI:
  647.         printf("SDI err, unit %d, ev 0%o, hdr 0x%X\n",
  648.             mp->ml_unit, mp->ml_event, SWAPW(mp->ml_hdr));
  649.         break;
  650.  
  651.     case M_FM_SMLDSK:
  652.         printf("sml dsk err unit %d, ev 0%o, cyl %d\n",
  653.             mp->ml_unit, mp->ml_event, mp->ml_sdecyl);
  654.         break;
  655.  
  656.     default:
  657.         printf("unknown err, unit %d, fmt 0%o, ev 0%o\n",
  658.             mp->ml_unit, mp->ml_format, mp->ml_event);
  659.     }
  660.  
  661.     if (raerr) {
  662.         register short *p = (short *)mp;
  663.         register int i;
  664.  
  665.         for (i = 0; i < mp->ml_header.ra_msglen; i += sizeof(*p))
  666.             printf("%x ", *p++);
  667.         printf("\n");
  668.     }
  669. }
  670.  
  671.  
  672. /*
  673.  * Find an unused command packet
  674.  */
  675. struct ms *
  676. ragetcp()
  677. {
  678.     register struct ms *mp;
  679.     register struct raca *cp;
  680.     register struct ra_softc *sc;
  681.     register int i;
  682.  
  683.     cp = &ra.ra_ca;
  684.     sc = &ra_softc;
  685.     i = sc->sc_lastcmd;
  686.     if ((cp->ca_cmddsc[i].high & (RA_OWN|RA_INT)) == RA_INT) {
  687.         cp->ca_cmddsc[i].high &= ~RA_INT;
  688.         mp = &ra.ra_cmd[i];
  689.         mp->ms_unit = mp->ms_modifier = 0;
  690.         mp->ms_opcode = mp->ms_flags = 0;
  691.         mp->ms_buffer.high = mp->ms_buffer.low = 0;
  692.         mp->ms_bytecnt = 0;
  693.         mp->ms_errlgfl = mp->ms_copyspd = 0;
  694.         sc->sc_lastcmd = (i + 1) % NCMD;
  695.         return(mp);
  696.     }
  697.     return(NULL);
  698. }
  699.  
  700. raread(dev)
  701.     dev_t dev;
  702. {
  703. #ifdef UCB_DBUFS
  704.     register int unit = minor(dev) >> 3;
  705.  
  706.     if (unit >= NRA) {
  707.         u.u_error = ENXIO;
  708.         return;
  709.     }
  710.     physio(rastrategy, &rrabuf[unit], dev, B_READ);
  711. #else
  712.     physio(rastrategy, &rrabuf, dev, B_READ);
  713. #endif
  714. }
  715.  
  716. rawrite(dev)
  717.     dev_t dev;
  718. {
  719. #ifdef UCB_DBUFS
  720.     register int unit = minor(dev) >> 3;
  721.  
  722.     if (unit >= NRA) {
  723.         u.u_error = ENXIO;
  724.         return;
  725.     }
  726.     physio(rastrategy, &rrabuf[unit], dev, B_WRITE);
  727. #else
  728.     physio(rastrategy, &rrabuf, dev, B_WRITE);
  729. #endif
  730. }
  731.  
  732. /* This function returns the Unibus virtual address for a given
  733.  * kernel virtual address in the "ra" structure.
  734.  */
  735. long uvaddr(ptr)
  736. u_short ptr;
  737. {
  738.     long addr;
  739.  
  740.     addr = ramap.b_xmem;
  741.     addr <<= 16;
  742.     addr |= (long)ramap.b_un.b_addr;
  743.     addr += ptr-((u_short)&ra);
  744.     return(addr);
  745. }
  746. #endif
  747.