1*25931Ssam /* udc.c 1.2 86/01/21 */
225872Ssam
325872Ssam #include "../machine/mtpr.h"
425872Ssam
525872Ssam #include "param.h"
625872Ssam #include "inode.h"
725872Ssam #include "fs.h"
825872Ssam
9*25931Ssam #include "../tahoevba/vbaparam.h"
10*25931Ssam #include "../tahoestand/udc.h"
1125872Ssam
1225872Ssam #include "saio.h"
1325872Ssam
1425872Ssam #ifdef NOIO
1525872Ssam #define MEMDISK 0x80000 /* Memory mapped disk at 1/2 Mega */
1625872Ssam #endif
1725872Ssam
1825872Ssam /* Some I/O addresses used to generate pulses for scopes */
1925872Ssam #define OUT1 0xffffb034
2025872Ssam #define OUT2 0xffffb018
2125872Ssam #define OUT3 0xffffb020
2225872Ssam #define OUT4 0xffffb004
2325872Ssam #define OUT5 0xffffb024
2425872Ssam #define OUT6 0xffffb00c
2525872Ssam #define OUT7 0xffffb02c
2625872Ssam
2725872Ssam #define IN1 0xffffb030
2825872Ssam #define IN2 0xffffb03c
2925872Ssam #define IN3 0xffffb004
3025872Ssam #define IN4 0xffffb00c
3125872Ssam #define IN5 0xffffb02c
3225872Ssam
3325872Ssam #undef scope_in
3425872Ssam #undef scope_out
3525872Ssam #define scope_out(x) movob(OUT/**/x,0)
3625872Ssam #define scope_in(x) dummy = *(char *)(IN/**/x)
3725872Ssam
3825872Ssam /*
3925872Ssam * Universal disk controller driver for the Motorola M68000/IPC.
4025872Ssam * Stand-alone version (no interrupts, etc.)
4125872Ssam */
4225872Ssam
4325872Ssam
4425872Ssam static struct UDPAC udpkt = {
4525872Ssam 2, 0, 21, 0, 0, 0, 0, SECTSIZ, {0, 0}, 0, 0, 3
4625872Ssam } ;
4725872Ssam
4825872Ssam long udstd[] = { /* May be used some day to boot from any of
4925872Ssam * several UDC controllers */
5025872Ssam 0xf0000
5125872Ssam };
5225872Ssam
5325872Ssam /*****************************************************
5425872Ssam /*
5525872Ssam /*The next layout of major/minor number assignments are for the UDC
5625872Ssam /*devices.
5725872Ssam /*
5825872Ssam /* 1
5925872Ssam /* 5 8 7 4 3 2 0
6025872Ssam /* +----------------+-----+-+-+-----+
6125872Ssam /* | Major device # | |D|R| FLS |
6225872Ssam /* +----------------+-----+-+-+-----+
6325872Ssam /* | | |_____ File system # ( 0-7 )
6425872Ssam /* | |_________ Fixed (0) or removable(1) media
6525872Ssam /* |___________ Drive # (0-1)
6625872Ssam /*
6725872Ssam /* For the floppy drives, the major / minor assignment will be
6825872Ssam /* 1
6925872Ssam /* 5 8 7 4 3 2 0
7025872Ssam /* +----------------+-----+---+-----+
7125872Ssam /* | 4 | | D | FLS |
7225872Ssam /* +----------------+-----+---+-----+
7325872Ssam /* | |_____ File system # ( 0-7 )
7425872Ssam /* |____________ Drive # (0-3)
7525872Ssam /*
7625872Ssam /****************************************************/
7725872Ssam
7825872Ssam #define UDCUNIT(x) ((minor(x) & 0x18) >> 3)
7925872Ssam
udstrategy(io,func)8025872Ssam udstrategy(io, func)
8125872Ssam register struct iob *io;
8225872Ssam long func; /* Known to be 'read' */
8325872Ssam {
8425872Ssam
8525872Ssam register unit = io->i_unit;
8625872Ssam register bn = io->i_bn;
8725872Ssam register char *cntaddr ;
8825872Ssam register char *addr ;
8925872Ssam register timeout , retries , i;
9025872Ssam #ifdef NOIO
9125872Ssam register int *memory = (int *)(bn*1024 + MEMDISK);
9225872Ssam #endif
9325872Ssam
94*25931Ssam cntaddr = (char *)(udstd[0] + VBIOBASE); /* Booting from cntrlr 0 */
9525872Ssam /*
9625872Ssam * prepare a command packet for the controller.
9725872Ssam */
9825872Ssam retries = 3;
9925872Ssam loop:
10025872Ssam #ifndef NOIO
10125872Ssam #ifndef SIMIO
10225872Ssam if (cntaddr[OB1]) {
10325872Ssam printf("UDC controller not ready, %x=%x\n",OB1+cntaddr,
10425872Ssam cntaddr[OB1] & 0xff);
10525872Ssam return(0);
10625872Ssam }
10725872Ssam #endif
10825872Ssam #endif
10925872Ssam udpkt._pkid = 0xAA ;
11025872Ssam udpkt._pkdev = UDCUNIT(unit);
11125872Ssam if (io->i_ino.i_dev == 3) udpkt._pkdev += 4; /* Floppy */
11225872Ssam udpkt._pkmem[0] = (((long)io->i_ma) >> 16) & 0xffff;
11325872Ssam udpkt._pkmem[1] = ((long)io->i_ma) & 0xffff;
11425872Ssam if (func == READ) {
11525872Ssam udpkt._pkcmd = UDREAD ;
11625872Ssam udpkt._pkfnc = UDWTRY ;
11725872Ssam } else {
11825872Ssam udpkt._pkcmd = UDWRITE ;
11925872Ssam udpkt._pkfnc = UDWSECT ;
12025872Ssam }
12125872Ssam udpkt._psecno = bn * (DEV_BSIZE/SECTSIZ);
12225872Ssam udpkt._pkcnt = (io->i_cc + SECTSIZ-1)/SECTSIZ ;
12325872Ssam if (movep21(&udpkt,cntaddr+0x105,sizeof(udpkt) )) {
12425872Ssam #ifndef NOIO
12525872Ssam #ifndef SIMIO
12625872Ssam cntaddr[OB1] = (char)0x80 ; /* signal packet transmitted */
12725872Ssam cntaddr[IB2] = (char)0 ; /* clear ACK/NAK field */
12825872Ssam cntaddr[INT] = (char)0x0 ; /* interrupt the controller */
12925872Ssam scope_out(1);
13025872Ssam #else
13125872Ssam dskio(&udpkt);
13225872Ssam #endif
13325872Ssam #endif
13425872Ssam }
13525872Ssam else {
13625872Ssam printf ("Wrong command packet arrived at UDC\n");
13725872Ssam printf ("Original UDC\n");
13825872Ssam for (i = 0; i < sizeof(udpkt); i++ )
13925872Ssam printf(" %0x\t%0x\n", ((char *)&udpkt)[i*2] & 0xff,
14025872Ssam cntaddr[0x105+i*2] & 0xff);
14125872Ssam }
14225872Ssam /*
14325872Ssam *
14425872Ssam * Wait until done (no interrupts now).
14525872Ssam *
14625872Ssam */
14725872Ssam wait:
14825872Ssam #ifndef SIMIO
14925872Ssam #ifndef NOIO
15025872Ssam timeout = 100;
15125872Ssam while (cntaddr[IB2] != (char)0x06 && cntaddr[IB2] != (char)0x15) {
15225872Ssam /**************
15325872Ssam DELAY(10000);
15425872Ssam timeout--;
15525872Ssam if (timeout <= 0) {
15625872Ssam printf("UDC controller timeout\n");
15725872Ssam return(0);
15825872Ssam }
15925872Ssam *****************/
16025872Ssam }
16125872Ssam scope_out(2);
16225872Ssam if (cntaddr[IB2] == (char)0x15) {
16325872Ssam if (retries-- < 0) {
16425872Ssam printf("Too many NAK from UDC - give up\n");
16525872Ssam return(0);
16625872Ssam } else goto loop;
16725872Ssam }
16825872Ssam
16925872Ssam while (cntaddr[IB1] != (char)DEVRDY)
17025872Ssam /* DELAY (10000); /* Wait for his response */;
17125872Ssam scope_out(3);
17225872Ssam
17325872Ssam
17425872Ssam /* Ignore unsolicited status messages */
17525872Ssam if (cntaddr[PKID] != (char)udpkt._pkid && cntaddr[PKSTT] == (char)0x80)
17625872Ssam {
17725872Ssam cntaddr[IB1] = (char)0;
17825872Ssam cntaddr[OB2] = (char)6;
17925872Ssam cntaddr[INT] = (char)0x80;
18025872Ssam goto loop;
18125872Ssam }
18225872Ssam if (cntaddr[PKID] != (char)udpkt._pkid ||
18325872Ssam cntaddr[PKDEV] != (char)udpkt._pkdev ||
18425872Ssam cntaddr[PKLEN] != (char)19 ||
18525872Ssam cntaddr[PKCMD] != (char)udpkt._pkcmd ||
18625872Ssam cntaddr[PKSTT] != (char)0x70 || /* Command completion */
18725872Ssam cntaddr[STAT1] != (char)0 ||
18825872Ssam cntaddr[STAT2] != (char)0 ) {
18925872Ssam printf ("Strange status from UDC:\n");
19025872Ssam printf("Packet id=%x,unit=%x,original command=%x,status type=%x,status=%x\n",
19125872Ssam cntaddr[PKID] & 0xff,
19225872Ssam cntaddr[PKDEV] & 0xff,
19325872Ssam cntaddr[PKCMD] & 0xff,
19425872Ssam cntaddr[PKSTT] & 0xff,
19525872Ssam (cntaddr[STAT1]*256+cntaddr[STAT2]) & 0xffff);
19625872Ssam if (cntaddr[PKLEN] > 9) {
19725872Ssam printf("More response info : ");
19825872Ssam for (i=1; i<=cntaddr[PKLEN]-9; i++)
19925872Ssam printf("%x ", cntaddr[STAT2+2*i] & 0xff);
20025872Ssam printf("\n");
20125872Ssam }
20225872Ssam cntaddr[IB1] = (char)0;
20325872Ssam cntaddr[OB2] = (char)6;
20425872Ssam cntaddr[INT] = (char)0x80;
20525872Ssam return(0);
20625872Ssam } else {
20725872Ssam cntaddr[IB1] = (char)0;
20825872Ssam cntaddr[OB2] = (char)6;
20925872Ssam cntaddr[INT] = (char)0x80;
21025872Ssam scope_out(4);
21125872Ssam mtpr(PADC, 0); /* So data will come in right */
21225872Ssam return(io->i_cc);
21325872Ssam }
21425872Ssam #else
21525872Ssam for (i=0; i<io->i_cc/4; i++)
21625872Ssam ((int *)io->i_buf)[i] = *memory++;
21725872Ssam return(io->i_cc);
21825872Ssam #endif
21925872Ssam #else
22025872Ssam while (udpkt._pkfnc != 0x7f) ; /* wait for completion */
22125872Ssam return(io->i_cc);
22225872Ssam #endif
22325872Ssam
22425872Ssam }
22525872Ssam
22625872Ssam /*
22725872Ssam * Transfer a 21 bytes packet to the controller.
22825872Ssam * the message is written to odd addresses, starting from
22925872Ssam * the given address.
23025872Ssam * For reliability, read it back and see if it's the same. If not,
23125872Ssam * return an error code.
23225872Ssam */
movep21(src,dest,cnt)23325872Ssam movep21(src, dest,cnt)
23425872Ssam
23525872Ssam char *src, *dest;
23625872Ssam int cnt;
23725872Ssam {
23825872Ssam #ifndef NOIO
23925872Ssam #ifndef SIMIO
24025872Ssam register char *running_src, *running_dest;
24125872Ssam register long running_cnt;
24225872Ssam
24325872Ssam running_src = src;
24425872Ssam running_dest = dest;
24525872Ssam running_cnt = cnt;
24625872Ssam
24725872Ssam for (; running_cnt>0; running_cnt--) {
24825872Ssam *running_dest++ = *running_src++;
24925872Ssam running_dest++;
25025872Ssam }
25125872Ssam running_src = src;
25225872Ssam running_dest = dest;
25325872Ssam running_cnt = cnt;
25425872Ssam for (; running_cnt>0; running_cnt--) {
25525872Ssam if (*running_dest++ != *running_src++) return(0);
25625872Ssam running_dest++;
25725872Ssam }
25825872Ssam return(1);
25925872Ssam #endif
26025872Ssam #endif
26125872Ssam }
26225872Ssam
26325872Ssam udopen(io)
26425872Ssam struct iob *io;
26525872Ssam {
26625872Ssam register char *cntaddr;
26725872Ssam /*
26825872Ssam * Just clean up any junk in the controller's response buffers.
26925872Ssam */
27025872Ssam #ifndef NOIO
27125872Ssam #ifndef SIMIO
272*25931Ssam cntaddr = (char *)(udstd[0] + VBIOBASE); /* Booting from cntrlr 0 */
27325872Ssam while (cntaddr[IB1] == (char)DEVRDY) {
27425872Ssam cntaddr[IB1] = (char)0;
27525872Ssam cntaddr[OB2] = (char)0x06; /* ACK */
27625872Ssam cntaddr[INT] = (char)0; /* Force him to listen and to respond */
27725872Ssam DELAY(50000);
27825872Ssam }
27925872Ssam #endif
28025872Ssam #endif
28125872Ssam }
28225872Ssam #ifdef SIMIO
dskio(addr)28325872Ssam dskio(addr)
28425872Ssam {
28525872Ssam asm(".byte 0x2");
28625872Ssam }
28725872Ssam #endif
288