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