home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / ENTERPRS / CPM / UTILS / S / UZI.ARK / DEVIO.C < prev    next >
Text File  |  1988-11-30  |  9KB  |  438 lines

  1. /**************************************************
  2. UZI (Unix Z80 Implementation) Kernel:  devio.c
  3. ***************************************************/
  4.  
  5.  
  6. int ok(), nogood();
  7. #define DEVIO
  8.  
  9. #include "unix.h"
  10. #include "extern.h"
  11.  
  12. /* Buffer pool management */
  13.  
  14. /********************************************************
  15. The high-level interface is through bread() and bfree().
  16. Bread() is given a device and block number, and a rewrite flag.
  17. If rewrite is 0, the block is actually read if it is not already
  18. in the buffer pool. If rewrite is set, it is assumed that the caller
  19. plans to rewrite the entire contents of the block, and it will
  20. not be read in, but only have a buffer named after it.
  21.  
  22. Bfree() is given a buffer pointer and a dirty flag.
  23. If the dirty flag is 0, the buffer is made available for further 
  24. use.  If the flag is 1, the buffer is marked "dirty", and
  25. it will eventually be written out to disk.  If the flag is 2,
  26. it will be immediately written out.
  27.  
  28. Zerobuf() returns a buffer of zeroes not belonging to any
  29. device.  It must be bfree'd after use, and must not be
  30. dirty. It is used when a read() wants to read an unallocated
  31. block of a file.
  32.  
  33. Bufsync() write outs all dirty blocks.
  34.  
  35. Note that a pointer to a buffer structure is the same as a
  36. pointer to the data.  This is very important.
  37.  
  38. ********************************************************/
  39.  
  40. unsigned bufclock = 0;  /* Time-stamp counter for LRU */
  41.  
  42. char *
  43. bread( dev, blk, rewrite)
  44. int dev;
  45. blkno_t blk;
  46. int rewrite;
  47. {
  48.     register bufptr bp;
  49.     bufptr bfind();
  50.     bufptr freebuf();
  51.  
  52.     if (bp = bfind(dev, blk))
  53.     {
  54.         if (bp->bf_busy)
  55.             panic("want busy block");
  56.         goto done;
  57.     }
  58.     bp = freebuf();
  59.  
  60.     bp->bf_dev = dev;
  61.     bp->bf_blk = blk;
  62.  
  63.     /* If rewrite is set, we are about to write over the entire block,
  64.     so we don't need the previous contents */
  65.  
  66.     ifnot (rewrite)
  67.         if (bdread(bp) == -1)
  68.         {
  69.             udata.u_error = EIO;
  70.             return (NULL);
  71.         }
  72.  
  73.     if (rewrite == 2)
  74.         bzero(bp->bf_data, 512);
  75.  
  76. done:
  77.     bp->bf_busy = 1;
  78.     bp->bf_time = ++bufclock;  /* Time stamp it */
  79.     return (bp->bf_data);
  80. }
  81.  
  82.  
  83.  
  84. brelse(bp)
  85. bufptr bp;
  86. {
  87.     bfree(bp, 0);
  88. }
  89.  
  90. bawrite(bp)
  91. bufptr bp;
  92. {
  93.     bfree(bp, 1);
  94. }
  95.  
  96.  
  97.  
  98. bfree(bp, dirty)
  99. register bufptr bp;
  100. int dirty;
  101. {
  102.  
  103.     bp->bf_dirty |= dirty;
  104.     bp->bf_busy = 0;
  105.  
  106.     if (dirty == 2)   /* Extra dirty */
  107.     {
  108.         if (bdwrite(bp) == -1)
  109.             udata.u_error = EIO;
  110.         bp->bf_dirty = 0;
  111.         return (-1);
  112.     }
  113.     return (0);
  114. }
  115.  
  116.  
  117. char *
  118. zerobuf()
  119. {
  120.     bufptr bp;
  121.     bufptr freebuf();
  122.  
  123.     bp = freebuf();
  124.     bp->bf_dev = -1;
  125.     bzero(bp->bf_data,512);
  126.     return(bp->bf_data);
  127. }
  128.  
  129.  
  130. bufsync()
  131. {
  132.     register bufptr bp;
  133.  
  134.     for (bp=bufpool; bp < bufpool+NBUFS; ++bp)
  135.     {
  136.         if (bp->bf_dev != -1 && bp->bf_dirty)
  137.             bdwrite(bp);
  138.     }
  139. }
  140.  
  141.  
  142. bufptr
  143. bfind(dev, blk)
  144. int dev;
  145. blkno_t blk;
  146. {
  147.     register bufptr bp;
  148.  
  149.     for (bp=bufpool; bp < bufpool+NBUFS; ++bp)
  150.     {
  151.         if (bp->bf_dev == dev && bp->bf_blk == blk)
  152.             return (bp);
  153.     }
  154.  
  155.     return (NULL);
  156. }
  157.  
  158.  
  159. bufptr
  160. freebuf()
  161. {
  162.     register bufptr bp;
  163.     register bufptr oldest;
  164.     register int oldtime;
  165.  
  166.     /* Try to find a non-busy buffer 
  167.     and write out the data if it is dirty */
  168.  
  169.     oldest = NULL;
  170.     oldtime = 0;
  171.     for (bp=bufpool; bp < bufpool+NBUFS; ++bp)
  172.     {
  173.         if (bufclock - bp->bf_time >= oldtime && !bp->bf_busy)
  174.         {
  175.             oldest = bp;
  176.             oldtime = bufclock - bp->bf_time;
  177.         }
  178.     }
  179.  
  180.     ifnot (oldest)
  181.         panic("no free buffers");
  182.     
  183.     if (oldest->bf_dirty)
  184.     {
  185.         if (bdwrite(oldest) == -1)
  186.             udata.u_error = EIO;
  187.         oldest->bf_dirty = 0;
  188.     }
  189.     return (oldest);
  190. }
  191.         
  192.  
  193. bufinit()
  194. {
  195.     register bufptr bp;
  196.  
  197.     for (bp=bufpool; bp < bufpool+NBUFS; ++bp)
  198.     {
  199.         bp->bf_dev = -1;
  200.     }
  201. }
  202.  
  203.  
  204. bufdump()
  205. {
  206.     register bufptr j;
  207.  
  208.     kprintf("\ndev\tblock\tdirty\tbusy\ttime clock %d\n", bufclock);
  209.     for (j=bufpool; j < bufpool+NBUFS; ++j)
  210.         kprintf("%d\t%u\t%d\t%d\t%u\n",
  211.             j->bf_dev,j->bf_blk,j->bf_dirty,j->bf_busy,j->bf_time);
  212. }
  213.  
  214.  
  215. /***************************************************
  216. Bdread() and bdwrite() are the block device interface routines.
  217. they are given a buffer pointer, which contains the device, block number,
  218. and data location.
  219. They basically validate the device and vector the call.
  220.  
  221. Cdread() and cdwrite are the same for character (or "raw") devices,
  222. and are handed a device number.
  223. Udata.u_base, count, and offset have the rest of the data.
  224. ****************************************************/
  225.  
  226. bdread(bp)
  227. bufptr bp;
  228. {
  229.     ifnot (validdev(bp->bf_dev))
  230.         panic("bdread: invalid dev");
  231.  
  232.     udata.u_buf = bp;
  233.     return ((*dev_tab[bp->bf_dev].dev_read)(dev_tab[bp->bf_dev].minor, 0));
  234. }
  235.  
  236. bdwrite(bp)
  237. bufptr bp;
  238. {
  239.    ifnot (validdev(bp->bf_dev))
  240.         panic("bdwrite: invalid dev");
  241.  
  242.     udata.u_buf = bp;
  243.     return ((*dev_tab[bp->bf_dev].dev_write)(dev_tab[bp->bf_dev].minor, 0));
  244. }
  245.  
  246. cdread(dev)
  247. int dev;
  248. {
  249.     ifnot (validdev(dev))
  250.         panic("cdread: invalid dev");
  251.     return ((*dev_tab[dev].dev_read)(dev_tab[dev].minor, 1));
  252. }
  253.  
  254. cdwrite(dev)
  255. int dev;
  256. {
  257.     ifnot (validdev(dev))
  258.         panic("cdwrite: invalid dev");
  259.     return ((*dev_tab[dev].dev_write)(dev_tab[dev].minor, 1));
  260. }
  261.  
  262.  
  263. swapread(dev, blkno, nbytes, buf)
  264. int dev;
  265. blkno_t blkno;
  266. unsigned nbytes;
  267. char *buf;
  268. {
  269.     swapbase = buf;
  270.     swapcnt = nbytes;
  271.     swapblk = blkno;
  272.     return ((*dev_tab[dev].dev_read)(dev_tab[dev].minor, 2));
  273. }
  274.  
  275.  
  276. swapwrite(dev, blkno, nbytes, buf)
  277. int dev;
  278. blkno_t blkno;
  279. unsigned nbytes;
  280. char *buf;
  281. {
  282.     swapbase = buf;
  283.     swapcnt = nbytes;
  284.     swapblk = blkno;
  285.     return ((*dev_tab[dev].dev_write)(dev_tab[dev].minor, 2));
  286. }
  287.  
  288.  
  289. /**************************************************
  290. The device driver read and write routines now have
  291. only two arguments, minor and rawflag.  If rawflag is
  292. zero, a single block is desired, and the necessary data
  293. can be found in udata.u_buf.
  294. Otherwise, a "raw" or character read is desired, and
  295. udata.u_offset, udata.u_count, and udata.u_base
  296. should be consulted instead.
  297. Any device other than a disk will have only raw access.
  298. *****************************************************/
  299.  
  300.  
  301.  
  302. d_open(dev)
  303. int dev;
  304. {
  305.     ifnot (validdev(dev))
  306.         return(-1);
  307.     return ((*dev_tab[dev].dev_open)(dev_tab[dev].minor));
  308. }
  309.  
  310.  
  311. d_close(dev)
  312. int dev;
  313. {
  314.     ifnot (validdev(dev))
  315.         panic("d_close: bad device");
  316.     (*dev_tab[dev].dev_close)(dev_tab[dev].minor);
  317. }
  318.  
  319.  
  320.  
  321. d_ioctl(dev,request,data)
  322. int dev;
  323. int request;
  324. char *data;
  325. {
  326.     ifnot (validdev(dev))
  327.     {
  328.         udata.u_error = ENXIO;
  329.         return(-1);
  330.     }
  331.     if((*dev_tab[dev].dev_ioctl)(dev_tab[dev].minor,request,data))
  332.     {
  333.         udata.u_error = EINVAL;
  334.         return(-1);
  335.     }
  336.         return(0);
  337. }
  338.  
  339.  
  340. static 
  341. ok()
  342. {
  343.     return(0);
  344. }
  345.  
  346.  
  347. static 
  348. nogood()
  349. {
  350.     return(-1);
  351. }
  352.  
  353.  
  354. validdev(dev)
  355. {
  356.     return(dev >= 0 && dev < (sizeof(dev_tab)/sizeof(struct devsw)));
  357. }
  358.  
  359.  
  360. /*************************************************************
  361. Character queue management routines
  362. ************************************************************/
  363.  
  364.  
  365. /* add something to the tail */
  366. insq(q,c)
  367. register struct s_queue *q;
  368. char c;
  369. {
  370.     di();
  371.     if (q->q_count == q->q_size)
  372.     {
  373.         ei();
  374.         return(0);
  375.     }
  376.     *(q->q_tail) = c;
  377.     ++q->q_count;
  378.     if (++q->q_tail >= q->q_base + q->q_size)
  379.         q->q_tail = q->q_base;
  380.     ei();
  381.     return(1);
  382. }
  383.  
  384. /* Remove something from the head. */
  385. remq(q,cp)
  386. register struct s_queue *q;
  387. char *cp;
  388. {
  389.     di();
  390.     ifnot (q->q_count)
  391.     {
  392.         ei();
  393.         return(0);
  394.     }
  395.     *cp = *(q->q_head);
  396.     --q->q_count;
  397.     if (++q->q_head >= q->q_base + q->q_size)
  398.         q->q_head = q->q_base;
  399.     ei();
  400.     return(1);
  401. }
  402.  
  403.  
  404. /* Remove something from the tail; the most recently added char. */
  405. uninsq(q,cp)
  406. register struct s_queue *q;
  407. char *cp;
  408. {
  409.     di();
  410.     ifnot (q->q_count)
  411.     {
  412.         ei();
  413.         return(0);
  414.     }
  415.     --q->q_count;
  416.     if (--q->q_tail <= q->q_base)
  417.         q->q_tail = q->q_base + q->q_size - 1;
  418.     *cp = *(q->q_tail);
  419.     ei();
  420.     return(1);
  421. }
  422.  
  423.  
  424. /* Returns true if the queue has more characters than its wakeup number */
  425. fullq(q)
  426. struct s_queue *q;
  427. {
  428.     di();
  429.     if (q->q_count > q->q_wakeup)
  430.     {
  431.         ei();
  432.         return (1);
  433.     }
  434.     ei();
  435.     return (0);
  436. }
  437.  
  438.