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 /