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 /