[comp.os.cpm] UZI, part 5 of 5

dbraun@cadavr.intel.com (Doug Braun ~) (11/29/88)

UZI, Part 5 of 5:

#!/bin/sh
#
#Run this file through sh to get:
#    devio.c
#    devwd.c
#    devflop.c
#    devmisc.c
#    filler.mac
echo -n 'Extracting devio.c ... '
sed 's/^X//' > devio.c << 'EOF_devio.c'
X/**************************************************
XUZI (Unix Z80 Implementation) Kernel:  devio.c
X***************************************************/
X
X
Xint ok(), nogood();
X#define DEVIO
X
X#include "unix.h"
X#include "extern.h"
X
X/* Buffer pool management */
X
X/********************************************************
XThe high-level interface is through bread() and bfree().
XBread() is given a device and block number, and a rewrite flag.
XIf rewrite is 0, the block is actually read if it is not already
Xin the buffer pool. If rewrite is set, it is assumed that the caller
Xplans to rewrite the entire contents of the block, and it will
Xnot be read in, but only have a buffer named after it.
X
XBfree() is given a buffer pointer and a dirty flag.
XIf the dirty flag is 0, the buffer is made available for further 
Xuse.  If the flag is 1, the buffer is marked "dirty", and
Xit will eventually be written out to disk.  If the flag is 2,
Xit will be immediately written out.
X
XZerobuf() returns a buffer of zeroes not belonging to any
Xdevice.  It must be bfree'd after use, and must not be
Xdirty. It is used when a read() wants to read an unallocated
Xblock of a file.
X
XBufsync() write outs all dirty blocks.
X
XNote that a pointer to a buffer structure is the same as a
Xpointer to the data.  This is very important.
X
X********************************************************/
X
Xunsigned bufclock = 0;  /* Time-stamp counter for LRU */
X
Xchar *
Xbread( dev, blk, rewrite)
Xint dev;
Xblkno_t blk;
Xint rewrite;
X{
X    register bufptr bp;
X    bufptr bfind();
X    bufptr freebuf();
X
X    if (bp = bfind(dev, blk))
X    {
X        if (bp->bf_busy)
X            panic("want busy block");
X        goto done;
X    }
X    bp = freebuf();
X
X    bp->bf_dev = dev;
X    bp->bf_blk = blk;
X
X    /* If rewrite is set, we are about to write over the entire block,
X    so we don't need the previous contents */
X
X    ifnot (rewrite)
X        if (bdread(bp) == -1)
X        {
X            udata.u_error = EIO;
X            return (NULL);
X        }
X
X    if (rewrite == 2)
X        bzero(bp->bf_data, 512);
X
Xdone:
X    bp->bf_busy = 1;
X    bp->bf_time = ++bufclock;  /* Time stamp it */
X    return (bp->bf_data);
X}
X
X
X
Xbrelse(bp)
Xbufptr bp;
X{
X    bfree(bp, 0);
X}
X
Xbawrite(bp)
Xbufptr bp;
X{
X    bfree(bp, 1);
X}
X
X
X
Xbfree(bp, dirty)
Xregister bufptr bp;
Xint dirty;
X{
X
X    bp->bf_dirty |= dirty;
X    bp->bf_busy = 0;
X
X    if (dirty == 2)   /* Extra dirty */
X    {
X        if (bdwrite(bp) == -1)
X            udata.u_error = EIO;
X        bp->bf_dirty = 0;
X        return (-1);
X    }
X    return (0);
X}
X
X
Xchar *
Xzerobuf()
X{
X    bufptr bp;
X    bufptr freebuf();
X
X    bp = freebuf();
X    bp->bf_dev = -1;
X    bzero(bp->bf_data,512);
X    return(bp->bf_data);
X}
X
X
Xbufsync()
X{
X    register bufptr bp;
X
X    for (bp=bufpool; bp < bufpool+NBUFS; ++bp)
X    {
X        if (bp->bf_dev != -1 && bp->bf_dirty)
X            bdwrite(bp);
X    }
X}
X
X
Xbufptr
Xbfind(dev, blk)
Xint dev;
Xblkno_t blk;
X{
X    register bufptr bp;
X
X    for (bp=bufpool; bp < bufpool+NBUFS; ++bp)
X    {
X        if (bp->bf_dev == dev && bp->bf_blk == blk)
X            return (bp);
X    }
X
X    return (NULL);
X}
X
X
Xbufptr
Xfreebuf()
X{
X    register bufptr bp;
X    register bufptr oldest;
X    register int oldtime;
X
X    /* Try to find a non-busy buffer 
X    and write out the data if it is dirty */
X
X    oldest = NULL;
X    oldtime = 0;
X    for (bp=bufpool; bp < bufpool+NBUFS; ++bp)
X    {
X        if (bufclock - bp->bf_time >= oldtime && !bp->bf_busy)
X        {
X            oldest = bp;
X            oldtime = bufclock - bp->bf_time;
X        }
X    }
X
X    ifnot (oldest)
X        panic("no free buffers");
X    
X    if (oldest->bf_dirty)
X    {
X        if (bdwrite(oldest) == -1)
X            udata.u_error = EIO;
X        oldest->bf_dirty = 0;
X    }
X    return (oldest);
X}
X        
X
Xbufinit()
X{
X    register bufptr bp;
X
X    for (bp=bufpool; bp < bufpool+NBUFS; ++bp)
X    {
X        bp->bf_dev = -1;
X    }
X}
X
X
Xbufdump()
X{
X    register bufptr j;
X
X    kprintf("\ndev\tblock\tdirty\tbusy\ttime clock %d\n", bufclock);
X    for (j=bufpool; j < bufpool+NBUFS; ++j)
X        kprintf("%d\t%u\t%d\t%d\t%u\n",
X            j->bf_dev,j->bf_blk,j->bf_dirty,j->bf_busy,j->bf_time);
X}
X
X
X/***************************************************
XBdread() and bdwrite() are the block device interface routines.
Xthey are given a buffer pointer, which contains the device, block number,
Xand data location.
XThey basically validate the device and vector the call.
X
XCdread() and cdwrite are the same for character (or "raw") devices,
Xand are handed a device number.
XUdata.u_base, count, and offset have the rest of the data.
X****************************************************/
X
Xbdread(bp)
Xbufptr bp;
X{
X    ifnot (validdev(bp->bf_dev))
X        panic("bdread: invalid dev");
X
X    udata.u_buf = bp;
X    return ((*dev_tab[bp->bf_dev].dev_read)(dev_tab[bp->bf_dev].minor, 0));
X}
X
Xbdwrite(bp)
Xbufptr bp;
X{
X   ifnot (validdev(bp->bf_dev))
X        panic("bdwrite: invalid dev");
X
X    udata.u_buf = bp;
X    return ((*dev_tab[bp->bf_dev].dev_write)(dev_tab[bp->bf_dev].minor, 0));
X}
X
Xcdread(dev)
Xint dev;
X{
X    ifnot (validdev(dev))
X        panic("cdread: invalid dev");
X    return ((*dev_tab[dev].dev_read)(dev_tab[dev].minor, 1));
X}
X
Xcdwrite(dev)
Xint dev;
X{
X    ifnot (validdev(dev))
X        panic("cdwrite: invalid dev");
X    return ((*dev_tab[dev].dev_write)(dev_tab[dev].minor, 1));
X}
X
X
Xswapread(dev, blkno, nbytes, buf)
Xint dev;
Xblkno_t blkno;
Xunsigned nbytes;
Xchar *buf;
X{
X    swapbase = buf;
X    swapcnt = nbytes;
X    swapblk = blkno;
X    return ((*dev_tab[dev].dev_read)(dev_tab[dev].minor, 2));
X}
X
X
Xswapwrite(dev, blkno, nbytes, buf)
Xint dev;
Xblkno_t blkno;
Xunsigned nbytes;
Xchar *buf;
X{
X    swapbase = buf;
X    swapcnt = nbytes;
X    swapblk = blkno;
X    return ((*dev_tab[dev].dev_write)(dev_tab[dev].minor, 2));
X}
X
X
X/**************************************************
XThe device driver read and write routines now have
Xonly two arguments, minor and rawflag.  If rawflag is
Xzero, a single block is desired, and the necessary data
Xcan be found in udata.u_buf.
XOtherwise, a "raw" or character read is desired, and
Xudata.u_offset, udata.u_count, and udata.u_base
Xshould be consulted instead.
XAny device other than a disk will have only raw access.
X*****************************************************/
X
X
X
Xd_open(dev)
Xint dev;
X{
X    ifnot (validdev(dev))
X        return(-1);
X    return ((*dev_tab[dev].dev_open)(dev_tab[dev].minor));
X}
X
X
Xd_close(dev)
Xint dev;
X{
X    ifnot (validdev(dev))
X        panic("d_close: bad device");
X    (*dev_tab[dev].dev_close)(dev_tab[dev].minor);
X}
X
X
X
Xd_ioctl(dev,request,data)
Xint dev;
Xint request;
Xchar *data;
X{
X    ifnot (validdev(dev))
X    {
X        udata.u_error = ENXIO;
X        return(-1);
X    }
X    if((*dev_tab[dev].dev_ioctl)(dev_tab[dev].minor,request,data))
X    {
X        udata.u_error = EINVAL;
X        return(-1);
X    }
X        return(0);
X}
X
X
Xstatic 
Xok()
X{
X    return(0);
X}
X
X
Xstatic 
Xnogood()
X{
X    return(-1);
X}
X
X
Xvaliddev(dev)
X{
X    return(dev >= 0 && dev < (sizeof(dev_tab)/sizeof(struct devsw)));
X}
X
X
X/*************************************************************
XCharacter queue management routines
X************************************************************/
X
X
X/* add something to the tail */
Xinsq(q,c)
Xregister struct s_queue *q;
Xchar c;
X{
X    di();
X    if (q->q_count == q->q_size)
X    {
X        ei();
X        return(0);
X    }
X    *(q->q_tail) = c;
X    ++q->q_count;
X    if (++q->q_tail >= q->q_base + q->q_size)
X        q->q_tail = q->q_base;
X    ei();
X    return(1);
X}
X
X/* Remove something from the head. */
Xremq(q,cp)
Xregister struct s_queue *q;
Xchar *cp;
X{
X    di();
X    ifnot (q->q_count)
X    {
X        ei();
X        return(0);
X    }
X    *cp = *(q->q_head);
X    --q->q_count;
X    if (++q->q_head >= q->q_base + q->q_size)
X        q->q_head = q->q_base;
X    ei();
X    return(1);
X}
X
X
X/* Remove something from the tail; the most recently added char. */
Xuninsq(q,cp)
Xregister struct s_queue *q;
Xchar *cp;
X{
X    di();
X    ifnot (q->q_count)
X    {
X        ei();
X        return(0);
X    }
X    --q->q_count;
X    if (--q->q_tail <= q->q_base)
X        q->q_tail = q->q_base + q->q_size - 1;
X    *cp = *(q->q_tail);
X    ei();
X    return(1);
X}
X
X
X/* Returns true if the queue has more characters than its wakeup number */
Xfullq(q)
Xstruct s_queue *q;
X{
X    di();
X    if (q->q_count > q->q_wakeup)
X    {
X        ei();
X        return (1);
X    }
X    ei();
X    return (0);
X}
X
EOF_devio.c
echo 'Done'

