home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Oakland CPM Archive
/
oakcpm.iso
/
cpm
/
uzi
/
uzi.ark
/
DEVWD.C
< prev
next >
Wrap
C/C++ Source or Header
|
1988-11-29
|
7KB
|
331 lines
/**************************************************
UZI (Unix Z80 Implementation) Kernel: devwd.c
***************************************************/
#include "unix.h"
#include "extern.h"
#define LUN 1
#define RDCMD 0x28
#define WRCMD 0x2a
static char cmdblk[10] = { 0, LUN<<5, 0, 0, 0, 0, 0, 0, 0, 0 };
extern char *dptr;
extern int dlen;
extern char *cptr;
extern int busid;
extern scsiop();
wd_read(minor, rawflag)
unsigned minor;
int rawflag;
{
cmdblk[0] = RDCMD;
if (setup(minor, rawflag))
return(0);
chkstat(scsiop(),1);
return(cmdblk[8] << 9);
}
wd_write(minor, rawflag)
unsigned minor;
int rawflag;
{
cmdblk[0] = WRCMD;
if (setup(minor, rawflag))
return(0);
chkstat(scsiop(),0);
return(cmdblk[8] << 9);
}
static
setup(minor, rawflag)
unsigned minor;
int rawflag;
{
register blkno_t block;
cptr = cmdblk;
busid = 1;
if (rawflag)
{
if (rawflag == 2)
{
cmdblk[8] = swapcnt >> 9;
dlen = swapcnt;
dptr = swapbase;
block = swapblk;
}
else
{
cmdblk[8] = udata.u_count >> 9;
dlen = udata.u_count;
dptr = udata.u_base;
block = udata.u_offset.o_blkno;
}
}
else
{
cmdblk[8] = 1;
dlen = 512;
dptr = udata.u_buf->bf_data;
block = udata.u_buf->bf_blk;
}
block += (minor & 0xff00);
if (block > (minor << 9))
{
if (cmdblk[0] == WRCMD)
udata.u_error = ENXIO;
return (1);
}
cmdblk[5] = block;
cmdblk[4] = block >> 8;
return(0);
}
static
chkstat(stat, rdflag)
int stat;
int rdflag;
{
if (stat)
{
kprintf("wd %s failure stat %x", rdflag ? "read": "write", stat);
panic("");
}
}
wd_open(minor)
int minor;
{
return(0);
}
/* The following is generic SCSI driver code, also used by devmt.c */
char *dptr;
int dlen;
char *cptr;
int busid;
scsiop()
{
#asm 8080
;
;
OUTIR MACRO
DB 0EDH
DB 0B3H
ENDM
;
OUTI MACRO
DB 0EDH
DB 0A3H
ENDM
;
SDATA EQU 0D8H
SCMD EQU 0D9H
;
DMAPORT EQU 78H
;
;ENTRY POINT:
;
PUSH B
;
LOOP1: CALL SWAIT
JZ HUNG ;ABORT IF PENDING TRANSACTION
LDA busid? ;OUTPUT SCSI BUS ADDRESS
OUT SDATA
MVI A,1 ;SELECT CONTROLLER
OUT SCMD ;ASSERT SELECT
..A2: IN SCMD ;WAIT FOR BSY TO BE ASSERTED
ANI 01
JNZ ..A2
XRA A
OUT SCMD ;DEASSERT IT
;
LHLD cptr?
.LOOP2: CALL SWAIT ;WAIT FOR REQ
JNZ LOST
IN SCMD
ANI 1FH
CPI 01100B ;CONTINUE AS LONG AS IT WANTS COMMANDS
JNZ ECMD
ANI 00100B
JZ SEQ ;ABORT IF IT HAS A MESSAGE
MOV A,M ;TRANSMIT COMMAND
OUT SDATA
INX H
JMP .LOOP2
;
ECMD: LHLD dlen?
MOV A,H
ORA L
JZ EDATA ;SKIP DATA I/O IF NECESSARY
CALL SWAIT
JNZ LOST
IN SCMD ;SEE IF IT REALLY WANTS DATA
ANI 10H
JZ EDATA
IN SCMD
ANI 08H ;CHECK FOR DATA READ OR WRITE
JNZ WIO
; FILL IN THE DMA PROGRAM WITH THE CORRECT ADDRESS AND LENGTH
LHLD dptr?
SHLD RDADR
LHLD dlen?
DCX H
SHLD RDCNT
;
LXI H,RDBLK
MVI B,RDLEN
MVI C,DMAPORT
OUTIR ;SEND PROGRAM TO DMA CONTROLLER
JMP EDATA
;
WIO:
LHLD dptr?
SHLD WRADR
LHLD dlen?
DCX H
SHLD WRCNT
;
LXI H,WRBLK
MVI B,WRLEN
MVI C,DMAPORT
OUTIR ;SEND PROGRAM TO DMA CONTROLLER
;
EDATA:
CALL SWAIT ;WAIT UNTIL THE CONTROLLER WANTS TO SEND NON-DATA
JNZ LOST
IN SCMD
ANI 10H
JNZ EDATA
;
;GET STATUS AND SHUT DOWN
;
MVI A,0A3H
OUT DMAPORT ;TURN OFF DMA CONTROLLER
IN SCMD
ANI 1FH
CPI 00100B
JNZ SEQ ;JUMP IF IT DOESN'T WANT TO SEND STATUS
;
IN SDATA
MOV L,A
MVI H,0
CALL SWAIT
JNZ LOST
IN SCMD
ANI 1FH
CPI 00000B
JNZ SEQ
IN SDATA ;READ FINAL MESSAGE BYTE
;
DONE: POP B
MOV A,H
ORA L
RET
;
;
LOST: LXI H,-1
JMP DONE
;
SEQ: CALL SWAIT
LXI H,-2
JNZ DONE
IN SDATA ;EAT EXTRA DATA
JMP SEQ
;
HUNG:
CALL WRESET
LXI H,-3
JMP DONE
;
; THIS WAITS FOR REQ TO BE ASSERTED OR FOR THE CONNECTION TO BE LOST.
;A NON-ZERO RETURN MEANS CONNECTION WAS LOST
;
SWAIT:
IN SCMD
ANI 01
RNZ ;RETURN IF NOT EVEN BUSY
IN SCMD
ANI 22H ;MASK OUT REQ AND MAKE SURE ACK FROM LAST CYCLE IS GONE
JNZ SWAIT
RET
;
WRESET:
MVI A,2
OUT SCMD
XTHL
XTHL
XTHL
XTHL
XRA A
OUT SCMD
RET
;
;
; THESE ARE THE DMA PROGRAMS FOR READ/WRITE
;
RDBLK: ;PORT A IS THE CONTROLLER, PORT B IS THE MEMORY
DB 0A3H ;RESET DMA
DB 01101101B ;WR0
DB SDATA
RDCNT: DS 2
DB 01101100B ;WR1
DB 11001100B ;PORT A CYCLE LENGTH = 4
DB 01010000B ;WR2
DB 11001101B ;PORT B CYCLE LENGTH = 3
DB 11001101B ;WR4 BURST MODE
RDADR: DS 2
DB 10001010B ;WR5 READY ACTIVE HIGH
DB 0CFH ;WR6 LOAD COMMAND
DB 87H ;WR6 GO COMMAND
RDLEN EQU $ - RDBLK
;
;
WRBLK:
DB 0A3H ;RESET DMA
DB 01101101B ;WR0
DB SDATA
WRCNT: DS 2
DB 01101100B ;WR1
DB 11001101B ;PORT A CYCLE LENGTH = 3 (FOR CONTROLLER)
DB 01010000B ;WR2
DB 11001101B ;PORT B CYCLE LENGTH = 3
DB 11001101B ;WR4 BURST MODE
WRADR: DS 2
DB 10001010B ;WR5 READY ACTIVE HIGH
DB 0CFH ;WR6 LOAD COMMAND
DB 00000001B ;WR0 (ONLY DIFFERENCE)
DB 0CFH ;WR6 LOAD COMMAND
DB 87H ;WR6 GO COMMAND
WRLEN EQU $ - WRBLK
#endasm
}