xref: /csrg-svn/sys/vax/stand/uda.c (revision 33408)
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*33408Skarels  *	@(#)uda.c	7.6 (Berkeley) 01/28/88
723247Smckusick  */
85153Ssam 
95153Ssam /*
105153Ssam  * UDA50/RAxx disk device driver
115153Ssam  */
129806Ssam #include "../machine/pte.h"
135153Ssam 
1432613Sbostic #include "param.h"
1532613Sbostic #include "inode.h"
1632613Sbostic #include "fs.h"
1732613Sbostic #include "disklabel.h"
189186Ssam 
195153Ssam #include "saio.h"
205153Ssam #include "savax.h"
215153Ssam 
2232613Sbostic #define	NRA		8	/* max. unit number on controller */
2330547Skarels #define	SECTSIZ 	512	/* sector size in bytes */
2432613Sbostic 
255153Ssam /*
2632613Sbostic  * Unused, but needed in udareg.h
275153Ssam  */
2832613Sbostic #define NRSP	1
2932613Sbostic #define NCMD	1
305153Ssam 
31*33408Skarels #include "../vaxuba/udareg.h"
329186Ssam #include "../vaxuba/ubareg.h"
33*33408Skarels #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  */
43*33408Skarels struct udadevice *udaddr[MAXNUBA];
445153Ssam 
4532613Sbostic struct	uda1 {
4632613Sbostic 	struct	uda1ca uda1_ca;	/* communications area */
4732613Sbostic 	struct	mscp uda1_rsp;	/* response packet */
4832613Sbostic 	struct	mscp uda1_cmd;	/* command packet */
4932613Sbostic } uda1;
505153Ssam 
5132613Sbostic struct	uda1 *ud_ubaddr[MAXNUBA];	/* Unibus address of uda structure */
5230547Skarels struct	disklabel ralabel[MAXNUBA * NRA];
53*33408Skarels static	u_int ratype[MAXNUBA * NRA];
5430547Skarels char	lbuf[SECTSIZ];
555153Ssam 
5611111Ssam raopen(io)
575153Ssam 	register struct iob *io;
585153Ssam {
595153Ssam 	register struct mscp *mp;
6032613Sbostic 	register struct disklabel *lp, *dlp;
6130547Skarels 	register struct udadevice *addr;
6232613Sbostic 	register struct uda1 *ubaddr;
6330547Skarels 	register unit;
6432613Sbostic 	static int udainit[MAXNUBA];
6530547Skarels 	int uba;
665153Ssam 
6730547Skarels 	unit = io->i_unit;
6830547Skarels 	uba = UNITTOUBA(unit);
6930547Skarels 	if (udaddr[uba] == 0)
7030547Skarels 		udaddr[uba] = (struct udadevice *)ubamem(unit, udastd[0]);
7130547Skarels 	addr = udaddr[uba];
7230547Skarels 	if (badaddr((char *)addr, sizeof(short))) {
7332194Skarels 		printf("nonexistent device\n");
7430547Skarels 		return (ENXIO);
7530547Skarels 	}
7630547Skarels 	if (ud_ubaddr[uba] == 0) {
7717231Smckusick 		/*
7830547Skarels 		 * Initialize cudbuf.i_unit so that controllers
7917231Smckusick 		 * on UNIBUSes other than 0 can be used.
8017231Smckusick 		 */
8130547Skarels 		cudbuf.i_unit = unit;
8232613Sbostic 		cudbuf.i_ma = (caddr_t)&uda1;
8332613Sbostic 		cudbuf.i_cc = sizeof(uda1);
8432613Sbostic 		ud_ubaddr[uba] = (struct uda1 *)ubasetup(&cudbuf, 2);
855153Ssam 	}
8630547Skarels 	ubaddr = ud_ubaddr[uba];
8730547Skarels 	if (udainit[uba] == 0) {
8830547Skarels 		addr->udaip = 0;
8930547Skarels 		while ((addr->udasa & UDA_STEP1) == 0)
9017231Smckusick 			;
9130547Skarels 		addr->udasa = UDA_ERR;
9230547Skarels 		while ((addr->udasa & UDA_STEP2) == 0)
9317231Smckusick 			;
9432613Sbostic 		addr->udasa = (short)&ubaddr->uda1_ca.ca_rspdsc;
9530547Skarels 		while ((addr->udasa & UDA_STEP3) == 0)
9617231Smckusick 			;
9730547Skarels 		addr->udasa =
9832613Sbostic 		    (short)(((int)&ubaddr->uda1_ca.ca_rspdsc) >> 16);
9930547Skarels 		while ((addr->udasa & UDA_STEP4) == 0)
10017231Smckusick 			;
10130547Skarels 		addr->udasa = UDA_GO;
10232613Sbostic 		uda1.uda1_ca.ca_rspdsc = (long)&ubaddr->uda1_rsp.mscp_cmdref;
10332613Sbostic 		uda1.uda1_ca.ca_cmddsc = (long)&ubaddr->uda1_cmd.mscp_cmdref;
10432613Sbostic 		/* uda1.uda1_cmd.mscp_cntflgs = 0; */
105*33408Skarels 		if (udcmd(M_OP_SETCTLRC, io)) {
10632613Sbostic 			printf("ra: open error, SETCTLRC\n");
10730547Skarels 			return (EIO);
10817231Smckusick 		}
10932613Sbostic 		udainit[uba] = 1;
11027075Skarels 	}
11130547Skarels 	lp = &ralabel[unit];
11232613Sbostic 	if (ratype[unit] == 0) {
11330547Skarels 		struct iob tio;
11430547Skarels 
11532613Sbostic 		uda1.uda1_cmd.mscp_unit = UNITTODRIVE(unit);
116*33408Skarels 		if (udcmd(M_OP_ONLINE, io)) {
11732613Sbostic 			printf("ra: open error, ONLINE\n");
11830547Skarels 			return (EIO);
11917231Smckusick 		}
120*33408Skarels 		ratype[unit] = uda1.uda1_rsp.mscp_onle.onle_drivetype;
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*33408Skarels 		*lp = *(struct disklabel *)(lbuf + LABELOFFSET);
131*33408Skarels 		if (lp->d_magic != DISKMAGIC || lp->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
138*33408Skarels 		}
1395153Ssam 	}
14030547Skarels 	if ((unsigned)io->i_boff >= lp->d_npartitions ||
14130547Skarels 	    (io->i_boff = lp->d_partitions[io->i_boff].p_offset) == -1) {
14232194Skarels 		printf("ra: bad partition\n");
14330547Skarels 		return (EUNIT);
14427075Skarels 	}
14530547Skarels 	return (0);
1465153Ssam }
1475153Ssam 
148*33408Skarels int
14930547Skarels udcmd(op, io)
1505153Ssam 	int op;
15130547Skarels 	register struct iob *io;
1525153Ssam {
153*33408Skarels 	register struct uda1 *u = &uda1;
15432613Sbostic 	register struct mscp *mp;
1555153Ssam 	int i;
1565153Ssam 
157*33408Skarels 	u->uda1_cmd.mscp_opcode = op;
158*33408Skarels 	u->uda1_cmd.mscp_msglen = MSCP_MSGLEN;
159*33408Skarels 	u->uda1_rsp.mscp_msglen = MSCP_MSGLEN;
160*33408Skarels 	u->uda1_ca.ca_rspdsc |= MSCP_OWN|MSCP_INT;
161*33408Skarels 	u->uda1_ca.ca_cmddsc |= MSCP_OWN|MSCP_INT;
16230547Skarels 	i = udaddr[UNITTOUBA(io->i_unit)]->udaip;
163*33408Skarels 	mp = &u->uda1_rsp;
1645153Ssam 	for (;;) {
165*33408Skarels 		if (u->uda1_ca.ca_cmdint)
166*33408Skarels 			u->uda1_ca.ca_cmdint = 0;
167*33408Skarels 		if (u->uda1_ca.ca_rspint == 0)
16832613Sbostic 			continue;
169*33408Skarels 		u->uda1_ca.ca_rspint = 0;
17032613Sbostic 		if (mp->mscp_opcode == (op | M_OP_END))
1715153Ssam 			break;
172*33408Skarels 		printf("unexpected rsp type %x op %x ignored\n",
173*33408Skarels 			MSCP_MSGTYPE(mp->mscp_msgtc), mp->mscp_opcode);
174*33408Skarels 		u->uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT;
1755153Ssam 	}
17632613Sbostic 	if ((mp->mscp_status&M_ST_MASK) != M_ST_SUCCESS)
177*33408Skarels 		return (-1);
178*33408Skarels 	return (0);
1795153Ssam }
1805153Ssam 
18111111Ssam rastrategy(io, func)
1825153Ssam 	register struct iob *io;
1835153Ssam {
1845153Ssam 	register struct mscp *mp;
1855153Ssam 	int ubinfo;
1865153Ssam 
1875153Ssam 	ubinfo = ubasetup(io, 1);
18832613Sbostic 	mp = &uda1.uda1_cmd;
18932194Skarels 	mp->mscp_unit = UNITTODRIVE(io->i_unit);
19032613Sbostic 	mp->mscp_seq.seq_lbn = io->i_bn;
19132613Sbostic 	mp->mscp_seq.seq_bytecount = io->i_cc;
19232613Sbostic 	mp->mscp_seq.seq_buffer = (ubinfo & 0x3ffff) | (((ubinfo>>28)&0xf)<<24);
193*33408Skarels 	if (udcmd(func == READ ? M_OP_READ : M_OP_WRITE, io)) {
1945153Ssam 		printf("ra: I/O error\n");
1955153Ssam 		ubafree(io, ubinfo);
1965153Ssam 		return(-1);
1975153Ssam 	}
1985153Ssam 	ubafree(io, ubinfo);
1995153Ssam 	return(io->i_cc);
2005153Ssam }
20110024Ssam 
20210024Ssam /*ARGSUSED*/
20311111Ssam raioctl(io, cmd, arg)
20410024Ssam 	struct iob *io;
20510024Ssam 	int cmd;
20610024Ssam 	caddr_t arg;
20710024Ssam {
20810024Ssam 
20910024Ssam 	return (ECMD);
21010024Ssam }
21130547Skarels 
21230547Skarels #ifdef COMPAT_42
21330547Skarels u_long ra25_off[] = { 0, 15884, 0, -1, -1, -1, 25916, -1 };
21432613Sbostic u_long rx50_off[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
21532613Sbostic u_long rd52_off[] = { 0, 15884, 0, 0, 0, 0, 25650, 0 };
21632613Sbostic u_long rd53_off[] = { 0, 15884, 0, 0, 0, 33440, 49324, 15884 };
21730547Skarels u_long ra60_off[] = { 0, 15884, 0, 49324, 131404, 49324, 242606, 49324 };
21830547Skarels u_long ra80_off[] = { 0, 15884, 0, -1, 49324, 49324, 49910, 131404 };
21930547Skarels #ifndef	UCBRA
22030547Skarels #ifdef RA_COMPAT
22130547Skarels u_long ra81_off[] = { 0, 16422, 0, 49324, 131404, 412490, 375564, 83538 };
22230547Skarels #else
22330547Skarels u_long ra81_off[] = { 0, 16422, 0, 375564, 391986, 699720, 375564, 83538 };
22430547Skarels #endif
22530547Skarels #else
22630547Skarels u_long ra81_off[] = { 0, 15884, 0, 242606, 258490, 565690, 242606, 49324 };
22730547Skarels #endif
22830547Skarels 
22932613Sbostic u_long	*ra_off[] = {
23032613Sbostic 	0,		/* 0 = unused */
23132613Sbostic 	ra80_off,	/* 1 = ra80 */
23232613Sbostic 	ra25_off,	/* 2 = rc25 removable */
23332613Sbostic 	ra25_off,	/* 3 = rc25 fixed */
23432613Sbostic 	ra60_off,	/* 4 = ra60 */
23532613Sbostic 	ra81_off,	/* 5 = ra81 */
23632613Sbostic 	0,		/* 6 = ? */
23732613Sbostic 	rx50_off,	/* 7 = rx50 */
23832613Sbostic 	rd52_off,	/* 8 = rd52 */
23932613Sbostic 	rd53_off,	/* 9 = rd53 */
24032613Sbostic };
24132613Sbostic 
242*33408Skarels #define NOFFS	(sizeof(ra_off)/sizeof(ra_off[0]))
24332613Sbostic 
24430547Skarels ramaptype(io, lp)
24530547Skarels 	register struct iob *io;
24630547Skarels 	register struct disklabel *lp;
24730547Skarels {
24830547Skarels 	register struct partition *pp;
249*33408Skarels 	register u_int i;
25030547Skarels 	register u_long *off;
25130547Skarels 
252*33408Skarels 	if ((i = ratype[io->i_unit]) >= NOFFS || (off = ra_off[i]) == 0) {
25332613Sbostic 		printf("ra%d: ra type %d unsupported\n", io->i_unit, i);
25430547Skarels 		lp->d_npartitions = 0;
25530547Skarels 		return;
25630547Skarels 	}
25730547Skarels 	lp->d_npartitions = 8;
25832613Sbostic 	for (pp = lp->d_partitions, i = 0; i < 8; pp++, i++)
25930547Skarels 		pp->p_offset = *off++;
26030547Skarels }
26130547Skarels #endif
262