echo -n 'Extracting devwd.c ... '
sed 's/^X//' > devwd.c << 'EOF_devwd.c'
X/**************************************************
XUZI (Unix Z80 Implementation) Kernel:  devwd.c
X***************************************************/
X
X
X#include "unix.h"
X#include "extern.h"
X
X#define LUN 1
X#define RDCMD 0x28
X#define WRCMD 0x2a
X
Xstatic char cmdblk[10] = { 0, LUN<<5, 0, 0, 0, 0, 0, 0, 0, 0 }; 
X
Xextern char *dptr;
Xextern int dlen;
Xextern char *cptr;
Xextern int busid;
Xextern scsiop();
X
Xwd_read(minor, rawflag)
Xunsigned minor;
Xint rawflag;
X{
X    cmdblk[0] = RDCMD;
X    if (setup(minor, rawflag))
X        return(0);
X
X    chkstat(scsiop(),1);
X
X    return(cmdblk[8] << 9);
X}
X
Xwd_write(minor, rawflag)
Xunsigned minor;
Xint rawflag;
X{
X    cmdblk[0] = WRCMD;
X    if (setup(minor, rawflag))
X        return(0);
X
X    chkstat(scsiop(),0);
X    return(cmdblk[8] << 9);
X}
X
X
Xstatic
Xsetup(minor, rawflag)
Xunsigned minor;
Xint rawflag;
X{
X    register blkno_t block;
X
X    cptr = cmdblk;
X    busid = 1;
X
X    if (rawflag)
X    {
X        if (rawflag == 2)
X        {
X            cmdblk[8] = swapcnt >> 9;
X            dlen = swapcnt;
X            dptr = swapbase;
X            block = swapblk;
X        }
X        else
X        {
X            cmdblk[8] = udata.u_count >> 9;
X            dlen = udata.u_count;
X            dptr = udata.u_base;
X            block = udata.u_offset.o_blkno;
X        }       
X    }
X    else
X    {
X        cmdblk[8] = 1;
X        dlen = 512;
X        dptr = udata.u_buf->bf_data;
X        block = udata.u_buf->bf_blk;
X    }
X
X    block += (minor & 0xff00);
X    if (block > (minor << 9))
X    {
X        if (cmdblk[0] == WRCMD)
X            udata.u_error = ENXIO;
X        return (1);
X    }
X
X    cmdblk[5] = block;
X    cmdblk[4] = block >> 8;
X    return(0);
X}
X
X
Xstatic
Xchkstat(stat, rdflag)
Xint stat;
Xint rdflag;
X{
X    if (stat)
X    {
X        kprintf("wd %s failure stat %x", rdflag ? "read": "write", stat);
X        panic("");
X    }
X}
X
X
Xwd_open(minor)
Xint minor;
X{
X    return(0);
X}
X
X
X/* The following is generic SCSI driver code, also used by devmt.c */
X
Xchar *dptr;
Xint dlen;
Xchar *cptr;
Xint busid;
X
Xscsiop()
X{
X
X#asm 8080
X;
X;
XOUTIR   MACRO
XDB      0EDH
XDB      0B3H
XENDM
X;
XOUTI    MACRO
XDB      0EDH
XDB      0A3H
XENDM
X;
XSDATA   EQU     0D8H
XSCMD    EQU     0D9H
X;
XDMAPORT EQU 78H
X;
X;ENTRY POINT:
X;
X        PUSH    B
X;
XLOOP1:  CALL    SWAIT
X        JZ      HUNG    ;ABORT IF PENDING TRANSACTION
X
X        LDA     busid?  ;OUTPUT SCSI BUS ADDRESS
X        OUT     SDATA
X        MVI     A,1     ;SELECT CONTROLLER
X        OUT     SCMD    ;ASSERT SELECT
X..A2:   IN      SCMD    ;WAIT FOR BSY TO BE ASSERTED
X        ANI     01
X        JNZ     ..A2
X        XRA     A
X        OUT     SCMD    ;DEASSERT IT
X;
X        LHLD    cptr?
X.LOOP2: CALL    SWAIT   ;WAIT FOR REQ
X        JNZ     LOST
X        IN      SCMD
X        ANI     1FH
X        CPI     01100B  ;CONTINUE AS LONG AS IT WANTS COMMANDS
X        JNZ     ECMD
X        ANI     00100B
X        JZ      SEQ     ;ABORT IF IT HAS A MESSAGE
X        MOV     A,M             ;TRANSMIT COMMAND
X        OUT     SDATA
X        INX     H
X        JMP     .LOOP2
X;       
XECMD:   LHLD    dlen?
X        MOV     A,H
X        ORA     L
X        JZ      EDATA   ;SKIP DATA I/O IF NECESSARY
X        CALL    SWAIT   
X        JNZ     LOST
X        IN      SCMD    ;SEE IF IT REALLY WANTS DATA
X        ANI     10H
X        JZ      EDATA
X        IN      SCMD
X        ANI     08H     ;CHECK FOR DATA READ OR WRITE
X        JNZ     WIO
X        
X        ; FILL IN THE DMA PROGRAM WITH THE CORRECT ADDRESS AND LENGTH
X        LHLD    dptr?
X        SHLD    RDADR
X        LHLD    dlen?
X        DCX     H
X        SHLD    RDCNT
X;
X        LXI     H,RDBLK
X        MVI     B,RDLEN
X        MVI     C,DMAPORT
X        OUTIR           ;SEND PROGRAM TO DMA CONTROLLER
X        JMP     EDATA
X;
XWIO:
X        LHLD    dptr?
X        SHLD    WRADR
X        LHLD    dlen?
X        DCX     H
X        SHLD    WRCNT
X;
X        LXI     H,WRBLK
X        MVI     B,WRLEN
X        MVI     C,DMAPORT
X        OUTIR           ;SEND PROGRAM TO DMA CONTROLLER
X
X;
XEDATA:
X        CALL    SWAIT   ;WAIT UNTIL THE CONTROLLER WANTS TO SEND NON-DATA
X        JNZ     LOST
X        IN      SCMD
X        ANI     10H
X        JNZ     EDATA
X;
X;GET STATUS AND SHUT DOWN
X;
X        MVI     A,0A3H
X        OUT     DMAPORT ;TURN OFF DMA CONTROLLER
X
X        IN      SCMD
X        ANI     1FH
X        CPI     00100B
X        JNZ     SEQ     ;JUMP IF IT DOESN'T WANT TO SEND STATUS
X;
X        IN      SDATA
X        MOV     L,A
X        MVI     H,0
X        CALL    SWAIT
X        JNZ     LOST
X        IN      SCMD
X        ANI     1FH
X        CPI     00000B
X        JNZ     SEQ
X        IN      SDATA   ;READ FINAL MESSAGE BYTE
X;
XDONE:   POP     B
X        MOV     A,H
X        ORA     L
X        RET
X;
X;
XLOST:   LXI     H,-1
X        JMP     DONE
X;
XSEQ:    CALL    SWAIT
X        LXI     H,-2
X        JNZ     DONE
X        IN      SDATA   ;EAT EXTRA DATA
X        JMP     SEQ
X;
XHUNG:
X        CALL    WRESET
X        LXI     H,-3
X        JMP     DONE
X;
X; THIS WAITS FOR REQ TO BE ASSERTED OR FOR THE CONNECTION TO BE LOST.
X;A NON-ZERO RETURN MEANS CONNECTION WAS LOST
X;
XSWAIT:
X        IN      SCMD
X        ANI     01
X        RNZ             ;RETURN IF NOT EVEN BUSY
X        IN      SCMD
X        ANI     22H     ;MASK OUT REQ AND MAKE SURE ACK FROM LAST CYCLE IS GONE
X        JNZ     SWAIT
X        RET
X;
XWRESET:
X        MVI     A,2
X        OUT     SCMD
X        XTHL
X        XTHL
X        XTHL
X        XTHL
X        XRA     A
X        OUT     SCMD
X        RET
X;       
X;
X; THESE ARE THE DMA PROGRAMS FOR READ/WRITE
X;
XRDBLK:  ;PORT A IS THE CONTROLLER, PORT B IS THE MEMORY
X
X        DB      0A3H    ;RESET DMA
X        DB      01101101B       ;WR0
X        DB      SDATA
XRDCNT:  DS      2
X        DB      01101100B       ;WR1 
X        DB      11001100B       ;PORT A CYCLE LENGTH = 4
X        DB      01010000B       ;WR2
X        DB      11001101B       ;PORT B CYCLE LENGTH = 3
X        DB      11001101B       ;WR4  BURST MODE
XRDADR:  DS      2
X        DB      10001010B       ;WR5  READY ACTIVE HIGH
X        DB      0CFH    ;WR6 LOAD COMMAND
X        DB      87H     ;WR6 GO COMMAND
X
XRDLEN   EQU $ - RDBLK
X;
X;
XWRBLK:
X
X        DB      0A3H    ;RESET DMA
X        DB      01101101B       ;WR0
X        DB      SDATA
XWRCNT:  DS      2
X        DB      01101100B       ;WR1 
X        DB      11001101B       ;PORT A CYCLE LENGTH = 3 (FOR CONTROLLER)
X        DB      01010000B       ;WR2
X        DB      11001101B       ;PORT B CYCLE LENGTH = 3
X        DB      11001101B       ;WR4  BURST MODE
XWRADR:  DS      2
X        DB      10001010B       ;WR5  READY ACTIVE HIGH
X        DB      0CFH    ;WR6 LOAD COMMAND
X        DB      00000001B       ;WR0   (ONLY DIFFERENCE)
X        DB      0CFH    ;WR6 LOAD COMMAND
X        DB      87H     ;WR6 GO COMMAND
X
XWRLEN   EQU $ - WRBLK
X
X#endasm
X        
X}
X 
EOF_devwd.c
echo 'Done'

