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