xref: /csrg-svn/sys/vax/uba/uda.c (revision 32523)
123353Smckusick /*
2*32523Sbostic  * Copyright (c) 1987 Regents of the University of California.
3*32523Sbostic  * All rights reserved.  The Berkeley software License Agreement
4*32523Sbostic  * specifies the terms and conditions for redistribution.
5*32523Sbostic  *
6*32523Sbostic  *	@(#)uda.c	7.8 (Berkeley) 10/23/87
7*32523Sbostic  *
823353Smckusick  */
923353Smckusick 
10*32523Sbostic /*
11*32523Sbostic  * UDA50/MSCP device driver
1217553Skarels  */
1317553Skarels 
14*32523Sbostic #define	POLLSTATS
15*32523Sbostic 
16*32523Sbostic /*
17*32523Sbostic  * TODO
18*32523Sbostic  *	write bad block forwarding code
19*32523Sbostic  */
20*32523Sbostic 
214743Swnj #include "ra.h"
22*32523Sbostic 
2317642Skarels #if NUDA > 0
24*32523Sbostic 
254743Swnj /*
26*32523Sbostic  * CONFIGURATION OPTIONS.  The next three defines are tunable -- tune away!
274743Swnj  *
28*32523Sbostic  * COMPAT_42 enables 4.2/4.3 compatibility (label mapping)
29*32523Sbostic  *
30*32523Sbostic  * NRSPL2 and NCMDL2 control the number of response and command
31*32523Sbostic  * packets respectively.  They may be any value from 0 to 7, though
32*32523Sbostic  * setting them higher than 5 is unlikely to be of any value.
33*32523Sbostic  * If you get warnings about your command ring being too small,
34*32523Sbostic  * try increasing the values by one.
35*32523Sbostic  *
36*32523Sbostic  * MAXUNIT controls the maximum unit number (number of drives per
37*32523Sbostic  * controller) we are prepared to handle.
38*32523Sbostic  *
39*32523Sbostic  * DEFAULT_BURST must be at least 1.
404743Swnj  */
41*32523Sbostic #define	COMPAT_42
42*32523Sbostic 
43*32523Sbostic #define	NRSPL2	5		/* log2 number of response packets */
44*32523Sbostic #define NCMDL2	5		/* log2 number of command packets */
45*32523Sbostic #define	MAXUNIT	8		/* maximum allowed unit number */
46*32523Sbostic #define	DEFAULT_BURST	4	/* default DMA burst size */
47*32523Sbostic 
489781Ssam #include "../machine/pte.h"
494743Swnj 
5017553Skarels #include "param.h"
5117553Skarels #include "systm.h"
5217553Skarels #include "buf.h"
5317553Skarels #include "conf.h"
5417553Skarels #include "dir.h"
5530536Skarels #include "file.h"
5630536Skarels #include "ioctl.h"
5717553Skarels #include "user.h"
5817553Skarels #include "map.h"
5917553Skarels #include "vm.h"
6030536Skarels #include "dkstat.h"
6117553Skarels #include "cmap.h"
6230536Skarels #include "disklabel.h"
6330536Skarels #include "syslog.h"
6430773Skarels #include "stat.h"
654743Swnj 
668482Sroot #include "../vax/cpu.h"
6717553Skarels #include "ubareg.h"
6817553Skarels #include "ubavar.h"
698613Sroot 
70*32523Sbostic #define	NRSP	(1 << NRSPL2)
71*32523Sbostic #define	NCMD	(1 << NCMDL2)
728613Sroot 
73*32523Sbostic #include "udareg.h"
748482Sroot #include "../vax/mscp.h"
75*32523Sbostic #include "../vax/mscpvar.h"
76*32523Sbostic #include "../vax/mtpr.h"
774743Swnj 
78*32523Sbostic /*
79*32523Sbostic  * Backwards compatibility:  Reuse the old names.  Should fix someday.
80*32523Sbostic  */
81*32523Sbostic #define	udaprobe	udprobe
82*32523Sbostic #define	udaslave	udslave
83*32523Sbostic #define	udaattach	udattach
84*32523Sbostic #define	udaopen		udopen
85*32523Sbostic #define	udaclose	udclose
86*32523Sbostic #define	udastrategy	udstrategy
87*32523Sbostic #define	udaread		udread
88*32523Sbostic #define	udawrite	udwrite
89*32523Sbostic #define	udaioctl	udioctl
90*32523Sbostic #define	udareset	udreset
91*32523Sbostic #define	udaintr		udintr
92*32523Sbostic #define	udadump		uddump
93*32523Sbostic #define	udasize		udsize
9417553Skarels 
95*32523Sbostic /*
96*32523Sbostic  * UDA communications area and MSCP packet pools, per controller.
97*32523Sbostic  */
98*32523Sbostic struct	uda {
99*32523Sbostic 	struct	udaca uda_ca;		/* communications area */
100*32523Sbostic 	struct	mscp uda_rsp[NRSP];	/* response packets */
101*32523Sbostic 	struct	mscp uda_cmd[NCMD];	/* command packets */
1024743Swnj } uda[NUDA];
1034743Swnj 
104*32523Sbostic /*
105*32523Sbostic  * Software status, per controller.
106*32523Sbostic  */
107*32523Sbostic struct	uda_softc {
108*32523Sbostic 	struct	uda *sc_uda;	/* Unibus address of uda struct */
109*32523Sbostic 	short	sc_state;	/* UDA50 state; see below */
110*32523Sbostic 	short	sc_flags;	/* flags; see below */
111*32523Sbostic 	int	sc_micro;	/* microcode revision */
112*32523Sbostic 	int	sc_ivec;	/* interrupt vector address */
113*32523Sbostic 	struct	mscp_info sc_mi;/* MSCP info (per mscpvar.h) */
114*32523Sbostic #ifndef POLLSTATS
115*32523Sbostic 	int	sc_wticks;	/* watchdog timer ticks */
116*32523Sbostic #else
117*32523Sbostic 	short	sc_wticks;
118*32523Sbostic 	short	sc_ncmd;
119*32523Sbostic #endif
120*32523Sbostic } uda_softc[NUDA];
12124742Sbloom 
122*32523Sbostic #ifdef POLLSTATS
123*32523Sbostic struct udastats {
124*32523Sbostic 	int	ncmd;
125*32523Sbostic 	int	cmd[NCMD + 1];
126*32523Sbostic } udastats = { NCMD + 1 };
127*32523Sbostic #endif
12817553Skarels 
129*32523Sbostic /*
130*32523Sbostic  * Controller states
131*32523Sbostic  */
132*32523Sbostic #define	ST_IDLE		0	/* uninitialised */
133*32523Sbostic #define	ST_STEP1	1	/* in `STEP 1' */
134*32523Sbostic #define	ST_STEP2	2	/* in `STEP 2' */
135*32523Sbostic #define	ST_STEP3	3	/* in `STEP 3' */
136*32523Sbostic #define	ST_SETCHAR	4	/* in `Set Controller Characteristics' */
137*32523Sbostic #define	ST_RUN		5	/* up and running */
1384743Swnj 
139*32523Sbostic /*
140*32523Sbostic  * Flags
141*32523Sbostic  */
142*32523Sbostic #define	SC_MAPPED	0x01	/* mapped in Unibus I/O space */
143*32523Sbostic #define	SC_INSTART	0x02	/* inside udastart() */
144*32523Sbostic #define	SC_GRIPED	0x04	/* griped about cmd ring too small */
145*32523Sbostic #define	SC_INSLAVE	0x08	/* inside udaslave() */
146*32523Sbostic #define	SC_DOWAKE	0x10	/* wakeup when ctlr init done */
147*32523Sbostic #define	SC_STARTPOLL	0x20	/* need to initiate polling */
14812421Ssam 
149*32523Sbostic /*
150*32523Sbostic  * Device to unit number and partition and back
151*32523Sbostic  */
152*32523Sbostic #define	UNITSHIFT	3
153*32523Sbostic #define	UNITMASK	7
154*32523Sbostic #define	udaunit(dev)	(minor(dev) >> UNITSHIFT)
155*32523Sbostic #define	udapart(dev)	(minor(dev) & UNITMASK)
156*32523Sbostic #define	udaminor(u, p)	(((u) << UNITSHIFT) | (p))
1574743Swnj 
15817553Skarels /*
159*32523Sbostic  * Drive status, per drive
16017553Skarels  */
161*32523Sbostic struct ra_info {
162*32523Sbostic 	daddr_t	ra_dsize;	/* size in sectors */
163*32523Sbostic 	u_long	ra_type;	/* drive type */
164*32523Sbostic 	u_long	ra_mediaid;	/* media id */
165*32523Sbostic 	int	ra_state;	/* open/closed state */
166*32523Sbostic 	struct	ra_geom {	/* geometry information */
167*32523Sbostic 		u_short	rg_nsectors;	/* sectors/track */
168*32523Sbostic 		u_short	rg_ngroups;	/* track groups */
169*32523Sbostic 		u_short	rg_ngpc;	/* groups/cylinder */
170*32523Sbostic 		u_short	rg_ntracks;	/* ngroups*ngpc */
171*32523Sbostic 		u_short	rg_ncyl;	/* ra_dsize/ntracks/nsectors */
172*32523Sbostic #ifdef notyet
173*32523Sbostic 		u_short	rg_rctsize;	/* size of rct */
174*32523Sbostic 		u_short	rg_rbns;	/* replacement blocks per track */
175*32523Sbostic 		u_short	rg_nrct;	/* number of rct copies */
176*32523Sbostic #endif
177*32523Sbostic 	} ra_geom;
178*32523Sbostic 	u_long	ra_openpart;	/* partitions open */
179*32523Sbostic 	u_long	ra_bopenpart;	/* block partitions open */
180*32523Sbostic 	u_long	ra_copenpart;	/* character partitions open */
181*32523Sbostic } ra_info[NRA];
18217553Skarels 
18330536Skarels /*
18430536Skarels  * Software state, per drive
18530536Skarels  */
18630536Skarels #define	CLOSED		0
18730536Skarels #define	WANTOPEN	1
18830536Skarels #define	RDLABEL		2
18930536Skarels #define	OPEN		3
19030536Skarels #define	OPENRAW		4
19117553Skarels 
192*32523Sbostic /*
193*32523Sbostic  * Definition of the driver for autoconf.
194*32523Sbostic  */
195*32523Sbostic int	udaprobe(), udaslave(), udaattach(), udadgo(), udaintr();
196*32523Sbostic struct	uba_ctlr *udaminfo[NUDA];
197*32523Sbostic struct	uba_device *udadinfo[NRA];
198*32523Sbostic struct	disklabel udalabel[NRA];
19917553Skarels 
200*32523Sbostic u_short	udastd[] = { 0772150, 0772550, 0777550, 0 };
201*32523Sbostic struct	uba_driver udadriver =
202*32523Sbostic  { udaprobe, udaslave, udaattach, udadgo, udastd, "ra", udadinfo, "uda",
203*32523Sbostic    udaminfo };
20417553Skarels 
205*32523Sbostic /*
206*32523Sbostic  * More driver definitions, for generic MSCP code.
207*32523Sbostic  */
208*32523Sbostic int	udadgram(), udactlrdone(), udaunconf(), udaiodone();
209*32523Sbostic int	udaonline(), udagotstatus(), udaioerror(), udareplace(), udabb();
2104743Swnj 
211*32523Sbostic struct	buf udautab[NRA];	/* per drive transfer queue */
2124743Swnj 
213*32523Sbostic struct	mscp_driver udamscpdriver =
214*32523Sbostic  { MAXUNIT, NRA, UNITSHIFT, udautab, udadinfo,
215*32523Sbostic    udadgram, udactlrdone, udaunconf, udaiodone,
216*32523Sbostic    udaonline, udagotstatus, udareplace, udaioerror, udabb,
217*32523Sbostic    "uda", "ra" };
218*32523Sbostic 
219*32523Sbostic /*
220*32523Sbostic  * Miscellaneous private variables.
221*32523Sbostic  */
222*32523Sbostic char	udasr_bits[] = UDASR_BITS;
223*32523Sbostic 
224*32523Sbostic struct	uba_device *udaip[NUDA][MAXUNIT];
225*32523Sbostic 				/* inverting pointers: ctlr & unit => Unibus
226*32523Sbostic 				   device pointer */
227*32523Sbostic 
228*32523Sbostic int	udaburst[NUDA] = { 0 };	/* burst size, per UDA50, zero => default;
229*32523Sbostic 				   in data space so patchable via adb */
230*32523Sbostic 
231*32523Sbostic struct	mscp udaslavereply;	/* get unit status response packet, set
232*32523Sbostic 				   for udaslave by udaunconf, via udaintr */
233*32523Sbostic 
234*32523Sbostic static struct uba_ctlr *probeum;/* this is a hack---autoconf should pass ctlr
235*32523Sbostic 				   info to slave routine; instead, we remember
236*32523Sbostic 				   the last ctlr argument to probe */
237*32523Sbostic 
238*32523Sbostic int	udawstart, udawatch();	/* watchdog timer */
239*32523Sbostic 
240*32523Sbostic /*
241*32523Sbostic  * Externals
242*32523Sbostic  */
243*32523Sbostic int	wakeup();
244*32523Sbostic int	hz;
245*32523Sbostic 
246*32523Sbostic /*
247*32523Sbostic  * Poke at a supposed UDA50 to see if it is there.
248*32523Sbostic  * This routine duplicates some of the code in udainit() only
249*32523Sbostic  * because autoconf has not set up the right information yet.
250*32523Sbostic  * We have to do everything `by hand'.
251*32523Sbostic  */
252*32523Sbostic udaprobe(reg, ctlr, um)
2534743Swnj 	caddr_t reg;
2544743Swnj 	int ctlr;
255*32523Sbostic 	struct uba_ctlr *um;
2564743Swnj {
2574743Swnj 	register int br, cvec;
258*32523Sbostic 	register struct uda_softc *sc;
259*32523Sbostic 	register struct udadevice *udaddr;
260*32523Sbostic 	register struct mscp_info *mi;
261*32523Sbostic 	int timeout, tries;
2624743Swnj 
263*32523Sbostic #ifdef VAX750
264*32523Sbostic 	/*
265*32523Sbostic 	 * The UDA50 wants to share BDPs on 750s, but not on 780s or
266*32523Sbostic 	 * 8600s.  (730s have no BDPs anyway.)  Toward this end, we
267*32523Sbostic 	 * here set the `keep bdp' flag in the per-driver information
268*32523Sbostic 	 * if this is a 750.  (We just need to do it once, but it is
269*32523Sbostic 	 * easiest to do it now, for each UDA50.)
270*32523Sbostic 	 */
271*32523Sbostic 	if (cpu == VAX_750)
272*32523Sbostic 		udadriver.ud_keepbdp = 1;
273*32523Sbostic #endif
27417553Skarels 
275*32523Sbostic 	probeum = um;			/* remember for udaslave() */
2764743Swnj #ifdef lint
277*32523Sbostic 	br = 0; cvec = br; br = cvec; udaintr(0);
2784743Swnj #endif
279*32523Sbostic 	/*
280*32523Sbostic 	 * Set up the controller-specific generic MSCP driver info.
281*32523Sbostic 	 * Note that this should really be done in the (nonexistent)
282*32523Sbostic 	 * controller attach routine.
283*32523Sbostic 	 */
284*32523Sbostic 	sc = &uda_softc[ctlr];
285*32523Sbostic 	mi = &sc->sc_mi;
286*32523Sbostic 	mi->mi_md = &udamscpdriver;
287*32523Sbostic 	mi->mi_ctlr = um->um_ctlr;
288*32523Sbostic 	mi->mi_tab = &um->um_tab;
289*32523Sbostic 	mi->mi_ip = udaip[ctlr];
290*32523Sbostic 	mi->mi_cmd.mri_size = NCMD;
291*32523Sbostic 	mi->mi_cmd.mri_desc = uda[ctlr].uda_ca.ca_cmddsc;
292*32523Sbostic 	mi->mi_cmd.mri_ring = uda[ctlr].uda_cmd;
293*32523Sbostic 	mi->mi_rsp.mri_size = NRSP;
294*32523Sbostic 	mi->mi_rsp.mri_desc = uda[ctlr].uda_ca.ca_rspdsc;
295*32523Sbostic 	mi->mi_rsp.mri_ring = uda[ctlr].uda_rsp;
296*32523Sbostic 	mi->mi_wtab.av_forw = mi->mi_wtab.av_back = &mi->mi_wtab;
297*32523Sbostic 
298*32523Sbostic 	/*
299*32523Sbostic 	 * More controller specific variables.  Again, this should
300*32523Sbostic 	 * be in the controller attach routine.
301*32523Sbostic 	 */
302*32523Sbostic 	if (udaburst[ctlr] == 0)
303*32523Sbostic 		udaburst[ctlr] = DEFAULT_BURST;
304*32523Sbostic 
305*32523Sbostic 	/*
306*32523Sbostic 	 * Get an interrupt vector.  Note that even if the controller
307*32523Sbostic 	 * does not respond, we keep the vector.  This is not a serious
308*32523Sbostic 	 * problem; but it would be easily fixed if we had a controller
309*32523Sbostic 	 * attach routine.  Sigh.
310*32523Sbostic 	 */
311*32523Sbostic 	sc->sc_ivec = (uba_hd[numuba].uh_lastiv -= 4);
31217553Skarels 	udaddr = (struct udadevice *) reg;
31317553Skarels 
314*32523Sbostic 	/*
315*32523Sbostic 	 * Initialise the controller (partially).  The UDA50 programmer's
316*32523Sbostic 	 * manual states that if initialisation fails, it should be retried
317*32523Sbostic 	 * at least once, but after a second failure the port should be
318*32523Sbostic 	 * considered `down'; it also mentions that the controller should
319*32523Sbostic 	 * initialise within ten seconds.  Or so I hear; I have not seen
320*32523Sbostic 	 * this manual myself.
321*32523Sbostic 	 */
322*32523Sbostic 	tries = 0;
323*32523Sbostic again:
324*32523Sbostic 	udaddr->udaip = 0;		/* start initialisation */
325*32523Sbostic 	timeout = todr() + 1000;	/* timeout in 10 seconds */
326*32523Sbostic 	while ((udaddr->udasa & UDA_STEP1) == 0)
327*32523Sbostic 		if (todr() > timeout)
328*32523Sbostic 			goto bad;
329*32523Sbostic 	udaddr->udasa = UDA_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) | UDA_IE |
330*32523Sbostic 		(sc->sc_ivec >> 2);
331*32523Sbostic 	while ((udaddr->udasa & UDA_STEP2) == 0)
332*32523Sbostic 		if (todr() > timeout)
333*32523Sbostic 			goto bad;
334*32523Sbostic 
335*32523Sbostic 	/* should have interrupted by now */
336*32523Sbostic #ifdef VAX630
337*32523Sbostic 	if (cpu == VAX_630)
338*32523Sbostic 		br = 0x15;	/* screwy interrupt structure */
33927254Skridle #endif
340*32523Sbostic 	return (sizeof (struct udadevice));
341*32523Sbostic bad:
342*32523Sbostic 	if (++tries < 2)
343*32523Sbostic 		goto again;
344*32523Sbostic 	return (0);
3454743Swnj }
3464743Swnj 
347*32523Sbostic /*
348*32523Sbostic  * Find a slave.  We allow wildcard slave numbers (something autoconf
349*32523Sbostic  * is not really prepared to deal with); and we need to know the
350*32523Sbostic  * controller number to talk to the UDA.  For the latter, we keep
351*32523Sbostic  * track of the last controller probed, since a controller probe
352*32523Sbostic  * immediately precedes all slave probes for that controller.  For the
353*32523Sbostic  * former, we simply put the unit number into ui->ui_slave after we
354*32523Sbostic  * have found one.
355*32523Sbostic  *
356*32523Sbostic  * Note that by the time udaslave is called, the interrupt vector
357*32523Sbostic  * for the UDA50 has been set up (so that udaunconf() will be called).
358*32523Sbostic  */
359*32523Sbostic udaslave(ui, reg)
360*32523Sbostic 	register struct uba_device *ui;
3614743Swnj 	caddr_t reg;
3624743Swnj {
363*32523Sbostic 	register struct uba_ctlr *um = probeum;
364*32523Sbostic 	register struct mscp *mp;
365*32523Sbostic 	register struct uda_softc *sc;
366*32523Sbostic 	register struct ra_info *ra;
367*32523Sbostic 	int next = 0, type, timeout, tries, i;
36817553Skarels 
369*32523Sbostic #ifdef lint
370*32523Sbostic 	i = 0; i = i;
371*32523Sbostic #endif
372*32523Sbostic 	/*
373*32523Sbostic 	 * Make sure the controller is fully initialised, by waiting
374*32523Sbostic 	 * for it if necessary.
375*32523Sbostic 	 */
376*32523Sbostic 	sc = &uda_softc[um->um_ctlr];
377*32523Sbostic 	if (sc->sc_state == ST_RUN)
378*32523Sbostic 		goto findunit;
379*32523Sbostic 	tries = 0;
380*32523Sbostic again:
381*32523Sbostic 	if (udainit(ui->ui_ctlr))
382*32523Sbostic 		return (0);
383*32523Sbostic 	timeout = todr() + 1000;		/* 10 seconds */
384*32523Sbostic 	while (todr() < timeout)
385*32523Sbostic 		if (sc->sc_state == ST_RUN)	/* made it */
386*32523Sbostic 			goto findunit;
387*32523Sbostic 	if (++tries < 2)
388*32523Sbostic 		goto again;
389*32523Sbostic 	printf("uda%d: controller hung\n", um->um_ctlr);
390*32523Sbostic 	return (0);
39117553Skarels 
392*32523Sbostic 	/*
393*32523Sbostic 	 * The controller is all set; go find the unit.  Grab an
394*32523Sbostic 	 * MSCP packet and send out a Get Unit Status command, with
395*32523Sbostic 	 * the `next unit' modifier if we are looking for a generic
396*32523Sbostic 	 * unit.  We set the `in slave' flag so that udaunconf()
397*32523Sbostic 	 * knows to copy the response to `udaslavereply'.
398*32523Sbostic 	 */
399*32523Sbostic findunit:
400*32523Sbostic 	udaslavereply.mscp_opcode = 0;
401*32523Sbostic 	sc->sc_flags |= SC_INSLAVE;
402*32523Sbostic 	if ((mp = mscp_getcp(&sc->sc_mi, MSCP_DONTWAIT)) == NULL)
403*32523Sbostic 		panic("udaslave");		/* `cannot happen' */
404*32523Sbostic 	mp->mscp_opcode = M_OP_GETUNITST;
405*32523Sbostic 	if (ui->ui_slave == '?') {
406*32523Sbostic 		mp->mscp_unit = next;
407*32523Sbostic 		mp->mscp_modifier = M_GUM_NEXTUNIT;
408*32523Sbostic 	} else {
409*32523Sbostic 		mp->mscp_unit = ui->ui_slave;
410*32523Sbostic 		mp->mscp_modifier = 0;
41117553Skarels 	}
412*32523Sbostic 	*mp->mscp_addr |= MSCP_OWN | MSCP_INT;
413*32523Sbostic 	i = ((struct udadevice *) reg)->udaip;	/* initiate polling */
414*32523Sbostic 	mp = &udaslavereply;
415*32523Sbostic 	timeout = todr() + 1000;
416*32523Sbostic 	while (todr() < timeout)
417*32523Sbostic 		if (mp->mscp_opcode)
418*32523Sbostic 			goto gotit;
419*32523Sbostic 	printf("uda%d: no response to Get Unit Status request\n",
420*32523Sbostic 		um->um_ctlr);
421*32523Sbostic 	sc->sc_flags &= ~SC_INSLAVE;
422*32523Sbostic 	return (0);
423*32523Sbostic 
424*32523Sbostic gotit:
425*32523Sbostic 	sc->sc_flags &= ~SC_INSLAVE;
426*32523Sbostic 
427*32523Sbostic 	/*
428*32523Sbostic 	 * Got a slave response.  If the unit is there, use it.
429*32523Sbostic 	 */
430*32523Sbostic 	switch (mp->mscp_status & M_ST_MASK) {
431*32523Sbostic 
432*32523Sbostic 	case M_ST_SUCCESS:	/* worked */
433*32523Sbostic 	case M_ST_AVAILABLE:	/* found another drive */
434*32523Sbostic 		break;		/* use it */
435*32523Sbostic 
436*32523Sbostic 	case M_ST_OFFLINE:
437*32523Sbostic 		/*
438*32523Sbostic 		 * Figure out why it is off line.  It may be because
439*32523Sbostic 		 * it is nonexistent, or because it is spun down, or
440*32523Sbostic 		 * for some other reason.
441*32523Sbostic 		 */
442*32523Sbostic 		switch (mp->mscp_status & ~M_ST_MASK) {
443*32523Sbostic 
444*32523Sbostic 		case M_OFFLINE_UNKNOWN:
445*32523Sbostic 			/*
446*32523Sbostic 			 * No such drive, and there are none with
447*32523Sbostic 			 * higher unit numbers either, if we are
448*32523Sbostic 			 * using M_GUM_NEXTUNIT.
449*32523Sbostic 			 */
450*32523Sbostic 			return (0);
451*32523Sbostic 
452*32523Sbostic 		case M_OFFLINE_UNMOUNTED:
453*32523Sbostic 			/*
454*32523Sbostic 			 * The drive is not spun up.  Use it anyway.
455*32523Sbostic 			 *
456*32523Sbostic 			 * N.B.: this seems to be a common occurrance
457*32523Sbostic 			 * after a power failure.  The first attempt
458*32523Sbostic 			 * to bring it on line seems to spin it up
459*32523Sbostic 			 * (and thus takes several minutes).  Perhaps
460*32523Sbostic 			 * we should note here that the on-line may
461*32523Sbostic 			 * take longer than usual.
462*32523Sbostic 			 */
463*32523Sbostic 			break;
464*32523Sbostic 
465*32523Sbostic 		default:
466*32523Sbostic 			/*
467*32523Sbostic 			 * In service, or something else equally unusable.
468*32523Sbostic 			 */
469*32523Sbostic 			printf("uda%d: unit %d off line: ", um->um_ctlr,
470*32523Sbostic 				mp->mscp_unit);
471*32523Sbostic 			mscp_printevent(mp);
472*32523Sbostic 			goto try_another;
473*32523Sbostic 		}
474*32523Sbostic 		break;
475*32523Sbostic 
476*32523Sbostic 	default:
477*32523Sbostic 		printf("uda%d: unable to get unit status: ", um->um_ctlr);
478*32523Sbostic 		mscp_printevent(mp);
479*32523Sbostic 		return (0);
48017553Skarels 	}
481*32523Sbostic 
482*32523Sbostic 	/*
483*32523Sbostic 	 * Does this ever happen?  What (if anything) does it mean?
484*32523Sbostic 	 */
485*32523Sbostic 	if (mp->mscp_unit < next) {
486*32523Sbostic 		printf("uda%d: unit %d, next %d\n",
487*32523Sbostic 			um->um_ctlr, mp->mscp_unit, next);
488*32523Sbostic 		return (0);
48917553Skarels 	}
490*32523Sbostic 
491*32523Sbostic 	if (mp->mscp_unit >= MAXUNIT) {
492*32523Sbostic 		printf("uda%d: cannot handle unit number %d (max is %d)\n",
493*32523Sbostic 			um->um_ctlr, mp->mscp_unit, MAXUNIT - 1);
494*32523Sbostic 		return (0);
495*32523Sbostic 	}
496*32523Sbostic 
497*32523Sbostic 	/*
498*32523Sbostic 	 * See if we already handle this drive.
499*32523Sbostic 	 * (Only likely if ui->ui_slave=='?'.)
500*32523Sbostic 	 */
501*32523Sbostic 	if (udaip[um->um_ctlr][mp->mscp_unit] != NULL) {
502*32523Sbostic try_another:
503*32523Sbostic 		if (ui->ui_slave != '?')
504*32523Sbostic 			return (0);
505*32523Sbostic 		next = mp->mscp_unit + 1;
506*32523Sbostic 		goto findunit;
507*32523Sbostic 	}
508*32523Sbostic 
509*32523Sbostic 	/*
510*32523Sbostic 	 * Voila!
511*32523Sbostic 	 */
512*32523Sbostic 	uda_rasave(ui->ui_unit, mp, 0);
513*32523Sbostic 	ui->ui_flags = 0;	/* not on line, nor anything else */
514*32523Sbostic 	ui->ui_slave = mp->mscp_unit;
515*32523Sbostic 	return (1);
5164743Swnj }
5174743Swnj 
518*32523Sbostic /*
519*32523Sbostic  * Attach a found slave.  Make sure the watchdog timer is running.
520*32523Sbostic  * If this disk is being profiled, fill in the `mspw' value (used by
521*32523Sbostic  * what?).  Set up the inverting pointer, and attempt to bring the
522*32523Sbostic  * drive on line and read its label.
523*32523Sbostic  */
524*32523Sbostic udaattach(ui)
5254743Swnj 	register struct uba_device *ui;
5264743Swnj {
527*32523Sbostic 	register int unit = ui->ui_unit;
528*32523Sbostic 
529*32523Sbostic 	if (udawstart == 0) {
530*32523Sbostic 		timeout(udawatch, (caddr_t) 0, hz);
531*32523Sbostic 		udawstart++;
532*32523Sbostic 	}
53312443Ssam 	if (ui->ui_dk >= 0)
534*32523Sbostic 		dk_mspw[ui->ui_dk] = 1.0 / (60 * 31 * 256);	/* approx */
535*32523Sbostic 	udaip[ui->ui_ctlr][ui->ui_slave] = ui;
536*32523Sbostic 	if (uda_rainit(ui, 0))
537*32523Sbostic 		printf("ra%d: offline", unit);
538*32523Sbostic 	else {
539*32523Sbostic 		printf("ra%d: %s\n", unit, udalabel[unit].d_typename);
540*32523Sbostic #ifdef notyet
541*32523Sbostic 		addswap(makedev(UDADEVNUM, udaminor(unit, 0)), &udalabel[unit]);
54226295Skarels #endif
54330536Skarels 	}
544*32523Sbostic }
545*32523Sbostic 
546*32523Sbostic /*
547*32523Sbostic  * Initialise a UDA50.  Return true iff something goes wrong.
548*32523Sbostic  */
549*32523Sbostic udainit(ctlr)
550*32523Sbostic 	int ctlr;
551*32523Sbostic {
552*32523Sbostic 	register struct uda_softc *sc;
553*32523Sbostic 	register struct udadevice *udaddr;
554*32523Sbostic 	struct uba_ctlr *um;
555*32523Sbostic 	int timo, ubinfo;
556*32523Sbostic 
557*32523Sbostic 	sc = &uda_softc[ctlr];
558*32523Sbostic 	um = udaminfo[ctlr];
559*32523Sbostic 	if ((sc->sc_flags & SC_MAPPED) == 0) {
560*32523Sbostic 		/*
561*32523Sbostic 		 * Map the communication area and command and
562*32523Sbostic 		 * response packets into Unibus space.
563*32523Sbostic 		 */
564*32523Sbostic 		ubinfo = uballoc(um->um_ubanum, (caddr_t) &uda[ctlr],
565*32523Sbostic 			sizeof (struct uda), UBA_CANTWAIT);
566*32523Sbostic 		if (ubinfo == 0) {
567*32523Sbostic 			printf("uda%d: uballoc map failed\n", ctlr);
568*32523Sbostic 			return (-1);
569*32523Sbostic 		}
570*32523Sbostic 		sc->sc_uda = (struct uda *) (ubinfo & 0x3ffff);
571*32523Sbostic 		sc->sc_flags |= SC_MAPPED;
572*32523Sbostic 	}
573*32523Sbostic 
57430536Skarels 	/*
575*32523Sbostic 	 * While we are thinking about it, reset the next command
576*32523Sbostic 	 * and response indicies.
57730536Skarels 	 */
578*32523Sbostic 	sc->sc_mi.mi_cmd.mri_next = 0;
579*32523Sbostic 	sc->sc_mi.mi_rsp.mri_next = 0;
580*32523Sbostic 
581*32523Sbostic 	/*
582*32523Sbostic 	 * Start up the hardware initialisation sequence.
583*32523Sbostic 	 */
584*32523Sbostic #define	STEP0MASK	(UDA_ERR | UDA_STEP4 | UDA_STEP3 | UDA_STEP2 | \
585*32523Sbostic 			 UDA_STEP1 | UDA_NV)
586*32523Sbostic 
587*32523Sbostic 	sc->sc_state = ST_IDLE;	/* in case init fails */
588*32523Sbostic 	udaddr = (struct udadevice *) um->um_addr;
589*32523Sbostic 	udaddr->udaip = 0;
590*32523Sbostic 	timo = todr() + 1000;
591*32523Sbostic 	while ((udaddr->udasa & STEP0MASK) == 0) {
592*32523Sbostic 		if (todr() > timo) {
593*32523Sbostic 			printf("uda%d: timeout during init\n", ctlr);
594*32523Sbostic 			return (-1);
595*32523Sbostic 		}
596*32523Sbostic 	}
597*32523Sbostic 	if ((udaddr->udasa & STEP0MASK) != UDA_STEP1) {
598*32523Sbostic 		printf("uda%d: init failed, sa=%b\n", ctlr,
599*32523Sbostic 			udaddr->udasa, udasr_bits);
600*32523Sbostic 		return (-1);
601*32523Sbostic 	}
602*32523Sbostic 
603*32523Sbostic 	/*
604*32523Sbostic 	 * Success!  Record new state, and start step 1 initialisation.
605*32523Sbostic 	 * The rest is done in the interrupt handler.
606*32523Sbostic 	 */
607*32523Sbostic 	sc->sc_state = ST_STEP1;
608*32523Sbostic 	udaddr->udasa = UDA_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) | UDA_IE |
609*32523Sbostic 	    (sc->sc_ivec >> 2);
610*32523Sbostic 	return (0);
6114743Swnj }
6124743Swnj 
6134743Swnj /*
614*32523Sbostic  * Open a drive.
6154743Swnj  */
616*32523Sbostic /*ARGSUSED*/
617*32523Sbostic udaopen(dev, flag, fmt)
6184743Swnj 	dev_t dev;
61930773Skarels 	int flag, fmt;
6204743Swnj {
621*32523Sbostic 	register int unit;
6224743Swnj 	register struct uba_device *ui;
6234743Swnj 	register struct uda_softc *sc;
62430536Skarels 	register struct disklabel *lp;
62530536Skarels 	register struct partition *pp;
62630916Skarels 	register struct ra_info *ra;
627*32523Sbostic 	int s, i, part, mask, error = 0;
62830536Skarels 	daddr_t start, end;
62930536Skarels 
630*32523Sbostic 	/*
631*32523Sbostic 	 * Make sure this is a reasonable open request.
632*32523Sbostic 	 */
633*32523Sbostic 	unit = udaunit(dev);
634*32523Sbostic 	if (unit >= NRA || (ui = udadinfo[unit]) == 0 || ui->ui_alive == 0)
6358576Sroot 		return (ENXIO);
636*32523Sbostic 
637*32523Sbostic 	/*
638*32523Sbostic 	 * Make sure the controller is running, by (re)initialising it if
639*32523Sbostic 	 * necessary.
640*32523Sbostic 	 */
6414743Swnj 	sc = &uda_softc[ui->ui_ctlr];
6425434Sroot 	s = spl5();
643*32523Sbostic 	if (sc->sc_state != ST_RUN) {
644*32523Sbostic 		if (sc->sc_state == ST_IDLE && udainit(ui->ui_ctlr)) {
645*32523Sbostic 			splx(s);
6468576Sroot 			return (EIO);
64717553Skarels 		}
648*32523Sbostic 		/*
649*32523Sbostic 		 * In case it does not come up, make sure we will be
650*32523Sbostic 		 * restarted in 10 seconds.  This corresponds to the
651*32523Sbostic 		 * 10 second timeouts in udaprobe() and udaslave().
652*32523Sbostic 		 */
653*32523Sbostic 		sc->sc_flags |= SC_DOWAKE;
654*32523Sbostic 		timeout(wakeup, (caddr_t) sc, 10 * hz);
655*32523Sbostic 		sleep((caddr_t) sc, PRIBIO);
656*32523Sbostic 		if (sc->sc_state != ST_RUN) {
657*32523Sbostic 			splx(s);
658*32523Sbostic 			printf("uda%d: controller hung\n", ui->ui_ctlr);
659*32523Sbostic 			return (EIO);
660*32523Sbostic 		}
661*32523Sbostic 		untimeout(wakeup, (caddr_t) sc);
6624743Swnj 	}
663*32523Sbostic 
664*32523Sbostic 	/*
665*32523Sbostic 	 * Wait for the state to settle
666*32523Sbostic 	 */
667*32523Sbostic 	ra = &ra_info[unit];
668*32523Sbostic 	while (ra->ra_state != OPEN && ra->ra_state != OPENRAW &&
669*32523Sbostic 	    ra->ra_state != CLOSED)
670*32523Sbostic 		sleep((caddr_t)ra, PZERO + 1);
671*32523Sbostic 
672*32523Sbostic 	/*
673*32523Sbostic 	 * If not on line, or we are not sure of the label, reinitialise
674*32523Sbostic 	 * the drive.
675*32523Sbostic 	 */
676*32523Sbostic 	if ((ui->ui_flags & UNIT_ONLINE) == 0 ||
677*32523Sbostic 	    (ra->ra_state != OPEN && ra->ra_state != OPENRAW))
678*32523Sbostic 		error = uda_rainit(ui, flag);
67930916Skarels 	splx(s);
680*32523Sbostic 	if (error)
681*32523Sbostic 		return (error);
68230536Skarels 
683*32523Sbostic 	part = udapart(dev);
684*32523Sbostic 	lp = &udalabel[unit];
68530536Skarels 	if (part >= lp->d_npartitions)
68630536Skarels 		return (ENXIO);
68730536Skarels 	/*
688*32523Sbostic 	 * Warn if a partition is opened that overlaps another
689*32523Sbostic 	 * already open, unless either is the `raw' partition
690*32523Sbostic 	 * (whole disk).
69130536Skarels 	 */
692*32523Sbostic #define	RAWPART		2	/* 'c' partition */	/* XXX */
693*32523Sbostic 	mask = 1 << part;
694*32523Sbostic 	if ((ra->ra_openpart & mask) == 0 && part != RAWPART) {
69530536Skarels 		pp = &lp->d_partitions[part];
69630536Skarels 		start = pp->p_offset;
69730536Skarels 		end = pp->p_offset + pp->p_size;
698*32523Sbostic 		for (pp = lp->d_partitions, i = 0;
699*32523Sbostic 		     i < lp->d_npartitions; pp++, i++) {
70030536Skarels 			if (pp->p_offset + pp->p_size <= start ||
701*32523Sbostic 			    pp->p_offset >= end || i == RAWPART)
70230536Skarels 				continue;
703*32523Sbostic 			if (ra->ra_openpart & (1 << i))
70430536Skarels 				log(LOG_WARNING,
70530536Skarels 				    "ra%d%c: overlaps open partition (%c)\n",
706*32523Sbostic 				    unit, part + 'a', i + 'a');
70717553Skarels 		}
70817553Skarels 	}
70930773Skarels 	switch (fmt) {
71030773Skarels 	case S_IFCHR:
711*32523Sbostic 		ra->ra_copenpart |= mask;
71230773Skarels 		break;
71330773Skarels 	case S_IFBLK:
714*32523Sbostic 		ra->ra_bopenpart |= mask;
71530773Skarels 		break;
71630773Skarels 	}
717*32523Sbostic 	ra->ra_openpart |= mask;
7188576Sroot 	return (0);
7194743Swnj }
7204743Swnj 
721*32523Sbostic udaclose(dev, flags, fmt)
72230536Skarels 	dev_t dev;
72330773Skarels 	int flags, fmt;
72430536Skarels {
725*32523Sbostic 	register int unit = udaunit(dev);
72630773Skarels 	register struct ra_info *ra = &ra_info[unit];
727*32523Sbostic 	int s, mask = (1 << udapart(dev));
72830536Skarels 
72930773Skarels 	switch (fmt) {
73030773Skarels 	case S_IFCHR:
731*32523Sbostic 		ra->ra_copenpart &= ~mask;
73230773Skarels 		break;
73330773Skarels 	case S_IFBLK:
734*32523Sbostic 		ra->ra_bopenpart &= ~mask;
73530773Skarels 		break;
73630773Skarels 	}
737*32523Sbostic 	ra->ra_openpart = ra->ra_copenpart | ra->ra_bopenpart;
738*32523Sbostic 
73930536Skarels 	/*
740*32523Sbostic 	 * Should wait for I/O to complete on this partition even if
741*32523Sbostic 	 * others are open, but wait for work on blkflush().
74230536Skarels 	 */
743*32523Sbostic 	if (ra->ra_openpart == 0) {
74430536Skarels 		s = spl5();
745*32523Sbostic 		while (udautab[unit].b_actf)
746*32523Sbostic 			sleep((caddr_t)&udautab[unit], PZERO - 1);
74730536Skarels 		splx(s);
748*32523Sbostic 		ra->ra_state = CLOSED;
74930536Skarels 	}
75030773Skarels 	return (0);
75130536Skarels }
75230536Skarels 
7534743Swnj /*
754*32523Sbostic  * Initialise a drive.  If it is not already, bring it on line,
755*32523Sbostic  * and set a timeout on it in case it fails to respond.
756*32523Sbostic  * When on line, read in the pack label.
7574743Swnj  */
758*32523Sbostic uda_rainit(ui, flags)
75930536Skarels 	register struct uba_device *ui;
760*32523Sbostic 	int flags;
76130536Skarels {
762*32523Sbostic 	register struct uda_softc *sc = &uda_softc[ui->ui_ctlr];
763*32523Sbostic 	register struct disklabel *lp;
76430536Skarels 	register struct mscp *mp;
765*32523Sbostic 	register int unit = ui->ui_unit;
766*32523Sbostic 	register struct ra_info *ra;
76730773Skarels 	char *msg, *readdisklabel();
768*32523Sbostic 	int s, i, udastrategy();
76930536Skarels 	extern int cold;
77030536Skarels 
771*32523Sbostic 	ra = &ra_info[unit];
772*32523Sbostic 	if ((ui->ui_flags & UNIT_ONLINE) == 0) {
773*32523Sbostic 		mp = mscp_getcp(&sc->sc_mi, MSCP_WAIT);
774*32523Sbostic 		mp->mscp_opcode = M_OP_ONLINE;
775*32523Sbostic 		mp->mscp_unit = ui->ui_slave;
776*32523Sbostic 		mp->mscp_cmdref = (long)&ui->ui_flags;
777*32523Sbostic 		*mp->mscp_addr |= MSCP_OWN | MSCP_INT;
778*32523Sbostic 		ra->ra_state = WANTOPEN;
779*32523Sbostic 		if (!cold)
780*32523Sbostic 			s = spl5();
781*32523Sbostic 		i = ((struct udadevice *)ui->ui_addr)->udaip;
78230536Skarels 
78330916Skarels 		if (cold) {
784*32523Sbostic 			i = todr() + 1000;
785*32523Sbostic 			while ((ui->ui_flags & UNIT_ONLINE) == 0)
786*32523Sbostic 				if (todr() > i)
787*32523Sbostic 					break;
78830916Skarels 		} else {
789*32523Sbostic 			timeout(wakeup, (caddr_t)&ui->ui_flags, 10 * hz);
790*32523Sbostic 			sleep((caddr_t)&ui->ui_flags, PSWP + 1);
791*32523Sbostic 			splx(s);
792*32523Sbostic 			untimeout(wakeup, (caddr_t)&ui->ui_flags);
79330916Skarels 		}
794*32523Sbostic 		if (ra->ra_state != OPENRAW) {
795*32523Sbostic 			ra->ra_state = CLOSED;
796*32523Sbostic 			wakeup((caddr_t)ra);
79730916Skarels 			return (EIO);
79830916Skarels 		}
79930536Skarels 	}
80030536Skarels 
801*32523Sbostic 	lp = &udalabel[unit];
80230916Skarels 	lp->d_secsize = DEV_BSIZE;
803*32523Sbostic 	lp->d_secperunit = ra->ra_dsize;
80430916Skarels 
80530536Skarels 	if (flags & O_NDELAY)
80630536Skarels 		return (0);
807*32523Sbostic 	ra->ra_state = RDLABEL;
80830536Skarels 	/*
809*32523Sbostic 	 * Set up default sizes until we have the label, or longer
810*32523Sbostic 	 * if there is none.  Set secpercyl, as readdisklabel wants
811*32523Sbostic 	 * to compute b_cylin (although we do not need it).
81230536Skarels 	 */
81330916Skarels 	lp->d_secpercyl = 1;
81430536Skarels 	lp->d_npartitions = 1;
81530536Skarels 	lp->d_partitions[0].p_size = lp->d_secperunit;
81630536Skarels 	lp->d_partitions[0].p_offset = 0;
817*32523Sbostic 
81830536Skarels 	/*
81930536Skarels 	 * Read pack label.
82030536Skarels 	 */
821*32523Sbostic 	if ((msg = readdisklabel(udaminor(unit, 0), udastrategy, lp)) != NULL) {
82230916Skarels 		log(LOG_ERR, "ra%d: %s\n", unit, msg);
82330536Skarels #ifdef COMPAT_42
824*32523Sbostic 		if (udamaptype(unit, lp))
825*32523Sbostic 			ra->ra_state = OPEN;
82630536Skarels 		else
827*32523Sbostic 			ra->ra_state = OPENRAW;
82831022Skarels #else
829*32523Sbostic 		ra->ra_state = OPENRAW;
830*32523Sbostic 		/* uda_makefakelabel(ra, lp); */
83130536Skarels #endif
83230773Skarels 	} else
833*32523Sbostic 		ra->ra_state = OPEN;
83430916Skarels 	wakeup((caddr_t)ra);
83530916Skarels 	return (0);
83630536Skarels }
83730536Skarels 
838*32523Sbostic /*
839*32523Sbostic  * Copy the geometry information for the given ra from a
840*32523Sbostic  * GET UNIT STATUS response.  If check, see if it changed.
841*32523Sbostic  */
842*32523Sbostic uda_rasave(unit, mp, check)
843*32523Sbostic 	int unit;
844*32523Sbostic 	register struct mscp *mp;
845*32523Sbostic 	int check;
846*32523Sbostic {
847*32523Sbostic 	register struct ra_info *ra = &ra_info[unit];
848*32523Sbostic 
849*32523Sbostic 	if (check && ra->ra_type != mp->mscp_guse.guse_drivetype) {
850*32523Sbostic 		printf("ra%d: changed types! was %d now %d\n",
851*32523Sbostic 			ra->ra_type, mp->mscp_guse.guse_drivetype);
852*32523Sbostic 		ra->ra_state = CLOSED;	/* ??? */
853*32523Sbostic 	}
854*32523Sbostic 	ra->ra_type = mp->mscp_guse.guse_drivetype;
855*32523Sbostic 	ra->ra_mediaid = mp->mscp_guse.guse_mediaid;
856*32523Sbostic 	ra->ra_geom.rg_nsectors = mp->mscp_guse.guse_nspt;
857*32523Sbostic 	ra->ra_geom.rg_ngroups = mp->mscp_guse.guse_group;
858*32523Sbostic 	ra->ra_geom.rg_ngpc = mp->mscp_guse.guse_ngpc;
859*32523Sbostic 	ra->ra_geom.rg_ntracks = ra->ra_geom.rg_ngroups * ra->ra_geom.rg_ngpc;
860*32523Sbostic 	/* ra_geom.rg_ncyl cannot be computed until we have ra_dsize */
861*32523Sbostic #ifdef notyet
862*32523Sbostic 	ra->ra_geom.rg_rctsize = mp->mscp_guse.guse_rctsize;
863*32523Sbostic 	ra->ra_geom.rg_rbns = mp->mscp_guse.guse_nrpt;
864*32523Sbostic 	ra->ra_geom.rg_nrct = mp->mscp_guse.guse_nrct;
865*32523Sbostic #endif
866*32523Sbostic }
867*32523Sbostic 
868*32523Sbostic /*
869*32523Sbostic  * Queue a transfer request, and if possible, hand it to the controller.
870*32523Sbostic  *
871*32523Sbostic  * This routine is broken into two so that the internal version
872*32523Sbostic  * udastrat1() can be called by the (nonexistent, as yet) bad block
873*32523Sbostic  * revectoring routine.
874*32523Sbostic  */
875*32523Sbostic udastrategy(bp)
8764743Swnj 	register struct buf *bp;
8774743Swnj {
878*32523Sbostic 	register int unit;
8794743Swnj 	register struct uba_device *ui;
88030536Skarels 	register struct disklabel *lp;
881*32523Sbostic 	register struct ra_info *ra;
882*32523Sbostic 	struct partition *pp;
883*32523Sbostic 	int p;
8844743Swnj 	daddr_t sz, maxsz;
8854743Swnj 
886*32523Sbostic 	/*
887*32523Sbostic 	 * Make sure this is a reasonable drive to use.
888*32523Sbostic 	 */
889*32523Sbostic 	if ((unit = udaunit(bp->b_dev)) >= NRA ||
890*32523Sbostic 	    (ui = udadinfo[unit]) == NULL || ui->ui_alive == 0 ||
891*32523Sbostic 	    (ra = &ra_info[unit])->ra_state == CLOSED) {
89224742Sbloom 		bp->b_error = ENXIO;
8934743Swnj 		goto bad;
89424742Sbloom 	}
895*32523Sbostic 
896*32523Sbostic 	/*
897*32523Sbostic 	 * If drive is open `raw' or reading label, let it at it.
898*32523Sbostic 	 */
899*32523Sbostic 	if (ra->ra_state < OPEN) {
900*32523Sbostic 		udastrat1(bp);
901*32523Sbostic 		return;
90224742Sbloom 	}
903*32523Sbostic 	p = udapart(bp->b_dev);
904*32523Sbostic 	if ((ra->ra_openpart & (1 << p)) == 0)	/* can't happen? */
905*32523Sbostic 		panic("udastrategy");
906*32523Sbostic 		/* alternatively, ENODEV */
907*32523Sbostic 
908*32523Sbostic 	/*
909*32523Sbostic 	 * Determine the size of the transfer, and make sure it is
910*32523Sbostic 	 * within the boundaries of the partition.
911*32523Sbostic 	 */
912*32523Sbostic 	pp = &udalabel[unit].d_partitions[p];
913*32523Sbostic 	maxsz = pp->p_size;
914*32523Sbostic 	if (pp->p_offset + pp->p_size > ra->ra_dsize)
915*32523Sbostic 		maxsz = ra->ra_dsize - pp->p_offset;
91630536Skarels 	sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT;
91730536Skarels 	if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) {
918*32523Sbostic 		/* if exactly at end of disk, return an EOF */
91924787Skarels 		if (bp->b_blkno == maxsz) {
92024787Skarels 			bp->b_resid = bp->b_bcount;
921*32523Sbostic 			biodone(bp);
922*32523Sbostic 			return;
92324787Skarels 		}
924*32523Sbostic 		/* or truncate if part of it fits */
92530536Skarels 		sz = maxsz - bp->b_blkno;
92630536Skarels 		if (sz <= 0) {
927*32523Sbostic 			bp->b_error = EINVAL;	/* or hang it up */
92830536Skarels 			goto bad;
92930536Skarels 		}
93030536Skarels 		bp->b_bcount = sz << DEV_BSHIFT;
93124742Sbloom 	}
932*32523Sbostic 	udastrat1(bp);
933*32523Sbostic 	return;
934*32523Sbostic bad:
935*32523Sbostic 	bp->b_flags |= B_ERROR;
936*32523Sbostic 	biodone(bp);
937*32523Sbostic }
938*32523Sbostic 
939*32523Sbostic /*
940*32523Sbostic  * Work routine for udastrategy.
941*32523Sbostic  */
942*32523Sbostic udastrat1(bp)
943*32523Sbostic 	register struct buf *bp;
944*32523Sbostic {
945*32523Sbostic 	register int unit = udaunit(bp->b_dev);
946*32523Sbostic 	register struct uba_ctlr *um;
947*32523Sbostic 	register struct buf *dp;
948*32523Sbostic 	struct uba_device *ui;
949*32523Sbostic 	int s = spl5();
950*32523Sbostic 
9514743Swnj 	/*
952*32523Sbostic 	 * Append the buffer to the drive queue, and if it is not
953*32523Sbostic 	 * already there, the drive to the controller queue.  (However,
954*32523Sbostic 	 * if the drive queue is marked to be requeued, we must be
955*32523Sbostic 	 * awaiting an on line or get unit status command; in this
956*32523Sbostic 	 * case, leave it off the controller queue.)
9574743Swnj 	 */
958*32523Sbostic 	um = (ui = udadinfo[unit])->ui_mi;
959*32523Sbostic 	dp = &udautab[unit];
960*32523Sbostic 	APPEND(bp, dp, av_forw);
961*32523Sbostic 	if (dp->b_active == 0 && (ui->ui_flags & UNIT_REQUEUE) == 0) {
962*32523Sbostic 		APPEND(dp, &um->um_tab, b_forw);
963*32523Sbostic 		dp->b_active++;
964*32523Sbostic 	}
965*32523Sbostic 
9664743Swnj 	/*
967*32523Sbostic 	 * Start activity on the controller.  Note that unlike other
968*32523Sbostic 	 * Unibus drivers, we must always do this, not just when the
969*32523Sbostic 	 * controller is not active.
9704743Swnj 	 */
971*32523Sbostic 	udastart(um);
9725434Sroot 	splx(s);
9734743Swnj }
9744743Swnj 
975*32523Sbostic /*
976*32523Sbostic  * Start up whatever transfers we can find.
977*32523Sbostic  * Note that udastart() must be called at spl5().
978*32523Sbostic  */
979*32523Sbostic udastart(um)
9804743Swnj 	register struct uba_ctlr *um;
9814743Swnj {
982*32523Sbostic 	register struct uda_softc *sc = &uda_softc[um->um_ctlr];
9834743Swnj 	register struct buf *bp, *dp;
9844743Swnj 	register struct mscp *mp;
985*32523Sbostic 	struct uba_device *ui;
9864743Swnj 	struct udadevice *udaddr;
987*32523Sbostic 	struct partition *pp;
988*32523Sbostic 	int i, sz;
9894743Swnj 
990*32523Sbostic #ifdef lint
991*32523Sbostic 	i = 0; i = i;
992*32523Sbostic #endif
993*32523Sbostic 	/*
994*32523Sbostic 	 * If it is not running, try (again and again...) to initialise
995*32523Sbostic 	 * it.  If it is currently initialising just ignore it for now.
996*32523Sbostic 	 */
997*32523Sbostic 	if (sc->sc_state != ST_RUN) {
998*32523Sbostic 		if (sc->sc_state == ST_IDLE && udainit(um->um_ctlr))
999*32523Sbostic 			printf("uda%d: still hung\n", um->um_ctlr);
1000*32523Sbostic 		return;
1001*32523Sbostic 	}
1002*32523Sbostic 
1003*32523Sbostic 	/*
1004*32523Sbostic 	 * If um_cmd is nonzero, this controller is on the Unibus
1005*32523Sbostic 	 * resource wait queue.  It will not help to try more requests;
1006*32523Sbostic 	 * instead, when the Unibus unblocks and calls udadgo(), we
1007*32523Sbostic 	 * will call udastart() again.
1008*32523Sbostic 	 */
1009*32523Sbostic 	if (um->um_cmd)
1010*32523Sbostic 		return;
1011*32523Sbostic 
1012*32523Sbostic 	sc->sc_flags |= SC_INSTART;
1013*32523Sbostic 	udaddr = (struct udadevice *) um->um_addr;
1014*32523Sbostic 
10154743Swnj loop:
1016*32523Sbostic 	/*
1017*32523Sbostic 	 * Service the drive at the head of the queue.  It may not
1018*32523Sbostic 	 * need anything, in which case it might be shutting down
1019*32523Sbostic 	 * in udaclose().
1020*32523Sbostic 	 */
1021*32523Sbostic 	if ((dp = um->um_tab.b_actf) == NULL)
1022*32523Sbostic 		goto out;
10234743Swnj 	if ((bp = dp->b_actf) == NULL) {
10244743Swnj 		dp->b_active = 0;
10254743Swnj 		um->um_tab.b_actf = dp->b_forw;
1026*32523Sbostic 		if (ra_info[dp - udautab].ra_openpart == 0)
1027*32523Sbostic 			wakeup((caddr_t)dp); /* finish close protocol */
1028*32523Sbostic 		goto loop;
10294743Swnj 	}
1030*32523Sbostic 
1031*32523Sbostic 	if (udaddr->udasa & UDA_ERR) {	/* ctlr fatal error */
1032*32523Sbostic 		udasaerror(um);
1033*32523Sbostic 		goto out;
10344743Swnj 	}
1035*32523Sbostic 
1036*32523Sbostic 	/*
1037*32523Sbostic 	 * Get an MSCP packet, then figure out what to do.  If
1038*32523Sbostic 	 * we cannot get a command packet, the command ring may
1039*32523Sbostic 	 * be too small:  We should have at least as many command
1040*32523Sbostic 	 * packets as credits, for best performance.
1041*32523Sbostic 	 */
1042*32523Sbostic 	if ((mp = mscp_getcp(&sc->sc_mi, MSCP_DONTWAIT)) == NULL) {
1043*32523Sbostic 		if (sc->sc_mi.mi_credits > MSCP_MINCREDITS &&
1044*32523Sbostic 		    (sc->sc_flags & SC_GRIPED) == 0) {
1045*32523Sbostic 			log(LOG_NOTICE, "uda%d: command ring too small\n",
1046*32523Sbostic 				um->um_ctlr);
1047*32523Sbostic 			sc->sc_flags |= SC_GRIPED;/* complain only once */
104817553Skarels 		}
1049*32523Sbostic 		goto out;
10504743Swnj 	}
10514743Swnj 
1052*32523Sbostic 	/*
1053*32523Sbostic 	 * Bring the drive on line if it is not already.  Get its status
1054*32523Sbostic 	 * if we do not already have it.  Otherwise just start the transfer.
1055*32523Sbostic 	 */
1056*32523Sbostic 	ui = udadinfo[udaunit(bp->b_dev)];
1057*32523Sbostic 	if ((ui->ui_flags & UNIT_ONLINE) == 0) {
1058*32523Sbostic 		mp->mscp_opcode = M_OP_ONLINE;
1059*32523Sbostic 		goto common;
10604743Swnj 	}
1061*32523Sbostic 	if ((ui->ui_flags & UNIT_HAVESTATUS) == 0) {
1062*32523Sbostic 		mp->mscp_opcode = M_OP_GETUNITST;
1063*32523Sbostic common:
1064*32523Sbostic if (ui->ui_flags & UNIT_REQUEUE) panic("udastart");
1065*32523Sbostic 		/*
1066*32523Sbostic 		 * Take the drive off the controller queue.  When the
1067*32523Sbostic 		 * command finishes, make sure the drive is requeued.
1068*32523Sbostic 		 */
1069*32523Sbostic 		um->um_tab.b_actf = dp->b_forw;
1070*32523Sbostic 		dp->b_active = 0;
1071*32523Sbostic 		ui->ui_flags |= UNIT_REQUEUE;
1072*32523Sbostic 		mp->mscp_unit = ui->ui_slave;
1073*32523Sbostic 		*mp->mscp_addr |= MSCP_OWN | MSCP_INT;
1074*32523Sbostic 		sc->sc_flags |= SC_STARTPOLL;
1075*32523Sbostic #ifdef POLLSTATS
1076*32523Sbostic 		sc->sc_ncmd++;
107725653Skarels #endif
1078*32523Sbostic 		goto loop;
107917553Skarels 	}
1080*32523Sbostic 
1081*32523Sbostic 	pp = &udalabel[ui->ui_unit].d_partitions[udapart(bp->b_dev)];
1082*32523Sbostic 	mp->mscp_opcode = (bp->b_flags & B_READ) ? M_OP_READ : M_OP_WRITE;
10834743Swnj 	mp->mscp_unit = ui->ui_slave;
1084*32523Sbostic 	mp->mscp_seq.seq_lbn = bp->b_blkno + pp->p_offset;
1085*32523Sbostic 	pp = &udalabel[ui->ui_unit].d_partitions[udapart(bp->b_dev)];
108630536Skarels 	sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT;
1087*32523Sbostic 	mp->mscp_seq.seq_bytecount = bp->b_blkno + sz > pp->p_size ?
1088*32523Sbostic 		(pp->p_size - bp->b_blkno) >> DEV_BSHIFT : bp->b_bcount;
1089*32523Sbostic 	/* mscp_cmdref is filled in by mscp_go() */
10904743Swnj 
10914743Swnj 	/*
1092*32523Sbostic 	 * Drop the packet pointer into the `command' field so udadgo()
1093*32523Sbostic 	 * can tell what to start.  If ubago returns 1, we can do another
1094*32523Sbostic 	 * transfer.  If not, um_cmd will still point at mp, so we will
1095*32523Sbostic 	 * know that we are waiting for resources.
10964743Swnj 	 */
1097*32523Sbostic 	um->um_cmd = (int)mp;
1098*32523Sbostic 	if (ubago(ui))
1099*32523Sbostic 		goto loop;
1100*32523Sbostic 
1101*32523Sbostic 	/*
1102*32523Sbostic 	 * All done, or blocked in ubago().  If we managed to
1103*32523Sbostic 	 * issue some commands, start up the beast.
1104*32523Sbostic 	 */
1105*32523Sbostic out:
1106*32523Sbostic 	if (sc->sc_flags & SC_STARTPOLL) {
1107*32523Sbostic #ifdef POLLSTATS
1108*32523Sbostic 		udastats.cmd[sc->sc_ncmd]++;
1109*32523Sbostic 		sc->sc_ncmd = 0;
1110*32523Sbostic #endif
1111*32523Sbostic 		i = ((struct udadevice *) um->um_addr)->udaip;
11124743Swnj 	}
1113*32523Sbostic 	sc->sc_flags &= ~(SC_INSTART | SC_STARTPOLL);
1114*32523Sbostic }
1115*32523Sbostic 
1116*32523Sbostic /*
1117*32523Sbostic  * Start a transfer.
1118*32523Sbostic  *
1119*32523Sbostic  * If we are not called from within udastart(), we must have been
1120*32523Sbostic  * blocked, so call udastart to do more requests (if any).  If
1121*32523Sbostic  * this calls us again immediately we will not recurse, because
1122*32523Sbostic  * that time we will be in udastart().  Clever....
1123*32523Sbostic  */
1124*32523Sbostic udadgo(um)
1125*32523Sbostic 	register struct uba_ctlr *um;
1126*32523Sbostic {
1127*32523Sbostic 	struct uda_softc *sc = &uda_softc[um->um_ctlr];
1128*32523Sbostic 	struct mscp *mp = (struct mscp *)um->um_cmd;
1129*32523Sbostic 
1130*32523Sbostic 	um->um_tab.b_active++;	/* another transfer going */
1131*32523Sbostic 
11324743Swnj 	/*
1133*32523Sbostic 	 * Fill in the MSCP packet and move the buffer to the
1134*32523Sbostic 	 * I/O wait queue.  Mark the controller as no longer on
1135*32523Sbostic 	 * the resource queue, and remember to initiate polling.
11364743Swnj 	 */
1137*32523Sbostic 	mp->mscp_seq.seq_buffer = (um->um_ubinfo & 0x3ffff) |
1138*32523Sbostic 		(UBAI_BDP(um->um_ubinfo) << 24);
1139*32523Sbostic 	mscp_go(&sc->sc_mi, mp, um->um_ubinfo);
1140*32523Sbostic 	um->um_cmd = 0;
1141*32523Sbostic 	um->um_ubinfo = 0;	/* tyke it awye */
1142*32523Sbostic 	sc->sc_flags |= SC_STARTPOLL;
1143*32523Sbostic #ifdef POLLSTATS
1144*32523Sbostic 	sc->sc_ncmd++;
1145*32523Sbostic #endif
1146*32523Sbostic 	if ((sc->sc_flags & SC_INSTART) == 0)
1147*32523Sbostic 		udastart(um);
11484743Swnj }
11494743Swnj 
1150*32523Sbostic udaiodone(mi, bp, info)
1151*32523Sbostic 	register struct mscp_info *mi;
1152*32523Sbostic 	struct buf *bp;
1153*32523Sbostic 	int info;
1154*32523Sbostic {
1155*32523Sbostic 	register struct uba_ctlr *um = udaminfo[mi->mi_ctlr];
1156*32523Sbostic 
1157*32523Sbostic 	um->um_ubinfo = info;
1158*32523Sbostic 	ubadone(um);
1159*32523Sbostic 	biodone(bp);
1160*32523Sbostic 	if (um->um_bdp && mi->mi_wtab.av_forw == &mi->mi_wtab)
1161*32523Sbostic 		ubarelse(um->um_ubanum, &um->um_bdp);
1162*32523Sbostic 	um->um_tab.b_active--;	/* another transfer done */
1163*32523Sbostic }
1164*32523Sbostic 
11654743Swnj /*
1166*32523Sbostic  * The error bit was set in the controller status register.  Gripe,
1167*32523Sbostic  * reset the controller, requeue pending transfers.
11684743Swnj  */
1169*32523Sbostic udasaerror(um)
1170*32523Sbostic 	register struct uba_ctlr *um;
11714743Swnj {
1172*32523Sbostic 
1173*32523Sbostic 	printf("uda%d: controller error, sa=%b\n", um->um_ctlr,
1174*32523Sbostic 		((struct udadevice *) um->um_addr)->udasa, udasr_bits);
1175*32523Sbostic 	mscp_requeue(&uda_softc[um->um_ctlr].sc_mi);
1176*32523Sbostic 	(void) udainit(um->um_ctlr);
1177*32523Sbostic }
1178*32523Sbostic 
1179*32523Sbostic /*
1180*32523Sbostic  * Interrupt routine.  Depending on the state of the controller,
1181*32523Sbostic  * continue initialisation, or acknowledge command and response
1182*32523Sbostic  * interrupts, and process responses.
1183*32523Sbostic  */
1184*32523Sbostic udaintr(ctlr)
1185*32523Sbostic 	int ctlr;
1186*32523Sbostic {
1187*32523Sbostic 	register struct uba_ctlr *um = udaminfo[ctlr];
1188*32523Sbostic 	register struct uda_softc *sc = &uda_softc[ctlr];
1189*32523Sbostic 	register struct udadevice *udaddr = (struct udadevice *) um->um_addr;
1190*32523Sbostic 	register struct uda *ud;
1191*32523Sbostic 	register struct mscp *mp;
11924743Swnj 	register int i;
11934743Swnj 
119427254Skridle #ifdef VAX630
1195*32523Sbostic 	(void) spl5();		/* Qbus interrupt protocol is odd */
119627254Skridle #endif
1197*32523Sbostic 	sc->sc_wticks = 0;	/* reset interrupt watchdog */
1198*32523Sbostic 
1199*32523Sbostic 	/*
1200*32523Sbostic 	 * Combinations during steps 1, 2, and 3: STEPnMASK
1201*32523Sbostic 	 * corresponds to which bits should be tested;
1202*32523Sbostic 	 * STEPnGOOD corresponds to the pattern that should
1203*32523Sbostic 	 * appear after the interrupt from STEPn initialisation.
1204*32523Sbostic 	 * All steps test the bits in ALLSTEPS.
1205*32523Sbostic 	 */
1206*32523Sbostic #define	ALLSTEPS	(UDA_ERR|UDA_STEP4|UDA_STEP3|UDA_STEP2|UDA_STEP1)
1207*32523Sbostic 
1208*32523Sbostic #define	STEP1MASK	(ALLSTEPS | UDA_IE | UDA_NCNRMASK)
1209*32523Sbostic #define	STEP1GOOD	(UDA_STEP2 | UDA_IE | (NCMDL2 << 3) | NRSPL2)
1210*32523Sbostic 
1211*32523Sbostic #define	STEP2MASK	(ALLSTEPS | UDA_IE | UDA_IVECMASK)
1212*32523Sbostic #define	STEP2GOOD	(UDA_STEP3 | UDA_IE | (sc->sc_ivec >> 2))
1213*32523Sbostic 
1214*32523Sbostic #define	STEP3MASK	ALLSTEPS
1215*32523Sbostic #define	STEP3GOOD	UDA_STEP4
1216*32523Sbostic 
12174743Swnj 	switch (sc->sc_state) {
1218*32523Sbostic 
1219*32523Sbostic 	case ST_IDLE:
1220*32523Sbostic 		/*
1221*32523Sbostic 		 * Ignore unsolicited interrupts.
1222*32523Sbostic 		 */
1223*32523Sbostic 		log(LOG_WARNING, "uda%d: stray intr\n", ctlr);
12244743Swnj 		return;
12254743Swnj 
1226*32523Sbostic 	case ST_STEP1:
1227*32523Sbostic 		/*
1228*32523Sbostic 		 * Begin step two initialisation.
1229*32523Sbostic 		 */
1230*32523Sbostic 		if ((udaddr->udasa & STEP1MASK) != STEP1GOOD) {
1231*32523Sbostic 			i = 1;
1232*32523Sbostic initfailed:
1233*32523Sbostic 			printf("uda%d: init step %d failed, sa=%b\n",
1234*32523Sbostic 				ctlr, i, udaddr->udasa, udasr_bits);
1235*32523Sbostic 			sc->sc_state = ST_IDLE;
1236*32523Sbostic 			if (sc->sc_flags & SC_DOWAKE) {
1237*32523Sbostic 				sc->sc_flags &= ~SC_DOWAKE;
1238*32523Sbostic 				wakeup((caddr_t) sc);
1239*32523Sbostic 			}
12404743Swnj 			return;
12414743Swnj 		}
1242*32523Sbostic 		udaddr->udasa = (int) &sc->sc_uda->uda_ca.ca_rspdsc[0] |
1243*32523Sbostic 			(cpu == VAX_780 || cpu == VAX_8600 ? UDA_PI : 0);
1244*32523Sbostic 		sc->sc_state = ST_STEP2;
12454743Swnj 		return;
12464743Swnj 
1247*32523Sbostic 	case ST_STEP2:
1248*32523Sbostic 		/*
1249*32523Sbostic 		 * Begin step 3 initialisation.
1250*32523Sbostic 		 */
1251*32523Sbostic 		if ((udaddr->udasa & STEP2MASK) != STEP2GOOD) {
1252*32523Sbostic 			i = 2;
1253*32523Sbostic 			goto initfailed;
12544743Swnj 		}
1255*32523Sbostic 		udaddr->udasa = ((int) &sc->sc_uda->uda_ca.ca_rspdsc[0]) >> 16;
1256*32523Sbostic 		sc->sc_state = ST_STEP3;
12574743Swnj 		return;
12584743Swnj 
1259*32523Sbostic 	case ST_STEP3:
1260*32523Sbostic 		/*
1261*32523Sbostic 		 * Set controller characteristics (finish initialisation).
1262*32523Sbostic 		 */
1263*32523Sbostic 		if ((udaddr->udasa & STEP3MASK) != STEP3GOOD) {
1264*32523Sbostic 			i = 3;
1265*32523Sbostic 			goto initfailed;
12664743Swnj 		}
1267*32523Sbostic 		i = udaddr->udasa & 0xff;
1268*32523Sbostic 		if (i != sc->sc_micro) {
1269*32523Sbostic 			sc->sc_micro = i;
1270*32523Sbostic 			printf("uda%d: version %d model %d\n",
1271*32523Sbostic 				ctlr, i & 0xf, i >> 4);
1272*32523Sbostic 		}
1273*32523Sbostic 
127417553Skarels 		/*
1275*32523Sbostic 		 * Present the burst size, then remove it.  Why this
1276*32523Sbostic 		 * should be done this way, I have no idea.
1277*32523Sbostic 		 *
1278*32523Sbostic 		 * Note that this assumes udaburst[ctlr] > 0.
127917553Skarels 		 */
1280*32523Sbostic 		udaddr->udasa = UDA_GO | (udaburst[ctlr] - 1) << 2;
12814743Swnj 		udaddr->udasa = UDA_GO;
1282*32523Sbostic 		printf("uda%d: DMA burst size set to %d\n",
1283*32523Sbostic 			ctlr, udaburst[ctlr]);
12844743Swnj 
1285*32523Sbostic 		udainitds(ctlr);	/* initialise data structures */
1286*32523Sbostic 
12874743Swnj 		/*
1288*32523Sbostic 		 * Before we can get a command packet, we need some
1289*32523Sbostic 		 * credits.  Fake some up to keep mscp_getcp() happy,
1290*32523Sbostic 		 * get a packet, and cancel all credits (the right
1291*32523Sbostic 		 * number should come back in the response to the
1292*32523Sbostic 		 * SCC packet).
12934743Swnj 		 */
1294*32523Sbostic 		sc->sc_mi.mi_credits = MSCP_MINCREDITS + 1;
1295*32523Sbostic 		mp = mscp_getcp(&sc->sc_mi, MSCP_DONTWAIT);
1296*32523Sbostic 		if (mp == NULL)	/* `cannot happen' */
1297*32523Sbostic 			panic("udaintr");
1298*32523Sbostic 		sc->sc_mi.mi_credits = 0;
1299*32523Sbostic 		mp->mscp_opcode = M_OP_SETCTLRC;
1300*32523Sbostic 		mp->mscp_unit = 0;
1301*32523Sbostic 		mp->mscp_sccc.sccc_ctlrflags = M_CF_ATTN | M_CF_MISC |
1302*32523Sbostic 			M_CF_THIS;
1303*32523Sbostic 		*mp->mscp_addr |= MSCP_OWN | MSCP_INT;
1304*32523Sbostic 		i = udaddr->udaip;
1305*32523Sbostic 		sc->sc_state = ST_SETCHAR;
13064743Swnj 		return;
13074743Swnj 
1308*32523Sbostic 	case ST_SETCHAR:
1309*32523Sbostic 	case ST_RUN:
1310*32523Sbostic 		/*
1311*32523Sbostic 		 * Handle Set Ctlr Characteristics responses and operational
1312*32523Sbostic 		 * responses (via mscp_dorsp).
1313*32523Sbostic 		 */
13144743Swnj 		break;
13154743Swnj 
13164743Swnj 	default:
1317*32523Sbostic 		printf("uda%d: driver bug, state %d\n", ctlr, sc->sc_state);
1318*32523Sbostic 		panic("udastate");
13194743Swnj 	}
13204743Swnj 
1321*32523Sbostic 	if (udaddr->udasa & UDA_ERR) {	/* ctlr fatal error */
1322*32523Sbostic 		udasaerror(um);
1323*32523Sbostic 		return;
13244743Swnj 	}
13254743Swnj 
1326*32523Sbostic 	ud = &uda[ctlr];
1327*32523Sbostic 
13284743Swnj 	/*
1329*32523Sbostic 	 * Handle buffer purge requests.
1330*32523Sbostic 	 * I have never seen these to work usefully, thus the log().
13314743Swnj 	 */
13324743Swnj 	if (ud->uda_ca.ca_bdp) {
1333*32523Sbostic 		log(LOG_DEBUG, "uda%d: purge bdp %d\n",
1334*32523Sbostic 			ctlr, ud->uda_ca.ca_bdp);
133526372Skarels 		UBAPURGE(um->um_hd->uh_uba, ud->uda_ca.ca_bdp);
13364743Swnj 		ud->uda_ca.ca_bdp = 0;
1337*32523Sbostic 		udaddr->udasa = 0;	/* signal purge complete */
13384743Swnj 	}
13394743Swnj 
13404743Swnj 	/*
1341*32523Sbostic 	 * Check for response and command ring transitions.
13424743Swnj 	 */
13434743Swnj 	if (ud->uda_ca.ca_rspint) {
13444743Swnj 		ud->uda_ca.ca_rspint = 0;
1345*32523Sbostic 		mscp_dorsp(&sc->sc_mi);
13464743Swnj 	}
13474743Swnj 	if (ud->uda_ca.ca_cmdint) {
13484743Swnj 		ud->uda_ca.ca_cmdint = 0;
1349*32523Sbostic 		MSCP_DOCMD(&sc->sc_mi);
13504743Swnj 	}
1351*32523Sbostic 	udastart(um);
13524743Swnj }
13534743Swnj 
1354*32523Sbostic #ifndef GENERIC_RAW
1355*32523Sbostic struct buf rudabuf[NRA];
1356*32523Sbostic 
13574743Swnj /*
1358*32523Sbostic  * Read and write.
13594743Swnj  */
1360*32523Sbostic udaread(dev, uio)
1361*32523Sbostic 	dev_t dev;
1362*32523Sbostic 	struct uio *uio;
13634743Swnj {
13644743Swnj 
1365*32523Sbostic 	return (physio(udastrategy, &rudabuf[udaunit(dev)], dev, B_READ,
1366*32523Sbostic 		minphys, uio));
1367*32523Sbostic }
13684743Swnj 
1369*32523Sbostic udawrite(dev, uio)
1370*32523Sbostic 	dev_t dev;
1371*32523Sbostic 	struct uio *uio;
1372*32523Sbostic {
13734743Swnj 
1374*32523Sbostic 	return (physio(udastrategy, &rudabuf[udaunit(dev)], dev, B_WRITE,
1375*32523Sbostic 		minphys, uio));
1376*32523Sbostic }
1377*32523Sbostic #endif /* GENERIC_RAW */
13784743Swnj 
137917553Skarels /*
1380*32523Sbostic  * Initialise the various data structures that control the UDA50.
138117553Skarels  */
1382*32523Sbostic udainitds(ctlr)
1383*32523Sbostic 	int ctlr;
1384*32523Sbostic {
1385*32523Sbostic 	register struct uda *ud = &uda[ctlr];
1386*32523Sbostic 	register struct uda *uud = uda_softc[ctlr].sc_uda;
1387*32523Sbostic 	register struct mscp *mp;
1388*32523Sbostic 	register int i;
13894743Swnj 
1390*32523Sbostic 	for (i = 0, mp = ud->uda_rsp; i < NRSP; i++, mp++) {
1391*32523Sbostic 		ud->uda_ca.ca_rspdsc[i] = MSCP_OWN | MSCP_INT |
1392*32523Sbostic 			(long)&uud->uda_rsp[i].mscp_cmdref;
1393*32523Sbostic 		mp->mscp_addr = &ud->uda_ca.ca_rspdsc[i];
1394*32523Sbostic 		mp->mscp_msglen = MSCP_MSGLEN;
13954743Swnj 	}
1396*32523Sbostic 	for (i = 0, mp = ud->uda_cmd; i < NCMD; i++, mp++) {
1397*32523Sbostic 		ud->uda_ca.ca_cmddsc[i] = MSCP_INT |
1398*32523Sbostic 			(long)&uud->uda_cmd[i].mscp_cmdref;
1399*32523Sbostic 		mp->mscp_addr = &ud->uda_ca.ca_cmddsc[i];
1400*32523Sbostic 		mp->mscp_msglen = MSCP_MSGLEN;
1401*32523Sbostic 	}
14024743Swnj }
14034743Swnj 
14044743Swnj /*
1405*32523Sbostic  * Handle an error datagram.  All we do now is decode it.
14064743Swnj  */
1407*32523Sbostic udadgram(mi, mp)
1408*32523Sbostic 	struct mscp_info *mi;
1409*32523Sbostic 	struct mscp *mp;
14104743Swnj {
141117553Skarels 
1412*32523Sbostic 	mscp_decodeerror(mi->mi_md->md_mname, mi->mi_ctlr, mp);
1413*32523Sbostic }
141417553Skarels 
1415*32523Sbostic /*
1416*32523Sbostic  * The Set Controller Characteristics command finished.
1417*32523Sbostic  * Record the new state of the controller.
1418*32523Sbostic  */
1419*32523Sbostic udactlrdone(mi, mp)
1420*32523Sbostic 	register struct mscp_info *mi;
1421*32523Sbostic 	struct mscp *mp;
1422*32523Sbostic {
1423*32523Sbostic 	register struct uda_softc *sc = &uda_softc[mi->mi_ctlr];
142417553Skarels 
1425*32523Sbostic 	if ((mp->mscp_status & M_ST_MASK) == M_ST_SUCCESS)
1426*32523Sbostic 		sc->sc_state = ST_RUN;
1427*32523Sbostic 	else {
1428*32523Sbostic 		printf("uda%d: SETCTLRC failed: ",
1429*32523Sbostic 			mi->mi_ctlr, mp->mscp_status);
1430*32523Sbostic 		mscp_printevent(mp);
1431*32523Sbostic 		sc->sc_state = ST_IDLE;
14324743Swnj 	}
1433*32523Sbostic 	if (sc->sc_flags & SC_DOWAKE) {
1434*32523Sbostic 		sc->sc_flags &= ~SC_DOWAKE;
1435*32523Sbostic 		wakeup((caddr_t)sc);
14366964Ssam 	}
14374743Swnj }
14384743Swnj 
14394743Swnj /*
1440*32523Sbostic  * Received a response from an as-yet unconfigured drive.  Configure it
1441*32523Sbostic  * in, if possible.
14424743Swnj  */
1443*32523Sbostic udaunconf(mi, mp)
1444*32523Sbostic 	struct mscp_info *mi;
1445*32523Sbostic 	register struct mscp *mp;
14464743Swnj {
14474743Swnj 
144817553Skarels 	/*
1449*32523Sbostic 	 * If it is a slave response, copy it to udaslavereply for
1450*32523Sbostic 	 * udaslave() to look at.
145117553Skarels 	 */
1452*32523Sbostic 	if (mp->mscp_opcode == (M_OP_GETUNITST | M_OP_END) &&
1453*32523Sbostic 	    (uda_softc[mi->mi_ctlr].sc_flags & SC_INSLAVE) != 0) {
1454*32523Sbostic 		udaslavereply = *mp;
1455*32523Sbostic 		return (MSCP_DONE);
14564743Swnj 	}
1457*32523Sbostic 
1458*32523Sbostic 	/*
1459*32523Sbostic 	 * Otherwise, it had better be an available attention response.
1460*32523Sbostic 	 */
1461*32523Sbostic 	if (mp->mscp_opcode != M_OP_AVAILATTN)
1462*32523Sbostic 		return (MSCP_FAILED);
1463*32523Sbostic 
1464*32523Sbostic 	/* do what autoconf does */
1465*32523Sbostic 	return (MSCP_FAILED);	/* not yet, arwhite, not yet */
14664743Swnj }
14674743Swnj 
1468*32523Sbostic /*
1469*32523Sbostic  * A drive came on line.  Check its type and size.  Return DONE if
1470*32523Sbostic  * we think the drive is truly on line.  In any case, awaken anyone
1471*32523Sbostic  * sleeping on the drive on-line-ness.
1472*32523Sbostic  */
1473*32523Sbostic udaonline(ui, mp)
1474*32523Sbostic 	register struct uba_device *ui;
1475*32523Sbostic 	struct mscp *mp;
14764743Swnj {
1477*32523Sbostic 	register struct ra_info *ra = &ra_info[ui->ui_unit];
14784743Swnj 
1479*32523Sbostic 	wakeup((caddr_t)&ui->ui_flags);
1480*32523Sbostic 	if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
1481*32523Sbostic 		printf("uda%d: attempt to bring ra%d on line failed: ",
1482*32523Sbostic 			ui->ui_ctlr, ui->ui_unit);
1483*32523Sbostic 		mscp_printevent(mp);
1484*32523Sbostic 		ra->ra_state = CLOSED;
1485*32523Sbostic 		return (MSCP_FAILED);
1486*32523Sbostic 	}
1487*32523Sbostic 
1488*32523Sbostic 	ra->ra_state = OPENRAW;
1489*32523Sbostic 	ra->ra_dsize = (daddr_t)mp->mscp_onle.onle_unitsize;
1490*32523Sbostic 	printf("ra%d: uda%d, unit %d, size = %d sectors\n", ui->ui_unit,
1491*32523Sbostic 		ui->ui_ctlr, mp->mscp_unit, ra->ra_dsize);
1492*32523Sbostic 	/* can now compute ncyl */
1493*32523Sbostic 	ra->ra_geom.rg_ncyl = ra->ra_dsize / ra->ra_geom.rg_ntracks /
1494*32523Sbostic 		ra->ra_geom.rg_nsectors;
1495*32523Sbostic 	return (MSCP_DONE);
14964743Swnj }
14974743Swnj 
1498*32523Sbostic /*
1499*32523Sbostic  * We got some (configured) unit's status.  Return DONE if it succeeded.
1500*32523Sbostic  */
1501*32523Sbostic udagotstatus(ui, mp)
1502*32523Sbostic 	register struct uba_device *ui;
1503*32523Sbostic 	register struct mscp *mp;
15044743Swnj {
15054743Swnj 
1506*32523Sbostic 	if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
1507*32523Sbostic 		printf("uda%d: attempt to get status for ra%d failed: ",
1508*32523Sbostic 			ui->ui_ctlr, ui->ui_unit);
1509*32523Sbostic 		mscp_printevent(mp);
1510*32523Sbostic 		return (MSCP_FAILED);
1511*32523Sbostic 	}
1512*32523Sbostic 	/* record for (future) bad block forwarding and whatever else */
1513*32523Sbostic 	uda_rasave(ui->ui_unit, mp, 1);
1514*32523Sbostic 	return (MSCP_DONE);
15154743Swnj }
15164743Swnj 
1517*32523Sbostic /*
1518*32523Sbostic  * A transfer failed.  We get a chance to fix or restart it.
1519*32523Sbostic  * Need to write the bad block forwaring code first....
1520*32523Sbostic  */
1521*32523Sbostic /*ARGSUSED*/
1522*32523Sbostic udaioerror(ui, mp, bp)
1523*32523Sbostic 	register struct uba_device *ui;
1524*32523Sbostic 	register struct mscp *mp;
1525*32523Sbostic 	struct buf *bp;
15264743Swnj {
15274743Swnj 
1528*32523Sbostic 	if (mp->mscp_flags & M_EF_BBLKR) {
1529*32523Sbostic 		/*
1530*32523Sbostic 		 * A bad block report.  Eventually we will
1531*32523Sbostic 		 * restart this transfer, but for now, just
1532*32523Sbostic 		 * log it and give up.
1533*32523Sbostic 		 */
1534*32523Sbostic 		log(LOG_ERR, "ra%d: bad block report: %d%s\n",
1535*32523Sbostic 			ui->ui_unit, mp->mscp_seq.seq_lbn,
1536*32523Sbostic 			mp->mscp_flags & M_EF_BBLKU ? " + others" : "");
1537*32523Sbostic 	} else {
1538*32523Sbostic 		/*
1539*32523Sbostic 		 * What the heck IS a `serious exception' anyway?
1540*32523Sbostic 		 * IT SURE WOULD BE NICE IF DEC SOLD DOCUMENTATION
1541*32523Sbostic 		 * FOR THEIR OWN CONTROLLERS.
1542*32523Sbostic 		 */
1543*32523Sbostic 		if (mp->mscp_flags & M_EF_SEREX)
1544*32523Sbostic 			log(LOG_ERR, "ra%d: serious exception reported\n",
1545*32523Sbostic 				ui->ui_unit);
15464743Swnj 	}
1547*32523Sbostic 	return (MSCP_FAILED);
15484743Swnj }
15494743Swnj 
1550*32523Sbostic /*
1551*32523Sbostic  * A replace operation finished.
1552*32523Sbostic  */
1553*32523Sbostic /*ARGSUSED*/
1554*32523Sbostic udareplace(ui, mp)
1555*32523Sbostic 	struct uba_device *ui;
1556*32523Sbostic 	struct mscp *mp;
15574743Swnj {
155817553Skarels 
1559*32523Sbostic 	panic("udareplace");
15604743Swnj }
156117553Skarels 
1562*32523Sbostic /*
1563*32523Sbostic  * A bad block related operation finished.
1564*32523Sbostic  */
1565*32523Sbostic /*ARGSUSED*/
1566*32523Sbostic udabb(ui, mp, bp)
1567*32523Sbostic 	struct uba_device *ui;
1568*32523Sbostic 	struct mscp *mp;
1569*32523Sbostic 	struct buf *bp;
157017553Skarels {
157117553Skarels 
1572*32523Sbostic 	panic("udabb");
157317553Skarels }
157417553Skarels 
1575*32523Sbostic 
1576*32523Sbostic /*
1577*32523Sbostic  * I/O controls.
1578*32523Sbostic  */
1579*32523Sbostic udaioctl(dev, cmd, data, flag)
158012511Ssam 	dev_t dev;
158130536Skarels 	int cmd;
158230536Skarels 	caddr_t data;
158330536Skarels 	int flag;
158412511Ssam {
1585*32523Sbostic 	register int unit = udaunit(dev);
158630536Skarels 	register struct disklabel *lp;
158730536Skarels 	int error = 0;
158812511Ssam 
1589*32523Sbostic 	lp = &udalabel[unit];
159030536Skarels 
159130536Skarels 	switch (cmd) {
159230536Skarels 
159330536Skarels 	case DIOCGDINFO:
159430536Skarels 		*(struct disklabel *)data = *lp;
159530536Skarels 		break;
159630536Skarels 
159730773Skarels 	case DIOCGPART:
159830773Skarels 		((struct partinfo *)data)->disklab = lp;
159930773Skarels 		((struct partinfo *)data)->part =
1600*32523Sbostic 		    &lp->d_partitions[udapart(dev)];
160130536Skarels 		break;
160230536Skarels 
160330536Skarels 	case DIOCSDINFO:
160430536Skarels 		if ((flag & FWRITE) == 0)
160530536Skarels 			error = EBADF;
160630536Skarels 		else
160730536Skarels 			*lp = *(struct disklabel *)data;
160830536Skarels 		break;
160930536Skarels 
1610*32523Sbostic 	case DIOCWDINFO: {
161130536Skarels 		struct buf *bp;
161230536Skarels 		struct disklabel *dlp;
161331390Skarels #ifdef notdef
161430536Skarels 		daddr_t alt, end;
161531390Skarels #endif
161630536Skarels 
1617*32523Sbostic 		if ((flag & FWRITE) == 0) {
1618*32523Sbostic 			error = EBADF;
1619*32523Sbostic 			break;
1620*32523Sbostic 		}
162130536Skarels 		*lp = *(struct disklabel *)data;
162230536Skarels 		bp = geteblk(lp->d_secsize);
1623*32523Sbostic 		bp->b_dev = makedev(major(dev), udaminor(udaunit(dev), 0));
162430536Skarels 		bp->b_bcount = lp->d_secsize;
162530536Skarels 		bp->b_blkno = LABELSECTOR;
162630536Skarels 		bp->b_flags = B_READ;
162730536Skarels 		dlp = (struct disklabel *)(bp->b_un.b_addr + LABELOFFSET);
1628*32523Sbostic 		udastrategy(bp);
162930536Skarels 		biowait(bp);
163030536Skarels 		if (bp->b_flags & B_ERROR) {
163130536Skarels 			error = u.u_error;		/* XXX */
163230536Skarels 			u.u_error = 0;
163330536Skarels 			goto bad;
163430536Skarels 		}
163530536Skarels 		*dlp = *lp;
163631390Skarels #ifdef notdef
163730536Skarels 		alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_ntracks + 1;
163830536Skarels 		end = alt + 8;
163930536Skarels 		for (;;) {
164030536Skarels 			bp->b_flags = B_WRITE;
1641*32523Sbostic 			udastrategy(bp);
164230536Skarels 			biowait(bp);
164330536Skarels 			if (bp->b_flags & B_ERROR) {
164430536Skarels 				error = u.u_error;	/* XXX */
164530536Skarels 				u.u_error = 0;
164630536Skarels 			}
164730536Skarels 			if (bp->b_blkno >= end)
164830536Skarels 				break;
164930536Skarels 			bp->b_blkno = alt;
165030536Skarels 			alt += 2;
165130536Skarels 		}
1652*32523Sbostic #else
1653*32523Sbostic 		bp->b_flags = B_WRITE;
1654*32523Sbostic 		udastrategy(bp);
1655*32523Sbostic 		biowait(bp);
1656*32523Sbostic 		if (bp->b_flags & B_ERROR) {
1657*32523Sbostic 			error = u.u_error;		/* XXX */
1658*32523Sbostic 			u.u_error = 0;
1659*32523Sbostic 		}
166031390Skarels #endif
166130536Skarels bad:
166230536Skarels 		brelse(bp);
166330536Skarels 		}
166430536Skarels 		break;
166530536Skarels 
1666*32523Sbostic #ifdef notyet
1667*32523Sbostic 	case UDAIOCREPLACE:
1668*32523Sbostic 		/*
1669*32523Sbostic 		 * Initiate bad block replacement for the given LBN.
1670*32523Sbostic 		 * (Should we allow modifiers?)
1671*32523Sbostic 		 */
1672*32523Sbostic 		error = EOPNOTSUPP;
1673*32523Sbostic 		break;
1674*32523Sbostic 
1675*32523Sbostic 	case UDAIOCGMICRO:
1676*32523Sbostic 		/*
1677*32523Sbostic 		 * Return the microcode revision for the UDA50 running
1678*32523Sbostic 		 * this drive.
1679*32523Sbostic 		 */
1680*32523Sbostic 		*(int *) data = uda_softc[uddinfo[unit]->ui_ctlr].sc_micro;
1681*32523Sbostic 		break;
1682*32523Sbostic #endif
1683*32523Sbostic 
168430536Skarels 	default:
168530536Skarels 		error = ENOTTY;
168630536Skarels 		break;
168730536Skarels 	}
1688*32523Sbostic 	return (error);
1689*32523Sbostic }
1690*32523Sbostic 
1691*32523Sbostic /*
1692*32523Sbostic  * A Unibus reset has occurred on UBA uban.  Reinitialise the controller(s)
1693*32523Sbostic  * on that Unibus, and requeue outstanding I/O.
1694*32523Sbostic  */
1695*32523Sbostic udareset(uban)
1696*32523Sbostic 	int uban;
1697*32523Sbostic {
1698*32523Sbostic 	register struct uba_ctlr *um;
1699*32523Sbostic 	register struct uda_softc *sc;
1700*32523Sbostic 	register int ctlr;
1701*32523Sbostic 
1702*32523Sbostic 	for (ctlr = 0, sc = uda_softc; ctlr < NUDA; ctlr++, sc++) {
1703*32523Sbostic 		if ((um = udaminfo[ctlr]) == NULL || um->um_ubanum != uban ||
1704*32523Sbostic 		    um->um_alive == 0)
1705*32523Sbostic 			continue;
1706*32523Sbostic 		printf(" uda%d", ctlr);
1707*32523Sbostic 
1708*32523Sbostic 		/*
1709*32523Sbostic 		 * Our BDP (if any) is gone; our command (if any) is
1710*32523Sbostic 		 * flushed; the device is no longer mapped; and the
1711*32523Sbostic 		 * UDA50 is not yet initialised.
1712*32523Sbostic 		 */
1713*32523Sbostic 		if (um->um_bdp) {
1714*32523Sbostic 			printf("<%d>", UBAI_BDP(um->um_bdp));
1715*32523Sbostic 			um->um_bdp = 0;
1716*32523Sbostic 		}
1717*32523Sbostic 		um->um_ubinfo = 0;
1718*32523Sbostic 		um->um_cmd = 0;
1719*32523Sbostic 		sc->sc_flags &= ~SC_MAPPED;
1720*32523Sbostic 		sc->sc_state = ST_IDLE;
1721*32523Sbostic 
1722*32523Sbostic 		/* reset queues and requeue pending transfers */
1723*32523Sbostic 		mscp_requeue(&sc->sc_mi);
1724*32523Sbostic 
1725*32523Sbostic 		/*
1726*32523Sbostic 		 * If it fails to initialise we will notice later and
1727*32523Sbostic 		 * try again (and again...).  Do not call udastart()
1728*32523Sbostic 		 * here; it will be done after the controller finishes
1729*32523Sbostic 		 * initialisation.
1730*32523Sbostic 		 */
1731*32523Sbostic 		if (udainit(ctlr))
1732*32523Sbostic 			printf(" (hung)");
1733*32523Sbostic 	}
1734*32523Sbostic }
1735*32523Sbostic 
1736*32523Sbostic /*
1737*32523Sbostic  * Watchdog timer:  If the controller is active, and no interrupts
1738*32523Sbostic  * have occurred for 30 seconds, assume it has gone away.
1739*32523Sbostic  */
1740*32523Sbostic udawatch()
1741*32523Sbostic {
1742*32523Sbostic 	register int i;
1743*32523Sbostic 	register struct uba_ctlr *um;
1744*32523Sbostic 	register struct uda_softc *sc;
1745*32523Sbostic 
1746*32523Sbostic 	timeout(udawatch, (caddr_t) 0, hz);	/* every second */
1747*32523Sbostic 	for (i = 0, sc = uda_softc; i < NUDA; i++, sc++) {
1748*32523Sbostic 		if ((um = udaminfo[i]) == 0 || !um->um_alive)
1749*32523Sbostic 			continue;
1750*32523Sbostic 		if (sc->sc_state == ST_IDLE)
1751*32523Sbostic 			continue;
1752*32523Sbostic 		if (sc->sc_state == ST_RUN && !um->um_tab.b_active)
1753*32523Sbostic 			sc->sc_wticks = 0;
1754*32523Sbostic 		else if (++sc->sc_wticks >= 30) {
1755*32523Sbostic 			sc->sc_wticks = 0;
1756*32523Sbostic 			printf("uda%d: lost interrupt\n", i);
1757*32523Sbostic 			ubareset(um->um_ubanum);
1758*32523Sbostic 		}
1759*32523Sbostic 	}
1760*32523Sbostic }
1761*32523Sbostic 
1762*32523Sbostic /*
1763*32523Sbostic  * Do a panic dump.  We set up the controller for one command packet
1764*32523Sbostic  * and one response packet, for which we use `struct uda1'.
1765*32523Sbostic  */
1766*32523Sbostic struct	uda1 {
1767*32523Sbostic 	struct	uda1ca uda1_ca;	/* communications area */
1768*32523Sbostic 	struct	mscp uda1_rsp;	/* response packet */
1769*32523Sbostic 	struct	mscp uda1_cmd;	/* command packet */
1770*32523Sbostic } uda1;
1771*32523Sbostic 
1772*32523Sbostic #define	DBSIZE	32		/* dump 16K at a time */
1773*32523Sbostic 
1774*32523Sbostic udadump(dev)
1775*32523Sbostic 	dev_t dev;
1776*32523Sbostic {
1777*32523Sbostic 	struct udadevice *udaddr;
1778*32523Sbostic 	struct uda1 *ud_ubaddr;
1779*32523Sbostic 	char *start;
1780*32523Sbostic 	int num, blk, unit, maxsz, blkoff, reg;
1781*32523Sbostic 	struct partition *pp;
1782*32523Sbostic 	register struct uba_regs *uba;
1783*32523Sbostic 	register struct uba_device *ui;
1784*32523Sbostic 	register struct uda1 *ud;
1785*32523Sbostic 	register struct pte *io;
1786*32523Sbostic 	register int i;
1787*32523Sbostic 
1788*32523Sbostic 	/*
1789*32523Sbostic 	 * Make sure the device is a reasonable place on which to dump.
1790*32523Sbostic 	 */
1791*32523Sbostic 	unit = udaunit(dev);
1792*32523Sbostic 	if (unit >= NRA)
1793*32523Sbostic 		return (ENXIO);
1794*32523Sbostic #define	phys(cast, addr)	((cast) ((int) addr & 0x7fffffff))
1795*32523Sbostic 	ui = phys(struct uba_device *, udadinfo[unit]);
1796*32523Sbostic 	if (ui == NULL || ui->ui_alive == 0)
1797*32523Sbostic 		return (ENXIO);
1798*32523Sbostic 
1799*32523Sbostic 	/*
1800*32523Sbostic 	 * Find and initialise the UBA; get the physical address of the
1801*32523Sbostic 	 * device registers, and of communications area and command and
1802*32523Sbostic 	 * response packet.
1803*32523Sbostic 	 */
1804*32523Sbostic 	uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba;
1805*32523Sbostic 	ubainit(uba);
1806*32523Sbostic 	udaddr = (struct udadevice *)ui->ui_physaddr;
1807*32523Sbostic 	ud = phys(struct uda1 *, &uda1);
1808*32523Sbostic 
1809*32523Sbostic 	/*
1810*32523Sbostic 	 * Map the ca+packets into Unibus I/O space so the UDA50 can get
1811*32523Sbostic 	 * at them.  Use the registers at the end of the Unibus map (since
1812*32523Sbostic 	 * we will use the registers at the beginning to map the memory
1813*32523Sbostic 	 * we are dumping).
1814*32523Sbostic 	 */
1815*32523Sbostic 	num = btoc(sizeof(struct uda1)) + 1;
1816*32523Sbostic 	reg = NUBMREG - num;
1817*32523Sbostic 	io = &uba->uba_map[reg];
1818*32523Sbostic 	for (i = 0; i < num; i++)
1819*32523Sbostic 		*(int *)io++ = UBAMR_MRV | (btop(ud) + i);
1820*32523Sbostic 	ud_ubaddr = (struct uda1 *)(((int)ud & PGOFSET) | (reg << 9));
1821*32523Sbostic 
1822*32523Sbostic 	/*
1823*32523Sbostic 	 * Initialise the controller, with one command and one response
1824*32523Sbostic 	 * packet.
1825*32523Sbostic 	 */
1826*32523Sbostic 	udaddr->udaip = 0;
1827*32523Sbostic 	if (udadumpwait(udaddr, UDA_STEP1))
1828*32523Sbostic 		return (EFAULT);
1829*32523Sbostic 	udaddr->udasa = UDA_ERR;
1830*32523Sbostic 	if (udadumpwait(udaddr, UDA_STEP2))
1831*32523Sbostic 		return (EFAULT);
1832*32523Sbostic 	udaddr->udasa = (int)&ud_ubaddr->uda1_ca.ca_rspdsc;
1833*32523Sbostic 	if (udadumpwait(udaddr, UDA_STEP3))
1834*32523Sbostic 		return (EFAULT);
1835*32523Sbostic 	udaddr->udasa = ((int)&ud_ubaddr->uda1_ca.ca_rspdsc) >> 16;
1836*32523Sbostic 	if (udadumpwait(udaddr, UDA_STEP4))
1837*32523Sbostic 		return (EFAULT);
1838*32523Sbostic 	uda_softc[ui->ui_ctlr].sc_micro = udaddr->udasa & 0xff;
1839*32523Sbostic 	udaddr->udasa = UDA_GO;
1840*32523Sbostic 
1841*32523Sbostic 	/*
1842*32523Sbostic 	 * Set up the command and response descriptor, then set the
1843*32523Sbostic 	 * controller characteristics and bring the drive on line.
1844*32523Sbostic 	 * Note that all uninitialised locations in uda1_cmd are zero.
1845*32523Sbostic 	 */
1846*32523Sbostic 	ud->uda1_ca.ca_rspdsc = (long)&ud_ubaddr->uda1_rsp.mscp_cmdref;
1847*32523Sbostic 	ud->uda1_ca.ca_cmddsc = (long)&ud_ubaddr->uda1_cmd.mscp_cmdref;
1848*32523Sbostic 	/* ud->uda1_cmd.mscp_sccc.sccc_ctlrflags = 0; */
1849*32523Sbostic 	/* ud->uda1_cmd.mscp_sccc.sccc_version = 0; */
1850*32523Sbostic 	if (udadumpcmd(M_OP_SETCTLRC, ud, ui))
1851*32523Sbostic 		return (EFAULT);
1852*32523Sbostic 	ud->uda1_cmd.mscp_unit = ui->ui_slave;
1853*32523Sbostic 	if (udadumpcmd(M_OP_ONLINE, ud, ui))
1854*32523Sbostic 		return (EFAULT);
1855*32523Sbostic 
1856*32523Sbostic 	pp = phys(struct partition *,
1857*32523Sbostic 	    &udalabel[unit].d_partitions[udapart(dev)]);
1858*32523Sbostic 	maxsz = pp->p_size;
1859*32523Sbostic 	blkoff = pp->p_offset;
1860*32523Sbostic 
1861*32523Sbostic 	/*
1862*32523Sbostic 	 * Dump all of physical memory, or as much as will fit in the
1863*32523Sbostic 	 * space provided.
1864*32523Sbostic 	 */
1865*32523Sbostic 	start = 0;
1866*32523Sbostic 	num = maxfree;
1867*32523Sbostic 	if (dumplo < 0)
1868*32523Sbostic 		return (EINVAL);
1869*32523Sbostic 	if (dumplo + num >= maxsz)
1870*32523Sbostic 		num = maxsz - dumplo;
1871*32523Sbostic 	blkoff += dumplo;
1872*32523Sbostic 
1873*32523Sbostic 	/*
1874*32523Sbostic 	 * Write out memory, DBSIZE pages at a time.
1875*32523Sbostic 	 * N.B.: this code depends on the fact that the sector
1876*32523Sbostic 	 * size == the page size.
1877*32523Sbostic 	 */
1878*32523Sbostic 	while (num > 0) {
1879*32523Sbostic 		blk = num > DBSIZE ? DBSIZE : num;
1880*32523Sbostic 		io = uba->uba_map;
1881*32523Sbostic 		/*
1882*32523Sbostic 		 * Map in the pages to write, leaving an invalid entry
1883*32523Sbostic 		 * at the end to guard against wild Unibus transfers.
1884*32523Sbostic 		 * Then do the write.
1885*32523Sbostic 		 */
1886*32523Sbostic 		for (i = 0; i < blk; i++)
1887*32523Sbostic 			*(int *) io++ = UBAMR_MRV | (btop(start) + i);
1888*32523Sbostic 		*(int *) io = 0;
1889*32523Sbostic 		ud->uda1_cmd.mscp_unit = ui->ui_slave;
1890*32523Sbostic 		ud->uda1_cmd.mscp_seq.seq_lbn = btop(start) + blkoff;
1891*32523Sbostic 		ud->uda1_cmd.mscp_seq.seq_bytecount = blk << PGSHIFT;
1892*32523Sbostic 		if (udadumpcmd(M_OP_WRITE, ud, ui))
1893*32523Sbostic 			return (EIO);
1894*32523Sbostic 		start += blk << PGSHIFT;
1895*32523Sbostic 		num -= blk;
1896*32523Sbostic 	}
1897*32523Sbostic 	return (0);		/* made it! */
1898*32523Sbostic }
1899*32523Sbostic 
1900*32523Sbostic /*
1901*32523Sbostic  * Wait for some of the bits in `bits' to come on.  If the error bit
1902*32523Sbostic  * comes on, or ten seconds pass without response, return true (error).
1903*32523Sbostic  */
1904*32523Sbostic udadumpwait(udaddr, bits)
1905*32523Sbostic 	register struct udadevice *udaddr;
1906*32523Sbostic 	register int bits;
1907*32523Sbostic {
1908*32523Sbostic 	register int timo = todr() + 1000;
1909*32523Sbostic 
1910*32523Sbostic 	while ((udaddr->udasa & bits) == 0) {
1911*32523Sbostic 		if (udaddr->udasa & UDA_ERR) {
1912*32523Sbostic 			printf("udasa=%b\ndump ", udaddr->udasa, udasr_bits);
1913*32523Sbostic 			return (1);
1914*32523Sbostic 		}
1915*32523Sbostic 		if (todr() >= timo) {
1916*32523Sbostic 			printf("timeout\ndump ");
1917*32523Sbostic 			return (1);
1918*32523Sbostic 		}
1919*32523Sbostic 	}
192030536Skarels 	return (0);
192130536Skarels }
192230536Skarels 
1923*32523Sbostic /*
1924*32523Sbostic  * Feed a command to the UDA50, wait for its response, and return
1925*32523Sbostic  * true iff something went wrong.
1926*32523Sbostic  */
1927*32523Sbostic udadumpcmd(op, ud, ui)
1928*32523Sbostic 	int op;
1929*32523Sbostic 	register struct uda1 *ud;
1930*32523Sbostic 	struct uba_device *ui;
1931*32523Sbostic {
1932*32523Sbostic 	register struct udadevice *udaddr;
1933*32523Sbostic 	register int n;
1934*32523Sbostic #define mp (&ud->uda1_rsp)
1935*32523Sbostic 
1936*32523Sbostic 	udaddr = (struct udadevice *) ui->ui_physaddr;
1937*32523Sbostic 	ud->uda1_cmd.mscp_opcode = op;
1938*32523Sbostic 	ud->uda1_cmd.mscp_msglen = MSCP_MSGLEN;
1939*32523Sbostic 	ud->uda1_rsp.mscp_msglen = MSCP_MSGLEN;
1940*32523Sbostic 	ud->uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT;
1941*32523Sbostic 	ud->uda1_ca.ca_cmddsc |= MSCP_OWN | MSCP_INT;
1942*32523Sbostic 	if (udaddr->udasa & UDA_ERR) {
1943*32523Sbostic 		printf("udasa=%b\ndump ", udaddr->udasa, udasr_bits);
1944*32523Sbostic 		return (1);
1945*32523Sbostic 	}
1946*32523Sbostic 	n = udaddr->udaip;
1947*32523Sbostic 	n = todr() + 1000;
1948*32523Sbostic 	for (;;) {
1949*32523Sbostic 		if (todr() > n) {
1950*32523Sbostic 			printf("timeout\ndump ");
1951*32523Sbostic 			return (1);
1952*32523Sbostic 		}
1953*32523Sbostic 		if (ud->uda1_ca.ca_cmdint)
1954*32523Sbostic 			ud->uda1_ca.ca_cmdint = 0;
1955*32523Sbostic 		if (ud->uda1_ca.ca_rspint == 0)
1956*32523Sbostic 			continue;
1957*32523Sbostic 		ud->uda1_ca.ca_rspint = 0;
1958*32523Sbostic 		if (mp->mscp_opcode == (op | M_OP_END))
1959*32523Sbostic 			break;
1960*32523Sbostic 		printf("\n");
1961*32523Sbostic 		switch (MSCP_MSGTYPE(mp->mscp_msgtc)) {
1962*32523Sbostic 
1963*32523Sbostic 		case MSCPT_SEQ:
1964*32523Sbostic 			printf("sequential");
1965*32523Sbostic 			break;
1966*32523Sbostic 
1967*32523Sbostic 		case MSCPT_DATAGRAM:
1968*32523Sbostic 			mscp_decodeerror("uda", ui->ui_ctlr, mp);
1969*32523Sbostic 			printf("datagram");
1970*32523Sbostic 			break;
1971*32523Sbostic 
1972*32523Sbostic 		case MSCPT_CREDITS:
1973*32523Sbostic 			printf("credits");
1974*32523Sbostic 			break;
1975*32523Sbostic 
1976*32523Sbostic 		case MSCPT_MAINTENANCE:
1977*32523Sbostic 			printf("maintenance");
1978*32523Sbostic 			break;
1979*32523Sbostic 
1980*32523Sbostic 		default:
1981*32523Sbostic 			printf("unknown (type 0x%x)",
1982*32523Sbostic 				MSCP_MSGTYPE(mp->mscp_msgtc));
1983*32523Sbostic 			break;
1984*32523Sbostic 		}
1985*32523Sbostic 		printf(" ignored\ndump ");
1986*32523Sbostic 		ud->uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT;
1987*32523Sbostic 	}
1988*32523Sbostic 	if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
1989*32523Sbostic 		printf("error: op 0x%x => 0x%x status 0x%x\ndump ", op,
1990*32523Sbostic 			mp->mscp_opcode, mp->mscp_status);
1991*32523Sbostic 		return (1);
1992*32523Sbostic 	}
1993*32523Sbostic 	return (0);
1994*32523Sbostic #undef mp
1995*32523Sbostic }
1996*32523Sbostic 
1997*32523Sbostic /*
1998*32523Sbostic  * Return the size of a partition, if known, or -1 if not.
1999*32523Sbostic  */
2000*32523Sbostic udasize(dev)
200130536Skarels 	dev_t dev;
200230536Skarels {
2003*32523Sbostic 	register int unit = udaunit(dev);
200430536Skarels 	register struct uba_device *ui;
2005*32523Sbostic 	register struct size *st;
200630536Skarels 
2007*32523Sbostic 	if (unit >= NRA || (ui = udadinfo[unit]) == NULL ||
2008*32523Sbostic 	    ui->ui_alive == 0 || (ui->ui_flags & UNIT_ONLINE) == 0 ||
2009*32523Sbostic 	    ra_info[unit].ra_state != OPEN)
201012511Ssam 		return (-1);
2011*32523Sbostic 	return ((int)udalabel[unit].d_partitions[udapart(dev)].p_size);
201212511Ssam }
201317553Skarels 
201430536Skarels #ifdef COMPAT_42
2015*32523Sbostic /*
2016*32523Sbostic  * Tables mapping unlabelled drives.
2017*32523Sbostic  */
201830536Skarels struct size {
201930536Skarels 	daddr_t nblocks;
202030536Skarels 	daddr_t blkoff;
2021*32523Sbostic } ra25_sizes[8] = {
202230536Skarels 	15884,	0,		/* A=blk 0 thru 15883 */
202330536Skarels 	10032,	15884,		/* B=blk 15884 thru 49323 */
202430536Skarels 	-1,	0,		/* C=blk 0 thru end */
202530536Skarels 	0,	0,		/* D=blk 340670 thru 356553 */
202630536Skarels 	0,	0,		/* E=blk 356554 thru 412489 */
202730536Skarels 	0,	0,		/* F=blk 412490 thru end */
202830536Skarels 	-1,	25916,		/* G=blk 49324 thru 131403 */
202930536Skarels 	0,	0,		/* H=blk 131404 thru end */
2030*32523Sbostic }, rx50_sizes[8] = {
2031*32523Sbostic 	800,	0,		/* A=blk 0 thru 799 */
2032*32523Sbostic 	0,	0,
2033*32523Sbostic 	-1,	0,		/* C=blk 0 thru end */
2034*32523Sbostic 	0,	0,
2035*32523Sbostic 	0,	0,
2036*32523Sbostic 	0,	0,
2037*32523Sbostic 	0,	0,
2038*32523Sbostic 	0,	0,
203930536Skarels }, rd52_sizes[8] = {
204030536Skarels 	15884,	0,		/* A=blk 0 thru 15883 */
204130536Skarels 	9766,	15884,		/* B=blk 15884 thru 25649 */
204230536Skarels 	-1,	0,		/* C=blk 0 thru end */
204330536Skarels 	0,	0,		/* D=unused */
204430536Skarels 	0,	0,		/* E=unused */
204530536Skarels 	0,	0,		/* F=unused */
204630536Skarels 	-1,	25650,		/* G=blk 25650 thru end */
204730536Skarels 	0,	0,		/* H=unused */
204830536Skarels }, rd53_sizes[8] = {
204930536Skarels 	15884,	0,		/* A=blk 0 thru 15883 */
205030536Skarels 	33440,	15884,		/* B=blk 15884 thru 49323 */
205130536Skarels 	-1,	0,		/* C=blk 0 thru end */
205230536Skarels 	0,	0,		/* D=unused */
205330536Skarels 	33440,	0,		/* E=blk 0 thru 33439 */
205430536Skarels 	-1,	33440,		/* F=blk 33440 thru end */
205530536Skarels 	-1,	49324,		/* G=blk 49324 thru end */
205630536Skarels 	-1,	15884,		/* H=blk 15884 thru end */
205730536Skarels }, ra60_sizes[8] = {
205830536Skarels 	15884,	0,		/* A=sectors 0 thru 15883 */
205930536Skarels 	33440,	15884,		/* B=sectors 15884 thru 49323 */
206030536Skarels 	400176,	0,		/* C=sectors 0 thru 400175 */
206130536Skarels 	82080,	49324,		/* 4.2 G => D=sectors 49324 thru 131403 */
206230536Skarels 	268772,	131404,		/* 4.2 H => E=sectors 131404 thru 400175 */
206330536Skarels 	350852,	49324,		/* F=sectors 49324 thru 400175 */
206430536Skarels 	157570,	242606,		/* UCB G => G=sectors 242606 thru 400175 */
206530536Skarels 	193282,	49324,		/* UCB H => H=sectors 49324 thru 242605 */
206630536Skarels }, ra80_sizes[8] = {
206730536Skarels 	15884,	0,		/* A=sectors 0 thru 15883 */
206830536Skarels 	33440,	15884,		/* B=sectors 15884 thru 49323 */
206930536Skarels 	242606,	0,		/* C=sectors 0 thru 242605 */
207030536Skarels 	0,	0,		/* D=unused */
207130536Skarels 	193282,	49324,		/* UCB H => E=sectors 49324 thru 242605 */
207230536Skarels 	82080,	49324,		/* 4.2 G => F=sectors 49324 thru 131403 */
207330536Skarels 	192696,	49910,		/* G=sectors 49910 thru 242605 */
207430536Skarels 	111202,	131404,		/* 4.2 H => H=sectors 131404 thru 242605 */
207530536Skarels }, ra81_sizes[8] ={
207630536Skarels /*
207730536Skarels  * These are the new standard partition sizes for ra81's.
207830536Skarels  * An RA_COMPAT system is compiled with D, E, and F corresponding
207930536Skarels  * to the 4.2 partitions for G, H, and F respectively.
208030536Skarels  */
208130536Skarels #ifndef	UCBRA
208230536Skarels 	15884,	0,		/* A=sectors 0 thru 15883 */
208330536Skarels 	66880,	16422,		/* B=sectors 16422 thru 83301 */
208430536Skarels 	891072,	0,		/* C=sectors 0 thru 891071 */
208530536Skarels #ifdef RA_COMPAT
208630536Skarels 	82080,	49324,		/* 4.2 G => D=sectors 49324 thru 131403 */
208730536Skarels 	759668,	131404,		/* 4.2 H => E=sectors 131404 thru 891071 */
208830536Skarels 	478582,	412490,		/* 4.2 F => F=sectors 412490 thru 891071 */
208930536Skarels #else
209030536Skarels 	15884,	375564,		/* D=sectors 375564 thru 391447 */
209130536Skarels 	307200,	391986,		/* E=sectors 391986 thru 699185 */
209230536Skarels 	191352,	699720,		/* F=sectors 699720 thru 891071 */
209330536Skarels #endif RA_COMPAT
209430536Skarels 	515508,	375564,		/* G=sectors 375564 thru 891071 */
209530536Skarels 	291346,	83538,		/* H=sectors 83538 thru 374883 */
209630536Skarels 
209730536Skarels /*
209830536Skarels  * These partitions correspond to the sizes used by sites at Berkeley,
209930536Skarels  * and by those sites that have received copies of the Berkeley driver
210030536Skarels  * with deltas 6.2 or greater (11/15/83).
210130536Skarels  */
210230536Skarels #else UCBRA
210330536Skarels 
210430536Skarels 	15884,	0,		/* A=sectors 0 thru 15883 */
210530536Skarels 	33440,	15884,		/* B=sectors 15884 thru 49323 */
210630536Skarels 	891072,	0,		/* C=sectors 0 thru 891071 */
210730536Skarels 	15884,	242606,		/* D=sectors 242606 thru 258489 */
210830536Skarels 	307200,	258490,		/* E=sectors 258490 thru 565689 */
210930536Skarels 	325382,	565690,		/* F=sectors 565690 thru 891071 */
211030536Skarels 	648466,	242606,		/* G=sectors 242606 thru 891071 */
211130536Skarels 	193282,	49324,		/* H=sectors 49324 thru 242605 */
211230536Skarels 
211330536Skarels #endif UCBRA
211430536Skarels };
211530536Skarels 
2116*32523Sbostic /*
2117*32523Sbostic  * Drive type index decoding table.  `ut_name' is null iff the
2118*32523Sbostic  * type is not known.
2119*32523Sbostic  */
2120*32523Sbostic struct	udatypes {
2121*32523Sbostic 	char	*ut_name;	/* drive type name */
2122*32523Sbostic 	struct	size *ut_sizes;	/* partition tables */
2123*32523Sbostic 	int	ut_nsectors, ut_ntracks, ut_ncylinders;
2124*32523Sbostic } udatypes[] = {
2125*32523Sbostic 	NULL,		NULL,
2126*32523Sbostic 		0, 0, 0,
2127*32523Sbostic 	"ra80",		ra80_sizes,	/* 1 = ra80 */
2128*32523Sbostic 		31, 14, 559,
2129*32523Sbostic 	"rc25-removable", ra25_sizes,	/* 2 = rc25-r */
2130*32523Sbostic 		42, 4, 302,
2131*32523Sbostic 	"rc25-fixed",	ra25_sizes,	/* 3 = rc25-f */
2132*32523Sbostic 		42, 4, 302,
2133*32523Sbostic 	"ra60",		ra60_sizes,	/* 4 = ra60 */
2134*32523Sbostic 		42, 4, 2382,
2135*32523Sbostic 	"ra81",		ra81_sizes,	/* 5 = ra81 */
2136*32523Sbostic 		51, 14, 1248,
2137*32523Sbostic 	NULL,		NULL,		/* 6 = ? */
2138*32523Sbostic 		0, 0, 0,
2139*32523Sbostic 	"rx50",		rx50_sizes,	/* 7 = rx50 */
2140*32523Sbostic 		10, 1, 80,
2141*32523Sbostic 	"rd52",		rd52_sizes,	/* 8 = rd52 */
2142*32523Sbostic 		18, 7, 480,
2143*32523Sbostic 	"rd53",		rd53_sizes,	/* 9 = rd53 */
2144*32523Sbostic 		18, 8, 963,
2145*32523Sbostic };
2146*32523Sbostic 
2147*32523Sbostic #define NTYPES (sizeof(udatypes) / sizeof(*udatypes))
2148*32523Sbostic 
2149*32523Sbostic udamaptype(unit, lp)
2150*32523Sbostic 	int unit;
215130536Skarels 	register struct disklabel *lp;
215230536Skarels {
2153*32523Sbostic 	register struct udatypes *ut;
2154*32523Sbostic 	register struct size *sz;
215530536Skarels 	register struct partition *pp;
2156*32523Sbostic 	register char *p;
2157*32523Sbostic 	register int i;
2158*32523Sbostic 	register struct ra_info *ra = &ra_info[unit];
215930536Skarels 
2160*32523Sbostic 	lp->d_secsize = 512;
2161*32523Sbostic 	lp->d_secperunit = ra->ra_dsize;
2162*32523Sbostic 	if ((u_long)ra->ra_type >= NTYPES) {
2163*32523Sbostic 		printf("ra%d: don't have a partition table for", unit);
2164*32523Sbostic 		mscp_printmedia(ra->ra_mediaid);
2165*32523Sbostic 		lp->d_nsectors = ra->ra_geom.rg_nsectors;
2166*32523Sbostic 		lp->d_ntracks = ra->ra_geom.rg_ntracks;
2167*32523Sbostic 		lp->d_ncylinders = ra->ra_geom.rg_ncyl;
2168*32523Sbostic 		printf(";\nusing (t,s,c)=(%d,%d,%d)\n", lp->d_nsectors,
2169*32523Sbostic 			lp->d_ntracks, lp->d_ncylinders);
2170*32523Sbostic 		lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
2171*32523Sbostic 		lp->d_typename[0] = 'r';
2172*32523Sbostic 		lp->d_typename[1] = 'a';
2173*32523Sbostic 		lp->d_typename[2] = '?';
2174*32523Sbostic 		lp->d_typename[3] = '?';
2175*32523Sbostic 		lp->d_typename[4] = 0;
217630536Skarels 		lp->d_npartitions = 1;
217730536Skarels 		lp->d_partitions[0].p_offset = 0;
217830536Skarels 		lp->d_partitions[0].p_size = lp->d_secperunit;
217930536Skarels 		return (0);
218030536Skarels 	}
2181*32523Sbostic 	ut = &udatypes[ra->ra_type];
2182*32523Sbostic 	p = ut->ut_name;
2183*32523Sbostic 	for (i = 0; i < sizeof(lp->d_typename) - 1 && *p; i++)
2184*32523Sbostic 		lp->d_typename[i] = *p++;
2185*32523Sbostic 	lp->d_typename[i] = 0;
2186*32523Sbostic 	sz = ut->ut_sizes;
2187*32523Sbostic 	/* GET nsectors, ntracks, ncylinders FROM SAVED GEOMETRY? */
2188*32523Sbostic 	lp->d_nsectors = ut->ut_nsectors;
2189*32523Sbostic 	lp->d_ntracks = ut->ut_ntracks;
2190*32523Sbostic 	lp->d_ncylinders = ut->ut_ncylinders;
219130536Skarels 	lp->d_npartitions = 8;
219230536Skarels 	lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
2193*32523Sbostic 	for (pp = lp->d_partitions; pp < &lp->d_partitions[8]; pp++, sz++) {
2194*32523Sbostic 		pp->p_offset = sz->blkoff;
2195*32523Sbostic 		if ((pp->p_size = sz->nblocks) == (u_long)-1)
2196*32523Sbostic 			pp->p_size = ra->ra_dsize - sz->blkoff;
219730536Skarels 	}
219830536Skarels 	return (1);
219930536Skarels }
2200*32523Sbostic #endif /* COMPAT_42 */
2201*32523Sbostic #endif /* NUDA > 0 */
2202