echo -n 'Extracting devflop.c ... '
sed 's/^X//' > devflop.c << 'EOF_devflop.c'
X/**************************************************
XUZI (Unix Z80 Implementation) Kernel:  devflop.c
X***************************************************/
X
X
X#include "unix.h"
X#include "extern.h"
X
Xextern ei();
X
X
X#define NUMTRKS 76
X#define NUMSECS 26
X
Xstatic char ftrack, fsector, ferror;
Xstatic char *fbuf;
X
Xstatic read(), write(), reset();
X
X
Xfd_read(minor, rawflag)
Xint16 minor;
Xint rawflag;
X{
X    return (fd(1, minor, rawflag));
X}
X
Xfd_write(minor, rawflag)
Xint16 minor;
Xint rawflag;
X{
X    return (fd(0, minor, rawflag));
X}
X
X
X
Xstatic
Xfd(rwflag, minor, rawflag)
Xint rwflag;
Xint minor;
Xint rawflag;
X{
X    register unsigned nblocks;
X    register unsigned firstblk;
X
X    if (rawflag)
X    {
X        if (rawflag == 2)
X        {
X            nblocks = swapcnt >> 7;
X            fbuf = swapbase;
X            firstblk = 4*swapblk;
X        }
X        else
X        {
X            nblocks = udata.u_count >> 7;
X            fbuf = udata.u_base;
X            firstblk = udata.u_offset.o_blkno * 4;
X        }       
X    }
X    else
X    {
X        nblocks = 4;
X        fbuf = udata.u_buf->bf_data;
X        firstblk = udata.u_buf->bf_blk * 4;
X    }
X
X    ftrack = firstblk / 26; 
X    fsector = firstblk % 26 + 1;
X    ferror = 0;
X
X    for (;;)
X    {
X        if (rwflag)
X            read();
X        else
X            write();
X
X        ifnot (--nblocks)
X            break;
X
X        if (++fsector == 27)
X        {
X            fsector = 1;
X            ++ftrack;
X        }
X        fbuf += 128;
X    }
X
X    if (ferror)
X    {
X        kprintf("fd_%s: error %d track %d sector %d\n",
X                    rwflag?"read":"write", ferror, ftrack, fsector);
X        panic("");
X    }
X
X    return(nblocks);
X}
X
X
Xfd_open(minor)
Xint minor;
X{
X    if (in(0x80) & 0x81)
X    {
X        udata.u_error = ENXIO;
X        return (-1);
X    }
X    reset();
X    return(0);
X}
X
X
Xfd_close(minor)
Xint minor;
X{
X    return(0);
X}
X
X
Xfd_ioctl(minor)
Xint minor;
X{
X    return(-1);
X}
X
X
X
X#asm 8080
X; ALL THE FUNCTIONS IN HERE ARE STATIC TO THIS PACKAGE
X
X;
X;THESE ARE 1771 FLOPPY DISK CONTROLLER COMMANDS,
X;I/O PORT ADDRESSES, AND FLAG MASKS:
X;
XRESTOR  EQU     08H     ;6MS STEP,LOAD HEAD
XSEEK    EQU     18H     ;6MS STEP,LOAD HEAD
XREADC   EQU     88H     ;NO HEAD LOAD
XWRITEC  EQU     0A8H    ;NO HEAD LOAD
XRESET   EQU     0D0H    ;RESET STATUS COMMAND
XSTATUS  EQU     80H
XCOMAND  EQU     80H
XTRACK   EQU     81H
XSECTOR  EQU     82H
XDATA    EQU     83H
XBUSY    EQU     01
XRDMASK  EQU     10011111B
XWRMASK  EQU     0FFH
X;
X;
X;THIS FLOPPY READ ROUTINE CALLS FREAD2. IF THE
X;READ IS UNSUCCESSFUL, THE DRIVE IS HOMED,
X;AND THE READ IS RETRIED.
X;
Xread?:  PUSH    B
X        CALL    FREAD2
X        LDA     ferror?
X        ANA     A       ;SET FLAGS
X        JZ      RDONE   ;READ WAS OK
X        CALL    FHOME
X        CALL    FREAD2
XRDONE:
X        POP     B
X        RET
X;
XFREAD2: CALL    FWAIT
X        LDA     fsector?
X        OUT     SECTOR
X        CALL    FTKSET
X        MVI     A,11
XFREAD3: STA     TRYNUM
X        CALL    FWAIT
X        LHLD    fbuf?
X        MVI     C,DATA
X        MVI     B,128
X        MVI     D,03
X        DI              ;ENTERING CRITICAL SECTION
X        MVI     A,READC
X        OUT     COMAND
X        XTHL    ;SHORT DELAY
X        XTHL
X        XTHL
X        XTHL
X.1LOOP: IN      STATUS
X        ANA     D
X        DCR     A
X        JZ      .1LOOP
X.Z80
X        INI
X.8080
X        JNZ     .1LOOP
X        CALL    ei?             ;LEAVING CRITICAL SECTION
X        CALL    FWAIT
X        IN      STATUS
X        ANI     RDMASK
X        JZ      FR1END
X        LDA     TRYNUM
X        DCR     A
X        JNZ     FREAD3
X        MVI     A,1
XFR1END: STA     ferror?
X        RET
X;
X;THIS IS THE FLOPPY WRITE ROUTINE. IT CALLS
X;THE ACTUAL WRITING SUBROUTINE, AND IF IT
X;WAS UNSUCCESSFUL, RESETS THE HEAD AND
X;TRIES AGAIN.
X;
Xwrite?: PUSH    B
X        CALL    FWR2
X        LDA     ferror?
X        ANA     A
X        JZ      WDONE
X        CALL    FHOME
X        CALL    FWR2
X        LDA     ferror?
XWDONE:  POP     B
X        RET
X;
XFWR2:   CALL    FWAIT
X        LDA     fsector?
X        OUT     SECTOR
X        XTHL
X        XTHL
X        MVI     A,RESET
X        OUT     COMAND
X        XTHL
X        XTHL
X        XTHL
X        XTHL
X        IN      STATUS
X        ANI     00100000B
X        JZ      FWR5    ;JMP IF HEAD NOT LOADED
X        LDA     ftrack? ;DESIRED TRACK
X        MOV     C,A
X        IN      TRACK   ;ACTUAL TRACK
X        CMP     C
X        JZ      FWR4    ;IF TRACK CORRECT
X        CALL    FTKSET
X        CALL    FWAIT
X        LXI     H,30    ;15MS DELAY
X        CALL    DELAY
X        JMP     FWR4
XFWR5:   CALL    FTKSET
X        LXI     H,50    ;25 MS DELAY
X        CALL    DELAY
X        CALL    FWAIT
X        LXI     H,20    ;15 MS DELAY
X        CALL    DELAY
XFWR4:   MVI     A,11
XFWR3:   STA     TRYNUM
X        CALL    FWAIT
X        LHLD    fbuf?
X        MVI     C,DATA
X        MVI     B,128
X        MVI     D,01
X        MVI     A,WRITEC
X        DI              ;ENTERING CRITICAL SECTION
X        OUT     COMAND
X.1A:    IN      STATUS
X        ANI     01
X        JZ      .1A
X.1B:    IN      STATUS
X        ANI     02
X        JNZ     .2LOOP
X        IN      STATUS
X        ANI     01
X        JZ      .2ERROR
X        JMP     .1B
X.2LOOP: IN      STATUS
X        XRA     D
X        JZ      .2LOOP
X.Z80
X        OUTI
X.8080
X        JNZ     .2LOOP
X        CALL    ei?             ;LEAVING CRITICAL SECTION
X        CALL    FWAIT
X        IN      STATUS
X        ANI     WRMASK
X        JZ      FW2END
X.2ERROR: LDA    TRYNUM
X        DCR     A
X        JNZ     FWR3
X        MVI     A,1
XFW2END: STA     ferror?
X        RET
X;
X;THESE 3 SUBROUTINES ARE USED BY THE FREAD2 AND
X;FWR2 ROUTINES:
X;
XFTKSET: CALL    FWAIT
X        LDA     ftrack?
X        OUT     DATA
X        MVI     A,SEEK
X        OUT     COMAND
X        RET
X;
XFWAIT:  IN      STATUS
X        ANI     10000001B
X        JNZ     FWAIT
X        RET
X;
Xreset?:
XFHOME:  PUSH    B
X        CALL    FWAIT
X        MVI     A,RESTOR
X        OUT     COMAND
X        POP     B
X        RET
X;
X        
X
X;THIS IS USED IN SEVERAL PLACES. IT GIVES
X; ( .5 * HL ) MILLISECONDS OF DELAY.
X;
XDELAY:  MVI     B,154
X.Z80
XDELAY1: DJNZ    DELAY1  ;.5 MS DELAY
X.8080
X        DCX     H
X        MOV     A,H
X        ORA     L
X        JNZ     DELAY   ;LOOP HL TIMES
X        RET
X
XTRYNUM: DS      1
X#endasm
X
EOF_devflop.c
echo 'Done'

