xref: /csrg-svn/sys/tahoe/stand/udc.c (revision 25931)
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