1 /* udc.c 1.2 86/01/21 */
2
3 #include "../machine/mtpr.h"
4
5 #include "param.h"
6 #include "inode.h"
7 #include "fs.h"
8
9 #include "../tahoevba/vbaparam.h"
10 #include "../tahoestand/udc.h"
11
12 #include "saio.h"
13
14 #ifdef NOIO
15 #define MEMDISK 0x80000 /* Memory mapped disk at 1/2 Mega */
16 #endif
17
18 /* Some I/O addresses used to generate pulses for scopes */
19 #define OUT1 0xffffb034
20 #define OUT2 0xffffb018
21 #define OUT3 0xffffb020
22 #define OUT4 0xffffb004
23 #define OUT5 0xffffb024
24 #define OUT6 0xffffb00c
25 #define OUT7 0xffffb02c
26
27 #define IN1 0xffffb030
28 #define IN2 0xffffb03c
29 #define IN3 0xffffb004
30 #define IN4 0xffffb00c
31 #define IN5 0xffffb02c
32
33 #undef scope_in
34 #undef scope_out
35 #define scope_out(x) movob(OUT/**/x,0)
36 #define scope_in(x) dummy = *(char *)(IN/**/x)
37
38 /*
39 * Universal disk controller driver for the Motorola M68000/IPC.
40 * Stand-alone version (no interrupts, etc.)
41 */
42
43
44 static struct UDPAC udpkt = {
45 2, 0, 21, 0, 0, 0, 0, SECTSIZ, {0, 0}, 0, 0, 3
46 } ;
47
48 long udstd[] = { /* May be used some day to boot from any of
49 * several UDC controllers */
50 0xf0000
51 };
52
53 /*****************************************************
54 /*
55 /*The next layout of major/minor number assignments are for the UDC
56 /*devices.
57 /*
58 /* 1
59 /* 5 8 7 4 3 2 0
60 /* +----------------+-----+-+-+-----+
61 /* | Major device # | |D|R| FLS |
62 /* +----------------+-----+-+-+-----+
63 /* | | |_____ File system # ( 0-7 )
64 /* | |_________ Fixed (0) or removable(1) media
65 /* |___________ Drive # (0-1)
66 /*
67 /* For the floppy drives, the major / minor assignment will be
68 /* 1
69 /* 5 8 7 4 3 2 0
70 /* +----------------+-----+---+-----+
71 /* | 4 | | D | FLS |
72 /* +----------------+-----+---+-----+
73 /* | |_____ File system # ( 0-7 )
74 /* |____________ Drive # (0-3)
75 /*
76 /****************************************************/
77
78 #define UDCUNIT(x) ((minor(x) & 0x18) >> 3)
79
udstrategy(io,func)80 udstrategy(io, func)
81 register struct iob *io;
82 long func; /* Known to be 'read' */
83 {
84
85 register unit = io->i_unit;
86 register bn = io->i_bn;
87 register char *cntaddr ;
88 register char *addr ;
89 register timeout , retries , i;
90 #ifdef NOIO
91 register int *memory = (int *)(bn*1024 + MEMDISK);
92 #endif
93
94 cntaddr = (char *)(udstd[0] + VBIOBASE); /* Booting from cntrlr 0 */
95 /*
96 * prepare a command packet for the controller.
97 */
98 retries = 3;
99 loop:
100 #ifndef NOIO
101 #ifndef SIMIO
102 if (cntaddr[OB1]) {
103 printf("UDC controller not ready, %x=%x\n",OB1+cntaddr,
104 cntaddr[OB1] & 0xff);
105 return(0);
106 }
107 #endif
108 #endif
109 udpkt._pkid = 0xAA ;
110 udpkt._pkdev = UDCUNIT(unit);
111 if (io->i_ino.i_dev == 3) udpkt._pkdev += 4; /* Floppy */
112 udpkt._pkmem[0] = (((long)io->i_ma) >> 16) & 0xffff;
113 udpkt._pkmem[1] = ((long)io->i_ma) & 0xffff;
114 if (func == READ) {
115 udpkt._pkcmd = UDREAD ;
116 udpkt._pkfnc = UDWTRY ;
117 } else {
118 udpkt._pkcmd = UDWRITE ;
119 udpkt._pkfnc = UDWSECT ;
120 }
121 udpkt._psecno = bn * (DEV_BSIZE/SECTSIZ);
122 udpkt._pkcnt = (io->i_cc + SECTSIZ-1)/SECTSIZ ;
123 if (movep21(&udpkt,cntaddr+0x105,sizeof(udpkt) )) {
124 #ifndef NOIO
125 #ifndef SIMIO
126 cntaddr[OB1] = (char)0x80 ; /* signal packet transmitted */
127 cntaddr[IB2] = (char)0 ; /* clear ACK/NAK field */
128 cntaddr[INT] = (char)0x0 ; /* interrupt the controller */
129 scope_out(1);
130 #else
131 dskio(&udpkt);
132 #endif
133 #endif
134 }
135 else {
136 printf ("Wrong command packet arrived at UDC\n");
137 printf ("Original UDC\n");
138 for (i = 0; i < sizeof(udpkt); i++ )
139 printf(" %0x\t%0x\n", ((char *)&udpkt)[i*2] & 0xff,
140 cntaddr[0x105+i*2] & 0xff);
141 }
142 /*
143 *
144 * Wait until done (no interrupts now).
145 *
146 */
147 wait:
148 #ifndef SIMIO
149 #ifndef NOIO
150 timeout = 100;
151 while (cntaddr[IB2] != (char)0x06 && cntaddr[IB2] != (char)0x15) {
152 /**************
153 DELAY(10000);
154 timeout--;
155 if (timeout <= 0) {
156 printf("UDC controller timeout\n");
157 return(0);
158 }
159 *****************/
160 }
161 scope_out(2);
162 if (cntaddr[IB2] == (char)0x15) {
163 if (retries-- < 0) {
164 printf("Too many NAK from UDC - give up\n");
165 return(0);
166 } else goto loop;
167 }
168
169 while (cntaddr[IB1] != (char)DEVRDY)
170 /* DELAY (10000); /* Wait for his response */;
171 scope_out(3);
172
173
174 /* Ignore unsolicited status messages */
175 if (cntaddr[PKID] != (char)udpkt._pkid && cntaddr[PKSTT] == (char)0x80)
176 {
177 cntaddr[IB1] = (char)0;
178 cntaddr[OB2] = (char)6;
179 cntaddr[INT] = (char)0x80;
180 goto loop;
181 }
182 if (cntaddr[PKID] != (char)udpkt._pkid ||
183 cntaddr[PKDEV] != (char)udpkt._pkdev ||
184 cntaddr[PKLEN] != (char)19 ||
185 cntaddr[PKCMD] != (char)udpkt._pkcmd ||
186 cntaddr[PKSTT] != (char)0x70 || /* Command completion */
187 cntaddr[STAT1] != (char)0 ||
188 cntaddr[STAT2] != (char)0 ) {
189 printf ("Strange status from UDC:\n");
190 printf("Packet id=%x,unit=%x,original command=%x,status type=%x,status=%x\n",
191 cntaddr[PKID] & 0xff,
192 cntaddr[PKDEV] & 0xff,
193 cntaddr[PKCMD] & 0xff,
194 cntaddr[PKSTT] & 0xff,
195 (cntaddr[STAT1]*256+cntaddr[STAT2]) & 0xffff);
196 if (cntaddr[PKLEN] > 9) {
197 printf("More response info : ");
198 for (i=1; i<=cntaddr[PKLEN]-9; i++)
199 printf("%x ", cntaddr[STAT2+2*i] & 0xff);
200 printf("\n");
201 }
202 cntaddr[IB1] = (char)0;
203 cntaddr[OB2] = (char)6;
204 cntaddr[INT] = (char)0x80;
205 return(0);
206 } else {
207 cntaddr[IB1] = (char)0;
208 cntaddr[OB2] = (char)6;
209 cntaddr[INT] = (char)0x80;
210 scope_out(4);
211 mtpr(PADC, 0); /* So data will come in right */
212 return(io->i_cc);
213 }
214 #else
215 for (i=0; i<io->i_cc/4; i++)
216 ((int *)io->i_buf)[i] = *memory++;
217 return(io->i_cc);
218 #endif
219 #else
220 while (udpkt._pkfnc != 0x7f) ; /* wait for completion */
221 return(io->i_cc);
222 #endif
223
224 }
225
226 /*
227 * Transfer a 21 bytes packet to the controller.
228 * the message is written to odd addresses, starting from
229 * the given address.
230 * For reliability, read it back and see if it's the same. If not,
231 * return an error code.
232 */
movep21(src,dest,cnt)233 movep21(src, dest,cnt)
234
235 char *src, *dest;
236 int cnt;
237 {
238 #ifndef NOIO
239 #ifndef SIMIO
240 register char *running_src, *running_dest;
241 register long running_cnt;
242
243 running_src = src;
244 running_dest = dest;
245 running_cnt = cnt;
246
247 for (; running_cnt>0; running_cnt--) {
248 *running_dest++ = *running_src++;
249 running_dest++;
250 }
251 running_src = src;
252 running_dest = dest;
253 running_cnt = cnt;
254 for (; running_cnt>0; running_cnt--) {
255 if (*running_dest++ != *running_src++) return(0);
256 running_dest++;
257 }
258 return(1);
259 #endif
260 #endif
261 }
262
263 udopen(io)
264 struct iob *io;
265 {
266 register char *cntaddr;
267 /*
268 * Just clean up any junk in the controller's response buffers.
269 */
270 #ifndef NOIO
271 #ifndef SIMIO
272 cntaddr = (char *)(udstd[0] + VBIOBASE); /* Booting from cntrlr 0 */
273 while (cntaddr[IB1] == (char)DEVRDY) {
274 cntaddr[IB1] = (char)0;
275 cntaddr[OB2] = (char)0x06; /* ACK */
276 cntaddr[INT] = (char)0; /* Force him to listen and to respond */
277 DELAY(50000);
278 }
279 #endif
280 #endif
281 }
282 #ifdef SIMIO
dskio(addr)283 dskio(addr)
284 {
285 asm(".byte 0x2");
286 }
287 #endif
288