echo -n 'Extracting devmisc.c ... '
sed 's/^X//' > devmisc.c << 'EOF_devmisc.c'
X/**************************************************
XUZI (Unix Z80 Implementation) Kernel:  devmisc.c
X***************************************************/
X
X
X#include "unix.h"
X#include "extern.h"
X
Xmem_read(minor, rawflag)
Xint minor;
Xint rawflag;
X{
X    bcopy((char *)(512*udata.u_offset.o_blkno+udata.u_offset.o_offset),
X                 udata.u_base, udata.u_count);
X    return(udata.u_count);
X}
X
Xmem_write(minor, rawflag)
Xint minor;
Xint rawflag;
X{
X    bcopy(udata.u_base,
X        (char *)(512*udata.u_offset.o_blkno+udata.u_offset.o_offset),
X                udata.u_count);
X    return(udata.u_count);
X}
X
X
X
Xnull_write(minor, rawflag)
Xint minor;
Xint rawflag;
X{
X    return(udata.u_count);
X}
X
X
X
Xstatic char lop = 0;
X
Xlpr_open()
X{
X    lop = 1;
X    return(0);
X}
X
Xlpr_close()
X{
X    if (lop)
X    {
X        lop  = 0;
X        lpout('\f');
X        lpout('\f');
X    }
X    return(0);
X}
X
X
X
Xlpr_write(minor, rawflag)
Xint minor;
Xint rawflag;
X{
X    unsigned n;
X
X    n = udata.u_count;
X    while (n--)
X        lpout(*udata.u_base++);
X    return(udata.u_count);
X}
X
X
Xlpout(c)
Xchar c;
X{
X    while(in(0x84)&02)
X        ;
X
X    out(c,0x85);
X    out(0xfe,0x86);
X    out(0xff,0x86);
X    out(0xff,0x85);
X}
X
X
X#include "devmt.c"
X
EOF_devmisc.c
echo 'Done'

echo -n 'Extracting filler.mac ... '
sed 's/^X//' > filler.mac << 'EOF_filler.mac'
X;**************************************************
X; UZI (Unix Z80 Implementation) Kernel:  filler.mac
X;**************************************************
X
X
Xdseg
Xstart:  db 1,2,3,4,5,6,7,8
X        ds 8000h-8-8-3-3-100h
X        db "MOMBASSA"
X        ;this should be at address 7ffd.
Xend     start
X
EOF_filler.mac
echo 'Done'

exit 0

Doug Braun				Intel Corp CAD
					408 765-4279

 / decwrl \
 | hplabs |
-| oliveb |- !intelca!mipos3!cadev4!dbraun
 | amd    |
 \ qantel /