home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V7 / usr / sys / dev / rx2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-17  |  8.5 KB  |  386 lines

  1. #
  2. /*
  3.  * RX02 floppy disk device driver
  4.  *
  5.  * Bill Shannon   CWRU   05/29/79
  6.  *
  7.  * Modified for Version 7 - 08/13/79 - Bill Shannon
  8.  *
  9.  *
  10.  *    Layout of logical devices:
  11.  *
  12.  *    name    min dev        unit    density
  13.  *    ----    -------        ----    -------
  14.  *    rx0       0          0    single
  15.  *    rx1       1          1    single
  16.  *    rx2       2          0    double
  17.  *    rx3       3          1    double
  18.  *
  19.  *
  20.  *    Stty function call may be used to format a disk.
  21.  *    To enable this feature, define CTRL in this module.
  22.  */
  23.  
  24. #include "../h/param.h"
  25. #include "../h/buf.h"
  26. #include "../h/dir.h"
  27. #include "../h/user.h"
  28. #include "../h/conf.h"
  29. #include "../h/tty.h"
  30.  
  31.  
  32. /* The following structure is used to access av_back as an integer */
  33.  
  34. struct {
  35.     int    dummy0;
  36.     struct    buf *dummy1;
  37.     struct    buf *dummy2;
  38.     struct    buf *dummy3;
  39.     int    seccnt;
  40. };
  41.  
  42. struct device {
  43.     int    rx2cs;
  44.     int    rx2db;
  45. };
  46.  
  47.  
  48. /*
  49.  *    the following defines use some fundamental
  50.  *    constants of the RX02.
  51.  */
  52. #define    RXADDR    ((struct device *) 0177170)
  53. #define    NSPB    ((minor(bp->b_dev)&2) ? 2 : 4)    /* Number of floppy sectors per unix block */
  54. #define    NBPS    ((minor(bp->b_dev)&2) ? 256 : 128)    /* Number of bytes per floppy sector    */
  55. #define    NRXBLKS    ((minor(bp->b_dev)&2) ? 1001 : 500)    /* Number of unix blocks on a floppy */
  56. #define    DENSITY    (minor(bp->b_dev)&2)    /* Density: 0 = single, 2 = double */
  57. #define    UNIT    (minor(bp->b_dev)&1)    /* Unit Number: 0 = left, 1 = right */
  58.  
  59. #define    CTRL    CTRL            /* define for control functions (formatting) */
  60.  
  61. #ifdef    CTRL
  62. #define    B_CTRL    020000
  63. #endif
  64.  
  65. #define    TRWAIT        while (ptcs->lobyte >= 0)
  66.  
  67. struct {
  68.     char     lobyte;
  69.     char    hibyte;
  70. };
  71.  
  72. struct    buf    rx2tab;
  73.  
  74. struct    buf    rrx2buf;
  75.  
  76. #ifdef CTRL
  77. struct    buf    crx2buf;    /* buffer header for control functions */
  78. #endif
  79.  
  80. #define    GO    0000001    /* execute command function    */
  81. #define    UNIT1    0000020    /* unit select (drive 0=0, 1=1)    */
  82. #define    RXDONE    0000040    /* function complete        */
  83. #define    INTENB    0000100    /* interrupt enable        */
  84. #define    TRANREQ    0000200    /* transfer request (data only)    */
  85. #define    RXINIT    0040000    /* rx211 initialize        */
  86. #define    RXERROR    0100000    /* general error bit        */
  87.  
  88. /*
  89.  *    rx211 control function bits 1-3 of rx2cs
  90.  */
  91. #define    FILL    0000000    /* fill buffer            */
  92. #define    EMPTY    0000002    /* empty buffer            */
  93. #define    WRITE    0000004    /* write buffer to disk        */
  94. #define    READ    0000006    /* read disk sector to buffer    */
  95. #define    FORMAT    0000010    /* set media density (format)    */
  96. #define    RSTAT    0000012    /* read disk status        */
  97. #define    WSDD    0000014    /* write sector deleted data    */
  98. #define    RDERR    0000016    /* read error register function    */
  99.  
  100. /*
  101.  *    states of driver, kept in b_active
  102.  */
  103. #define    SREAD    1    /* read started  */
  104. #define    SEMPTY    2    /* empty started */
  105. #define    SFILL    3    /* fill started  */
  106. #define    SWRITE    4    /* write started */
  107. #define    SINIT    5    /* init started  */
  108. #define    SFORMAT    6    /* format started */
  109.  
  110.  
  111. rx2open(dev, flag)
  112. {
  113.     if(minor(dev) >= 4)
  114.         u.u_error = ENXIO;
  115. }
  116.  
  117. rx2strategy(bp)
  118. register struct buf *bp;
  119. {
  120.  
  121.     if(bp->b_flags & B_PHYS)
  122.         mapalloc(bp);
  123.     if(bp->b_blkno >= NRXBLKS) {
  124.         if(bp->b_flags&B_READ)
  125.             bp->b_resid = bp->b_bcount;
  126.         else {
  127.             bp->b_flags =| B_ERROR;
  128.             bp->b_error = ENXIO;
  129.         }
  130.         iodone(bp);
  131.         return;
  132.     }
  133.     bp->av_forw = (struct buf *) NULL;
  134.     /*
  135.      * seccnt is actually the number of floppy sectors transferred,
  136.      * incremented by one after each successful transfer of a sector.
  137.      */
  138.     bp->seccnt = 0;
  139.     /*
  140.      * We'll modify b_resid as each piece of the transfer
  141.      * successfully completes.  It will also tell us when
  142.      * the transfer is complete.
  143.      */
  144.     bp->b_resid = bp->b_bcount;
  145.     spl5();
  146.     if(rx2tab.b_actf == NULL)
  147.         rx2tab.b_actf = bp;
  148.     else
  149.         rx2tab.b_actl->av_forw = bp;
  150.     rx2tab.b_actl = bp;
  151.     if(rx2tab.b_active == NULL)
  152.         rx2start();
  153.     spl0();
  154. }
  155.  
  156. rx2start()
  157. {
  158.     register int *ptcs, *ptdb;
  159.     register struct buf *bp;
  160.     int sector, track;
  161.     char *addr, *xmem;
  162.  
  163.     if((bp = rx2tab.b_actf) == NULL) {
  164.         rx2tab.b_active = NULL;
  165.         return;
  166.     }
  167.  
  168.     ptcs = &RXADDR->rx2cs;
  169.     ptdb = &RXADDR->rx2db;
  170.  
  171.  
  172. #ifdef CTRL
  173.     if (bp->b_flags&B_CTRL) {    /* is it a control request ? */
  174.         rx2tab.b_active = SFORMAT;
  175.         *ptcs = FORMAT | GO | INTENB | (UNIT << 4) | (DENSITY << 7);
  176.         TRWAIT;
  177.         *ptdb = 'I';
  178.     } else
  179. #endif
  180.     if(bp->b_flags&B_READ) {
  181.         rx2tab.b_active = SREAD;
  182.         rx2factr((int)bp->b_blkno * NSPB + bp->seccnt, §or, &track);
  183.         *ptcs = READ | GO | INTENB | (UNIT << 4) | (DENSITY << 7);
  184.         TRWAIT;
  185.         *ptdb = sector;
  186.         TRWAIT;
  187.         *ptdb = track;
  188.     } else {
  189.         rx2tab.b_active = SFILL;
  190.         rx2addr(bp, &addr, &xmem);
  191.         *ptcs = FILL | GO | INTENB | (xmem << 12) | (DENSITY << 7);
  192.         TRWAIT;
  193.         *ptdb = (bp->b_resid >= NBPS ? NBPS : bp->b_resid) >> 1;
  194.         TRWAIT;
  195.         *ptdb = addr;
  196.     }
  197. }
  198.  
  199. rx2intr() {
  200.     register int *ptcs, *ptdb;
  201.     register struct buf *bp;
  202.     int sector, track;
  203.     char *addr, *xmem;
  204.  
  205.     /* fix for error recovery by duke!phs!dennis */
  206.     if (rx2tab.b_active == SINIT) {
  207.         rx2start();
  208.         return;
  209.     }
  210.  
  211.     if((bp = rx2tab.b_actf) == NULL)
  212.         return;
  213.  
  214.     ptcs = &RXADDR->rx2cs;
  215.     ptdb = &RXADDR->rx2db;
  216.  
  217.     if(*ptcs < 0) {
  218.         if(rx2tab.b_errcnt++ > 10 || rx2tab.b_active == SFORMAT) {
  219.             bp->b_flags =| B_ERROR;
  220.             deverror(bp, *ptcs, *ptdb);
  221.             rx2tab.b_errcnt = 0;
  222.             rx2tab.b_actf = bp->av_forw;
  223.             iodone(bp);
  224.         }
  225.         *ptcs = RXINIT;
  226.         *ptcs = INTENB;
  227.         rx2tab.b_active = SINIT;
  228.         return;
  229.     }
  230.     switch (rx2tab.b_active) {
  231.  
  232.     case SREAD:            /* read done, start empty */
  233.         rx2tab.b_active = SEMPTY;
  234.         rx2addr(bp, &addr, &xmem);
  235.         *ptcs = EMPTY | GO | INTENB | (xmem << 12) | (DENSITY << 7);
  236.         TRWAIT;
  237.         *ptdb = (bp->b_resid >= NBPS ? NBPS : bp->b_resid) >> 1;
  238.         TRWAIT;
  239.         *ptdb = addr;
  240.         return;
  241.  
  242.     case SFILL:            /* fill done, start write */
  243.         rx2tab.b_active = SWRITE;
  244.         rx2factr((int)bp->b_blkno * NSPB + bp->seccnt, §or, &track);
  245.         *ptcs = WRITE | GO | INTENB | (UNIT << 4) | (DENSITY << 7);
  246.         TRWAIT;
  247.         *ptdb = sector;
  248.         TRWAIT;
  249.         *ptdb = track;
  250.         return;
  251.  
  252.     case SWRITE:            /* write done, start next fill */
  253.     case SEMPTY:            /* empty done, start next read */
  254.         /*
  255.          * increment amount remaining to be transferred.
  256.          * if it becomes positive, last transfer was a
  257.          * partial sector and we're done, so set remaining
  258.          * to zero.
  259.          */
  260.         if (bp->b_resid <= NBPS) {
  261. done:
  262.             bp->b_resid = 0;
  263.             rx2tab.b_errcnt = 0;
  264.             rx2tab.b_actf = bp->av_forw;
  265.             iodone(bp);
  266.             break;
  267.         }
  268.  
  269.         bp->b_resid -= NBPS;
  270.         bp->seccnt++;
  271.         break;
  272.  
  273. #ifdef CTRL
  274.     case SFORMAT:            /* format done (whew!!!) */
  275.         goto done;        /* driver's getting too big... */
  276. #endif
  277.     }
  278.     /* end up here from states SWRITE, SEMPTY, and SINIT */
  279.  
  280.     rx2start();
  281. }
  282.  
  283. /*
  284.  *    rx2factr -- calculates the physical sector and physical
  285.  *    track on the disk for a given logical sector.
  286.  *    call:
  287.  *        rx2factr(logical_sector,&p_sector,&p_track);
  288.  *    the logical sector number (0 - 2001) is converted
  289.  *    to a physical sector number (1 - 26) and a physical
  290.  *    track number (0 - 76).
  291.  *    the logical sectors specify physical sectors that
  292.  *    are interleaved with a factor of 2. thus the sectors
  293.  *    are read in the following order for increasing
  294.  *    logical sector numbers (1,3, ... 23,25,2,4, ... 24,26)
  295.  *    There is also a 6 sector slew between tracks.
  296.  *    Logical sectors start at track 1, sector 1; go to
  297.  *    track 76 and then to track 0.  Thus, for example, unix block number
  298.  *    498 starts at track 0, sector 21 and runs thru track 0, sector 2.
  299.  */
  300. rx2factr(sectr, psectr, ptrck)
  301. register int sectr;
  302. int *psectr, *ptrck;
  303. {
  304.     register int p1, p2;
  305.  
  306.     p1 = sectr/26;
  307.     p2 = sectr%26;
  308.     /* 2 to 1 interleave */
  309.     p2 = (2*p2 + (p2 >= 13 ? 1 : 0)) % 26;
  310.     /* 6 sector per track slew */
  311.     *psectr = 1 + (p2 + 6*p1) % 26;
  312.     if (++p1 >= 77)
  313.         p1 = 0;
  314.     *ptrck = p1;
  315. }
  316.  
  317.  
  318. /*
  319.  *    rx2addr -- compute core address where next sector
  320.  *    goes to / comes from based on bp->b_un.b_addr, bp->b_xmem,
  321.  *    and bp->seccnt.
  322.  */
  323. rx2addr(bp, addr, xmem)
  324. register struct buf *bp;
  325. register char **addr, **xmem;
  326. {
  327.     *addr = bp->b_un.b_addr + bp->seccnt * NBPS;
  328.     *xmem = bp->b_xmem;
  329.     if (*addr < bp->b_un.b_addr)            /* overflow, bump xmem */
  330.         (*xmem)++;
  331. }
  332.  
  333.  
  334. rx2read(dev)
  335. {
  336.     physio(rx2strategy, &rrx2buf, dev, B_READ, minor(dev)&2 ? 1001 : 500);
  337. }
  338.  
  339.  
  340. rx2write(dev)
  341. {
  342.     physio(rx2strategy, &rrx2buf, dev, B_WRITE, minor(dev)&2 ? 1001 : 500);
  343. }
  344.  
  345.  
  346. #ifdef CTRL
  347. /*
  348.  *    rx2sgtty -- format RX02 disk, single or double density.
  349.  *    stty with word 0 == 010 does format.  density determined
  350.  *    by device opened.
  351.  */
  352. rx2ioctl(dev, cmd, addr, flag)
  353. {
  354.     register struct buf *bp;
  355.     struct rx2iocb {
  356.         int    ioc_cmd;    /* command */
  357.         int    ioc_res1;    /* reserved */
  358.         int    ioc_res2;    /* reserved */
  359.     } iocb;
  360.  
  361.     if (cmd != TIOCSETP) {
  362. err:
  363.         u.u_error = ENXIO;
  364.         return(0);
  365.     }
  366.     if (copyin(addr, (caddr_t)&iocb, sizeof (iocb))) {
  367.         u.u_error = EFAULT;
  368.         return(1);
  369.     }
  370.     if (iocb.ioc_cmd != FORMAT)
  371.         goto err;
  372.     bp = &crx2buf;
  373.     spl6();
  374.     while (bp->b_flags & B_BUSY) {
  375.         bp->b_flags =| B_WANTED;
  376.         sleep(bp, PRIBIO);
  377.     }
  378.     bp->b_flags = B_BUSY | B_CTRL;
  379.     bp->b_dev = dev;
  380.     bp->b_error = 0;
  381.     rx2strategy(bp);
  382.     iowait(bp);
  383.     bp->b_flags = 0;
  384. }
  385. #endif
  386.