xref: /original-bsd/sys/vax/bi/kdb.c (revision 0dce6c9d)
1094078b2Skarels /*
2d30dd393Sbostic  * Copyright (c) 1988 Regents of the University of California.
3d30dd393Sbostic  * All rights reserved.
4094078b2Skarels  *
5d30dd393Sbostic  * This code is derived from software contributed to Berkeley by
6d30dd393Sbostic  * Chris Torek.
7d30dd393Sbostic  *
8f70f8c97Sbostic  * %sccs.include.redist.c%
9d30dd393Sbostic  *
10*0dce6c9dSbostic  *	@(#)kdb.c	7.10 (Berkeley) 12/16/90
11d30dd393Sbostic  */
12d30dd393Sbostic 
13d30dd393Sbostic /*
14094078b2Skarels  * KDB50/MSCP device driver
15094078b2Skarels  */
16094078b2Skarels 
17094078b2Skarels /*
18094078b2Skarels  * TODO
19094078b2Skarels  *	rethink BI software interface
20094078b2Skarels  *	write bad block forwarding code
21094078b2Skarels  */
22094078b2Skarels 
23094078b2Skarels #include "kra.h"		/* XXX */
24094078b2Skarels 
25094078b2Skarels #define	DRIVENAMES	"kra"	/* XXX */
26094078b2Skarels 
27094078b2Skarels #if NKDB > 0
28094078b2Skarels 
29094078b2Skarels /*
30094078b2Skarels  * CONFIGURATION OPTIONS.  The next three defines are tunable -- tune away!
31094078b2Skarels  *
32094078b2Skarels  * NRSPL2 and NCMDL2 control the number of response and command
33094078b2Skarels  * packets respectively.  They may be any value from 0 to 7, though
34094078b2Skarels  * setting them higher than 5 is unlikely to be of any value.
35094078b2Skarels  * If you get warnings about your command ring being too small,
36094078b2Skarels  * try increasing the values by one.
37094078b2Skarels  *
38094078b2Skarels  * MAXUNIT controls the maximum slave number (and hence number of drives
39094078b2Skarels  * per controller) we are prepared to handle.
40094078b2Skarels  */
41094078b2Skarels #define	NRSPL2	5		/* log2 number of response packets */
42094078b2Skarels #define NCMDL2	5		/* log2 number of command packets */
43094078b2Skarels #define	MAXUNIT	8		/* maximum allowed unit number */
44094078b2Skarels 
45*0dce6c9dSbostic #include "sys/param.h"
46*0dce6c9dSbostic #include "sys/systm.h"
47*0dce6c9dSbostic #include "sys/malloc.h"
48*0dce6c9dSbostic #include "sys/map.h"
49*0dce6c9dSbostic #include "sys/buf.h"
50*0dce6c9dSbostic #include "sys/conf.h"
51*0dce6c9dSbostic #include "sys/user.h"
52*0dce6c9dSbostic #include "sys/proc.h"
53*0dce6c9dSbostic #include "sys/vm.h"
54*0dce6c9dSbostic #include "sys/dkstat.h"
55*0dce6c9dSbostic #include "sys/cmap.h"
56*0dce6c9dSbostic #include "sys/syslog.h"
57*0dce6c9dSbostic #include "sys/kernel.h"
58094078b2Skarels 
59094078b2Skarels #define	NRSP	(1 << NRSPL2)
60094078b2Skarels #define	NCMD	(1 << NCMDL2)
61094078b2Skarels 
62*0dce6c9dSbostic #include "../include/pte.h"
63*0dce6c9dSbostic #include "../include/cpu.h"
64094078b2Skarels #include "../vax/mscp.h"
65094078b2Skarels #include "../vax/mscpvar.h"
66*0dce6c9dSbostic #include "../include/mtpr.h"
67094078b2Skarels 
68094078b2Skarels #include "bireg.h"
69094078b2Skarels #include "kdbreg.h"
701ad6111aSkarels 
71*0dce6c9dSbostic #include "../uba/ubavar.h"
72094078b2Skarels 
73094078b2Skarels /*
74094078b2Skarels  * Conversions from kernel virtual to physical and page table addresses.
75094078b2Skarels  * PHYS works only for kernel text and primary (compile time) data addresses.
76094078b2Skarels  */
77094078b2Skarels #define	PHYS(cast, addr) \
78094078b2Skarels 	((cast) ((int)(addr) & 0x7fffffff))
79094078b2Skarels 
80094078b2Skarels /*
81094078b2Skarels  * KDB variables, per controller.
82094078b2Skarels  */
83094078b2Skarels struct kdbinfo {
84094078b2Skarels 	/* software info, per KDB */
85094078b2Skarels 	struct	kdb_regs *ki_kdb;	/* KDB registers */
86094078b2Skarels 	struct	kdb_regs *ki_physkdb;	/* phys address of KDB registers */
87094078b2Skarels 	short	ki_state;		/* KDB50 state; see below */
88094078b2Skarels 	short	ki_flags;		/* flags; see below */
89094078b2Skarels 	int	ki_micro;		/* microcode revision */
90094078b2Skarels 	short	ki_vec;			/* scb vector offset */
91094078b2Skarels 	short	ki_wticks;		/* watchdog timer ticks */
92094078b2Skarels 
93094078b2Skarels 	/*
94094078b2Skarels 	 * KDB PTEs must be contiguous.  Some I/O is done on addresses
95094078b2Skarels 	 * for which this is true (PTEs in Sysmap and Usrptmap), but
96094078b2Skarels 	 * other transfers may have PTEs that are scattered in physical
97094078b2Skarels 	 * space.  Ki_map maps a physically contiguous PTE space used
98f4cfff1bSbostic 	 * for these transfers.
99094078b2Skarels 	 */
100094078b2Skarels #define KI_MAPSIZ	(NCMD + 2)
101094078b2Skarels 	struct	map *ki_map;		/* resource map */
102094078b2Skarels #define KI_PTES		256
103f4cfff1bSbostic 	struct	pte ki_pte[KI_PTES];	/* contiguous PTE space */
104094078b2Skarels 	long	ki_ptephys;		/* phys address of &ki_pte[0] */
105094078b2Skarels 
106094078b2Skarels 	struct	mscp_info ki_mi;	/* MSCP info (per mscpvar.h) */
107094078b2Skarels 	struct	buf ki_tab;		/* controller queue */
108094078b2Skarels 
109094078b2Skarels 	/* stuff read and written by hardware */
110094078b2Skarels 	struct	kdbca ki_ca;		/* communications area */
111094078b2Skarels 	struct	mscp ki_rsp[NRSP];	/* response packets */
112094078b2Skarels 	struct	mscp ki_cmd[NCMD];	/* command packets */
113094078b2Skarels } kdbinfo[NKDB];
114094078b2Skarels 
115094078b2Skarels #define	ki_ctlr	ki_mi.mi_ctlr
116094078b2Skarels 
117094078b2Skarels /*
118094078b2Skarels  * Controller states
119094078b2Skarels  */
120094078b2Skarels #define	ST_IDLE		0	/* uninitialised */
121094078b2Skarels #define	ST_STEP1	1	/* in `STEP 1' */
122094078b2Skarels #define	ST_STEP2	2	/* in `STEP 2' */
123094078b2Skarels #define	ST_STEP3	3	/* in `STEP 3' */
124094078b2Skarels #define	ST_SETCHAR	4	/* in `Set Controller Characteristics' */
125094078b2Skarels #define	ST_RUN		5	/* up and running */
126094078b2Skarels 
127094078b2Skarels /*
128094078b2Skarels  * Flags
129094078b2Skarels  */
130094078b2Skarels #define	KDB_ALIVE	0x01	/* this KDB50 exists */
131094078b2Skarels #define	KDB_GRIPED	0x04	/* griped about cmd ring too small */
132094078b2Skarels #define	KDB_INSLAVE	0x08	/* inside kdbslave() */
133094078b2Skarels #define	KDB_DOWAKE	0x10	/* wakeup when ctlr init done */
134094078b2Skarels 
135094078b2Skarels struct kdbstats kdbstats;	/* statistics */
136094078b2Skarels 
137094078b2Skarels /*
138094078b2Skarels  * Device to unit number and partition:
139094078b2Skarels  */
140094078b2Skarels #define	UNITSHIFT	3
141094078b2Skarels #define	UNITMASK	7
142094078b2Skarels #define	kdbunit(dev)	(minor(dev) >> UNITSHIFT)
143094078b2Skarels #define	kdbpart(dev)	(minor(dev) & UNITMASK)
144094078b2Skarels 
145094078b2Skarels /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */
146094078b2Skarels /* THESE SHOULD BE SHARED WITH uda.c (but not yet) */
147094078b2Skarels struct size {
148094078b2Skarels 	daddr_t nblocks;
149094078b2Skarels 	daddr_t blkoff;
150094078b2Skarels } kra81_sizes[8] = {
151094078b2Skarels #ifdef MARYLAND
152094078b2Skarels 	67832,	0,		/* A=cyl    0 thru   94 + 2 sectors */
153094078b2Skarels 	67828,	67832,		/* B=cyl   95 thru  189 - 2 sectors */
154094078b2Skarels 	-1,	0,		/* C=cyl    0 thru 1247 */
155094078b2Skarels 	-1,	135660,		/* D=cyl  190 thru 1247 */
156094078b2Skarels 	449466,	49324,		/* E xxx */
157094078b2Skarels 	64260,	498790,		/* F xxx */
158094078b2Skarels 	328022,	563050,		/* G xxx */
159094078b2Skarels 	0,	0,
160094078b2Skarels #else
161094078b2Skarels 	15884,	0,		/* a */
162094078b2Skarels 	33440,	15884,		/* b */
163094078b2Skarels 	-1,	0,		/* c */
164094078b2Skarels 	-1,	49324,		/* d */
165094078b2Skarels 	449466,	49324,		/* e */
166094078b2Skarels 	64260,	498790,		/* f */
167094078b2Skarels 	328022,	563050,		/* g */
168094078b2Skarels 	0,	0,
169094078b2Skarels #endif
170094078b2Skarels }, kra80_sizes[8] = {
171094078b2Skarels 	15884,	0,		/* A=blk 0 thru 15883 */
172094078b2Skarels 	33440,	15884,		/* B=blk 15884 thru 49323 */
173094078b2Skarels 	-1,	0,		/* C=blk 0 thru end */
174094078b2Skarels 	0,	0,
175094078b2Skarels 	0,	0,
176094078b2Skarels 	0,	0,
177094078b2Skarels 	82080,	49324,		/* G=blk 49324 thru 131403 */
178094078b2Skarels 	-1,	131404,		/* H=blk 131404 thru end */
179094078b2Skarels }, kra60_sizes[8] = {
180094078b2Skarels 	15884,	0,		/* A=blk 0 thru 15883 */
181094078b2Skarels 	33440,	15884,		/* B=blk 15884 thru 49323 */
182094078b2Skarels 	-1,	0,		/* C=blk 0 thru end */
183094078b2Skarels 	-1,	49324,		/* D=blk 49324 thru end */
184094078b2Skarels 	0,	0,
185094078b2Skarels 	0,	0,
186094078b2Skarels 	82080,	49324,		/* G=blk 49324 thru 131403 */
187094078b2Skarels 	-1,	131404,		/* H=blk 131404 thru end */
188094078b2Skarels };
189094078b2Skarels /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */
190094078b2Skarels 
191094078b2Skarels /*
192094078b2Skarels  * Drive type index decoding table.  `ut_name' is null iff the
193094078b2Skarels  * type is not known.
194094078b2Skarels  */
195094078b2Skarels struct	kdbtypes {
196094078b2Skarels 	char	*ut_name;	/* drive type name */
197094078b2Skarels 	struct	size *ut_sizes;	/* partition tables */
198094078b2Skarels } kdbtypes[] = {
199094078b2Skarels 	NULL,		NULL,
200094078b2Skarels 	"ra80",		kra80_sizes,	/* 1 = ra80 */
201094078b2Skarels 	NULL,		NULL,
202094078b2Skarels 	NULL,		NULL,
203094078b2Skarels 	"ra60",		kra60_sizes,	/* 4 = ra60 */
204094078b2Skarels 	"ra81",		kra81_sizes,	/* 5 = ra81 */
205094078b2Skarels };
206094078b2Skarels 
207094078b2Skarels #define NTYPES 6
208094078b2Skarels 
209094078b2Skarels /*
210094078b2Skarels  * Definition of the driver for autoconf and generic MSCP code.
211094078b2Skarels  * SOME OF THIS IS BOGUS (must fix config)
212094078b2Skarels  */
213094078b2Skarels 
214094078b2Skarels #ifdef notdef		/* not when driver is for kra disks */
215094078b2Skarels /*
216094078b2Skarels  * Some of these variables (per-drive stuff) are shared
217094078b2Skarels  * with the UDA50 code (why not, they are the same drives).
218094078b2Skarels  * N.B.: kdbdinfo must not be shared.
219094078b2Skarels  */
220094078b2Skarels #define	kdbutab		udautab		/* shared */
221094078b2Skarels #define	kdbslavereply	udaslavereply	/* shared */
222094078b2Skarels #endif
223094078b2Skarels 
224094078b2Skarels int	kdbprobe();		/* XXX */
225094078b2Skarels int	kdbslave(), kdbattach();
226094078b2Skarels 
227094078b2Skarels int	kdbdgram(), kdbctlrdone(), kdbunconf(), kdbiodone();
228094078b2Skarels int	kdbonline(), kdbgotstatus(), kdbioerror();
229094078b2Skarels 
230094078b2Skarels struct	uba_device *kdbdinfo[NKRA];	/* uba_device indeed! */
231094078b2Skarels struct	buf kdbutab[NKRA];	/* per drive transfer queue */
232094078b2Skarels 
233094078b2Skarels u_short kdbstd[] = { 0 };	/* XXX */
234094078b2Skarels struct uba_driver kdbdriver =	/* XXX */
235094078b2Skarels  { kdbprobe, kdbslave, kdbattach, 0, kdbstd, DRIVENAMES, kdbdinfo, "kdb" };
236094078b2Skarels 
237094078b2Skarels struct	mscp_driver kdbmscpdriver =
238baf0763aSkarels  { MAXUNIT, NKRA, UNITSHIFT, kdbutab, (struct disklabel *)0, kdbdinfo,
239094078b2Skarels    kdbdgram, kdbctlrdone, kdbunconf, kdbiodone,
240094078b2Skarels    kdbonline, kdbgotstatus, NULL, kdbioerror, NULL,
241094078b2Skarels    "kdb", DRIVENAMES };
242094078b2Skarels 
243094078b2Skarels /*
244094078b2Skarels  * Miscellaneous private variables.
245094078b2Skarels  */
246094078b2Skarels char	kdbsr_bits[] = KDBSR_BITS;
247094078b2Skarels 
248094078b2Skarels struct	uba_device *kdbip[NKDB][MAXUNIT];
249094078b2Skarels 				/* inverting pointers: ctlr & unit => `Unibus'
250094078b2Skarels 				   device pointer */
251094078b2Skarels 
252094078b2Skarels daddr_t	ra_dsize[NKRA];		/* drive sizes, from on line end packets */
253094078b2Skarels 
254094078b2Skarels struct	mscp kdbslavereply;	/* get unit status response packet, set
255094078b2Skarels 				   for kdbslave by kdbunconf, via kdbintr */
256094078b2Skarels 
257094078b2Skarels int	kdbwstart, kdbwatch();	/* watchdog timer */
258094078b2Skarels int	wakeup();
259094078b2Skarels 
260094078b2Skarels /*
261094078b2Skarels  * If kdbprobe is called, return 0 to keep Unibus code from attempting
262094078b2Skarels  * to use this device.	XXX rethink
263094078b2Skarels  */
264094078b2Skarels /* ARGSUSED */
kdbprobe(reg,ctlr)265094078b2Skarels kdbprobe(reg, ctlr)
266094078b2Skarels 	caddr_t reg;
267094078b2Skarels 	int ctlr;
268094078b2Skarels {
269094078b2Skarels 
270094078b2Skarels 	return (0);
271094078b2Skarels }
272094078b2Skarels 
273094078b2Skarels /*
274094078b2Skarels  * Configure in a KDB50 controller.
275094078b2Skarels  */
kdbconfig(kdbnum,va,pa,vec)276094078b2Skarels kdbconfig(kdbnum, va, pa, vec)
277094078b2Skarels 	int kdbnum;
278094078b2Skarels 	struct biiregs *va, *pa;
279094078b2Skarels 	int vec;
280094078b2Skarels {
281094078b2Skarels 	register struct kdbinfo *ki;
282094078b2Skarels #define mi (&ki->ki_mi)
283094078b2Skarels 
284094078b2Skarels #ifdef lint
285094078b2Skarels 	extern int (*kdbint0[])();
286094078b2Skarels 
287094078b2Skarels 	(*kdbint0[0])(0);	/* this is a config botch */
288094078b2Skarels 	kdbintr(0);
289094078b2Skarels #endif
290094078b2Skarels 
291094078b2Skarels 	/*
292094078b2Skarels 	 * Set up local KDB status.
293094078b2Skarels 	 */
294094078b2Skarels 	ki = &kdbinfo[kdbnum];
295094078b2Skarels 	ki->ki_kdb = (struct kdb_regs *)va;
296094078b2Skarels 	ki->ki_physkdb = (struct kdb_regs *)pa;
297094078b2Skarels 	ki->ki_vec = vec;
2981ad6111aSkarels 	ki->ki_map =
2991ad6111aSkarels 	    (struct map *)malloc((u_long)(KI_MAPSIZ * sizeof(struct map)),
300094078b2Skarels 	    M_DEVBUF, M_NOWAIT);
301f4cfff1bSbostic 	if (ki->ki_map == NULL) {
302f4cfff1bSbostic 		printf("kdb%d: cannot get memory for ptes\n", kdbnum);
303094078b2Skarels 		return;
304f4cfff1bSbostic 	}
305f4cfff1bSbostic 	ki->ki_ptephys = PHYS(long, ki->ki_pte); /* kvtophys(ki->ki_pte) */
306094078b2Skarels 	ki->ki_flags = KDB_ALIVE;
307f4cfff1bSbostic 
308f4cfff1bSbostic 	/* THE FOLLOWING IS ONLY NEEDED TO CIRCUMVENT A BUG IN rminit */
309f4cfff1bSbostic 	bzero((caddr_t)ki->ki_map, KI_MAPSIZ * sizeof(struct map));
310094078b2Skarels 
311094078b2Skarels 	rminit(ki->ki_map, (long)KI_PTES, (long)1, "kdb", KI_MAPSIZ);
312094078b2Skarels 
313094078b2Skarels 	/*
314094078b2Skarels 	 * Set up the generic MSCP structures.
315094078b2Skarels 	 */
316094078b2Skarels 	mi->mi_md = &kdbmscpdriver;
317094078b2Skarels 	mi->mi_ctlr = kdbnum;	/* also sets ki->ki_ctlr */
318094078b2Skarels 	mi->mi_tab = &ki->ki_tab;
319094078b2Skarels 	mi->mi_ip = kdbip[kdbnum];
320094078b2Skarels 	mi->mi_cmd.mri_size = NCMD;
321094078b2Skarels 	mi->mi_cmd.mri_desc = ki->ki_ca.ca_cmddsc;
322094078b2Skarels 	mi->mi_cmd.mri_ring = ki->ki_cmd;
323094078b2Skarels 	mi->mi_rsp.mri_size = NRSP;
324094078b2Skarels 	mi->mi_rsp.mri_desc = ki->ki_ca.ca_rspdsc;
325094078b2Skarels 	mi->mi_rsp.mri_ring = ki->ki_rsp;
326094078b2Skarels 	mi->mi_wtab.av_forw = mi->mi_wtab.av_back = &mi->mi_wtab;
327094078b2Skarels #undef mi
328094078b2Skarels }
329094078b2Skarels 
330094078b2Skarels /*
331094078b2Skarels  * Find a slave.
332094078b2Skarels  * Note that by the time kdbslave is called, the interrupt vector
333094078b2Skarels  * for the KDB50 has been set up (so that kdbunconf() will be called).
334094078b2Skarels  */
kdbslave(ui)335094078b2Skarels kdbslave(ui)
336094078b2Skarels 	register struct uba_device *ui;
337094078b2Skarels {
338094078b2Skarels 	register struct kdbinfo *ki;
339094078b2Skarels 	register struct mscp *mp;
340094078b2Skarels 	int next = 0, type, timeout, tries, i;
341094078b2Skarels 
342094078b2Skarels #ifdef lint
343094078b2Skarels 	i = 0; i = i;
344094078b2Skarels #endif
345094078b2Skarels 	/*
346094078b2Skarels 	 * Make sure the controller is fully initialised, by waiting
347094078b2Skarels 	 * for it if necessary.
348094078b2Skarels 	 */
349094078b2Skarels 	ki = &kdbinfo[ui->ui_ctlr];
350094078b2Skarels 	if (ki->ki_state == ST_RUN)
351094078b2Skarels 		goto findunit;
352094078b2Skarels 	tries = 0;
353094078b2Skarels again:
354094078b2Skarels 	if (kdbinit(ki))
355094078b2Skarels 		return (0);
356094078b2Skarels 	timeout = todr() + 1000;		/* 10 seconds */
357094078b2Skarels 	while (todr() < timeout)
358094078b2Skarels 		if (ki->ki_state == ST_RUN)	/* made it */
359094078b2Skarels 			goto findunit;
360094078b2Skarels 	if (++tries < 2)
361094078b2Skarels 		goto again;
362094078b2Skarels 	printf("kdb%d: controller hung\n", ki->ki_ctlr);
363094078b2Skarels 	return (0);
364094078b2Skarels 
365094078b2Skarels 	/*
366094078b2Skarels 	 * The controller is all set; go find the unit.  Grab an
367094078b2Skarels 	 * MSCP packet and send out a Get Unit Status command, with
368094078b2Skarels 	 * the `next unit' modifier if we are looking for a generic
369094078b2Skarels 	 * unit.  We set the `in slave' flag so that kdbunconf()
370094078b2Skarels 	 * knows to copy the response to `kdbslavereply'.
371094078b2Skarels 	 */
372094078b2Skarels findunit:
373094078b2Skarels 	kdbslavereply.mscp_opcode = 0;
374094078b2Skarels 	ki->ki_flags |= KDB_INSLAVE;
375094078b2Skarels 	if ((mp = mscp_getcp(&ki->ki_mi, MSCP_DONTWAIT)) == NULL)
376094078b2Skarels 		panic("kdbslave");		/* `cannot happen' */
377094078b2Skarels 	mp->mscp_opcode = M_OP_GETUNITST;
378094078b2Skarels 	if (ui->ui_slave == '?') {
379094078b2Skarels 		mp->mscp_unit = next;
380094078b2Skarels 		mp->mscp_modifier = M_GUM_NEXTUNIT;
381094078b2Skarels 	} else {
382094078b2Skarels 		mp->mscp_unit = ui->ui_slave;
383094078b2Skarels 		mp->mscp_modifier = 0;
384094078b2Skarels 	}
385094078b2Skarels 	*mp->mscp_addr |= MSCP_OWN | MSCP_INT;
386094078b2Skarels 	i = ki->ki_kdb->kdb_ip;	/* initiate polling */
387094078b2Skarels 	mp = &kdbslavereply;
388094078b2Skarels 	timeout = todr() + 1000;
389094078b2Skarels 	while (todr() < timeout)
390094078b2Skarels 		if (mp->mscp_opcode)
391094078b2Skarels 			goto gotit;
392094078b2Skarels 	printf("kdb%d: no response to Get Unit Status request\n",
393094078b2Skarels 		ki->ki_ctlr);
394094078b2Skarels 	ki->ki_flags &= ~KDB_INSLAVE;
395094078b2Skarels 	return (0);
396094078b2Skarels 
397094078b2Skarels gotit:
398094078b2Skarels 	ki->ki_flags &= ~KDB_INSLAVE;
399094078b2Skarels 
400094078b2Skarels 	/*
401094078b2Skarels 	 * Got a slave response.  If the unit is there, use it.
402094078b2Skarels 	 */
403094078b2Skarels 	switch (mp->mscp_status & M_ST_MASK) {
404094078b2Skarels 
405094078b2Skarels 	case M_ST_SUCCESS:	/* worked */
406094078b2Skarels 	case M_ST_AVAILABLE:	/* found another drive */
407094078b2Skarels 		break;		/* use it */
408094078b2Skarels 
409094078b2Skarels 	case M_ST_OFFLINE:
410094078b2Skarels 		/*
411094078b2Skarels 		 * Figure out why it is off line.  It may be because
412094078b2Skarels 		 * it is nonexistent, or because it is spun down, or
413094078b2Skarels 		 * for some other reason.
414094078b2Skarels 		 */
415094078b2Skarels 		switch (mp->mscp_status & ~M_ST_MASK) {
416094078b2Skarels 
417094078b2Skarels 		case M_OFFLINE_UNKNOWN:
418094078b2Skarels 			/*
419094078b2Skarels 			 * No such drive, and there are none with
420094078b2Skarels 			 * higher unit numbers either, if we are
421094078b2Skarels 			 * using M_GUM_NEXTUNIT.
422094078b2Skarels 			 */
423094078b2Skarels 			return (0);
424094078b2Skarels 
425094078b2Skarels 		case M_OFFLINE_UNMOUNTED:
426094078b2Skarels 			/*
427094078b2Skarels 			 * The drive is not spun up.  Use it anyway.
428094078b2Skarels 			 *
429094078b2Skarels 			 * N.B.: this seems to be a common occurrance
430094078b2Skarels 			 * after a power failure.  The first attempt
431094078b2Skarels 			 * to bring it on line seems to spin it up
432094078b2Skarels 			 * (and thus takes several minutes).  Perhaps
433094078b2Skarels 			 * we should note here that the on-line may
434094078b2Skarels 			 * take longer than usual.
435094078b2Skarels 			 */
436094078b2Skarels 			break;
437094078b2Skarels 
438094078b2Skarels 		default:
439094078b2Skarels 			/*
440094078b2Skarels 			 * In service, or something else equally unusable.
441094078b2Skarels 			 */
442094078b2Skarels 			printf("kdb%d: unit %d off line:", ki->ki_ctlr,
443094078b2Skarels 				mp->mscp_unit);
444094078b2Skarels 			mscp_printevent(mp);
445094078b2Skarels 			goto try_another;
446094078b2Skarels 		}
447094078b2Skarels 		break;
448094078b2Skarels 
449094078b2Skarels 	default:
450094078b2Skarels 		printf("kdb%d: unable to get unit status:", ki->ki_ctlr);
451094078b2Skarels 		mscp_printevent(mp);
452094078b2Skarels 		return (0);
453094078b2Skarels 	}
454094078b2Skarels 
455094078b2Skarels 	/*
456094078b2Skarels 	 * Does this ever happen?  What (if anything) does it mean?
457094078b2Skarels 	 */
458094078b2Skarels 	if (mp->mscp_unit < next) {
459094078b2Skarels 		printf("kdb%d: unit %d, next %d\n",
460094078b2Skarels 			ki->ki_ctlr, mp->mscp_unit, next);
461094078b2Skarels 		return (0);
462094078b2Skarels 	}
463094078b2Skarels 
464094078b2Skarels 	if (mp->mscp_unit >= MAXUNIT) {
465094078b2Skarels 		printf("kdb%d: cannot handle unit number %d (max is %d)\n",
466094078b2Skarels 			ki->ki_ctlr, mp->mscp_unit, MAXUNIT - 1);
467094078b2Skarels 		return (0);
468094078b2Skarels 	}
469094078b2Skarels 
470094078b2Skarels 	/*
471094078b2Skarels 	 * See if we already handle this drive.
472094078b2Skarels 	 * (Only likely if ui->ui_slave=='?'.)
473094078b2Skarels 	 */
474094078b2Skarels 	if (kdbip[ki->ki_ctlr][mp->mscp_unit] != NULL)
475094078b2Skarels 		goto try_another;
476094078b2Skarels 
477094078b2Skarels 	/*
478094078b2Skarels 	 * Make sure we know about this kind of drive.
479094078b2Skarels 	 * Others say we should treat unknowns as RA81s; I am
480094078b2Skarels 	 * not sure this is safe.
481094078b2Skarels 	 */
482094078b2Skarels 	type = mp->mscp_guse.guse_drivetype;
483094078b2Skarels 	if (type >= NTYPES || kdbtypes[type].ut_name == 0) {
484094078b2Skarels 		register long id = mp->mscp_guse.guse_mediaid;
485094078b2Skarels 
486094078b2Skarels 		printf("kdb%d: unit %d: media ID `", ki->ki_ctlr,
487094078b2Skarels 			mp->mscp_unit);
488094078b2Skarels 		printf("%c%c %c%c%c%d",
489094078b2Skarels 			MSCP_MID_CHAR(4, id), MSCP_MID_CHAR(3, id),
490094078b2Skarels 			MSCP_MID_CHAR(2, id), MSCP_MID_CHAR(1, id),
491094078b2Skarels 			MSCP_MID_CHAR(0, id), MSCP_MID_NUM(id));
492094078b2Skarels 		printf("' is of unknown type %d; ignored\n", type);
493094078b2Skarels try_another:
494094078b2Skarels 		if (ui->ui_slave != '?')
495094078b2Skarels 			return (0);
496094078b2Skarels 		next = mp->mscp_unit + 1;
497094078b2Skarels 		goto findunit;
498094078b2Skarels 	}
499094078b2Skarels 
500094078b2Skarels 	/*
501094078b2Skarels 	 * Voila!
502094078b2Skarels 	 */
503094078b2Skarels 	ui->ui_type = type;
504094078b2Skarels 	ui->ui_flags = 0;	/* not on line, nor anything else */
505094078b2Skarels 	ui->ui_slave = mp->mscp_unit;
506094078b2Skarels 	return (1);
507094078b2Skarels }
508094078b2Skarels 
509094078b2Skarels /*
510094078b2Skarels  * Attach a found slave.  Make sure the watchdog timer is running.
511939f3037Smckusick  * If this disk is being profiled, fill in the `wpms' value (used by
512094078b2Skarels  * what?).  Set up the inverting pointer, and attempt to bring the
513094078b2Skarels  * drive on line.
514094078b2Skarels  */
kdbattach(ui)515094078b2Skarels kdbattach(ui)
516094078b2Skarels 	register struct uba_device *ui;
517094078b2Skarels {
518094078b2Skarels 
519094078b2Skarels 	if (kdbwstart == 0) {
520094078b2Skarels 		timeout(kdbwatch, (caddr_t)0, hz);
521094078b2Skarels 		kdbwstart++;
522094078b2Skarels 	}
523094078b2Skarels 	if (ui->ui_dk >= 0)
524939f3037Smckusick 		dk_wpms[ui->ui_dk] = (60 * 31 * 256);	/* approx */
525094078b2Skarels 	kdbip[ui->ui_ctlr][ui->ui_slave] = ui;
526094078b2Skarels 	(void) kdb_bringonline(ui, 1);
527094078b2Skarels 	/* should we get its status too? */
528094078b2Skarels }
529094078b2Skarels 
530094078b2Skarels /*
531094078b2Skarels  * Initialise a KDB50.  Return true iff something goes wrong.
532094078b2Skarels  */
kdbinit(ki)533094078b2Skarels kdbinit(ki)
534094078b2Skarels 	register struct kdbinfo *ki;
535094078b2Skarels {
536094078b2Skarels 	register struct kdb_regs *ka = ki->ki_kdb;
537094078b2Skarels 	int timo;
538094078b2Skarels 
539094078b2Skarels 	/*
540094078b2Skarels 	 * While we are thinking about it, reset the next command
541094078b2Skarels 	 * and response indicies.
542094078b2Skarels 	 */
543094078b2Skarels 	ki->ki_mi.mi_cmd.mri_next = 0;
544094078b2Skarels 	ki->ki_mi.mi_rsp.mri_next = 0;
545094078b2Skarels 
546094078b2Skarels 	/*
547094078b2Skarels 	 * Start up the hardware initialisation sequence.
548094078b2Skarels 	 */
549094078b2Skarels #define	STEP0MASK (KDB_ERR | KDB_STEP4 | KDB_STEP3 | KDB_STEP2 | KDB_STEP1)
550094078b2Skarels 
551094078b2Skarels 	ki->ki_state = ST_IDLE;	/* in case init fails */
552094078b2Skarels 
553094078b2Skarels 	bi_reset(&ka->kdb_bi);	/* reset bi node (but not the BI itself) */
554094078b2Skarels 
555094078b2Skarels 	timo = todr() + 1000;
556094078b2Skarels 	while ((ka->kdb_sa & STEP0MASK) == 0) {
557094078b2Skarels 		if (todr() > timo) {
558094078b2Skarels 			printf("kdb%d: timeout during init\n", ki->ki_ctlr);
559094078b2Skarels 			return (-1);
560094078b2Skarels 		}
561094078b2Skarels 	}
562094078b2Skarels 	if ((ka->kdb_sa & STEP0MASK) != KDB_STEP1) {
563094078b2Skarels 		printf("kdb%d: init failed, sa=%b\n", ki->ki_ctlr,
564094078b2Skarels 			ka->kdb_sa, kdbsr_bits);
565094078b2Skarels 		return (-1);
566094078b2Skarels 	}
567094078b2Skarels 
568094078b2Skarels 	/*
569094078b2Skarels 	 * Success!  Record new state, and start step 1 initialisation.
570094078b2Skarels 	 * The rest is done in the interrupt handler.
571094078b2Skarels 	 */
572094078b2Skarels 	ki->ki_state = ST_STEP1;
573094078b2Skarels 	ka->kdb_bi.bi_intrdes = 1 << mastercpu;
574094078b2Skarels #ifdef unneeded /* is it? */
575094078b2Skarels 	ka->kdb_bi.bi_csr = (ka->kdb_bi.bi_csr&~BICSR_ARB_MASK)|BICSR_ARB_???;
576094078b2Skarels #endif
577094078b2Skarels 	ka->kdb_bi.bi_bcicsr |= BCI_STOPEN | BCI_IDENTEN | BCI_UINTEN |
578094078b2Skarels 		BCI_INTEN;
579094078b2Skarels 
580094078b2Skarels /* I THINK THIS IS WRONG */
581094078b2Skarels /* Mach uses 0x601d0, which includes IPL16, but 1d0 is IPL17, nexzvec...? */
582094078b2Skarels 	ka->kdb_bi.bi_eintrcsr = BIEIC_IPL15 | ki->ki_vec;	/* ??? */
583094078b2Skarels /* END I THINK WRONG */
584094078b2Skarels 
585094078b2Skarels 	ka->kdb_bi.bi_uintrcsr = ki->ki_vec;
586094078b2Skarels 	ka->kdb_sw = KDB_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) | KDB_IE |
587094078b2Skarels 		(ki->ki_vec >> 2);
588094078b2Skarels 	return (0);
589094078b2Skarels }
590094078b2Skarels 
591094078b2Skarels /*
592094078b2Skarels  * Open a drive.
593094078b2Skarels  */
594094078b2Skarels /*ARGSUSED*/
kdbopen(dev,flag)595094078b2Skarels kdbopen(dev, flag)
596094078b2Skarels 	dev_t dev;
597094078b2Skarels 	int flag;
598094078b2Skarels {
599094078b2Skarels 	register int unit;
600094078b2Skarels 	register struct uba_device *ui;
601094078b2Skarels 	register struct kdbinfo *ki;
602094078b2Skarels 	int s;
603094078b2Skarels 
604094078b2Skarels 	/*
605094078b2Skarels 	 * Make sure this is a reasonable open request.
606094078b2Skarels 	 */
607094078b2Skarels 	unit = kdbunit(dev);
608094078b2Skarels 	if (unit >= NKRA || (ui = kdbdinfo[unit]) == 0 || ui->ui_alive == 0)
609094078b2Skarels 		return (ENXIO);
610094078b2Skarels 
611094078b2Skarels 	/*
612094078b2Skarels 	 * Make sure the controller is running, by (re)initialising it if
613094078b2Skarels 	 * necessary.
614094078b2Skarels 	 */
615094078b2Skarels 	ki = &kdbinfo[ui->ui_ctlr];
616094078b2Skarels 	s = spl5();
617094078b2Skarels 	if (ki->ki_state != ST_RUN) {
618094078b2Skarels 		if (ki->ki_state == ST_IDLE && kdbinit(ki)) {
619094078b2Skarels 			splx(s);
620094078b2Skarels 			return (EIO);
621094078b2Skarels 		}
622094078b2Skarels 		/*
623094078b2Skarels 		 * In case it does not come up, make sure we will be
624094078b2Skarels 		 * restarted in 10 seconds.  This corresponds to the
625094078b2Skarels 		 * 10 second timeouts in kdbprobe() and kdbslave().
626094078b2Skarels 		 */
627094078b2Skarels 		ki->ki_flags |= KDB_DOWAKE;
628094078b2Skarels 		timeout(wakeup, (caddr_t)&ki->ki_flags, 10 * hz);
629094078b2Skarels 		sleep((caddr_t)&ki->ki_flags, PRIBIO);
630094078b2Skarels 		if (ki->ki_state != ST_RUN) {
631094078b2Skarels 			splx(s);
632094078b2Skarels 			printf("kdb%d: controller hung\n", ui->ui_ctlr);
633094078b2Skarels 			return (EIO);
634094078b2Skarels 		}
635094078b2Skarels 		untimeout(wakeup, (caddr_t)&ki->ki_flags);
636094078b2Skarels 	}
637094078b2Skarels 	if ((ui->ui_flags & UNIT_ONLINE) == 0) {
638094078b2Skarels 		/*
639094078b2Skarels 		 * Bring the drive on line so we can find out how
640094078b2Skarels 		 * big it is.  If it is not spun up, it will not
641094078b2Skarels 		 * come on line; this cannot really be considered
642094078b2Skarels 		 * an `error condition'.
643094078b2Skarels 		 */
644094078b2Skarels 		if (kdb_bringonline(ui, 0)) {
645094078b2Skarels 			splx(s);
646094078b2Skarels 			printf("%s%d: drive will not come on line\n",
647094078b2Skarels 				kdbdriver.ud_dname, unit);
648094078b2Skarels 			return (EIO);
649094078b2Skarels 		}
650094078b2Skarels 	}
651094078b2Skarels 	splx(s);
652094078b2Skarels 	return (0);
653094078b2Skarels }
654094078b2Skarels 
655094078b2Skarels /*
656094078b2Skarels  * Bring a drive on line.  In case it fails to respond, we set
657094078b2Skarels  * a timeout on it.  The `nosleep' parameter should be set if
658094078b2Skarels  * we are to spin-wait; otherwise this must be called at spl5().
659094078b2Skarels  */
kdb_bringonline(ui,nosleep)660094078b2Skarels kdb_bringonline(ui, nosleep)
661094078b2Skarels 	register struct uba_device *ui;
662094078b2Skarels 	int nosleep;
663094078b2Skarels {
664094078b2Skarels 	register struct kdbinfo *ki = &kdbinfo[ui->ui_ctlr];
665094078b2Skarels 	register struct mscp *mp;
666094078b2Skarels 	int i;
667094078b2Skarels 
668094078b2Skarels 	if (nosleep) {
669094078b2Skarels 		mp = mscp_getcp(&ki->ki_mi, MSCP_DONTWAIT);
670094078b2Skarels 		if (mp == NULL)
671094078b2Skarels 			return (-1);
672094078b2Skarels 	} else
673094078b2Skarels 		mp = mscp_getcp(&ki->ki_mi, MSCP_WAIT);
674094078b2Skarels 	mp->mscp_opcode = M_OP_ONLINE;
675094078b2Skarels 	mp->mscp_unit = ui->ui_slave;
676094078b2Skarels 	mp->mscp_cmdref = (long)&ui->ui_flags;
677094078b2Skarels 	*mp->mscp_addr |= MSCP_OWN | MSCP_INT;
678094078b2Skarels 	i = ki->ki_kdb->kdb_ip;
679094078b2Skarels 
680094078b2Skarels 	if (nosleep) {
681094078b2Skarels 		i = todr() + 1000;
682094078b2Skarels 		while ((ui->ui_flags & UNIT_ONLINE) == 0)
683094078b2Skarels 			if (todr() > i)
684094078b2Skarels 				return (-1);
685094078b2Skarels 	} else {
686094078b2Skarels 		timeout(wakeup, (caddr_t)&ui->ui_flags, 10 * hz);
687094078b2Skarels 		sleep((caddr_t)&ui->ui_flags, PRIBIO);
688094078b2Skarels 		if ((ui->ui_flags & UNIT_ONLINE) == 0)
689094078b2Skarels 			return (-1);
690094078b2Skarels 		untimeout(wakeup, (caddr_t)&ui->ui_flags);
691094078b2Skarels 	}
692094078b2Skarels 	return (0);	/* made it */
693094078b2Skarels }
694094078b2Skarels 
695094078b2Skarels /*
696094078b2Skarels  * Queue a transfer request, and if possible, hand it to the controller.
697094078b2Skarels  *
698094078b2Skarels  * This routine is broken into two so that the internal version
699094078b2Skarels  * kdbstrat1() can be called by the (nonexistent, as yet) bad block
700094078b2Skarels  * revectoring routine.
701094078b2Skarels  */
kdbstrategy(bp)702094078b2Skarels kdbstrategy(bp)
703094078b2Skarels 	register struct buf *bp;
704094078b2Skarels {
705094078b2Skarels 	register int unit;
706094078b2Skarels 	register struct uba_device *ui;
707094078b2Skarels 	register struct size *st;
708094078b2Skarels 	daddr_t sz, maxsz;
709094078b2Skarels 
710094078b2Skarels 	/*
711094078b2Skarels 	 * Make sure this is a reasonable drive to use.
712094078b2Skarels 	 */
713094078b2Skarels 	if ((unit = kdbunit(bp->b_dev)) >= NKRA ||
714094078b2Skarels 	    (ui = kdbdinfo[unit]) == NULL || ui->ui_alive == 0) {
715094078b2Skarels 		bp->b_error = ENXIO;
716094078b2Skarels 		bp->b_flags |= B_ERROR;
717094078b2Skarels 		biodone(bp);
718094078b2Skarels 		return;
719094078b2Skarels 	}
720094078b2Skarels 
721094078b2Skarels 	/*
722094078b2Skarels 	 * Determine the size of the transfer, and make sure it is
723094078b2Skarels 	 * within the boundaries of the drive.
724094078b2Skarels 	 */
725094078b2Skarels 	sz = (bp->b_bcount + 511) >> 9;
726094078b2Skarels 	st = &kdbtypes[ui->ui_type].ut_sizes[kdbpart(bp->b_dev)];
727094078b2Skarels 	if ((maxsz = st->nblocks) < 0)
728094078b2Skarels 		maxsz = ra_dsize[unit] - st->blkoff;
729094078b2Skarels 	if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz ||
730094078b2Skarels 	    st->blkoff >= ra_dsize[unit]) {
731094078b2Skarels 		/* if exactly at end of disk, return an EOF */
732094078b2Skarels 		if (bp->b_blkno == maxsz)
733094078b2Skarels 			bp->b_resid = bp->b_bcount;
734094078b2Skarels 		else {
735094078b2Skarels 			bp->b_error = EINVAL;
736094078b2Skarels 			bp->b_flags |= B_ERROR;
737094078b2Skarels 		}
738094078b2Skarels 		biodone(bp);
739094078b2Skarels 		return;
740094078b2Skarels 	}
741094078b2Skarels 	kdbstrat1(bp);
742094078b2Skarels }
743094078b2Skarels 
744094078b2Skarels /*
745094078b2Skarels  * Work routine for kdbstrategy.
746094078b2Skarels  */
kdbstrat1(bp)747094078b2Skarels kdbstrat1(bp)
748094078b2Skarels 	register struct buf *bp;
749094078b2Skarels {
750094078b2Skarels 	register int unit = kdbunit(bp->b_dev);
751094078b2Skarels 	register struct buf *dp;
752094078b2Skarels 	register struct kdbinfo *ki;
753094078b2Skarels 	struct uba_device *ui;
754094078b2Skarels 	int s;
755094078b2Skarels 
756094078b2Skarels 	/*
757094078b2Skarels 	 * Append the buffer to the drive queue, and if it is not
758094078b2Skarels 	 * already there, the drive to the controller queue.  (However,
759094078b2Skarels 	 * if the drive queue is marked to be requeued, we must be
760094078b2Skarels 	 * awaiting an on line or get unit status command; in this
761094078b2Skarels 	 * case, leave it off the controller queue.)
762094078b2Skarels 	 */
763094078b2Skarels 	ui = kdbdinfo[unit];
764094078b2Skarels 	ki = &kdbinfo[ui->ui_ctlr];
765094078b2Skarels 	dp = &kdbutab[unit];
766094078b2Skarels 	s = spl5();
767094078b2Skarels 	APPEND(bp, dp, av_forw);
768094078b2Skarels 	if (dp->b_active == 0 && (ui->ui_flags & UNIT_REQUEUE) == 0) {
769094078b2Skarels 		APPEND(dp, &ki->ki_tab, b_forw);
770094078b2Skarels 		dp->b_active++;
771094078b2Skarels 	}
772094078b2Skarels 
773094078b2Skarels 	/*
774094078b2Skarels 	 * Start activity on the controller.
775094078b2Skarels 	 */
776094078b2Skarels 	kdbstart(ki);
777094078b2Skarels 	splx(s);
778094078b2Skarels }
779094078b2Skarels 
780094078b2Skarels /*
781094078b2Skarels  * Find the physical address of some contiguous PTEs that map the
782094078b2Skarels  * transfer described in `bp', creating them (by copying) if
783094078b2Skarels  * necessary.  Store the physical base address of the map through
784094078b2Skarels  * mapbase, and the page offset through offset, and any resource
785094078b2Skarels  * information in *info (or 0 if none).
786094078b2Skarels  *
787094078b2Skarels  * If we cannot allocate space, return a nonzero status.
788094078b2Skarels  */
789094078b2Skarels int
kdbmap(ki,bp,mapbase,offset,info)790094078b2Skarels kdbmap(ki, bp, mapbase, offset, info)
791094078b2Skarels 	struct kdbinfo *ki;
792094078b2Skarels 	register struct buf *bp;
793094078b2Skarels 	long *mapbase, *offset;
794094078b2Skarels 	int *info;
795094078b2Skarels {
796094078b2Skarels 	register struct pte *spte, *dpte;
797094078b2Skarels 	register struct proc *rp;
798094078b2Skarels 	register int i, a, o;
799094078b2Skarels 	u_int v;
800094078b2Skarels 	int npf;
801094078b2Skarels 
802094078b2Skarels 	o = (int)bp->b_un.b_addr & PGOFSET;
803094078b2Skarels 
804094078b2Skarels 	/* handle contiguous cases */
805094078b2Skarels 	if ((bp->b_flags & B_PHYS) == 0) {
806094078b2Skarels 		spte = kvtopte(bp->b_un.b_addr);
807094078b2Skarels 		kdbstats.ks_sys++;
808094078b2Skarels 		*mapbase = PHYS(long, spte);
809094078b2Skarels 		*offset = o;
810094078b2Skarels 		*info = 0;
811094078b2Skarels 		return (0);
812094078b2Skarels 	}
813094078b2Skarels 	if (bp->b_flags & B_PAGET) {
814094078b2Skarels 		spte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)];
815094078b2Skarels if (spte->pg_v == 0) panic("kdbmap");
816094078b2Skarels 		kdbstats.ks_paget++;
817094078b2Skarels 		*mapbase = PHYS(long, spte);
818094078b2Skarels 		*offset = o;
819094078b2Skarels 		*info = 0;
820094078b2Skarels 		return (0);
821094078b2Skarels 	}
822094078b2Skarels 
823094078b2Skarels 	/* potentially discontiguous or invalid ptes */
824094078b2Skarels 	v = btop(bp->b_un.b_addr);
825094078b2Skarels 	rp = bp->b_flags & B_DIRTY ? &proc[2] : bp->b_proc;
826094078b2Skarels 	if (bp->b_flags & B_UAREA)
827094078b2Skarels 		spte = &rp->p_addr[v];
828094078b2Skarels 	else
829094078b2Skarels 		spte = vtopte(rp, v);
830094078b2Skarels 	npf = btoc(bp->b_bcount + o);
831094078b2Skarels 
832094078b2Skarels #ifdef notdef
833094078b2Skarels 	/*
834094078b2Skarels 	 * The current implementation of the VM system requires
835094078b2Skarels 	 * that all of these be done with a copy.  Even if the
836094078b2Skarels 	 * PTEs could be used now, they may be snatched out from
837094078b2Skarels 	 * under us later.  It would be nice if we could stop that....
838094078b2Skarels 	 */
839094078b2Skarels 
840094078b2Skarels 	/* check for invalid */
841094078b2Skarels 	/* CONSIDER CHANGING VM TO VALIDATE PAGES EARLIER */
842094078b2Skarels 	for (dpte = spte, i = npf; --i >= 0; dpte++)
843094078b2Skarels 		if (dpte->pg_v == 0)
844094078b2Skarels 			goto copy1;
845094078b2Skarels 	/*
846094078b2Skarels 	 * Check for discontiguous physical pte addresses.  It is
847094078b2Skarels 	 * not necessary to check each pte, since they come in clumps
848094078b2Skarels 	 * of pages.
849094078b2Skarels 	 */
850094078b2Skarels 	i = howmany(npf + (((int)spte & PGOFSET) / sizeof (*spte)), NPTEPG);
851094078b2Skarels 	/* often i==1, and we can avoid work */
852094078b2Skarels 	if (--i > 0) {
853094078b2Skarels 		dpte = kvtopte(spte);
854094078b2Skarels 		a = dpte->pg_pfnum;
855094078b2Skarels 		while (--i >= 0)
856094078b2Skarels 			if ((++dpte)->pg_pfnum != ++a)
857094078b2Skarels 				goto copy2;
858094078b2Skarels 	}
859094078b2Skarels 
860094078b2Skarels 	/* made it */
861094078b2Skarels 	kdbstats.ks_contig++;
862094078b2Skarels 	*mapbase = kvtophys(spte);
863094078b2Skarels 	*offset = o;
864094078b2Skarels 	*info = 0;
865094078b2Skarels 	return (0);
866094078b2Skarels 
867094078b2Skarels copy1:
868094078b2Skarels 	kdbstats.ks_inval++;		/* temp */
869094078b2Skarels copy2:
870094078b2Skarels #endif /* notdef */
871094078b2Skarels 	kdbstats.ks_copies++;
872094078b2Skarels 	i = npf + 1;
873094078b2Skarels 	if ((a = rmalloc(ki->ki_map, (long)i)) == 0) {
874094078b2Skarels 		kdbstats.ks_mapwait++;
875094078b2Skarels 		return (-1);
876094078b2Skarels 	}
877094078b2Skarels 	*info = (i << 16) | a;
878094078b2Skarels 	a--;
879094078b2Skarels 	/* if offset > PGOFSET, btop(offset) indexes mapbase */
880094078b2Skarels 	*mapbase = ki->ki_ptephys;
881094078b2Skarels 	*offset = (a << PGSHIFT) | o;
882094078b2Skarels 	dpte = &ki->ki_pte[a];
883094078b2Skarels 	while (--i > 0)
884094078b2Skarels 		*(int *)dpte++ = PG_V | *(int *)spte++;
885094078b2Skarels 	*(int *)dpte = 0;
886094078b2Skarels 	return (0);
887094078b2Skarels }
888094078b2Skarels 
889094078b2Skarels #define	KDBFREE(ki, info) if (info) \
890094078b2Skarels 	rmfree((ki)->ki_map, (long)((info) >> 16), (long)((info) & 0xffff))
891094078b2Skarels 
892094078b2Skarels /*
893094078b2Skarels  * Start up whatever transfers we can find.
894094078b2Skarels  * Note that kdbstart() must be called at spl5().
895094078b2Skarels  */
kdbstart(ki)896094078b2Skarels kdbstart(ki)
897094078b2Skarels 	register struct kdbinfo *ki;
898094078b2Skarels {
899094078b2Skarels 	register struct buf *bp, *dp;
900094078b2Skarels 	register struct mscp *mp;
901094078b2Skarels 	register struct uba_device *ui;
902094078b2Skarels 	long mapbase, offset;
903094078b2Skarels 	int info, ncmd = 0;
904094078b2Skarels 
905094078b2Skarels 	/*
906094078b2Skarels 	 * If it is not running, try (again and again...) to initialise
907094078b2Skarels 	 * it.  If it is currently initialising just ignore it for now.
908094078b2Skarels 	 */
909094078b2Skarels 	if (ki->ki_state != ST_RUN) {
910094078b2Skarels 		if (ki->ki_state == ST_IDLE && kdbinit(ki))
911094078b2Skarels 			printf("kdb%d: still hung\n", ki->ki_ctlr);
912094078b2Skarels 		return;
913094078b2Skarels 	}
914094078b2Skarels 
915094078b2Skarels loop:
916094078b2Skarels 	/* if insufficient credit, avoid overhead */
917094078b2Skarels 	if (ki->ki_mi.mi_credits <= MSCP_MINCREDITS)
918094078b2Skarels 		goto out;
919094078b2Skarels 
920094078b2Skarels 	/*
921f4cfff1bSbostic 	 * Service the drive at the head of the queue.  It may not
922f4cfff1bSbostic 	 * need anything; eventually this will finish up the close
923f4cfff1bSbostic 	 * protocol, but that is yet to be implemented here.
924094078b2Skarels 	 */
925094078b2Skarels 	if ((dp = ki->ki_tab.b_actf) == NULL)
926094078b2Skarels 		goto out;
927f4cfff1bSbostic 	if ((bp = dp->b_actf) == NULL) {
928f4cfff1bSbostic 		dp->b_active = 0;
929f4cfff1bSbostic 		ki->ki_tab.b_actf = dp->b_forw;
930f4cfff1bSbostic 		goto loop;
931f4cfff1bSbostic 	}
932094078b2Skarels 
933094078b2Skarels 	if (ki->ki_kdb->kdb_sa & KDB_ERR) {	/* ctlr fatal error */
934094078b2Skarels 		kdbsaerror(ki);
935094078b2Skarels 		goto out;
936094078b2Skarels 	}
937094078b2Skarels 
938094078b2Skarels 	 /* find or create maps for this transfer */
939094078b2Skarels 	 if (kdbmap(ki, bp, &mapbase, &offset, &info))
940094078b2Skarels 		goto out;	/* effectively, resource wait */
941094078b2Skarels 
942094078b2Skarels 	/*
943094078b2Skarels 	 * Get an MSCP packet, then figure out what to do.  If
944094078b2Skarels 	 * we cannot get a command packet, the command ring may
945094078b2Skarels 	 * be too small:  We should have at least as many command
946094078b2Skarels 	 * packets as credits, for best performance.
947094078b2Skarels 	 */
948094078b2Skarels 	if ((mp = mscp_getcp(&ki->ki_mi, MSCP_DONTWAIT)) == NULL) {
949094078b2Skarels 		if (ki->ki_mi.mi_credits > MSCP_MINCREDITS &&
950094078b2Skarels 		    (ki->ki_flags & KDB_GRIPED) == 0) {
951094078b2Skarels 			log(LOG_NOTICE, "kdb%d: command ring too small\n",
952094078b2Skarels 				ki->ki_ctlr);
953094078b2Skarels 			ki->ki_flags |= KDB_GRIPED;/* complain only once */
954094078b2Skarels 		}
955094078b2Skarels 		KDBFREE(ki, info);
956094078b2Skarels 		goto out;
957094078b2Skarels 	}
958094078b2Skarels 
959094078b2Skarels 	/*
960094078b2Skarels 	 * Bring the drive on line if it is not already.  Get its status
961094078b2Skarels 	 * if we do not already have it.  Otherwise just start the transfer.
962094078b2Skarels 	 */
963094078b2Skarels 	ui = kdbdinfo[kdbunit(bp->b_dev)];
964094078b2Skarels 	if ((ui->ui_flags & UNIT_ONLINE) == 0) {
965094078b2Skarels 		mp->mscp_opcode = M_OP_ONLINE;
966094078b2Skarels 		goto common;
967094078b2Skarels 	}
968094078b2Skarels 	if ((ui->ui_flags & UNIT_HAVESTATUS) == 0) {
969094078b2Skarels 		mp->mscp_opcode = M_OP_GETUNITST;
970094078b2Skarels common:
971094078b2Skarels if (ui->ui_flags & UNIT_REQUEUE) panic("kdbstart");
972094078b2Skarels 		/*
973094078b2Skarels 		 * Take the drive off the controller queue.  When the
974094078b2Skarels 		 * command finishes, make sure the drive is requeued.
975094078b2Skarels 		 * Give up any mapping (not needed now).  This last is
976094078b2Skarels 		 * not efficient, but is rare.
977094078b2Skarels 		 */
978094078b2Skarels 		KDBFREE(ki, info);
979094078b2Skarels 		ki->ki_tab.b_actf = dp->b_forw;
980094078b2Skarels 		dp->b_active = 0;
981094078b2Skarels 		ui->ui_flags |= UNIT_REQUEUE;
982094078b2Skarels 		mp->mscp_unit = ui->ui_slave;
983094078b2Skarels 		*mp->mscp_addr |= MSCP_OWN | MSCP_INT;
984094078b2Skarels 		ncmd++;
985094078b2Skarels 		goto loop;
986094078b2Skarels 	}
987094078b2Skarels 
988094078b2Skarels 	mp->mscp_opcode = (bp->b_flags & B_READ) ? M_OP_READ : M_OP_WRITE;
989094078b2Skarels 	mp->mscp_unit = ui->ui_slave;
990094078b2Skarels 	mp->mscp_seq.seq_lbn = bp->b_blkno +
991094078b2Skarels 		kdbtypes[ui->ui_type].ut_sizes[kdbpart(bp->b_dev)].blkoff;
992094078b2Skarels 	mp->mscp_seq.seq_bytecount = bp->b_bcount;
993094078b2Skarels 
994094078b2Skarels 	mp->mscp_seq.seq_buffer = offset | KDB_MAP;
995094078b2Skarels 	mp->mscp_seq.seq_mapbase = mapbase;
996094078b2Skarels 
997094078b2Skarels 	/* profile the drive */
998094078b2Skarels 	if (ui->ui_dk >= 0) {
999094078b2Skarels 		dk_busy |= 1 << ui->ui_dk;
1000094078b2Skarels 		dk_xfer[ui->ui_dk]++;
1001094078b2Skarels 		dk_wds[ui->ui_dk] += bp->b_bcount >> 6;
1002094078b2Skarels 	}
1003094078b2Skarels 
1004094078b2Skarels 	/*
1005094078b2Skarels 	 * Fill in the rest of the MSCP packet and move the buffer to the
1006094078b2Skarels 	 * I/O wait queue.
1007094078b2Skarels 	 */
1008094078b2Skarels 	mscp_go(&ki->ki_mi, mp, info);
1009094078b2Skarels 	ncmd++;			/* note the transfer */
1010094078b2Skarels 	ki->ki_tab.b_active++;	/* another one going */
1011094078b2Skarels 	goto loop;
1012094078b2Skarels 
1013094078b2Skarels out:
1014094078b2Skarels 	if (ncmd >= KS_MAXC)
1015094078b2Skarels 		ncmd = KS_MAXC - 1;
1016094078b2Skarels 	kdbstats.ks_cmd[ncmd]++;
1017094078b2Skarels 	if (ncmd)		/* start some transfers */
1018094078b2Skarels 		ncmd = ki->ki_kdb->kdb_ip;
1019094078b2Skarels }
1020094078b2Skarels 
1021094078b2Skarels /* ARGSUSED */
1022094078b2Skarels kdbiodone(mi, bp, info)
1023094078b2Skarels 	struct mscp_info *mi;
1024094078b2Skarels 	struct buf *bp;
1025094078b2Skarels 	int info;
1026094078b2Skarels {
1027094078b2Skarels 	register struct kdbinfo *ki = &kdbinfo[mi->mi_ctlr];
1028094078b2Skarels 
1029094078b2Skarels 	KDBFREE(ki, info);
1030094078b2Skarels 	biodone(bp);
1031094078b2Skarels 	ki->ki_tab.b_active--;	/* another one done */
1032094078b2Skarels }
1033094078b2Skarels 
1034094078b2Skarels /*
1035094078b2Skarels  * The error bit was set in the controller status register.  Gripe,
1036094078b2Skarels  * reset the controller, requeue pending transfers.
1037094078b2Skarels  */
kdbsaerror(ki)1038094078b2Skarels kdbsaerror(ki)
1039094078b2Skarels 	register struct kdbinfo *ki;
1040094078b2Skarels {
1041094078b2Skarels 
1042094078b2Skarels 	printf("kdb%d: controller error, sa=%b\n", ki->ki_ctlr,
1043094078b2Skarels 		ki->ki_kdb->kdb_sa, kdbsr_bits);
1044094078b2Skarels 	mscp_requeue(&ki->ki_mi);
1045094078b2Skarels 	(void) kdbinit(ki);
1046094078b2Skarels }
1047094078b2Skarels 
1048094078b2Skarels /*
1049094078b2Skarels  * Interrupt routine.  Depending on the state of the controller,
1050094078b2Skarels  * continue initialisation, or acknowledge command and response
1051094078b2Skarels  * interrupts, and process responses.
1052094078b2Skarels  */
kdbintr(ctlr)1053094078b2Skarels kdbintr(ctlr)
1054094078b2Skarels 	int ctlr;
1055094078b2Skarels {
1056094078b2Skarels 	register struct kdbinfo *ki = &kdbinfo[ctlr];
1057094078b2Skarels 	register struct kdb_regs *kdbaddr = ki->ki_kdb;
1058094078b2Skarels 	register struct mscp *mp;
1059094078b2Skarels 	register int i;
1060094078b2Skarels 
1061094078b2Skarels 	ki->ki_wticks = 0;	/* reset interrupt watchdog */
1062094078b2Skarels 
1063094078b2Skarels 	/*
1064094078b2Skarels 	 * Combinations during steps 1, 2, and 3: STEPnMASK
1065094078b2Skarels 	 * corresponds to which bits should be tested;
1066094078b2Skarels 	 * STEPnGOOD corresponds to the pattern that should
1067094078b2Skarels 	 * appear after the interrupt from STEPn initialisation.
1068094078b2Skarels 	 * All steps test the bits in ALLSTEPS.
1069094078b2Skarels 	 */
1070094078b2Skarels #define	ALLSTEPS	(KDB_ERR|KDB_STEP4|KDB_STEP3|KDB_STEP2|KDB_STEP1)
1071094078b2Skarels 
1072094078b2Skarels #define	STEP1MASK	(ALLSTEPS | KDB_IE | KDB_NCNRMASK)
1073094078b2Skarels #define	STEP1GOOD	(KDB_STEP2 | KDB_IE | (NCMDL2 << 3) | NRSPL2)
1074094078b2Skarels 
1075094078b2Skarels #define	STEP2MASK	(ALLSTEPS | KDB_IE | KDB_IVECMASK)
1076094078b2Skarels #define	STEP2GOOD	(KDB_STEP3 | KDB_IE | (ki->ki_vec >> 2))
1077094078b2Skarels 
1078094078b2Skarels #define	STEP3MASK	ALLSTEPS
1079094078b2Skarels #define	STEP3GOOD	KDB_STEP4
1080094078b2Skarels 
1081094078b2Skarels 	switch (ki->ki_state) {
1082094078b2Skarels 
1083094078b2Skarels 	case ST_IDLE:
1084094078b2Skarels 		/*
1085094078b2Skarels 		 * Ignore unsolicited interrupts.
1086094078b2Skarels 		 */
1087094078b2Skarels 		log(LOG_WARNING, "kdb%d: stray intr\n", ctlr);
1088094078b2Skarels 		return;
1089094078b2Skarels 
1090094078b2Skarels 	case ST_STEP1:
1091094078b2Skarels 		/*
1092094078b2Skarels 		 * Begin step two initialisation.
1093094078b2Skarels 		 */
1094094078b2Skarels 		if ((kdbaddr->kdb_sa & STEP1MASK) != STEP1GOOD) {
1095094078b2Skarels 			i = 1;
1096094078b2Skarels initfailed:
1097094078b2Skarels 			printf("kdb%d: init step %d failed, sa=%b\n",
1098094078b2Skarels 				ctlr, i, kdbaddr->kdb_sa, kdbsr_bits);
1099094078b2Skarels 			ki->ki_state = ST_IDLE;
1100094078b2Skarels 			if (ki->ki_flags & KDB_DOWAKE) {
1101094078b2Skarels 				ki->ki_flags &= ~KDB_DOWAKE;
1102094078b2Skarels 				wakeup((caddr_t)&ki->ki_flags);
1103094078b2Skarels 			}
1104094078b2Skarels 			return;
1105094078b2Skarels 		}
1106094078b2Skarels 		kdbaddr->kdb_sw = PHYS(int, &ki->ki_ca.ca_rspdsc[0]);
1107094078b2Skarels 		ki->ki_state = ST_STEP2;
1108094078b2Skarels 		return;
1109094078b2Skarels 
1110094078b2Skarels 	case ST_STEP2:
1111094078b2Skarels 		/*
1112094078b2Skarels 		 * Begin step 3 initialisation.
1113094078b2Skarels 		 */
1114094078b2Skarels 		if ((kdbaddr->kdb_sa & STEP2MASK) != STEP2GOOD) {
1115094078b2Skarels 			i = 2;
1116094078b2Skarels 			goto initfailed;
1117094078b2Skarels 		}
1118094078b2Skarels 		kdbaddr->kdb_sw = PHYS(int, &ki->ki_ca.ca_rspdsc[0]) >> 16;
1119094078b2Skarels 		ki->ki_state = ST_STEP3;
1120094078b2Skarels 		return;
1121094078b2Skarels 
1122094078b2Skarels 	case ST_STEP3:
1123094078b2Skarels 		/*
1124094078b2Skarels 		 * Set controller characteristics (finish initialisation).
1125094078b2Skarels 		 */
1126094078b2Skarels 		if ((kdbaddr->kdb_sa & STEP3MASK) != STEP3GOOD) {
1127094078b2Skarels 			i = 3;
1128094078b2Skarels 			goto initfailed;
1129094078b2Skarels 		}
1130094078b2Skarels 		i = kdbaddr->kdb_sa & 0xff;
1131094078b2Skarels 		if (i != ki->ki_micro) {
1132094078b2Skarels 			ki->ki_micro = i;
1133094078b2Skarels 			printf("kdb%d: version %d model %d\n",
1134094078b2Skarels 				ctlr, i & 0xf, i >> 4);
1135094078b2Skarels 		}
1136094078b2Skarels 
1137094078b2Skarels 		kdbaddr->kdb_sw = KDB_GO;
1138094078b2Skarels 
1139094078b2Skarels 		/* initialise hardware data structures */
1140094078b2Skarels 		for (i = 0, mp = ki->ki_rsp; i < NRSP; i++, mp++) {
1141094078b2Skarels 			ki->ki_ca.ca_rspdsc[i] = MSCP_OWN | MSCP_INT |
1142094078b2Skarels 				PHYS(long, &ki->ki_rsp[i].mscp_cmdref);
1143094078b2Skarels 			mp->mscp_addr = &ki->ki_ca.ca_rspdsc[i];
1144094078b2Skarels 			mp->mscp_msglen = MSCP_MSGLEN;
1145094078b2Skarels 		}
1146094078b2Skarels 		for (i = 0, mp = ki->ki_cmd; i < NCMD; i++, mp++) {
1147094078b2Skarels 			ki->ki_ca.ca_cmddsc[i] = MSCP_INT |
1148094078b2Skarels 				PHYS(long, &ki->ki_cmd[i].mscp_cmdref);
1149094078b2Skarels 			mp->mscp_addr = &ki->ki_ca.ca_cmddsc[i];
1150094078b2Skarels 			mp->mscp_msglen = MSCP_MSGLEN;
1151094078b2Skarels 		}
1152094078b2Skarels 
1153094078b2Skarels 		/*
1154094078b2Skarels 		 * Before we can get a command packet, we need some
1155094078b2Skarels 		 * credits.  Fake some up to keep mscp_getcp() happy,
1156094078b2Skarels 		 * get a packet, and cancel all credits (the right
1157094078b2Skarels 		 * number should come back in the response to the
1158094078b2Skarels 		 * SCC packet).
1159094078b2Skarels 		 */
1160094078b2Skarels 		ki->ki_mi.mi_credits = MSCP_MINCREDITS + 1;
1161094078b2Skarels 		mp = mscp_getcp(&ki->ki_mi, MSCP_DONTWAIT);
1162094078b2Skarels 		if (mp == NULL)	/* `cannot happen' */
1163094078b2Skarels 			panic("kdbintr");
1164094078b2Skarels 		ki->ki_mi.mi_credits = 0;
1165094078b2Skarels 		mp->mscp_opcode = M_OP_SETCTLRC;
1166094078b2Skarels 		mp->mscp_unit = 0;
1167094078b2Skarels 		mp->mscp_sccc.sccc_ctlrflags = M_CF_ATTN | M_CF_MISC |
1168094078b2Skarels 			M_CF_THIS;
1169094078b2Skarels 		*mp->mscp_addr |= MSCP_OWN | MSCP_INT;
1170094078b2Skarels 		i = kdbaddr->kdb_ip;
1171094078b2Skarels 		ki->ki_state = ST_SETCHAR;
1172094078b2Skarels 		return;
1173094078b2Skarels 
1174094078b2Skarels 	case ST_SETCHAR:
1175094078b2Skarels 	case ST_RUN:
1176094078b2Skarels 		/*
1177094078b2Skarels 		 * Handle Set Ctlr Characteristics responses and operational
1178094078b2Skarels 		 * responses (via mscp_dorsp).
1179094078b2Skarels 		 */
1180094078b2Skarels 		break;
1181094078b2Skarels 
1182094078b2Skarels 	default:
1183094078b2Skarels 		log(LOG_ERR, "kdb%d: driver bug, state %d\n", ctlr,
1184094078b2Skarels 			ki->ki_state);
1185094078b2Skarels 		return;
1186094078b2Skarels 	}
1187094078b2Skarels 
1188094078b2Skarels 	if (kdbaddr->kdb_sa & KDB_ERR) {/* ctlr fatal error */
1189094078b2Skarels 		kdbsaerror(ki);
1190094078b2Skarels 		return;
1191094078b2Skarels 	}
1192094078b2Skarels 
1193094078b2Skarels 	/*
1194094078b2Skarels 	 * Handle buffer purge requests.
1195094078b2Skarels 	 * KDB DOES NOT HAVE BDPs
1196094078b2Skarels 	 */
1197094078b2Skarels 	if (ki->ki_ca.ca_bdp) {
1198094078b2Skarels 		printf("kdb%d: purge bdp %d\n", ctlr, ki->ki_ca.ca_bdp);
1199094078b2Skarels 		panic("kdb purge");
1200094078b2Skarels 	}
1201094078b2Skarels 
1202094078b2Skarels 	/*
1203094078b2Skarels 	 * Check for response and command ring transitions.
1204094078b2Skarels 	 */
1205094078b2Skarels 	if (ki->ki_ca.ca_rspint) {
1206094078b2Skarels 		ki->ki_ca.ca_rspint = 0;
1207094078b2Skarels 		mscp_dorsp(&ki->ki_mi);
1208094078b2Skarels 	}
1209094078b2Skarels 	if (ki->ki_ca.ca_cmdint) {
1210094078b2Skarels 		ki->ki_ca.ca_cmdint = 0;
1211094078b2Skarels 		MSCP_DOCMD(&ki->ki_mi);
1212094078b2Skarels 	}
1213094078b2Skarels 	if (ki->ki_tab.b_actf != NULL)
1214094078b2Skarels 		kdbstart(ki);
1215094078b2Skarels }
1216094078b2Skarels 
1217094078b2Skarels /*
1218094078b2Skarels  * Handle an error datagram.  All we do now is decode it.
1219094078b2Skarels  */
1220094078b2Skarels kdbdgram(mi, mp)
1221094078b2Skarels 	struct mscp_info *mi;
1222094078b2Skarels 	struct mscp *mp;
1223094078b2Skarels {
1224094078b2Skarels 
1225094078b2Skarels 	mscp_decodeerror(mi->mi_md->md_mname, mi->mi_ctlr, mp);
1226094078b2Skarels }
1227094078b2Skarels 
1228094078b2Skarels /*
1229094078b2Skarels  * The Set Controller Characteristics command finished.
1230094078b2Skarels  * Record the new state of the controller.
1231094078b2Skarels  */
1232094078b2Skarels kdbctlrdone(mi, mp)
1233094078b2Skarels 	struct mscp_info *mi;
1234094078b2Skarels 	struct mscp *mp;
1235094078b2Skarels {
1236094078b2Skarels 	register struct kdbinfo *ki = &kdbinfo[mi->mi_ctlr];
1237094078b2Skarels 
1238094078b2Skarels 	if ((mp->mscp_status & M_ST_MASK) == M_ST_SUCCESS)
1239094078b2Skarels 		ki->ki_state = ST_RUN;
1240094078b2Skarels 	else {
1241094078b2Skarels 		printf("kdb%d: SETCTLRC failed, status 0x%x\n",
1242094078b2Skarels 			ki->ki_ctlr, mp->mscp_status);
1243094078b2Skarels 		ki->ki_state = ST_IDLE;
1244094078b2Skarels 	}
1245094078b2Skarels 	if (ki->ki_flags & KDB_DOWAKE) {
1246094078b2Skarels 		ki->ki_flags &= ~KDB_DOWAKE;
1247094078b2Skarels 		wakeup((caddr_t)&ki->ki_flags);
1248094078b2Skarels 	}
1249094078b2Skarels }
1250094078b2Skarels 
1251094078b2Skarels /*
1252094078b2Skarels  * Received a response from an as-yet unconfigured drive.  Configure it
1253094078b2Skarels  * in, if possible.
1254094078b2Skarels  */
1255094078b2Skarels kdbunconf(mi, mp)
1256094078b2Skarels 	struct mscp_info *mi;
1257094078b2Skarels 	register struct mscp *mp;
1258094078b2Skarels {
1259094078b2Skarels 
1260094078b2Skarels 	/*
1261094078b2Skarels 	 * If it is a slave response, copy it to kdbslavereply for
1262094078b2Skarels 	 * kdbslave() to look at.
1263094078b2Skarels 	 */
1264094078b2Skarels 	if (mp->mscp_opcode == (M_OP_GETUNITST | M_OP_END) &&
1265094078b2Skarels 	    (kdbinfo[mi->mi_ctlr].ki_flags & KDB_INSLAVE) != 0) {
1266094078b2Skarels 		kdbslavereply = *mp;
1267094078b2Skarels 		return (MSCP_DONE);
1268094078b2Skarels 	}
1269094078b2Skarels 
1270094078b2Skarels 	/*
1271094078b2Skarels 	 * Otherwise, it had better be an available attention response.
1272094078b2Skarels 	 */
1273094078b2Skarels 	if (mp->mscp_opcode != M_OP_AVAILATTN)
1274094078b2Skarels 		return (MSCP_FAILED);
1275094078b2Skarels 
1276094078b2Skarels 	/* do what autoconf does */
1277094078b2Skarels 	return (MSCP_FAILED);	/* not yet */
1278094078b2Skarels }
1279094078b2Skarels 
1280094078b2Skarels /*
1281094078b2Skarels  * A drive came on line.  Check its type and size.  Return DONE if
1282094078b2Skarels  * we think the drive is truly on line.  In any case, awaken anyone
1283094078b2Skarels  * sleeping on the drive on-line-ness.
1284094078b2Skarels  */
kdbonline(ui,mp)1285094078b2Skarels kdbonline(ui, mp)
1286094078b2Skarels 	register struct uba_device *ui;
1287094078b2Skarels 	struct mscp *mp;
1288094078b2Skarels {
1289094078b2Skarels 	register int type;
1290094078b2Skarels 
1291094078b2Skarels 	wakeup((caddr_t)&ui->ui_flags);
1292094078b2Skarels 	if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
1293094078b2Skarels 		printf("kdb%d: attempt to bring %s%d on line failed:",
1294094078b2Skarels 			ui->ui_ctlr, kdbdriver.ud_dname, ui->ui_unit);
1295094078b2Skarels 		mscp_printevent(mp);
1296094078b2Skarels 		return (MSCP_FAILED);
1297094078b2Skarels 	}
1298094078b2Skarels 
1299094078b2Skarels 	type = mp->mscp_onle.onle_drivetype;
1300094078b2Skarels 	if (type >= NTYPES || kdbtypes[type].ut_name == 0) {
1301094078b2Skarels 		printf("kdb%d: %s%d: unknown type %d\n",
1302094078b2Skarels 			ui->ui_ctlr, kdbdriver.ud_dname, ui->ui_unit, type);
1303094078b2Skarels 		return (MSCP_FAILED);
1304094078b2Skarels 	}
1305094078b2Skarels 	/*
1306094078b2Skarels 	 * Note any change of types.  Not sure if we should do
1307094078b2Skarels 	 * something special about them, or if so, what....
1308094078b2Skarels 	 */
1309094078b2Skarels 	if (type != ui->ui_type) {
1310094078b2Skarels 		printf("%s%d: changed types! was %s\n",
1311094078b2Skarels 			kdbdriver.ud_dname, ui->ui_unit,
1312094078b2Skarels 			kdbtypes[ui->ui_type].ut_name);
1313094078b2Skarels 		ui->ui_type = type;
1314094078b2Skarels 	}
1315094078b2Skarels 	ra_dsize[ui->ui_unit] = (daddr_t) mp->mscp_onle.onle_unitsize;
1316094078b2Skarels 	printf("%s%d: %s, size = %d sectors\n",
1317094078b2Skarels 		kdbdriver.ud_dname, ui->ui_unit,
1318094078b2Skarels 		kdbtypes[type].ut_name, ra_dsize[ui->ui_unit]);
1319094078b2Skarels 	return (MSCP_DONE);
1320094078b2Skarels }
1321094078b2Skarels 
1322094078b2Skarels /*
1323094078b2Skarels  * We got some (configured) unit's status.  Return DONE if it succeeded.
1324094078b2Skarels  */
kdbgotstatus(ui,mp)1325094078b2Skarels kdbgotstatus(ui, mp)
1326094078b2Skarels 	register struct uba_device *ui;
1327094078b2Skarels 	register struct mscp *mp;
1328094078b2Skarels {
1329094078b2Skarels 
1330094078b2Skarels 	if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
1331094078b2Skarels 		printf("kdb%d: attempt to get status for %s%d failed:",
1332094078b2Skarels 			ui->ui_ctlr, kdbdriver.ud_dname, ui->ui_unit);
1333094078b2Skarels 		mscp_printevent(mp);
1334094078b2Skarels 		return (MSCP_FAILED);
1335094078b2Skarels 	}
1336094078b2Skarels 	/* need to record later for bad block forwarding - for now, print */
1337094078b2Skarels 	printf("\
1338094078b2Skarels %s%d: unit %d, nspt %d, group %d, ngpc %d, rctsize %d, nrpt %d, nrct %d\n",
1339094078b2Skarels 		kdbdriver.ud_dname, ui->ui_unit, mp->mscp_unit,
1340094078b2Skarels 		mp->mscp_guse.guse_nspt, mp->mscp_guse.guse_group,
1341094078b2Skarels 		mp->mscp_guse.guse_ngpc, mp->mscp_guse.guse_rctsize,
1342094078b2Skarels 		mp->mscp_guse.guse_nrpt, mp->mscp_guse.guse_nrct);
1343094078b2Skarels 	return (MSCP_DONE);
1344094078b2Skarels }
1345094078b2Skarels 
1346094078b2Skarels /*
1347094078b2Skarels  * A transfer failed.  We get a chance to fix or restart it.
1348094078b2Skarels  * Need to write the bad block forwaring code first....
1349094078b2Skarels  */
1350094078b2Skarels /*ARGSUSED*/
kdbioerror(ui,mp,bp)1351094078b2Skarels kdbioerror(ui, mp, bp)
1352094078b2Skarels 	register struct uba_device *ui;
1353094078b2Skarels 	register struct mscp *mp;
1354094078b2Skarels 	struct buf *bp;
1355094078b2Skarels {
1356094078b2Skarels 
1357094078b2Skarels 	if (mp->mscp_flags & M_EF_BBLKR) {
1358094078b2Skarels 		/*
1359094078b2Skarels 		 * A bad block report.  Eventually we will
1360094078b2Skarels 		 * restart this transfer, but for now, just
1361094078b2Skarels 		 * log it and give up.
1362094078b2Skarels 		 */
1363094078b2Skarels 		log(LOG_ERR, "%s%d: bad block report: %d%s\n",
1364094078b2Skarels 			kdbdriver.ud_dname, ui->ui_unit, mp->mscp_seq.seq_lbn,
1365094078b2Skarels 			mp->mscp_flags & M_EF_BBLKU ? " + others" : "");
1366094078b2Skarels 	} else {
1367094078b2Skarels 		/*
1368094078b2Skarels 		 * What the heck IS a `serious exception' anyway?
1369094078b2Skarels 		 */
1370094078b2Skarels 		if (mp->mscp_flags & M_EF_SEREX)
1371094078b2Skarels 			log(LOG_ERR, "%s%d: serious exception reported\n",
1372094078b2Skarels 				kdbdriver.ud_dname, ui->ui_unit);
1373094078b2Skarels 	}
1374094078b2Skarels 	return (MSCP_FAILED);
1375094078b2Skarels }
1376094078b2Skarels 
1377094078b2Skarels 
1378094078b2Skarels #ifdef notyet
1379094078b2Skarels /*
1380094078b2Skarels  * I/O controls.  Not yet!
1381094078b2Skarels  */
kdbioctl(dev,cmd,flag,data)1382094078b2Skarels kdbioctl(dev, cmd, flag, data)
1383094078b2Skarels 	dev_t dev;
1384094078b2Skarels 	int cmd, flag;
1385094078b2Skarels 	caddr_t data;
1386094078b2Skarels {
1387094078b2Skarels 	int error = 0;
1388094078b2Skarels 	register int unit = kdbunit(dev);
1389094078b2Skarels 
1390094078b2Skarels 	if (unit >= NKRA || uddinfo[unit] == NULL)
1391094078b2Skarels 		return (ENXIO);
1392094078b2Skarels 
1393094078b2Skarels 	switch (cmd) {
1394094078b2Skarels 
1395094078b2Skarels 	case KDBIOCREPLACE:
1396094078b2Skarels 		/*
1397094078b2Skarels 		 * Initiate bad block replacement for the given LBN.
1398094078b2Skarels 		 * (Should we allow modifiers?)
1399094078b2Skarels 		 */
1400094078b2Skarels 		error = EOPNOTSUPP;
1401094078b2Skarels 		break;
1402094078b2Skarels 
1403094078b2Skarels 	case KDBIOCGMICRO:
1404094078b2Skarels 		/*
1405094078b2Skarels 		 * Return the microcode revision for the KDB50 running
1406094078b2Skarels 		 * this drive.
1407094078b2Skarels 		 */
1408094078b2Skarels 		*(int *)data = kdbinfo[kdbdinfo[unit]->ui_ctlr].ki_micro;
1409094078b2Skarels 		break;
1410094078b2Skarels 
1411094078b2Skarels 	case KDBIOCGSIZE:
1412094078b2Skarels 		/*
1413094078b2Skarels 		 * Return the size (in 512 byte blocks) of this
1414094078b2Skarels 		 * disk drive.
1415094078b2Skarels 		 */
1416094078b2Skarels 		*(daddr_t *)data = ra_dsize[unit];
1417094078b2Skarels 		break;
1418094078b2Skarels 
1419094078b2Skarels 	default:
1420094078b2Skarels 		error = EINVAL;
1421094078b2Skarels 		break;
1422094078b2Skarels 	}
1423094078b2Skarels 	return (error);
1424094078b2Skarels }
1425094078b2Skarels #endif
1426094078b2Skarels 
1427094078b2Skarels #ifdef notyet
1428094078b2Skarels /*
1429094078b2Skarels  * Reset a KDB50 (self test and all).
1430094078b2Skarels  * What if it fails?
1431094078b2Skarels  */
kdbreset(ki)1432094078b2Skarels kdbreset(ki)
1433094078b2Skarels 	register struct kdbinfo *ki;
1434094078b2Skarels {
1435094078b2Skarels 
1436094078b2Skarels 	printf("reset kdb%d", ki->ki_ctlr);
1437094078b2Skarels 	bi_selftest(&ki->ki_kdb.kdb_bi);
1438094078b2Skarels 	ki->ki_state = ST_IDLE;
1439094078b2Skarels 	rminit(ki->ki_map, (long)KI_PTES, (long)1, "kdb", KI_MAPSIZ);
1440094078b2Skarels 	mscp_requeue(&ki->ki_mi);
1441094078b2Skarels 	if (kdbinit(ctlr))
1442094078b2Skarels 		printf(" (hung)");
1443094078b2Skarels 	printf("\n");
1444094078b2Skarels }
1445094078b2Skarels #endif
1446094078b2Skarels 
1447094078b2Skarels /*
1448094078b2Skarels  * Watchdog timer:  If the controller is active, and no interrupts
1449094078b2Skarels  * have occurred for 30 seconds, assume it has gone away.
1450094078b2Skarels  */
kdbwatch()1451094078b2Skarels kdbwatch()
1452094078b2Skarels {
1453094078b2Skarels 	register struct kdbinfo *ki;
1454094078b2Skarels 	register int i;
1455094078b2Skarels 
1456094078b2Skarels 	timeout(kdbwatch, (caddr_t)0, hz);	/* every second */
1457094078b2Skarels 	for (i = 0, ki = kdbinfo; i < NKDB; i++, ki++) {
1458094078b2Skarels 		if ((ki->ki_flags & KDB_ALIVE) == 0)
1459094078b2Skarels 			continue;
1460094078b2Skarels 		if (ki->ki_state == ST_IDLE)
1461094078b2Skarels 			continue;
1462094078b2Skarels 		if (ki->ki_state == ST_RUN && !ki->ki_tab.b_active)
1463094078b2Skarels 			ki->ki_wticks = 0;
1464094078b2Skarels 		else if (++ki->ki_wticks >= 30) {
1465094078b2Skarels 			ki->ki_wticks = 0;
1466094078b2Skarels 			printf("kdb%d: lost interrupt\n", i);
1467094078b2Skarels 			/* kdbreset(ki); */
1468094078b2Skarels 			panic("kdb lost interrupt");
1469094078b2Skarels 		}
1470094078b2Skarels 	}
1471094078b2Skarels }
1472094078b2Skarels 
1473094078b2Skarels /*
1474094078b2Skarels  * Do a panic dump.
1475094078b2Skarels  */
1476094078b2Skarels #define	DBSIZE	32		/* dump 16K at a time */
1477094078b2Skarels 
1478094078b2Skarels struct kdbdumpspace {
1479094078b2Skarels 	struct	kdb1ca kd_ca;
1480094078b2Skarels 	struct	mscp kd_rsp;
1481094078b2Skarels 	struct	mscp kd_cmd;
1482094078b2Skarels } kdbdumpspace;
1483094078b2Skarels 
kdbdump(dev)1484094078b2Skarels kdbdump(dev)
1485094078b2Skarels 	dev_t dev;
1486094078b2Skarels {
1487094078b2Skarels 	register struct kdbdumpspace *kd;
1488094078b2Skarels 	register struct kdb_regs *k;
1489094078b2Skarels 	register int i;
1490094078b2Skarels 	struct uba_device *ui;
1491094078b2Skarels 	char *start;
1492094078b2Skarels 	int num, blk, unit, maxsz, blkoff;
1493094078b2Skarels 
1494094078b2Skarels 	/*
1495094078b2Skarels 	 * Make sure the device is a reasonable place on which to dump.
1496094078b2Skarels 	 */
1497094078b2Skarels 	unit = kdbunit(dev);
1498094078b2Skarels 	if (unit >= NKRA)
1499094078b2Skarels 		return (ENXIO);
1500094078b2Skarels 	ui = PHYS(struct uba_device *, kdbdinfo[unit]);
1501094078b2Skarels 	if (ui == NULL || ui->ui_alive == 0)
1502094078b2Skarels 		return (ENXIO);
1503094078b2Skarels 
1504094078b2Skarels 	/*
1505094078b2Skarels 	 * Find and initialise the KDB; get the physical address of the
1506094078b2Skarels 	 * device registers, and of communications area and command and
1507094078b2Skarels 	 * response packet.
1508094078b2Skarels 	 */
1509094078b2Skarels 	k = PHYS(struct kdbinfo *, &kdbinfo[ui->ui_ctlr])->ki_physkdb;
1510094078b2Skarels 	kd = PHYS(struct kdbdumpspace *, &kdbdumpspace);
1511094078b2Skarels 
1512094078b2Skarels 	/*
1513094078b2Skarels 	 * Initialise the controller, with one command and one response
1514094078b2Skarels 	 * packet.
1515094078b2Skarels 	 */
1516094078b2Skarels 	bi_reset(&k->kdb_bi);
1517094078b2Skarels 	if (kdbdumpwait(k, KDB_STEP1))
1518094078b2Skarels 		return (EFAULT);
1519094078b2Skarels 	k->kdb_sw = KDB_ERR;
1520094078b2Skarels 	if (kdbdumpwait(k, KDB_STEP2))
1521094078b2Skarels 		return (EFAULT);
1522094078b2Skarels 	k->kdb_sw = (int)&kd->kd_ca.ca_rspdsc;
1523094078b2Skarels 	if (kdbdumpwait(k, KDB_STEP3))
1524094078b2Skarels 		return (EFAULT);
1525094078b2Skarels 	k->kdb_sw = ((int)&kd->kd_ca.ca_rspdsc) >> 16;
1526094078b2Skarels 	if (kdbdumpwait(k, KDB_STEP4))
1527094078b2Skarels 		return (EFAULT);
1528094078b2Skarels 	k->kdb_sw = KDB_GO;
1529094078b2Skarels 
1530094078b2Skarels 	/*
1531094078b2Skarels 	 * Set up the command and response descriptor, then set the
1532094078b2Skarels 	 * controller characteristics and bring the drive on line.
1533094078b2Skarels 	 * Note that all uninitialised locations in kd_cmd are zero.
1534094078b2Skarels 	 */
1535094078b2Skarels 	kd->kd_ca.ca_rspdsc = (long)&kd->kd_rsp.mscp_cmdref;
1536094078b2Skarels 	kd->kd_ca.ca_cmddsc = (long)&kd->kd_cmd.mscp_cmdref;
1537094078b2Skarels 	/* kd->kd_cmd.mscp_sccc.sccc_ctlrflags = 0; */
1538094078b2Skarels 	/* kd->kd_cmd.mscp_sccc.sccc_version = 0; */
1539094078b2Skarels 	if (kdbdumpcmd(M_OP_SETCTLRC, k, kd, ui->ui_ctlr))
1540094078b2Skarels 		return (EFAULT);
1541094078b2Skarels 	kd->kd_cmd.mscp_unit = ui->ui_slave;
1542094078b2Skarels 	if (kdbdumpcmd(M_OP_ONLINE, k, kd, ui->ui_ctlr))
1543094078b2Skarels 		return (EFAULT);
1544094078b2Skarels 
1545094078b2Skarels 	/*
1546094078b2Skarels 	 * Pick up the drive type from the on line end packet;
1547094078b2Skarels 	 * convert that to a dump area size and a disk offset.
1548094078b2Skarels 	 * Note that the assembler uses pc-relative addressing
1549094078b2Skarels 	 * to get at kdbtypes[], no need for PHYS().
1550094078b2Skarels 	 */
1551094078b2Skarels 	i = kd->kd_rsp.mscp_onle.onle_drivetype;
1552094078b2Skarels 	if (i >= NTYPES || kdbtypes[i].ut_name == 0) {
1553094078b2Skarels 		printf("disk type %d unknown\ndump ");
1554094078b2Skarels 		return (EINVAL);
1555094078b2Skarels 	}
1556094078b2Skarels 	printf("on %s ", kdbtypes[i].ut_name);
1557094078b2Skarels 
1558094078b2Skarels 	maxsz = kdbtypes[i].ut_sizes[kdbpart(dev)].nblocks;
1559094078b2Skarels 	blkoff = kdbtypes[i].ut_sizes[kdbpart(dev)].blkoff;
1560094078b2Skarels 
1561094078b2Skarels 	/*
1562094078b2Skarels 	 * Dump all of physical memory, or as much as will fit in the
1563094078b2Skarels 	 * space provided.
1564094078b2Skarels 	 */
1565094078b2Skarels 	start = 0;
1566094078b2Skarels 	num = maxfree;
1567094078b2Skarels 	if (dumplo < 0)
1568094078b2Skarels 		return (EINVAL);
1569094078b2Skarels 	if (dumplo + num >= maxsz)
1570094078b2Skarels 		num = maxsz - dumplo;
1571094078b2Skarels 	blkoff += dumplo;
1572094078b2Skarels 
1573094078b2Skarels 	/*
1574094078b2Skarels 	 * Write out memory, DBSIZE pages at a time.
1575094078b2Skarels 	 * N.B.: this code depends on the fact that the sector
1576094078b2Skarels 	 * size == the page size.
1577094078b2Skarels 	 */
1578094078b2Skarels 	while (num > 0) {
1579094078b2Skarels 		blk = num > DBSIZE ? DBSIZE : num;
1580094078b2Skarels 		kd->kd_cmd.mscp_unit = ui->ui_slave;
1581094078b2Skarels 		kd->kd_cmd.mscp_seq.seq_lbn = btop(start) + blkoff;
1582094078b2Skarels 		kd->kd_cmd.mscp_seq.seq_bytecount = blk << PGSHIFT;
1583094078b2Skarels 		kd->kd_cmd.mscp_seq.seq_buffer = (long)start | KDB_PHYS;
1584094078b2Skarels 		if (kdbdumpcmd(M_OP_WRITE, k, kd, ui->ui_ctlr))
1585094078b2Skarels 			return (EIO);
1586094078b2Skarels 		start += blk << PGSHIFT;
1587094078b2Skarels 		num -= blk;
1588094078b2Skarels 	}
1589094078b2Skarels 	return (0);		/* made it! */
1590094078b2Skarels }
1591094078b2Skarels 
1592094078b2Skarels /*
1593094078b2Skarels  * Wait for some of the bits in `bits' to come on.  If the error bit
1594094078b2Skarels  * comes on, or ten seconds pass without response, return true (error).
1595094078b2Skarels  */
kdbdumpwait(k,bits)1596094078b2Skarels kdbdumpwait(k, bits)
1597094078b2Skarels 	register struct kdb_regs *k;
1598094078b2Skarels 	register int bits;
1599094078b2Skarels {
1600094078b2Skarels 	register int timo = todr() + 1000;
1601094078b2Skarels 
1602094078b2Skarels 	while ((k->kdb_sa & bits) == 0) {
1603094078b2Skarels 		if (k->kdb_sa & KDB_ERR) {
1604094078b2Skarels 			printf("kdb_sa=%b\ndump ", k->kdb_sa, kdbsr_bits);
1605094078b2Skarels 			return (1);
1606094078b2Skarels 		}
1607094078b2Skarels 		if (todr() >= timo) {
1608094078b2Skarels 			printf("timeout\ndump ");
1609094078b2Skarels 			return (1);
1610094078b2Skarels 		}
1611094078b2Skarels 	}
1612094078b2Skarels 	return (0);
1613094078b2Skarels }
1614094078b2Skarels 
1615094078b2Skarels /*
1616094078b2Skarels  * Feed a command to the KDB50, wait for its response, and return
1617094078b2Skarels  * true iff something went wrong.
1618094078b2Skarels  */
kdbdumpcmd(op,k,kd,ctlr)1619094078b2Skarels kdbdumpcmd(op, k, kd, ctlr)
1620094078b2Skarels 	int op;
1621094078b2Skarels 	register struct kdb_regs *k;
1622094078b2Skarels 	register struct kdbdumpspace *kd;
1623094078b2Skarels 	int ctlr;
1624094078b2Skarels {
1625094078b2Skarels 	register int n;
1626094078b2Skarels #define mp (&kd->kd_rsp)
1627094078b2Skarels 
1628094078b2Skarels 	kd->kd_cmd.mscp_opcode = op;
1629094078b2Skarels 	kd->kd_cmd.mscp_msglen = MSCP_MSGLEN;
1630094078b2Skarels 	kd->kd_rsp.mscp_msglen = MSCP_MSGLEN;
1631094078b2Skarels 	kd->kd_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT;
1632094078b2Skarels 	kd->kd_ca.ca_cmddsc |= MSCP_OWN | MSCP_INT;
1633094078b2Skarels 	if (k->kdb_sa & KDB_ERR) {
1634094078b2Skarels 		printf("kdb_sa=%b\ndump ", k->kdb_sa, kdbsr_bits);
1635094078b2Skarels 		return (1);
1636094078b2Skarels 	}
1637094078b2Skarels 	n = k->kdb_ip;
1638094078b2Skarels 	n = todr() + 1000;
1639094078b2Skarels 	for (;;) {
1640094078b2Skarels 		if (todr() > n) {
1641094078b2Skarels 			printf("timeout\ndump ");
1642094078b2Skarels 			return (1);
1643094078b2Skarels 		}
1644094078b2Skarels 		if (kd->kd_ca.ca_cmdint)
1645094078b2Skarels 			kd->kd_ca.ca_cmdint = 0;
1646094078b2Skarels 		if (kd->kd_ca.ca_rspint == 0)
1647094078b2Skarels 			continue;
1648094078b2Skarels 		kd->kd_ca.ca_rspint = 0;
1649094078b2Skarels 		if (mp->mscp_opcode == (op | M_OP_END))
1650094078b2Skarels 			break;
1651094078b2Skarels 		printf("\n");
1652094078b2Skarels 		switch (MSCP_MSGTYPE(mp->mscp_msgtc)) {
1653094078b2Skarels 
1654094078b2Skarels 		case MSCPT_SEQ:
1655094078b2Skarels 			printf("sequential");
1656094078b2Skarels 			break;
1657094078b2Skarels 
1658094078b2Skarels 		case MSCPT_DATAGRAM:
1659094078b2Skarels 			mscp_decodeerror("kdb", ctlr, mp);
1660094078b2Skarels 			printf("datagram");
1661094078b2Skarels 			break;
1662094078b2Skarels 
1663094078b2Skarels 		case MSCPT_CREDITS:
1664094078b2Skarels 			printf("credits");
1665094078b2Skarels 			break;
1666094078b2Skarels 
1667094078b2Skarels 		case MSCPT_MAINTENANCE:
1668094078b2Skarels 			printf("maintenance");
1669094078b2Skarels 			break;
1670094078b2Skarels 
1671094078b2Skarels 		default:
1672094078b2Skarels 			printf("unknown (type 0x%x)",
1673094078b2Skarels 				MSCP_MSGTYPE(mp->mscp_msgtc));
1674094078b2Skarels 			break;
1675094078b2Skarels 		}
1676094078b2Skarels 		printf(" ignored\ndump ");
1677094078b2Skarels 		kd->kd_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT;
1678094078b2Skarels 	}
1679094078b2Skarels 	if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
1680094078b2Skarels 		printf("error: op 0x%x => 0x%x status 0x%x\ndump ", op,
1681094078b2Skarels 			mp->mscp_opcode, mp->mscp_status);
1682094078b2Skarels 		return (1);
1683094078b2Skarels 	}
1684094078b2Skarels 	return (0);
1685094078b2Skarels #undef mp
1686094078b2Skarels }
1687094078b2Skarels 
1688094078b2Skarels /*
1689094078b2Skarels  * Return the size of a partition, if known, or -1 if not.
1690094078b2Skarels  */
kdbsize(dev)1691094078b2Skarels kdbsize(dev)
1692094078b2Skarels 	dev_t dev;
1693094078b2Skarels {
1694094078b2Skarels 	register int unit = kdbunit(dev);
1695094078b2Skarels 	register struct uba_device *ui;
1696094078b2Skarels 	register struct size *st;
1697094078b2Skarels 
1698094078b2Skarels 	if (unit >= NKRA || (ui = kdbdinfo[unit]) == NULL || ui->ui_alive == 0)
1699094078b2Skarels 		return (-1);
1700094078b2Skarels 	st = &kdbtypes[ui->ui_type].ut_sizes[kdbpart(dev)];
1701094078b2Skarels 	if (st->nblocks == -1) {
1702094078b2Skarels 		int s = spl5();
1703094078b2Skarels 
1704094078b2Skarels 		/*
1705094078b2Skarels 		 * We need to have the drive on line to find the size
1706094078b2Skarels 		 * of this particular partition.
1707094078b2Skarels 		 * IS IT OKAY TO GO TO SLEEP IN THIS ROUTINE?
1708094078b2Skarels 		 * (If not, better not page on one of these...)
1709094078b2Skarels 		 */
1710094078b2Skarels 		if ((ui->ui_flags & UNIT_ONLINE) == 0) {
1711094078b2Skarels 			if (kdb_bringonline(ui, 0)) {
1712094078b2Skarels 				splx(s);
1713094078b2Skarels 				return (-1);
1714094078b2Skarels 			}
1715094078b2Skarels 		}
1716094078b2Skarels 		splx(s);
1717094078b2Skarels 		if (st->blkoff > ra_dsize[unit])
1718094078b2Skarels 			return (-1);
1719094078b2Skarels 		return (ra_dsize[unit] - st->blkoff);
1720094078b2Skarels 	}
1721094078b2Skarels 	return (st->nblocks);
1722094078b2Skarels }
1723094078b2Skarels 
1724094078b2Skarels #endif NKDB > 0
1725