xref: /original-bsd/sys/tahoe/stand/udc.c (revision e59fb703)
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 
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  */
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
283 dskio(addr)
284 {
285 	asm(".byte 0x2");
286 }
287 #endif
288