xref: /original-bsd/sys/tahoe/stand/udc.c (revision 15ab15aa)
1*15ab15aaSsam /*	udc.c	1.2	86/01/21	*/
2055f71fcSsam 
3055f71fcSsam #include "../machine/mtpr.h"
4055f71fcSsam 
5055f71fcSsam #include "param.h"
6055f71fcSsam #include "inode.h"
7055f71fcSsam #include "fs.h"
8055f71fcSsam 
9*15ab15aaSsam #include "../tahoevba/vbaparam.h"
10*15ab15aaSsam #include "../tahoestand/udc.h"
11055f71fcSsam 
12055f71fcSsam #include "saio.h"
13055f71fcSsam 
14055f71fcSsam #ifdef	NOIO
15055f71fcSsam #define	MEMDISK	0x80000		/* Memory mapped disk at 1/2 Mega */
16055f71fcSsam #endif
17055f71fcSsam 
18055f71fcSsam /*  Some I/O addresses used to generate pulses for scopes */
19055f71fcSsam #define	OUT1	0xffffb034
20055f71fcSsam #define	OUT2	0xffffb018
21055f71fcSsam #define	OUT3	0xffffb020
22055f71fcSsam #define	OUT4	0xffffb004
23055f71fcSsam #define	OUT5	0xffffb024
24055f71fcSsam #define	OUT6	0xffffb00c
25055f71fcSsam #define	OUT7	0xffffb02c
26055f71fcSsam 
27055f71fcSsam #define	IN1	0xffffb030
28055f71fcSsam #define	IN2	0xffffb03c
29055f71fcSsam #define	IN3	0xffffb004
30055f71fcSsam #define	IN4	0xffffb00c
31055f71fcSsam #define	IN5	0xffffb02c
32055f71fcSsam 
33055f71fcSsam #undef	scope_in
34055f71fcSsam #undef	scope_out
35055f71fcSsam #define	scope_out(x)	movob(OUT/**/x,0)
36055f71fcSsam #define	scope_in(x)	dummy =  *(char *)(IN/**/x)
37055f71fcSsam 
38055f71fcSsam /*
39055f71fcSsam  *  Universal disk controller driver for the Motorola M68000/IPC.
40055f71fcSsam  *	Stand-alone version (no interrupts, etc.)
41055f71fcSsam  */
42055f71fcSsam 
43055f71fcSsam 
44055f71fcSsam static struct UDPAC udpkt = {
45055f71fcSsam 	2, 0, 21, 0, 0, 0, 0, SECTSIZ, {0, 0}, 0, 0, 3
46055f71fcSsam } ;
47055f71fcSsam 
48055f71fcSsam long udstd[] = { 	/* May be used some day to boot from any of
49055f71fcSsam 			 *  several UDC controllers */
50055f71fcSsam 	0xf0000
51055f71fcSsam };
52055f71fcSsam 
53055f71fcSsam /*****************************************************
54055f71fcSsam /*
55055f71fcSsam /*The next layout of major/minor number assignments are for the UDC
56055f71fcSsam /*devices.
57055f71fcSsam /*
58055f71fcSsam /* 	  1
59055f71fcSsam /*	  5		 8 7     4 3 2   0
60055f71fcSsam /*	 +----------------+-----+-+-+-----+
61055f71fcSsam /*	 | Major device # |     |D|R| FLS |
62055f71fcSsam /*	 +----------------+-----+-+-+-----+
63055f71fcSsam /*				 | |   |_____ File system # ( 0-7 )
64055f71fcSsam /*				 | |_________ Fixed (0) or removable(1) media
65055f71fcSsam /*				 |___________ Drive # (0-1)
66055f71fcSsam /*
67055f71fcSsam /* For the floppy drives, the major / minor assignment will be
68055f71fcSsam /* 	  1
69055f71fcSsam /*	  5		 8 7     4 3 2   0
70055f71fcSsam /*	 +----------------+-----+---+-----+
71055f71fcSsam /*	 |      4         |     | D | FLS |
72055f71fcSsam /*	 +----------------+-----+---+-----+
73055f71fcSsam /*				  |    |_____ File system # ( 0-7 )
74055f71fcSsam /*				  |____________ Drive # (0-3)
75055f71fcSsam /*
76055f71fcSsam /****************************************************/
77055f71fcSsam 
78055f71fcSsam #define	UDCUNIT(x)	((minor(x) & 0x18) >> 3)
79055f71fcSsam 
udstrategy(io,func)80055f71fcSsam udstrategy(io, func)
81055f71fcSsam register struct iob *io;
82055f71fcSsam long func;		/* Known to be 'read' */
83055f71fcSsam {
84055f71fcSsam 
85055f71fcSsam 	register unit = io->i_unit;
86055f71fcSsam 	register bn = io->i_bn;
87055f71fcSsam 	register char *cntaddr ;
88055f71fcSsam 	register char *addr ;
89055f71fcSsam 	register timeout , retries , i;
90055f71fcSsam #ifdef NOIO
91055f71fcSsam 	register int	*memory = (int *)(bn*1024 + MEMDISK);
92055f71fcSsam #endif
93055f71fcSsam 
94*15ab15aaSsam 	cntaddr = (char *)(udstd[0] + VBIOBASE); /* Booting from cntrlr 0 */
95055f71fcSsam 	/*
96055f71fcSsam 	 * prepare a command packet for the controller.
97055f71fcSsam 	 */
98055f71fcSsam 	retries = 3;
99055f71fcSsam loop:
100055f71fcSsam #ifndef NOIO
101055f71fcSsam #ifndef SIMIO
102055f71fcSsam 	if (cntaddr[OB1]) {
103055f71fcSsam 		printf("UDC controller not ready, %x=%x\n",OB1+cntaddr,
104055f71fcSsam 			cntaddr[OB1] & 0xff);
105055f71fcSsam 		return(0);
106055f71fcSsam 	}
107055f71fcSsam #endif
108055f71fcSsam #endif
109055f71fcSsam 	udpkt._pkid = 0xAA ;
110055f71fcSsam  	udpkt._pkdev = UDCUNIT(unit);
111055f71fcSsam 	if (io->i_ino.i_dev == 3) udpkt._pkdev += 4;  /* Floppy */
112055f71fcSsam 	udpkt._pkmem[0] = (((long)io->i_ma) >> 16) & 0xffff;
113055f71fcSsam 	udpkt._pkmem[1] = ((long)io->i_ma) & 0xffff;
114055f71fcSsam 	if (func == READ) {
115055f71fcSsam 		udpkt._pkcmd = UDREAD ;
116055f71fcSsam 		udpkt._pkfnc = UDWTRY ;
117055f71fcSsam 	} else {
118055f71fcSsam 		udpkt._pkcmd = UDWRITE ;
119055f71fcSsam 		udpkt._pkfnc = UDWSECT ;
120055f71fcSsam 	}
121055f71fcSsam 	udpkt._psecno = bn * (DEV_BSIZE/SECTSIZ);
122055f71fcSsam 	udpkt._pkcnt = (io->i_cc + SECTSIZ-1)/SECTSIZ ;
123055f71fcSsam 	if (movep21(&udpkt,cntaddr+0x105,sizeof(udpkt) )) {
124055f71fcSsam #ifndef NOIO
125055f71fcSsam #ifndef SIMIO
126055f71fcSsam 		cntaddr[OB1] = (char)0x80 ;		/* signal packet transmitted */
127055f71fcSsam 		cntaddr[IB2] = (char)0 ;		/* clear ACK/NAK field */
128055f71fcSsam 		cntaddr[INT] = (char)0x0 ;		/* interrupt the controller */
129055f71fcSsam 		scope_out(1);
130055f71fcSsam #else
131055f71fcSsam 		dskio(&udpkt);
132055f71fcSsam #endif
133055f71fcSsam #endif
134055f71fcSsam 	}
135055f71fcSsam 	else {
136055f71fcSsam 		printf ("Wrong command packet arrived at UDC\n");
137055f71fcSsam 		printf ("Original	UDC\n");
138055f71fcSsam 		for (i = 0; i < sizeof(udpkt); i++ )
139055f71fcSsam 			printf("   %0x\t%0x\n", ((char *)&udpkt)[i*2] & 0xff,
140055f71fcSsam 				cntaddr[0x105+i*2] & 0xff);
141055f71fcSsam 	}
142055f71fcSsam /*
143055f71fcSsam  *
144055f71fcSsam  * Wait until done (no interrupts now).
145055f71fcSsam  *
146055f71fcSsam  */
147055f71fcSsam wait:
148055f71fcSsam #ifndef SIMIO
149055f71fcSsam #ifndef NOIO
150055f71fcSsam 	timeout  =  100;
151055f71fcSsam 	while (cntaddr[IB2] != (char)0x06 && cntaddr[IB2] != (char)0x15) {
152055f71fcSsam /**************
153055f71fcSsam 		DELAY(10000);
154055f71fcSsam 		timeout--;
155055f71fcSsam 		if (timeout <= 0) {
156055f71fcSsam 			printf("UDC controller timeout\n");
157055f71fcSsam 			return(0);
158055f71fcSsam 		}
159055f71fcSsam *****************/
160055f71fcSsam 	}
161055f71fcSsam 	scope_out(2);
162055f71fcSsam 	if (cntaddr[IB2] == (char)0x15) {
163055f71fcSsam 		if (retries-- < 0) {
164055f71fcSsam 			printf("Too many NAK from UDC - give up\n");
165055f71fcSsam 			return(0);
166055f71fcSsam 		} else goto loop;
167055f71fcSsam 	}
168055f71fcSsam 
169055f71fcSsam 	while (cntaddr[IB1] != (char)DEVRDY)
170055f71fcSsam /*		DELAY (10000);		/* Wait for his response */;
171055f71fcSsam 	scope_out(3);
172055f71fcSsam 
173055f71fcSsam 
174055f71fcSsam 	/* Ignore unsolicited status messages */
175055f71fcSsam 	if (cntaddr[PKID] != (char)udpkt._pkid && cntaddr[PKSTT] == (char)0x80)
176055f71fcSsam 	{
177055f71fcSsam 		cntaddr[IB1] = (char)0;
178055f71fcSsam 		cntaddr[OB2] = (char)6;
179055f71fcSsam 		cntaddr[INT] = (char)0x80;
180055f71fcSsam 		goto loop;
181055f71fcSsam 	}
182055f71fcSsam 	if (cntaddr[PKID] != (char)udpkt._pkid ||
183055f71fcSsam 		cntaddr[PKDEV] != (char)udpkt._pkdev ||
184055f71fcSsam 		cntaddr[PKLEN] != (char)19 ||
185055f71fcSsam 		cntaddr[PKCMD] != (char)udpkt._pkcmd ||
186055f71fcSsam 		cntaddr[PKSTT] != (char)0x70 ||	/* Command completion */
187055f71fcSsam 		cntaddr[STAT1] != (char)0 ||
188055f71fcSsam 		cntaddr[STAT2] != (char)0 ) {
189055f71fcSsam 			printf ("Strange status from UDC:\n");
190055f71fcSsam 			printf("Packet id=%x,unit=%x,original command=%x,status type=%x,status=%x\n",
191055f71fcSsam 			cntaddr[PKID] & 0xff,
192055f71fcSsam 			cntaddr[PKDEV] & 0xff,
193055f71fcSsam 			cntaddr[PKCMD] & 0xff,
194055f71fcSsam 			cntaddr[PKSTT] & 0xff,
195055f71fcSsam 			(cntaddr[STAT1]*256+cntaddr[STAT2]) & 0xffff);
196055f71fcSsam 			if  (cntaddr[PKLEN] > 9) {
197055f71fcSsam 				printf("More response info : ");
198055f71fcSsam 				for (i=1; i<=cntaddr[PKLEN]-9; i++)
199055f71fcSsam 					printf("%x ", cntaddr[STAT2+2*i] & 0xff);
200055f71fcSsam 				printf("\n");
201055f71fcSsam 			}
202055f71fcSsam 			cntaddr[IB1] = (char)0;
203055f71fcSsam 			cntaddr[OB2] = (char)6;
204055f71fcSsam 			cntaddr[INT] = (char)0x80;
205055f71fcSsam 			return(0);
206055f71fcSsam 	} else {
207055f71fcSsam 		cntaddr[IB1] = (char)0;
208055f71fcSsam 		cntaddr[OB2] = (char)6;
209055f71fcSsam 		cntaddr[INT] = (char)0x80;
210055f71fcSsam 		scope_out(4);
211055f71fcSsam 		mtpr(PADC, 0);		/* So data will come in right */
212055f71fcSsam 		return(io->i_cc);
213055f71fcSsam 	  }
214055f71fcSsam #else
215055f71fcSsam 	for (i=0; i<io->i_cc/4; i++)
216055f71fcSsam 		((int *)io->i_buf)[i] = *memory++;
217055f71fcSsam 	return(io->i_cc);
218055f71fcSsam #endif
219055f71fcSsam #else
220055f71fcSsam 	while (udpkt._pkfnc != 0x7f) ;		/* wait for completion */
221055f71fcSsam 	return(io->i_cc);
222055f71fcSsam #endif
223055f71fcSsam 
224055f71fcSsam }
225055f71fcSsam 
226055f71fcSsam /*
227055f71fcSsam  *	Transfer a 21 bytes packet to the controller.
228055f71fcSsam  *  the message is written to odd addresses, starting from
229055f71fcSsam  *  the given address.
230055f71fcSsam  *	For reliability, read it back and see if it's the same. If not,
231055f71fcSsam  *  return an error code.
232055f71fcSsam  */
movep21(src,dest,cnt)233055f71fcSsam movep21(src, dest,cnt)
234055f71fcSsam 
235055f71fcSsam char	*src, *dest;
236055f71fcSsam int cnt;
237055f71fcSsam {
238055f71fcSsam #ifndef	NOIO
239055f71fcSsam #ifndef SIMIO
240055f71fcSsam 	register char *running_src,  *running_dest;
241055f71fcSsam 	register long running_cnt;
242055f71fcSsam 
243055f71fcSsam 	running_src = src;
244055f71fcSsam 	running_dest = dest;
245055f71fcSsam 	running_cnt = cnt;
246055f71fcSsam 
247055f71fcSsam 	for (; running_cnt>0; running_cnt--) {
248055f71fcSsam 		*running_dest++ = *running_src++;
249055f71fcSsam 		running_dest++;
250055f71fcSsam 	}
251055f71fcSsam 	running_src = src;
252055f71fcSsam 	running_dest = dest;
253055f71fcSsam 	running_cnt = cnt;
254055f71fcSsam 	for (; running_cnt>0; running_cnt--) {
255055f71fcSsam 		if (*running_dest++ != *running_src++) return(0);
256055f71fcSsam 		running_dest++;
257055f71fcSsam 	}
258055f71fcSsam 	return(1);
259055f71fcSsam #endif
260055f71fcSsam #endif
261055f71fcSsam }
262055f71fcSsam 
263055f71fcSsam udopen(io)
264055f71fcSsam struct iob *io;
265055f71fcSsam {
266055f71fcSsam 	register char *cntaddr;
267055f71fcSsam /*
268055f71fcSsam  * Just clean up any junk in the controller's response buffers.
269055f71fcSsam  */
270055f71fcSsam #ifndef NOIO
271055f71fcSsam #ifndef SIMIO
272*15ab15aaSsam 	cntaddr = (char *)(udstd[0] + VBIOBASE); /* Booting from cntrlr 0 */
273055f71fcSsam 	while (cntaddr[IB1] == (char)DEVRDY) {
274055f71fcSsam 		cntaddr[IB1] = (char)0;
275055f71fcSsam 		cntaddr[OB2] = (char)0x06;  /* ACK */
276055f71fcSsam 		cntaddr[INT] = (char)0;	/* Force him to listen and to respond */
277055f71fcSsam 		DELAY(50000);
278055f71fcSsam 	}
279055f71fcSsam #endif
280055f71fcSsam #endif
281055f71fcSsam }
282055f71fcSsam #ifdef SIMIO
dskio(addr)283055f71fcSsam dskio(addr)
284055f71fcSsam {
285055f71fcSsam 	asm(".byte 0x2");
286055f71fcSsam }
287055f71fcSsam #endif
288