-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathdevwd.c
More file actions
330 lines (294 loc) · 6.56 KB
/
devwd.c
File metadata and controls
330 lines (294 loc) · 6.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
/**************************************************
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
}