home *** CD-ROM | disk | FTP | other *** search
- /**************************************************
- UZI (Unix Z80 Implementation) Kernel: devio.c
- ***************************************************/
-
-
- int ok(), nogood();
- #define DEVIO
-
- #include "unix.h"
- #include "extern.h"
-
- /* Buffer pool management */
-
- /********************************************************
- The high-level interface is through bread() and bfree().
- Bread() is given a device and block number, and a rewrite flag.
- If rewrite is 0, the block is actually read if it is not already
- in the buffer pool. If rewrite is set, it is assumed that the caller
- plans to rewrite the entire contents of the block, and it will
- not be read in, but only have a buffer named after it.
-
- Bfree() is given a buffer pointer and a dirty flag.
- If the dirty flag is 0, the buffer is made available for further
- use. If the flag is 1, the buffer is marked "dirty", and
- it will eventually be written out to disk. If the flag is 2,
- it will be immediately written out.
-
- Zerobuf() returns a buffer of zeroes not belonging to any
- device. It must be bfree'd after use, and must not be
- dirty. It is used when a read() wants to read an unallocated
- block of a file.
-
- Bufsync() write outs all dirty blocks.
-
- Note that a pointer to a buffer structure is the same as a
- pointer to the data. This is very important.
-
- ********************************************************/
-
- unsigned bufclock = 0; /* Time-stamp counter for LRU */
-
- char *
- bread( dev, blk, rewrite)
- int dev;
- blkno_t blk;
- int rewrite;
- {
- register bufptr bp;
- bufptr bfind();
- bufptr freebuf();
-
- if (bp = bfind(dev, blk))
- {
- if (bp->bf_busy)
- panic("want busy block");
- goto done;
- }
- bp = freebuf();
-
- bp->bf_dev = dev;
- bp->bf_blk = blk;
-
- /* If rewrite is set, we are about to write over the entire block,
- so we don't need the previous contents */
-
- ifnot (rewrite)
- if (bdread(bp) == -1)
- {
- udata.u_error = EIO;
- return (NULL);
- }
-
- if (rewrite == 2)
- bzero(bp->bf_data, 512);
-
- done:
- bp->bf_busy = 1;
- bp->bf_time = ++bufclock; /* Time stamp it */
- return (bp->bf_data);
- }
-
-
-
- brelse(bp)
- bufptr bp;
- {
- bfree(bp, 0);
- }
-
- bawrite(bp)
- bufptr bp;
- {
- bfree(bp, 1);
- }
-
-
-
- bfree(bp, dirty)
- register bufptr bp;
- int dirty;
- {
-
- bp->bf_dirty |= dirty;
- bp->bf_busy = 0;
-
- if (dirty == 2) /* Extra dirty */
- {
- if (bdwrite(bp) == -1)
- udata.u_error = EIO;
- bp->bf_dirty = 0;
- return (-1);
- }
- return (0);
- }
-
-
- char *
- zerobuf()
- {
- bufptr bp;
- bufptr freebuf();
-
- bp = freebuf();
- bp->bf_dev = -1;
- bzero(bp->bf_data,512);
- return(bp->bf_data);
- }
-
-
- bufsync()
- {
- register bufptr bp;
-
- for (bp=bufpool; bp < bufpool+NBUFS; ++bp)
- {
- if (bp->bf_dev != -1 && bp->bf_dirty)
- bdwrite(bp);
- }
- }
-
-
- bufptr
- bfind(dev, blk)
- int dev;
- blkno_t blk;
- {
- register bufptr bp;
-
- for (bp=bufpool; bp < bufpool+NBUFS; ++bp)
- {
- if (bp->bf_dev == dev && bp->bf_blk == blk)
- return (bp);
- }
-
- return (NULL);
- }
-
-
- bufptr
- freebuf()
- {
- register bufptr bp;
- register bufptr oldest;
- register int oldtime;
-
- /* Try to find a non-busy buffer
- and write out the data if it is dirty */
-
- oldest = NULL;
- oldtime = 0;
- for (bp=bufpool; bp < bufpool+NBUFS; ++bp)
- {
- if (bufclock - bp->bf_time >= oldtime && !bp->bf_busy)
- {
- oldest = bp;
- oldtime = bufclock - bp->bf_time;
- }
- }
-
- ifnot (oldest)
- panic("no free buffers");
-
- if (oldest->bf_dirty)
- {
- if (bdwrite(oldest) == -1)
- udata.u_error = EIO;
- oldest->bf_dirty = 0;
- }
- return (oldest);
- }
-
-
- bufinit()
- {
- register bufptr bp;
-
- for (bp=bufpool; bp < bufpool+NBUFS; ++bp)
- {
- bp->bf_dev = -1;
- }
- }
-
-
- bufdump()
- {
- register bufptr j;
-
- kprintf("\ndev\tblock\tdirty\tbusy\ttime clock %d\n", bufclock);
- for (j=bufpool; j < bufpool+NBUFS; ++j)
- kprintf("%d\t%u\t%d\t%d\t%u\n",
- j->bf_dev,j->bf_blk,j->bf_dirty,j->bf_busy,j->bf_time);
- }
-
-
- /***************************************************
- Bdread() and bdwrite() are the block device interface routines.
- they are given a buffer pointer, which contains the device, block number,
- and data location.
- They basically validate the device and vector the call.
-
- Cdread() and cdwrite are the same for character (or "raw") devices,
- and are handed a device number.
- Udata.u_base, count, and offset have the rest of the data.
- ****************************************************/
-
- bdread(bp)
- bufptr bp;
- {
- ifnot (validdev(bp->bf_dev))
- panic("bdread: invalid dev");
-
- udata.u_buf = bp;
- return ((*dev_tab[bp->bf_dev].dev_read)(dev_tab[bp->bf_dev].minor, 0));
- }
-
- bdwrite(bp)
- bufptr bp;
- {
- ifnot (validdev(bp->bf_dev))
- panic("bdwrite: invalid dev");
-
- udata.u_buf = bp;
- return ((*dev_tab[bp->bf_dev].dev_write)(dev_tab[bp->bf_dev].minor, 0));
- }
-
- cdread(dev)
- int dev;
- {
- ifnot (validdev(dev))
- panic("cdread: invalid dev");
- return ((*dev_tab[dev].dev_read)(dev_tab[dev].minor, 1));
- }
-
- cdwrite(dev)
- int dev;
- {
- ifnot (validdev(dev))
- panic("cdwrite: invalid dev");
- return ((*dev_tab[dev].dev_write)(dev_tab[dev].minor, 1));
- }
-
-
- swapread(dev, blkno, nbytes, buf)
- int dev;
- blkno_t blkno;
- unsigned nbytes;
- char *buf;
- {
- swapbase = buf;
- swapcnt = nbytes;
- swapblk = blkno;
- return ((*dev_tab[dev].dev_read)(dev_tab[dev].minor, 2));
- }
-
-
- swapwrite(dev, blkno, nbytes, buf)
- int dev;
- blkno_t blkno;
- unsigned nbytes;
- char *buf;
- {
- swapbase = buf;
- swapcnt = nbytes;
- swapblk = blkno;
- return ((*dev_tab[dev].dev_write)(dev_tab[dev].minor, 2));
- }
-
-
- /**************************************************
- The device driver read and write routines now have
- only two arguments, minor and rawflag. If rawflag is
- zero, a single block is desired, and the necessary data
- can be found in udata.u_buf.
- Otherwise, a "raw" or character read is desired, and
- udata.u_offset, udata.u_count, and udata.u_base
- should be consulted instead.
- Any device other than a disk will have only raw access.
- *****************************************************/
-
-
-
- d_open(dev)
- int dev;
- {
- ifnot (validdev(dev))
- return(-1);
- return ((*dev_tab[dev].dev_open)(dev_tab[dev].minor));
- }
-
-
- d_close(dev)
- int dev;
- {
- ifnot (validdev(dev))
- panic("d_close: bad device");
- (*dev_tab[dev].dev_close)(dev_tab[dev].minor);
- }
-
-
-
- d_ioctl(dev,request,data)
- int dev;
- int request;
- char *data;
- {
- ifnot (validdev(dev))
- {
- udata.u_error = ENXIO;
- return(-1);
- }
- if((*dev_tab[dev].dev_ioctl)(dev_tab[dev].minor,request,data))
- {
- udata.u_error = EINVAL;
- return(-1);
- }
- return(0);
- }
-
-
- static
- ok()
- {
- return(0);
- }
-
-
- static
- nogood()
- {
- return(-1);
- }
-
-
- validdev(dev)
- {
- return(dev >= 0 && dev < (sizeof(dev_tab)/sizeof(struct devsw)));
- }
-
-
- /*************************************************************
- Character queue management routines
- ************************************************************/
-
-
- /* add something to the tail */
- insq(q,c)
- register struct s_queue *q;
- char c;
- {
- di();
- if (q->q_count == q->q_size)
- {
- ei();
- return(0);
- }
- *(q->q_tail) = c;
- ++q->q_count;
- if (++q->q_tail >= q->q_base + q->q_size)
- q->q_tail = q->q_base;
- ei();
- return(1);
- }
-
- /* Remove something from the head. */
- remq(q,cp)
- register struct s_queue *q;
- char *cp;
- {
- di();
- ifnot (q->q_count)
- {
- ei();
- return(0);
- }
- *cp = *(q->q_head);
- --q->q_count;
- if (++q->q_head >= q->q_base + q->q_size)
- q->q_head = q->q_base;
- ei();
- return(1);
- }
-
-
- /* Remove something from the tail; the most recently added char. */
- uninsq(q,cp)
- register struct s_queue *q;
- char *cp;
- {
- di();
- ifnot (q->q_count)
- {
- ei();
- return(0);
- }
- --q->q_count;
- if (--q->q_tail <= q->q_base)
- q->q_tail = q->q_base + q->q_size - 1;
- *cp = *(q->q_tail);
- ei();
- return(1);
- }
-
-
- /* Returns true if the queue has more characters than its wakeup number */
- fullq(q)
- struct s_queue *q;
- {
- di();
- if (q->q_count > q->q_wakeup)
- {
- ei();
- return (1);
- }
- ei();
- return (0);
- }
-
-