xref: /csrg-svn/sys/vax/stand/uda.c (revision 32613)
123247Smckusick /*
229315Smckusick  * Copyright (c) 1982, 1986 Regents of the University of California.
323247Smckusick  * All rights reserved.  The Berkeley software License Agreement
423247Smckusick  * specifies the terms and conditions for redistribution.
523247Smckusick  *
6*32613Sbostic  *	@(#)uda.c	7.4 (Berkeley) 11/13/87
723247Smckusick  */
85153Ssam 
95153Ssam /*
105153Ssam  * UDA50/RAxx disk device driver
115153Ssam  */
129806Ssam #include "../machine/pte.h"
135153Ssam 
14*32613Sbostic #include "param.h"
15*32613Sbostic #include "inode.h"
16*32613Sbostic #include "fs.h"
17*32613Sbostic #include "disklabel.h"
189186Ssam 
195153Ssam #include "saio.h"
205153Ssam #include "savax.h"
215153Ssam 
22*32613Sbostic #define	NRA		8	/* max. unit number on controller */
2330547Skarels #define	SECTSIZ 	512	/* sector size in bytes */
24*32613Sbostic 
255153Ssam /*
26*32613Sbostic  * Unused, but needed in udareg.h
275153Ssam  */
28*32613Sbostic #define NRSP	1
29*32613Sbostic #define NCMD	1
305153Ssam 
319186Ssam #include "../vaxuba/udareg.h"
329186Ssam #include "../vaxuba/ubareg.h"
339186Ssam #include "../vax/mscp.h"
345153Ssam 
3511181Ssam u_short udastd[] = { 0772150 };
365153Ssam 
375153Ssam struct iob	cudbuf;
385153Ssam 
3930547Skarels /*
4030547Skarels  * Per-controller structures use dimension MAXNUBA,
4130547Skarels  * as only one controller per UNIBUS is supported.
4230547Skarels  */
4330547Skarels struct udadevice *udaddr[MAXNUBA] = { 0 };
445153Ssam 
45*32613Sbostic struct	uda1 {
46*32613Sbostic 	struct	uda1ca uda1_ca;	/* communications area */
47*32613Sbostic 	struct	mscp uda1_rsp;	/* response packet */
48*32613Sbostic 	struct	mscp uda1_cmd;	/* command packet */
49*32613Sbostic } uda1;
505153Ssam 
51*32613Sbostic struct	uda1 *ud_ubaddr[MAXNUBA];	/* Unibus address of uda structure */
5230547Skarels struct	disklabel ralabel[MAXNUBA * NRA];
5330547Skarels static	int ratype[MAXNUBA * NRA];
5430547Skarels char	lbuf[SECTSIZ];
5530547Skarels struct	mscp *udcmd();
565153Ssam 
5711111Ssam raopen(io)
585153Ssam 	register struct iob *io;
595153Ssam {
605153Ssam 	register struct mscp *mp;
61*32613Sbostic 	register struct disklabel *lp, *dlp;
6230547Skarels 	register struct udadevice *addr;
63*32613Sbostic 	register struct uda1 *ubaddr;
6430547Skarels 	register unit;
65*32613Sbostic 	static int udainit[MAXNUBA];
6630547Skarels 	int uba;
675153Ssam 
6830547Skarels 	unit = io->i_unit;
6930547Skarels 	uba = UNITTOUBA(unit);
7030547Skarels 	if (udaddr[uba] == 0)
7130547Skarels 		udaddr[uba] = (struct udadevice *)ubamem(unit, udastd[0]);
7230547Skarels 	addr = udaddr[uba];
7330547Skarels 	if (badaddr((char *)addr, sizeof(short))) {
7432194Skarels 		printf("nonexistent device\n");
7530547Skarels 		return (ENXIO);
7630547Skarels 	}
7730547Skarels 	if (ud_ubaddr[uba] == 0) {
7817231Smckusick 		/*
7930547Skarels 		 * Initialize cudbuf.i_unit so that controllers
8017231Smckusick 		 * on UNIBUSes other than 0 can be used.
8117231Smckusick 		 */
8230547Skarels 		cudbuf.i_unit = unit;
83*32613Sbostic 		cudbuf.i_ma = (caddr_t)&uda1;
84*32613Sbostic 		cudbuf.i_cc = sizeof(uda1);
85*32613Sbostic 		ud_ubaddr[uba] = (struct uda1 *)ubasetup(&cudbuf, 2);
865153Ssam 	}
8730547Skarels 	ubaddr = ud_ubaddr[uba];
8830547Skarels 	if (udainit[uba] == 0) {
8930547Skarels 		addr->udaip = 0;
9030547Skarels 		while ((addr->udasa & UDA_STEP1) == 0)
9117231Smckusick 			;
9230547Skarels 		addr->udasa = UDA_ERR;
9330547Skarels 		while ((addr->udasa & UDA_STEP2) == 0)
9417231Smckusick 			;
95*32613Sbostic 		addr->udasa = (short)&ubaddr->uda1_ca.ca_rspdsc;
9630547Skarels 		while ((addr->udasa & UDA_STEP3) == 0)
9717231Smckusick 			;
9830547Skarels 		addr->udasa =
99*32613Sbostic 		    (short)(((int)&ubaddr->uda1_ca.ca_rspdsc) >> 16);
10030547Skarels 		while ((addr->udasa & UDA_STEP4) == 0)
10117231Smckusick 			;
10230547Skarels 		addr->udasa = UDA_GO;
103*32613Sbostic 		uda1.uda1_ca.ca_rspdsc = (long)&ubaddr->uda1_rsp.mscp_cmdref;
104*32613Sbostic 		uda1.uda1_ca.ca_cmddsc = (long)&ubaddr->uda1_cmd.mscp_cmdref;
105*32613Sbostic 		/* uda1.uda1_cmd.mscp_cntflgs = 0; */
106*32613Sbostic 		if (udcmd(M_OP_SETCTLRC, io) == 0) {
107*32613Sbostic 			printf("ra: open error, SETCTLRC\n");
10830547Skarels 			return (EIO);
10917231Smckusick 		}
110*32613Sbostic 		udainit[uba] = 1;
11127075Skarels 	}
11230547Skarels 	lp = &ralabel[unit];
113*32613Sbostic 	if (ratype[unit] == 0) {
11430547Skarels 		struct iob tio;
11530547Skarels 
116*32613Sbostic 		uda1.uda1_cmd.mscp_unit = UNITTODRIVE(unit);
117*32613Sbostic 		if (udcmd(M_OP_ONLINE, io) == 0) {
118*32613Sbostic 			printf("ra: open error, ONLINE\n");
11930547Skarels 			return (EIO);
12017231Smckusick 		}
12130547Skarels 		tio = *io;
12230547Skarels 		tio.i_bn = LABELSECTOR;
12330547Skarels 		tio.i_ma = lbuf;
12430547Skarels 		tio.i_cc = SECTSIZ;
12530547Skarels 		tio.i_flgs |= F_RDDATA;
12630547Skarels 		if (rastrategy(&tio, READ) != SECTSIZ) {
12732194Skarels 			printf("can't read disk label\n");
12830547Skarels 			return (EIO);
12930547Skarels 		}
130*32613Sbostic 		dlp = (struct disklabel *)(lbuf + LABELOFFSET);
131*32613Sbostic 		if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
13230547Skarels 			printf("ra%d: unlabeled\n", unit);
13330547Skarels #ifdef COMPAT_42
13430547Skarels 			ramaptype(io, lp);
13530547Skarels #else
13630547Skarels 			return (ENXIO);
13730547Skarels #endif
13832194Skarels 		} else
139*32613Sbostic 			*lp = *dlp;
1405153Ssam 	}
14130547Skarels 	if ((unsigned)io->i_boff >= lp->d_npartitions ||
14230547Skarels 	    (io->i_boff = lp->d_partitions[io->i_boff].p_offset) == -1) {
14332194Skarels 		printf("ra: bad partition\n");
14430547Skarels 		return (EUNIT);
14527075Skarels 	}
14630547Skarels 	return (0);
1475153Ssam }
1485153Ssam 
1495153Ssam struct mscp *
15030547Skarels udcmd(op, io)
1515153Ssam 	int op;
15230547Skarels 	register struct iob *io;
1535153Ssam {
154*32613Sbostic 	register struct mscp *mp;
1555153Ssam 	int i;
1565153Ssam 
157*32613Sbostic 	uda1.uda1_cmd.mscp_opcode = op;
158*32613Sbostic 	uda1.uda1_cmd.mscp_msglen = MSCP_MSGLEN;
159*32613Sbostic 	uda1.uda1_rsp.mscp_msglen = MSCP_MSGLEN;
160*32613Sbostic 	uda1.uda1_ca.ca_rspdsc |= MSCP_OWN|MSCP_INT;
161*32613Sbostic 	uda1.uda1_ca.ca_cmddsc |= MSCP_OWN|MSCP_INT;
16230547Skarels 	i = udaddr[UNITTOUBA(io->i_unit)]->udaip;
163*32613Sbostic 	mp = &uda1.uda1_rsp;
1645153Ssam 	for (;;) {
165*32613Sbostic 		if (uda1.uda1_ca.ca_cmdint)
166*32613Sbostic 			uda1.uda1_ca.ca_cmdint = 0;
167*32613Sbostic 		if (uda1.uda1_ca.ca_rspint == 0)
168*32613Sbostic 			continue;
169*32613Sbostic 		uda1.uda1_ca.ca_rspint = 0;
170*32613Sbostic 		if (mp->mscp_opcode == (op | M_OP_END))
1715153Ssam 			break;
172*32613Sbostic 		printf("unexpected mscp response (type 0x%x) ignored",
173*32613Sbostic 				MSCP_MSGTYPE(mp->mscp_msgtc));
174*32613Sbostic 		uda1.uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT;
1755153Ssam 	}
176*32613Sbostic 	if ((mp->mscp_status&M_ST_MASK) != M_ST_SUCCESS)
1775153Ssam 		return(0);
178*32613Sbostic 	if (mp->mscp_opcode == (M_OP_ONLINE|M_OP_END))
179*32613Sbostic 		ratype[io->i_unit] = mp->mscp_onle.onle_drivetype;
1805153Ssam 	return(mp);
1815153Ssam }
1825153Ssam 
18311111Ssam rastrategy(io, func)
1845153Ssam 	register struct iob *io;
1855153Ssam {
1865153Ssam 	register struct mscp *mp;
1875153Ssam 	int ubinfo;
1885153Ssam 
1895153Ssam 	ubinfo = ubasetup(io, 1);
190*32613Sbostic 	mp = &uda1.uda1_cmd;
19132194Skarels 	mp->mscp_unit = UNITTODRIVE(io->i_unit);
192*32613Sbostic 	mp->mscp_seq.seq_lbn = io->i_bn;
193*32613Sbostic 	mp->mscp_seq.seq_bytecount = io->i_cc;
194*32613Sbostic 	mp->mscp_seq.seq_buffer = (ubinfo & 0x3ffff) | (((ubinfo>>28)&0xf)<<24);
19530547Skarels 	if ((mp = udcmd(func == READ ? M_OP_READ : M_OP_WRITE, io)) == 0) {
1965153Ssam 		printf("ra: I/O error\n");
1975153Ssam 		ubafree(io, ubinfo);
1985153Ssam 		return(-1);
1995153Ssam 	}
2005153Ssam 	ubafree(io, ubinfo);
2015153Ssam 	return(io->i_cc);
2025153Ssam }
20310024Ssam 
20410024Ssam /*ARGSUSED*/
20511111Ssam raioctl(io, cmd, arg)
20610024Ssam 	struct iob *io;
20710024Ssam 	int cmd;
20810024Ssam 	caddr_t arg;
20910024Ssam {
21010024Ssam 
21110024Ssam 	return (ECMD);
21210024Ssam }
21330547Skarels 
21430547Skarels #ifdef COMPAT_42
21530547Skarels u_long ra25_off[] = { 0, 15884, 0, -1, -1, -1, 25916, -1 };
216*32613Sbostic u_long rx50_off[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
217*32613Sbostic u_long rd52_off[] = { 0, 15884, 0, 0, 0, 0, 25650, 0 };
218*32613Sbostic u_long rd53_off[] = { 0, 15884, 0, 0, 0, 33440, 49324, 15884 };
21930547Skarels u_long ra60_off[] = { 0, 15884, 0, 49324, 131404, 49324, 242606, 49324 };
22030547Skarels u_long ra80_off[] = { 0, 15884, 0, -1, 49324, 49324, 49910, 131404 };
22130547Skarels #ifndef	UCBRA
22230547Skarels #ifdef RA_COMPAT
22330547Skarels u_long ra81_off[] = { 0, 16422, 0, 49324, 131404, 412490, 375564, 83538 };
22430547Skarels #else
22530547Skarels u_long ra81_off[] = { 0, 16422, 0, 375564, 391986, 699720, 375564, 83538 };
22630547Skarels #endif
22730547Skarels #else
22830547Skarels u_long ra81_off[] = { 0, 15884, 0, 242606, 258490, 565690, 242606, 49324 };
22930547Skarels #endif
23030547Skarels 
231*32613Sbostic u_long	*ra_off[] = {
232*32613Sbostic 	0,		/* 0 = unused */
233*32613Sbostic 	ra80_off,	/* 1 = ra80 */
234*32613Sbostic 	ra25_off,	/* 2 = rc25 removable */
235*32613Sbostic 	ra25_off,	/* 3 = rc25 fixed */
236*32613Sbostic 	ra60_off,	/* 4 = ra60 */
237*32613Sbostic 	ra81_off,	/* 5 = ra81 */
238*32613Sbostic 	0,		/* 6 = ? */
239*32613Sbostic 	rx50_off,	/* 7 = rx50 */
240*32613Sbostic 	rd52_off,	/* 8 = rd52 */
241*32613Sbostic 	rd53_off,	/* 9 = rd53 */
242*32613Sbostic };
243*32613Sbostic 
244*32613Sbostic #define NOFFS	(sizeof(ra_off)/sizeof(int))
245*32613Sbostic 
24630547Skarels ramaptype(io, lp)
24730547Skarels 	register struct iob *io;
24830547Skarels 	register struct disklabel *lp;
24930547Skarels {
25030547Skarels 	register struct partition *pp;
251*32613Sbostic 	register int i;
25230547Skarels 	register u_long *off;
25330547Skarels 
254*32613Sbostic 	i = ratype[io->i_unit];
255*32613Sbostic 	if ((unsigned)i >= NOFFS || (off = ra_off[i]) == 0) {
256*32613Sbostic 		printf("ra%d: ra type %d unsupported\n", io->i_unit, i);
25730547Skarels 		lp->d_npartitions = 0;
25830547Skarels 		return;
25930547Skarels 	}
26030547Skarels 	lp->d_npartitions = 8;
261*32613Sbostic 	for (pp = lp->d_partitions, i = 0; i < 8; pp++, i++)
26230547Skarels 		pp->p_offset = *off++;
26330547Skarels }
26430547Skarels #endif
265