xref: /freebsd/sys/geom/geom_ccd.c (revision a56bb8a5cc5eff26d3330f5dcd3533e67f82fb8f)
1a56bb8a5SSatoshi Asami /*	$NetBSD: ccd.c,v 1.22 1995/12/08 19:13:26 thorpej Exp $	*/
2a56bb8a5SSatoshi Asami 
3a56bb8a5SSatoshi Asami /*
4a56bb8a5SSatoshi Asami  * Copyright (c) 1995 Jason R. Thorpe.
5a56bb8a5SSatoshi Asami  * All rights reserved.
6a56bb8a5SSatoshi Asami  *
7a56bb8a5SSatoshi Asami  * Redistribution and use in source and binary forms, with or without
8a56bb8a5SSatoshi Asami  * modification, are permitted provided that the following conditions
9a56bb8a5SSatoshi Asami  * are met:
10a56bb8a5SSatoshi Asami  * 1. Redistributions of source code must retain the above copyright
11a56bb8a5SSatoshi Asami  *    notice, this list of conditions and the following disclaimer.
12a56bb8a5SSatoshi Asami  * 2. Redistributions in binary form must reproduce the above copyright
13a56bb8a5SSatoshi Asami  *    notice, this list of conditions and the following disclaimer in the
14a56bb8a5SSatoshi Asami  *    documentation and/or other materials provided with the distribution.
15a56bb8a5SSatoshi Asami  * 3. All advertising materials mentioning features or use of this software
16a56bb8a5SSatoshi Asami  *    must display the following acknowledgement:
17a56bb8a5SSatoshi Asami  *	This product includes software developed for the NetBSD Project
18a56bb8a5SSatoshi Asami  *	by Jason R. Thorpe.
19a56bb8a5SSatoshi Asami  * 4. The name of the author may not be used to endorse or promote products
20a56bb8a5SSatoshi Asami  *    derived from this software without specific prior written permission.
21a56bb8a5SSatoshi Asami  *
22a56bb8a5SSatoshi Asami  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23a56bb8a5SSatoshi Asami  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24a56bb8a5SSatoshi Asami  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25a56bb8a5SSatoshi Asami  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26a56bb8a5SSatoshi Asami  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27a56bb8a5SSatoshi Asami  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28a56bb8a5SSatoshi Asami  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29a56bb8a5SSatoshi Asami  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30a56bb8a5SSatoshi Asami  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31a56bb8a5SSatoshi Asami  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32a56bb8a5SSatoshi Asami  * SUCH DAMAGE.
33a56bb8a5SSatoshi Asami  */
34a56bb8a5SSatoshi Asami 
35a56bb8a5SSatoshi Asami /*
36a56bb8a5SSatoshi Asami  * Copyright (c) 1988 University of Utah.
37a56bb8a5SSatoshi Asami  * Copyright (c) 1990, 1993
38a56bb8a5SSatoshi Asami  *	The Regents of the University of California.  All rights reserved.
39a56bb8a5SSatoshi Asami  *
40a56bb8a5SSatoshi Asami  * This code is derived from software contributed to Berkeley by
41a56bb8a5SSatoshi Asami  * the Systems Programming Group of the University of Utah Computer
42a56bb8a5SSatoshi Asami  * Science Department.
43a56bb8a5SSatoshi Asami  *
44a56bb8a5SSatoshi Asami  * Redistribution and use in source and binary forms, with or without
45a56bb8a5SSatoshi Asami  * modification, are permitted provided that the following conditions
46a56bb8a5SSatoshi Asami  * are met:
47a56bb8a5SSatoshi Asami  * 1. Redistributions of source code must retain the above copyright
48a56bb8a5SSatoshi Asami  *    notice, this list of conditions and the following disclaimer.
49a56bb8a5SSatoshi Asami  * 2. Redistributions in binary form must reproduce the above copyright
50a56bb8a5SSatoshi Asami  *    notice, this list of conditions and the following disclaimer in the
51a56bb8a5SSatoshi Asami  *    documentation and/or other materials provided with the distribution.
52a56bb8a5SSatoshi Asami  * 3. All advertising materials mentioning features or use of this software
53a56bb8a5SSatoshi Asami  *    must display the following acknowledgement:
54a56bb8a5SSatoshi Asami  *	This product includes software developed by the University of
55a56bb8a5SSatoshi Asami  *	California, Berkeley and its contributors.
56a56bb8a5SSatoshi Asami  * 4. Neither the name of the University nor the names of its contributors
57a56bb8a5SSatoshi Asami  *    may be used to endorse or promote products derived from this software
58a56bb8a5SSatoshi Asami  *    without specific prior written permission.
59a56bb8a5SSatoshi Asami  *
60a56bb8a5SSatoshi Asami  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
61a56bb8a5SSatoshi Asami  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
62a56bb8a5SSatoshi Asami  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
63a56bb8a5SSatoshi Asami  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
64a56bb8a5SSatoshi Asami  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
65a56bb8a5SSatoshi Asami  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
66a56bb8a5SSatoshi Asami  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
67a56bb8a5SSatoshi Asami  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
68a56bb8a5SSatoshi Asami  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
69a56bb8a5SSatoshi Asami  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
70a56bb8a5SSatoshi Asami  * SUCH DAMAGE.
71a56bb8a5SSatoshi Asami  *
72a56bb8a5SSatoshi Asami  * from: Utah $Hdr: cd.c 1.6 90/11/28$
73a56bb8a5SSatoshi Asami  *
74a56bb8a5SSatoshi Asami  *	@(#)cd.c	8.2 (Berkeley) 11/16/93
75a56bb8a5SSatoshi Asami  */
76a56bb8a5SSatoshi Asami 
77a56bb8a5SSatoshi Asami /*
78a56bb8a5SSatoshi Asami  * "Concatenated" disk driver.
79a56bb8a5SSatoshi Asami  *
80a56bb8a5SSatoshi Asami  * Dynamic configuration and disklabel support by:
81a56bb8a5SSatoshi Asami  *	Jason R. Thorpe <thorpej@nas.nasa.gov>
82a56bb8a5SSatoshi Asami  *	Numerical Aerodynamic Simulation Facility
83a56bb8a5SSatoshi Asami  *	Mail Stop 258-6
84a56bb8a5SSatoshi Asami  *	NASA Ames Research Center
85a56bb8a5SSatoshi Asami  *	Moffett Field, CA 94035
86a56bb8a5SSatoshi Asami  */
87a56bb8a5SSatoshi Asami 
88a56bb8a5SSatoshi Asami #include <sys/param.h>
89a56bb8a5SSatoshi Asami #include <sys/systm.h>
90a56bb8a5SSatoshi Asami #include <sys/proc.h>
91a56bb8a5SSatoshi Asami #include <sys/errno.h>
92a56bb8a5SSatoshi Asami #include <sys/dkstat.h>
93a56bb8a5SSatoshi Asami #include <sys/buf.h>
94a56bb8a5SSatoshi Asami #include <sys/malloc.h>
95a56bb8a5SSatoshi Asami #include <sys/namei.h>
96a56bb8a5SSatoshi Asami #include <sys/conf.h>
97a56bb8a5SSatoshi Asami #include <sys/stat.h>
98a56bb8a5SSatoshi Asami #include <sys/ioctl.h>
99a56bb8a5SSatoshi Asami #include <sys/disklabel.h>
100a56bb8a5SSatoshi Asami #include <sys/device.h>
101a56bb8a5SSatoshi Asami #include <sys/disk.h>
102a56bb8a5SSatoshi Asami #include <sys/syslog.h>
103a56bb8a5SSatoshi Asami #include <sys/fcntl.h>
104a56bb8a5SSatoshi Asami #include <sys/vnode.h>
105a56bb8a5SSatoshi Asami 
106a56bb8a5SSatoshi Asami #include <dev/ccdvar.h>
107a56bb8a5SSatoshi Asami 
108a56bb8a5SSatoshi Asami #if defined(CCDDEBUG) && !defined(DEBUG)
109a56bb8a5SSatoshi Asami #define DEBUG
110a56bb8a5SSatoshi Asami #endif
111a56bb8a5SSatoshi Asami 
112a56bb8a5SSatoshi Asami #ifdef DEBUG
113a56bb8a5SSatoshi Asami int ccddebug = 0x00;
114a56bb8a5SSatoshi Asami #define CCDB_FOLLOW	0x01
115a56bb8a5SSatoshi Asami #define CCDB_INIT	0x02
116a56bb8a5SSatoshi Asami #define CCDB_IO		0x04
117a56bb8a5SSatoshi Asami #define CCDB_LABEL	0x08
118a56bb8a5SSatoshi Asami #define CCDB_VNODE	0x10
119a56bb8a5SSatoshi Asami #endif
120a56bb8a5SSatoshi Asami 
121a56bb8a5SSatoshi Asami #define	ccdunit(x)	DISKUNIT(x)
122a56bb8a5SSatoshi Asami 
123a56bb8a5SSatoshi Asami struct ccdbuf {
124a56bb8a5SSatoshi Asami 	struct buf	cb_buf;		/* new I/O buf */
125a56bb8a5SSatoshi Asami 	struct buf	*cb_obp;	/* ptr. to original I/O buf */
126a56bb8a5SSatoshi Asami 	int		cb_unit;	/* target unit */
127a56bb8a5SSatoshi Asami 	int		cb_comp;	/* target component */
128a56bb8a5SSatoshi Asami };
129a56bb8a5SSatoshi Asami 
130a56bb8a5SSatoshi Asami #define	getccdbuf()		\
131a56bb8a5SSatoshi Asami 	((struct ccdbuf *)malloc(sizeof(struct ccdbuf), M_DEVBUF, M_WAITOK))
132a56bb8a5SSatoshi Asami #define putccdbuf(cbp)		\
133a56bb8a5SSatoshi Asami 	free((caddr_t)(cbp), M_DEVBUF)
134a56bb8a5SSatoshi Asami 
135a56bb8a5SSatoshi Asami #define CCDLABELDEV(dev)	\
136a56bb8a5SSatoshi Asami 	(MAKEDISKDEV(major((dev)), ccdunit((dev)), RAW_PART))
137a56bb8a5SSatoshi Asami 
138a56bb8a5SSatoshi Asami /* {b,c}devsw[] function prototypes */
139a56bb8a5SSatoshi Asami dev_type_open(ccdopen);
140a56bb8a5SSatoshi Asami dev_type_close(ccdclose);
141a56bb8a5SSatoshi Asami dev_type_strategy(ccdstrategy);
142a56bb8a5SSatoshi Asami dev_type_ioctl(ccdioctl);
143a56bb8a5SSatoshi Asami dev_type_read(ccdread);
144a56bb8a5SSatoshi Asami dev_type_write(ccdwrite);
145a56bb8a5SSatoshi Asami 
146a56bb8a5SSatoshi Asami /* called by main() at boot time */
147a56bb8a5SSatoshi Asami void	ccdattach __P((int));
148a56bb8a5SSatoshi Asami 
149a56bb8a5SSatoshi Asami /* called by biodone() at interrupt time */
150a56bb8a5SSatoshi Asami void	ccdiodone __P((struct ccdbuf *cbp));
151a56bb8a5SSatoshi Asami 
152a56bb8a5SSatoshi Asami static	void ccdstart __P((struct ccd_softc *, struct buf *));
153a56bb8a5SSatoshi Asami static	void ccdinterleave __P((struct ccd_softc *, int));
154a56bb8a5SSatoshi Asami static	void ccdintr __P((struct ccd_softc *, struct buf *));
155a56bb8a5SSatoshi Asami static	int ccdinit __P((struct ccddevice *, char **, struct proc *));
156a56bb8a5SSatoshi Asami static	int ccdlookup __P((char *, struct proc *p, struct vnode **));
157a56bb8a5SSatoshi Asami static	struct ccdbuf *ccdbuffer __P((struct ccd_softc *, struct buf *,
158a56bb8a5SSatoshi Asami 		daddr_t, caddr_t, long));
159a56bb8a5SSatoshi Asami static	void ccdgetdisklabel __P((dev_t));
160a56bb8a5SSatoshi Asami static	void ccdmakedisklabel __P((struct ccd_softc *));
161a56bb8a5SSatoshi Asami static	int ccdlock __P((struct ccd_softc *));
162a56bb8a5SSatoshi Asami static	void ccdunlock __P((struct ccd_softc *));
163a56bb8a5SSatoshi Asami 
164a56bb8a5SSatoshi Asami #ifdef DEBUG
165a56bb8a5SSatoshi Asami static	void printiinfo __P((struct ccdiinfo *));
166a56bb8a5SSatoshi Asami #endif
167a56bb8a5SSatoshi Asami 
168a56bb8a5SSatoshi Asami /* Non-private for the benefit of libkvm. */
169a56bb8a5SSatoshi Asami struct	ccd_softc *ccd_softc;
170a56bb8a5SSatoshi Asami struct	ccddevice *ccddevs;
171a56bb8a5SSatoshi Asami int	numccd = 0;
172a56bb8a5SSatoshi Asami 
173a56bb8a5SSatoshi Asami /*
174a56bb8a5SSatoshi Asami  * Called by main() during pseudo-device attachment.  All we need
175a56bb8a5SSatoshi Asami  * to do is allocate enough space for devices to be configured later.
176a56bb8a5SSatoshi Asami  */
177a56bb8a5SSatoshi Asami void
178a56bb8a5SSatoshi Asami ccdattach(num)
179a56bb8a5SSatoshi Asami 	int num;
180a56bb8a5SSatoshi Asami {
181a56bb8a5SSatoshi Asami 	int i;
182a56bb8a5SSatoshi Asami 
183a56bb8a5SSatoshi Asami 	if (num <= 0) {
184a56bb8a5SSatoshi Asami #ifdef DIAGNOSTIC
185a56bb8a5SSatoshi Asami 		panic("ccdattach: count <= 0");
186a56bb8a5SSatoshi Asami #endif
187a56bb8a5SSatoshi Asami 		return;
188a56bb8a5SSatoshi Asami 	}
189a56bb8a5SSatoshi Asami 
190a56bb8a5SSatoshi Asami 	ccd_softc = (struct ccd_softc *)malloc(num * sizeof(struct ccd_softc),
191a56bb8a5SSatoshi Asami 	    M_DEVBUF, M_NOWAIT);
192a56bb8a5SSatoshi Asami 	ccddevs = (struct ccddevice *)malloc(num * sizeof(struct ccddevice),
193a56bb8a5SSatoshi Asami 	    M_DEVBUF, M_NOWAIT);
194a56bb8a5SSatoshi Asami 	if ((ccd_softc == NULL) || (ccddevs == NULL)) {
195a56bb8a5SSatoshi Asami 		printf("WARNING: no memory for concatenated disks\n");
196a56bb8a5SSatoshi Asami 		if (ccd_softc != NULL)
197a56bb8a5SSatoshi Asami 			free(ccd_softc, M_DEVBUF);
198a56bb8a5SSatoshi Asami 		if (ccddevs != NULL)
199a56bb8a5SSatoshi Asami 			free(ccddevs, M_DEVBUF);
200a56bb8a5SSatoshi Asami 		return;
201a56bb8a5SSatoshi Asami 	}
202a56bb8a5SSatoshi Asami 	numccd = num;
203a56bb8a5SSatoshi Asami 	bzero(ccd_softc, num * sizeof(struct ccd_softc));
204a56bb8a5SSatoshi Asami 	bzero(ccddevs, num * sizeof(struct ccddevice));
205a56bb8a5SSatoshi Asami 
206a56bb8a5SSatoshi Asami 	/* XXX: is this necessary? */
207a56bb8a5SSatoshi Asami 	for (i = 0; i < numccd; ++i)
208a56bb8a5SSatoshi Asami 		ccddevs[i].ccd_dk = -1;
209a56bb8a5SSatoshi Asami }
210a56bb8a5SSatoshi Asami 
211a56bb8a5SSatoshi Asami static int
212a56bb8a5SSatoshi Asami ccdinit(ccd, cpaths, p)
213a56bb8a5SSatoshi Asami 	struct ccddevice *ccd;
214a56bb8a5SSatoshi Asami 	char **cpaths;
215a56bb8a5SSatoshi Asami 	struct proc *p;
216a56bb8a5SSatoshi Asami {
217a56bb8a5SSatoshi Asami 	register struct ccd_softc *cs = &ccd_softc[ccd->ccd_unit];
218a56bb8a5SSatoshi Asami 	register struct ccdcinfo *ci;
219a56bb8a5SSatoshi Asami 	register size_t size;
220a56bb8a5SSatoshi Asami 	register int ix;
221a56bb8a5SSatoshi Asami 	struct vnode *vp;
222a56bb8a5SSatoshi Asami 	struct vattr va;
223a56bb8a5SSatoshi Asami 	size_t minsize;
224a56bb8a5SSatoshi Asami 	int maxsecsize;
225a56bb8a5SSatoshi Asami 	struct partinfo dpart;
226a56bb8a5SSatoshi Asami 	struct ccdgeom *ccg = &cs->sc_geom;
227a56bb8a5SSatoshi Asami 	char tmppath[MAXPATHLEN];
228a56bb8a5SSatoshi Asami 	int error;
229a56bb8a5SSatoshi Asami 
230a56bb8a5SSatoshi Asami #ifdef DEBUG
231a56bb8a5SSatoshi Asami 	if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
232a56bb8a5SSatoshi Asami 		printf("ccdinit: unit %d\n", ccd->ccd_unit);
233a56bb8a5SSatoshi Asami #endif
234a56bb8a5SSatoshi Asami 
235a56bb8a5SSatoshi Asami #ifdef WORKING_DISK_STATISTICS		/* XXX !! */
236a56bb8a5SSatoshi Asami 	cs->sc_dk = ccd->ccd_dk;
237a56bb8a5SSatoshi Asami #endif
238a56bb8a5SSatoshi Asami 	cs->sc_size = 0;
239a56bb8a5SSatoshi Asami 	cs->sc_ileave = ccd->ccd_interleave;
240a56bb8a5SSatoshi Asami 	cs->sc_nccdisks = ccd->ccd_ndev;
241a56bb8a5SSatoshi Asami 
242a56bb8a5SSatoshi Asami 	/* Allocate space for the component info. */
243a56bb8a5SSatoshi Asami 	cs->sc_cinfo = malloc(cs->sc_nccdisks * sizeof(struct ccdcinfo),
244a56bb8a5SSatoshi Asami 	    M_DEVBUF, M_WAITOK);
245a56bb8a5SSatoshi Asami 
246a56bb8a5SSatoshi Asami 	/*
247a56bb8a5SSatoshi Asami 	 * Verify that each component piece exists and record
248a56bb8a5SSatoshi Asami 	 * relevant information about it.
249a56bb8a5SSatoshi Asami 	 */
250a56bb8a5SSatoshi Asami 	maxsecsize = 0;
251a56bb8a5SSatoshi Asami 	minsize = 0;
252a56bb8a5SSatoshi Asami 	for (ix = 0; ix < cs->sc_nccdisks; ix++) {
253a56bb8a5SSatoshi Asami 		vp = ccd->ccd_vpp[ix];
254a56bb8a5SSatoshi Asami 		ci = &cs->sc_cinfo[ix];
255a56bb8a5SSatoshi Asami 		ci->ci_vp = vp;
256a56bb8a5SSatoshi Asami 
257a56bb8a5SSatoshi Asami 		/*
258a56bb8a5SSatoshi Asami 		 * Copy in the pathname of the component.
259a56bb8a5SSatoshi Asami 		 */
260a56bb8a5SSatoshi Asami 		bzero(tmppath, sizeof(tmppath));	/* sanity */
261a56bb8a5SSatoshi Asami 		if (error = copyinstr(cpaths[ix], tmppath,
262a56bb8a5SSatoshi Asami 		    MAXPATHLEN, &ci->ci_pathlen)) {
263a56bb8a5SSatoshi Asami #ifdef DEBUG
264a56bb8a5SSatoshi Asami 			if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
265a56bb8a5SSatoshi Asami 				printf("ccd%d: can't copy path, error = %d\n",
266a56bb8a5SSatoshi Asami 				    ccd->ccd_unit, error);
267a56bb8a5SSatoshi Asami #endif
268a56bb8a5SSatoshi Asami 			free(cs->sc_cinfo, M_DEVBUF);
269a56bb8a5SSatoshi Asami 			return (error);
270a56bb8a5SSatoshi Asami 		}
271a56bb8a5SSatoshi Asami 		ci->ci_path = malloc(ci->ci_pathlen, M_DEVBUF, M_WAITOK);
272a56bb8a5SSatoshi Asami 		bcopy(tmppath, ci->ci_path, ci->ci_pathlen);
273a56bb8a5SSatoshi Asami 
274a56bb8a5SSatoshi Asami 		/*
275a56bb8a5SSatoshi Asami 		 * XXX: Cache the component's dev_t.
276a56bb8a5SSatoshi Asami 		 */
277a56bb8a5SSatoshi Asami 		if (error = VOP_GETATTR(vp, &va, p->p_ucred, p)) {
278a56bb8a5SSatoshi Asami #ifdef DEBUG
279a56bb8a5SSatoshi Asami 			if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
280a56bb8a5SSatoshi Asami 				printf("ccd%d: %s: getattr failed %s = %d\n",
281a56bb8a5SSatoshi Asami 				    ccd->ccd_unit, ci->ci_path,
282a56bb8a5SSatoshi Asami 				    "error", error);
283a56bb8a5SSatoshi Asami #endif
284a56bb8a5SSatoshi Asami 			free(ci->ci_path, M_DEVBUF);
285a56bb8a5SSatoshi Asami 			free(cs->sc_cinfo, M_DEVBUF);
286a56bb8a5SSatoshi Asami 			return (error);
287a56bb8a5SSatoshi Asami 		}
288a56bb8a5SSatoshi Asami 		ci->ci_dev = va.va_rdev;
289a56bb8a5SSatoshi Asami 
290a56bb8a5SSatoshi Asami 		/*
291a56bb8a5SSatoshi Asami 		 * Get partition information for the component.
292a56bb8a5SSatoshi Asami 		 */
293a56bb8a5SSatoshi Asami 		if (error = VOP_IOCTL(vp, DIOCGPART, (caddr_t)&dpart,
294a56bb8a5SSatoshi Asami 		    FREAD, p->p_ucred, p)) {
295a56bb8a5SSatoshi Asami #ifdef DEBUG
296a56bb8a5SSatoshi Asami 			if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
297a56bb8a5SSatoshi Asami 				 printf("ccd%d: %s: ioctl failed, error = %d\n",
298a56bb8a5SSatoshi Asami 				     ccd->ccd_unit, ci->ci_path, error);
299a56bb8a5SSatoshi Asami #endif
300a56bb8a5SSatoshi Asami 			free(ci->ci_path, M_DEVBUF);
301a56bb8a5SSatoshi Asami 			free(cs->sc_cinfo, M_DEVBUF);
302a56bb8a5SSatoshi Asami 			return (error);
303a56bb8a5SSatoshi Asami 		}
304a56bb8a5SSatoshi Asami 		if (dpart.part->p_fstype == FS_BSDFFS) {
305a56bb8a5SSatoshi Asami 			maxsecsize =
306a56bb8a5SSatoshi Asami 			    ((dpart.disklab->d_secsize > maxsecsize) ?
307a56bb8a5SSatoshi Asami 			    dpart.disklab->d_secsize : maxsecsize);
308a56bb8a5SSatoshi Asami 			size = dpart.part->p_size;
309a56bb8a5SSatoshi Asami 		} else {
310a56bb8a5SSatoshi Asami #ifdef DEBUG
311a56bb8a5SSatoshi Asami 			if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
312a56bb8a5SSatoshi Asami 				printf("ccd%d: %s: incorrect partition type\n",
313a56bb8a5SSatoshi Asami 				    ccd->ccd_unit, ci->ci_path);
314a56bb8a5SSatoshi Asami #endif
315a56bb8a5SSatoshi Asami 			free(ci->ci_path, M_DEVBUF);
316a56bb8a5SSatoshi Asami 			free(cs->sc_cinfo, M_DEVBUF);
317a56bb8a5SSatoshi Asami 			return (EFTYPE);
318a56bb8a5SSatoshi Asami 		}
319a56bb8a5SSatoshi Asami 
320a56bb8a5SSatoshi Asami 		/*
321a56bb8a5SSatoshi Asami 		 * Calculate the size, truncating to an interleave
322a56bb8a5SSatoshi Asami 		 * boundary if necessary.
323a56bb8a5SSatoshi Asami 		 */
324a56bb8a5SSatoshi Asami 		if (size < 0)
325a56bb8a5SSatoshi Asami 			size = 0;
326a56bb8a5SSatoshi Asami 
327a56bb8a5SSatoshi Asami 		if (cs->sc_ileave > 1)
328a56bb8a5SSatoshi Asami 			size -= size % cs->sc_ileave;
329a56bb8a5SSatoshi Asami 
330a56bb8a5SSatoshi Asami 		if (size == 0) {
331a56bb8a5SSatoshi Asami #ifdef DEBUG
332a56bb8a5SSatoshi Asami 			if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
333a56bb8a5SSatoshi Asami 				printf("ccd%d: %s: size == 0\n",
334a56bb8a5SSatoshi Asami 				    ccd->ccd_unit, ci->ci_path);
335a56bb8a5SSatoshi Asami #endif
336a56bb8a5SSatoshi Asami 			free(ci->ci_path, M_DEVBUF);
337a56bb8a5SSatoshi Asami 			free(cs->sc_cinfo, M_DEVBUF);
338a56bb8a5SSatoshi Asami 			return (ENODEV);
339a56bb8a5SSatoshi Asami 		}
340a56bb8a5SSatoshi Asami 
341a56bb8a5SSatoshi Asami 		if (minsize == 0 || size < minsize)
342a56bb8a5SSatoshi Asami 			minsize = size;
343a56bb8a5SSatoshi Asami 		ci->ci_size = size;
344a56bb8a5SSatoshi Asami 		cs->sc_size += size;
345a56bb8a5SSatoshi Asami 	}
346a56bb8a5SSatoshi Asami 
347a56bb8a5SSatoshi Asami 	/*
348a56bb8a5SSatoshi Asami 	 * Don't allow the interleave to be smaller than
349a56bb8a5SSatoshi Asami 	 * the biggest component sector.
350a56bb8a5SSatoshi Asami 	 */
351a56bb8a5SSatoshi Asami 	if ((cs->sc_ileave > 0) &&
352a56bb8a5SSatoshi Asami 	    (cs->sc_ileave < (maxsecsize / DEV_BSIZE))) {
353a56bb8a5SSatoshi Asami #ifdef DEBUG
354a56bb8a5SSatoshi Asami 		if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
355a56bb8a5SSatoshi Asami 			printf("ccd%d: interleave must be at least %d\n",
356a56bb8a5SSatoshi Asami 			    ccd->ccd_unit, (maxsecsize / DEV_BSIZE));
357a56bb8a5SSatoshi Asami #endif
358a56bb8a5SSatoshi Asami 		free(ci->ci_path, M_DEVBUF);
359a56bb8a5SSatoshi Asami 		free(cs->sc_cinfo, M_DEVBUF);
360a56bb8a5SSatoshi Asami 		return (EINVAL);
361a56bb8a5SSatoshi Asami 	}
362a56bb8a5SSatoshi Asami 
363a56bb8a5SSatoshi Asami 	/*
364a56bb8a5SSatoshi Asami 	 * If uniform interleave is desired set all sizes to that of
365a56bb8a5SSatoshi Asami 	 * the smallest component.
366a56bb8a5SSatoshi Asami 	 */
367a56bb8a5SSatoshi Asami 	if (ccd->ccd_flags & CCDF_UNIFORM) {
368a56bb8a5SSatoshi Asami 		for (ci = cs->sc_cinfo;
369a56bb8a5SSatoshi Asami 		     ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++)
370a56bb8a5SSatoshi Asami 			ci->ci_size = minsize;
371a56bb8a5SSatoshi Asami 		cs->sc_size = cs->sc_nccdisks * minsize;
372a56bb8a5SSatoshi Asami 	}
373a56bb8a5SSatoshi Asami 
374a56bb8a5SSatoshi Asami 	/*
375a56bb8a5SSatoshi Asami 	 * Construct the interleave table.
376a56bb8a5SSatoshi Asami 	 */
377a56bb8a5SSatoshi Asami 	ccdinterleave(cs, ccd->ccd_unit);
378a56bb8a5SSatoshi Asami 
379a56bb8a5SSatoshi Asami 	/*
380a56bb8a5SSatoshi Asami 	 * Create pseudo-geometry based on 1MB cylinders.  It's
381a56bb8a5SSatoshi Asami 	 * pretty close.
382a56bb8a5SSatoshi Asami 	 */
383a56bb8a5SSatoshi Asami 	ccg->ccg_secsize = DEV_BSIZE;
384a56bb8a5SSatoshi Asami 	ccg->ccg_ntracks = 1;
385a56bb8a5SSatoshi Asami 	ccg->ccg_nsectors = 1024 * (1024 / ccg->ccg_secsize);
386a56bb8a5SSatoshi Asami 	ccg->ccg_ncylinders = cs->sc_size / ccg->ccg_nsectors;
387a56bb8a5SSatoshi Asami 
388a56bb8a5SSatoshi Asami #ifdef WORKING_DISK_STATISTICS		/* XXX !! */
389a56bb8a5SSatoshi Asami 	if (ccd->ccd_dk >= 0)
390a56bb8a5SSatoshi Asami 		dk_wpms[ccd->ccd_dk] = 32 * (60 * DEV_BSIZE / 2);     /* XXX */
391a56bb8a5SSatoshi Asami #endif
392a56bb8a5SSatoshi Asami 
393a56bb8a5SSatoshi Asami 	cs->sc_flags |= CCDF_INITED;
394a56bb8a5SSatoshi Asami 	cs->sc_cflags = ccd->ccd_flags;	/* So we can find out later... */
395a56bb8a5SSatoshi Asami 	cs->sc_unit = ccd->ccd_unit;
396a56bb8a5SSatoshi Asami 	return (0);
397a56bb8a5SSatoshi Asami }
398a56bb8a5SSatoshi Asami 
399a56bb8a5SSatoshi Asami static void
400a56bb8a5SSatoshi Asami ccdinterleave(cs, unit)
401a56bb8a5SSatoshi Asami 	register struct ccd_softc *cs;
402a56bb8a5SSatoshi Asami 	int unit;
403a56bb8a5SSatoshi Asami {
404a56bb8a5SSatoshi Asami 	register struct ccdcinfo *ci, *smallci;
405a56bb8a5SSatoshi Asami 	register struct ccdiinfo *ii;
406a56bb8a5SSatoshi Asami 	register daddr_t bn, lbn;
407a56bb8a5SSatoshi Asami 	register int ix;
408a56bb8a5SSatoshi Asami 	u_long size;
409a56bb8a5SSatoshi Asami 
410a56bb8a5SSatoshi Asami #ifdef DEBUG
411a56bb8a5SSatoshi Asami 	if (ccddebug & CCDB_INIT)
412a56bb8a5SSatoshi Asami 		printf("ccdinterleave(%x): ileave %d\n", cs, cs->sc_ileave);
413a56bb8a5SSatoshi Asami #endif
414a56bb8a5SSatoshi Asami 	/*
415a56bb8a5SSatoshi Asami 	 * Allocate an interleave table.
416a56bb8a5SSatoshi Asami 	 * Chances are this is too big, but we don't care.
417a56bb8a5SSatoshi Asami 	 */
418a56bb8a5SSatoshi Asami 	size = (cs->sc_nccdisks + 1) * sizeof(struct ccdiinfo);
419a56bb8a5SSatoshi Asami 	cs->sc_itable = (struct ccdiinfo *)malloc(size, M_DEVBUF, M_WAITOK);
420a56bb8a5SSatoshi Asami 	bzero((caddr_t)cs->sc_itable, size);
421a56bb8a5SSatoshi Asami 
422a56bb8a5SSatoshi Asami 	/*
423a56bb8a5SSatoshi Asami 	 * Trivial case: no interleave (actually interleave of disk size).
424a56bb8a5SSatoshi Asami 	 * Each table entry represents a single component in its entirety.
425a56bb8a5SSatoshi Asami 	 */
426a56bb8a5SSatoshi Asami 	if (cs->sc_ileave == 0) {
427a56bb8a5SSatoshi Asami 		bn = 0;
428a56bb8a5SSatoshi Asami 		ii = cs->sc_itable;
429a56bb8a5SSatoshi Asami 
430a56bb8a5SSatoshi Asami 		for (ix = 0; ix < cs->sc_nccdisks; ix++) {
431a56bb8a5SSatoshi Asami 			/* Allocate space for ii_index. */
432a56bb8a5SSatoshi Asami 			ii->ii_index = malloc(sizeof(int), M_DEVBUF, M_WAITOK);
433a56bb8a5SSatoshi Asami 			ii->ii_ndisk = 1;
434a56bb8a5SSatoshi Asami 			ii->ii_startblk = bn;
435a56bb8a5SSatoshi Asami 			ii->ii_startoff = 0;
436a56bb8a5SSatoshi Asami 			ii->ii_index[0] = ix;
437a56bb8a5SSatoshi Asami 			bn += cs->sc_cinfo[ix].ci_size;
438a56bb8a5SSatoshi Asami 			ii++;
439a56bb8a5SSatoshi Asami 		}
440a56bb8a5SSatoshi Asami 		ii->ii_ndisk = 0;
441a56bb8a5SSatoshi Asami #ifdef DEBUG
442a56bb8a5SSatoshi Asami 		if (ccddebug & CCDB_INIT)
443a56bb8a5SSatoshi Asami 			printiinfo(cs->sc_itable);
444a56bb8a5SSatoshi Asami #endif
445a56bb8a5SSatoshi Asami 		return;
446a56bb8a5SSatoshi Asami 	}
447a56bb8a5SSatoshi Asami 
448a56bb8a5SSatoshi Asami 	/*
449a56bb8a5SSatoshi Asami 	 * The following isn't fast or pretty; it doesn't have to be.
450a56bb8a5SSatoshi Asami 	 */
451a56bb8a5SSatoshi Asami 	size = 0;
452a56bb8a5SSatoshi Asami 	bn = lbn = 0;
453a56bb8a5SSatoshi Asami 	for (ii = cs->sc_itable; ; ii++) {
454a56bb8a5SSatoshi Asami 		/* Allocate space for ii_index. */
455a56bb8a5SSatoshi Asami 		ii->ii_index = malloc((sizeof(int) * cs->sc_nccdisks),
456a56bb8a5SSatoshi Asami 		    M_DEVBUF, M_WAITOK);
457a56bb8a5SSatoshi Asami 
458a56bb8a5SSatoshi Asami 		/*
459a56bb8a5SSatoshi Asami 		 * Locate the smallest of the remaining components
460a56bb8a5SSatoshi Asami 		 */
461a56bb8a5SSatoshi Asami 		smallci = NULL;
462a56bb8a5SSatoshi Asami 		for (ci = cs->sc_cinfo;
463a56bb8a5SSatoshi Asami 		     ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++)
464a56bb8a5SSatoshi Asami 			if (ci->ci_size > size &&
465a56bb8a5SSatoshi Asami 			    (smallci == NULL ||
466a56bb8a5SSatoshi Asami 			     ci->ci_size < smallci->ci_size))
467a56bb8a5SSatoshi Asami 				smallci = ci;
468a56bb8a5SSatoshi Asami 
469a56bb8a5SSatoshi Asami 		/*
470a56bb8a5SSatoshi Asami 		 * Nobody left, all done
471a56bb8a5SSatoshi Asami 		 */
472a56bb8a5SSatoshi Asami 		if (smallci == NULL) {
473a56bb8a5SSatoshi Asami 			ii->ii_ndisk = 0;
474a56bb8a5SSatoshi Asami 			break;
475a56bb8a5SSatoshi Asami 		}
476a56bb8a5SSatoshi Asami 
477a56bb8a5SSatoshi Asami 		/*
478a56bb8a5SSatoshi Asami 		 * Record starting logical block and component offset
479a56bb8a5SSatoshi Asami 		 */
480a56bb8a5SSatoshi Asami 		ii->ii_startblk = bn / cs->sc_ileave;
481a56bb8a5SSatoshi Asami 		ii->ii_startoff = lbn;
482a56bb8a5SSatoshi Asami 
483a56bb8a5SSatoshi Asami 		/*
484a56bb8a5SSatoshi Asami 		 * Determine how many disks take part in this interleave
485a56bb8a5SSatoshi Asami 		 * and record their indices.
486a56bb8a5SSatoshi Asami 		 */
487a56bb8a5SSatoshi Asami 		ix = 0;
488a56bb8a5SSatoshi Asami 		for (ci = cs->sc_cinfo;
489a56bb8a5SSatoshi Asami 		     ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++)
490a56bb8a5SSatoshi Asami 			if (ci->ci_size >= smallci->ci_size)
491a56bb8a5SSatoshi Asami 				ii->ii_index[ix++] = ci - cs->sc_cinfo;
492a56bb8a5SSatoshi Asami 		ii->ii_ndisk = ix;
493a56bb8a5SSatoshi Asami 		bn += ix * (smallci->ci_size - size);
494a56bb8a5SSatoshi Asami 		lbn = smallci->ci_size / cs->sc_ileave;
495a56bb8a5SSatoshi Asami 		size = smallci->ci_size;
496a56bb8a5SSatoshi Asami 	}
497a56bb8a5SSatoshi Asami #ifdef DEBUG
498a56bb8a5SSatoshi Asami 	if (ccddebug & CCDB_INIT)
499a56bb8a5SSatoshi Asami 		printiinfo(cs->sc_itable);
500a56bb8a5SSatoshi Asami #endif
501a56bb8a5SSatoshi Asami }
502a56bb8a5SSatoshi Asami 
503a56bb8a5SSatoshi Asami /* ARGSUSED */
504a56bb8a5SSatoshi Asami int
505a56bb8a5SSatoshi Asami ccdopen(dev, flags, fmt, p)
506a56bb8a5SSatoshi Asami 	dev_t dev;
507a56bb8a5SSatoshi Asami 	int flags, fmt;
508a56bb8a5SSatoshi Asami 	struct proc *p;
509a56bb8a5SSatoshi Asami {
510a56bb8a5SSatoshi Asami 	int unit = ccdunit(dev);
511a56bb8a5SSatoshi Asami 	struct ccd_softc *cs;
512a56bb8a5SSatoshi Asami 	struct disklabel *lp;
513a56bb8a5SSatoshi Asami 	int error = 0, part, pmask;
514a56bb8a5SSatoshi Asami 
515a56bb8a5SSatoshi Asami #ifdef DEBUG
516a56bb8a5SSatoshi Asami 	if (ccddebug & CCDB_FOLLOW)
517a56bb8a5SSatoshi Asami 		printf("ccdopen(%x, %x)\n", dev, flags);
518a56bb8a5SSatoshi Asami #endif
519a56bb8a5SSatoshi Asami 	if (unit >= numccd)
520a56bb8a5SSatoshi Asami 		return (ENXIO);
521a56bb8a5SSatoshi Asami 	cs = &ccd_softc[unit];
522a56bb8a5SSatoshi Asami 
523a56bb8a5SSatoshi Asami 	if (error = ccdlock(cs))
524a56bb8a5SSatoshi Asami 		return (error);
525a56bb8a5SSatoshi Asami 
526a56bb8a5SSatoshi Asami 	lp = &cs->sc_dkdev.dk_label;
527a56bb8a5SSatoshi Asami 
528a56bb8a5SSatoshi Asami 	part = DISKPART(dev);
529a56bb8a5SSatoshi Asami 	pmask = (1 << part);
530a56bb8a5SSatoshi Asami 
531a56bb8a5SSatoshi Asami 	/*
532a56bb8a5SSatoshi Asami 	 * If we're initialized, check to see if there are any other
533a56bb8a5SSatoshi Asami 	 * open partitions.  If not, then it's safe to update
534a56bb8a5SSatoshi Asami 	 * the in-core disklabel.
535a56bb8a5SSatoshi Asami 	 */
536a56bb8a5SSatoshi Asami 	if ((cs->sc_flags & CCDF_INITED) && (cs->sc_dkdev.dk_openmask == 0))
537a56bb8a5SSatoshi Asami 		ccdgetdisklabel(dev);
538a56bb8a5SSatoshi Asami 
539a56bb8a5SSatoshi Asami 	/* Check that the partition exists. */
540a56bb8a5SSatoshi Asami 	if (part != RAW_PART && ((part > lp->d_npartitions) ||
541a56bb8a5SSatoshi Asami 	    (lp->d_partitions[part].p_fstype == FS_UNUSED))) {
542a56bb8a5SSatoshi Asami 		error = ENXIO;
543a56bb8a5SSatoshi Asami 		goto done;
544a56bb8a5SSatoshi Asami 	}
545a56bb8a5SSatoshi Asami 
546a56bb8a5SSatoshi Asami 	/* Prevent our unit from being unconfigured while open. */
547a56bb8a5SSatoshi Asami 	switch (fmt) {
548a56bb8a5SSatoshi Asami 	case S_IFCHR:
549a56bb8a5SSatoshi Asami 		cs->sc_dkdev.dk_copenmask |= pmask;
550a56bb8a5SSatoshi Asami 		break;
551a56bb8a5SSatoshi Asami 
552a56bb8a5SSatoshi Asami 	case S_IFBLK:
553a56bb8a5SSatoshi Asami 		cs->sc_dkdev.dk_bopenmask |= pmask;
554a56bb8a5SSatoshi Asami 		break;
555a56bb8a5SSatoshi Asami 	}
556a56bb8a5SSatoshi Asami 	cs->sc_dkdev.dk_openmask =
557a56bb8a5SSatoshi Asami 	    cs->sc_dkdev.dk_copenmask | cs->sc_dkdev.dk_bopenmask;
558a56bb8a5SSatoshi Asami 
559a56bb8a5SSatoshi Asami  done:
560a56bb8a5SSatoshi Asami 	ccdunlock(cs);
561a56bb8a5SSatoshi Asami 	return (0);
562a56bb8a5SSatoshi Asami }
563a56bb8a5SSatoshi Asami 
564a56bb8a5SSatoshi Asami /* ARGSUSED */
565a56bb8a5SSatoshi Asami int
566a56bb8a5SSatoshi Asami ccdclose(dev, flags, fmt, p)
567a56bb8a5SSatoshi Asami 	dev_t dev;
568a56bb8a5SSatoshi Asami 	int flags, fmt;
569a56bb8a5SSatoshi Asami 	struct proc *p;
570a56bb8a5SSatoshi Asami {
571a56bb8a5SSatoshi Asami 	int unit = ccdunit(dev);
572a56bb8a5SSatoshi Asami 	struct ccd_softc *cs;
573a56bb8a5SSatoshi Asami 	int error = 0, part;
574a56bb8a5SSatoshi Asami 
575a56bb8a5SSatoshi Asami #ifdef DEBUG
576a56bb8a5SSatoshi Asami 	if (ccddebug & CCDB_FOLLOW)
577a56bb8a5SSatoshi Asami 		printf("ccdclose(%x, %x)\n", dev, flags);
578a56bb8a5SSatoshi Asami #endif
579a56bb8a5SSatoshi Asami 
580a56bb8a5SSatoshi Asami 	if (unit >= numccd)
581a56bb8a5SSatoshi Asami 		return (ENXIO);
582a56bb8a5SSatoshi Asami 	cs = &ccd_softc[unit];
583a56bb8a5SSatoshi Asami 
584a56bb8a5SSatoshi Asami 	if (error = ccdlock(cs))
585a56bb8a5SSatoshi Asami 		return (error);
586a56bb8a5SSatoshi Asami 
587a56bb8a5SSatoshi Asami 	part = DISKPART(dev);
588a56bb8a5SSatoshi Asami 
589a56bb8a5SSatoshi Asami 	/* ...that much closer to allowing unconfiguration... */
590a56bb8a5SSatoshi Asami 	switch (fmt) {
591a56bb8a5SSatoshi Asami 	case S_IFCHR:
592a56bb8a5SSatoshi Asami 		cs->sc_dkdev.dk_copenmask &= ~(1 << part);
593a56bb8a5SSatoshi Asami 		break;
594a56bb8a5SSatoshi Asami 
595a56bb8a5SSatoshi Asami 	case S_IFBLK:
596a56bb8a5SSatoshi Asami 		cs->sc_dkdev.dk_bopenmask &= ~(1 << part);
597a56bb8a5SSatoshi Asami 		break;
598a56bb8a5SSatoshi Asami 	}
599a56bb8a5SSatoshi Asami 	cs->sc_dkdev.dk_openmask =
600a56bb8a5SSatoshi Asami 	    cs->sc_dkdev.dk_copenmask | cs->sc_dkdev.dk_bopenmask;
601a56bb8a5SSatoshi Asami 
602a56bb8a5SSatoshi Asami 	ccdunlock(cs);
603a56bb8a5SSatoshi Asami 	return (0);
604a56bb8a5SSatoshi Asami }
605a56bb8a5SSatoshi Asami 
606a56bb8a5SSatoshi Asami void
607a56bb8a5SSatoshi Asami ccdstrategy(bp)
608a56bb8a5SSatoshi Asami 	register struct buf *bp;
609a56bb8a5SSatoshi Asami {
610a56bb8a5SSatoshi Asami 	register int unit = ccdunit(bp->b_dev);
611a56bb8a5SSatoshi Asami 	register struct ccd_softc *cs = &ccd_softc[unit];
612a56bb8a5SSatoshi Asami 	register daddr_t bn;
613a56bb8a5SSatoshi Asami 	register int sz, s;
614a56bb8a5SSatoshi Asami 	int wlabel;
615a56bb8a5SSatoshi Asami 	struct disklabel *lp;
616a56bb8a5SSatoshi Asami 
617a56bb8a5SSatoshi Asami #ifdef DEBUG
618a56bb8a5SSatoshi Asami 	if (ccddebug & CCDB_FOLLOW)
619a56bb8a5SSatoshi Asami 		printf("ccdstrategy(%x): unit %d\n", bp, unit);
620a56bb8a5SSatoshi Asami #endif
621a56bb8a5SSatoshi Asami 	if ((cs->sc_flags & CCDF_INITED) == 0) {
622a56bb8a5SSatoshi Asami 		bp->b_error = ENXIO;
623a56bb8a5SSatoshi Asami 		bp->b_flags |= B_ERROR;
624a56bb8a5SSatoshi Asami 		goto done;
625a56bb8a5SSatoshi Asami 	}
626a56bb8a5SSatoshi Asami 
627a56bb8a5SSatoshi Asami 	/* If it's a nil transfer, wake up the top half now. */
628a56bb8a5SSatoshi Asami 	if (bp->b_bcount == 0)
629a56bb8a5SSatoshi Asami 		goto done;
630a56bb8a5SSatoshi Asami 
631a56bb8a5SSatoshi Asami 	lp = &cs->sc_dkdev.dk_label;
632a56bb8a5SSatoshi Asami 
633a56bb8a5SSatoshi Asami 	/*
634a56bb8a5SSatoshi Asami 	 * Do bounds checking and adjust transfer.  If there's an
635a56bb8a5SSatoshi Asami 	 * error, the bounds check will flag that for us.
636a56bb8a5SSatoshi Asami 	 */
637a56bb8a5SSatoshi Asami 	wlabel = cs->sc_flags & (CCDF_WLABEL|CCDF_LABELLING);
638a56bb8a5SSatoshi Asami 	if (DISKPART(bp->b_dev) != RAW_PART)
639a56bb8a5SSatoshi Asami 		if (bounds_check_with_label(bp, lp, wlabel) <= 0)
640a56bb8a5SSatoshi Asami 			goto done;
641a56bb8a5SSatoshi Asami 
642a56bb8a5SSatoshi Asami 	bp->b_resid = bp->b_bcount;
643a56bb8a5SSatoshi Asami 
644a56bb8a5SSatoshi Asami 	/*
645a56bb8a5SSatoshi Asami 	 * "Start" the unit.
646a56bb8a5SSatoshi Asami 	 */
647a56bb8a5SSatoshi Asami 	s = splbio();
648a56bb8a5SSatoshi Asami 	ccdstart(cs, bp);
649a56bb8a5SSatoshi Asami 	splx(s);
650a56bb8a5SSatoshi Asami 	return;
651a56bb8a5SSatoshi Asami done:
652a56bb8a5SSatoshi Asami 	biodone(bp);
653a56bb8a5SSatoshi Asami }
654a56bb8a5SSatoshi Asami 
655a56bb8a5SSatoshi Asami static void
656a56bb8a5SSatoshi Asami ccdstart(cs, bp)
657a56bb8a5SSatoshi Asami 	register struct ccd_softc *cs;
658a56bb8a5SSatoshi Asami 	register struct buf *bp;
659a56bb8a5SSatoshi Asami {
660a56bb8a5SSatoshi Asami 	register long bcount, rcount;
661a56bb8a5SSatoshi Asami 	struct ccdbuf *cbp;
662a56bb8a5SSatoshi Asami 	caddr_t addr;
663a56bb8a5SSatoshi Asami 	daddr_t bn;
664a56bb8a5SSatoshi Asami 	struct partition *pp;
665a56bb8a5SSatoshi Asami 
666a56bb8a5SSatoshi Asami #ifdef DEBUG
667a56bb8a5SSatoshi Asami 	if (ccddebug & CCDB_FOLLOW)
668a56bb8a5SSatoshi Asami 		printf("ccdstart(%x, %x)\n", cs, bp);
669a56bb8a5SSatoshi Asami #endif
670a56bb8a5SSatoshi Asami 
671a56bb8a5SSatoshi Asami #ifdef WORKING_DISK_STATISTICS		/* XXX !! */
672a56bb8a5SSatoshi Asami 	/*
673a56bb8a5SSatoshi Asami 	 * Instrumentation (not very meaningful)
674a56bb8a5SSatoshi Asami 	 */
675a56bb8a5SSatoshi Asami 	cs->sc_nactive++;
676a56bb8a5SSatoshi Asami 	if (cs->sc_dk >= 0) {
677a56bb8a5SSatoshi Asami 		dk_busy |= 1 << cs->sc_dk;
678a56bb8a5SSatoshi Asami 		dk_xfer[cs->sc_dk]++;
679a56bb8a5SSatoshi Asami 		dk_wds[cs->sc_dk] += bp->b_bcount >> 6;
680a56bb8a5SSatoshi Asami 	}
681a56bb8a5SSatoshi Asami #endif
682a56bb8a5SSatoshi Asami 
683a56bb8a5SSatoshi Asami 	/*
684a56bb8a5SSatoshi Asami 	 * Translate the partition-relative block number to an absolute.
685a56bb8a5SSatoshi Asami 	 */
686a56bb8a5SSatoshi Asami 	bn = bp->b_blkno;
687a56bb8a5SSatoshi Asami 	if (DISKPART(bp->b_dev) != RAW_PART) {
688a56bb8a5SSatoshi Asami 		pp = &cs->sc_dkdev.dk_label.d_partitions[DISKPART(bp->b_dev)];
689a56bb8a5SSatoshi Asami 		bn += pp->p_offset;
690a56bb8a5SSatoshi Asami 	}
691a56bb8a5SSatoshi Asami 
692a56bb8a5SSatoshi Asami 	/*
693a56bb8a5SSatoshi Asami 	 * Allocate component buffers and fire off the requests
694a56bb8a5SSatoshi Asami 	 */
695a56bb8a5SSatoshi Asami 	addr = bp->b_data;
696a56bb8a5SSatoshi Asami 	for (bcount = bp->b_bcount; bcount > 0; bcount -= rcount) {
697a56bb8a5SSatoshi Asami 		cbp = ccdbuffer(cs, bp, bn, addr, bcount);
698a56bb8a5SSatoshi Asami 		rcount = cbp->cb_buf.b_bcount;
699a56bb8a5SSatoshi Asami 		if ((cbp->cb_buf.b_flags & B_READ) == 0)
700a56bb8a5SSatoshi Asami 			cbp->cb_buf.b_vp->v_numoutput++;
701a56bb8a5SSatoshi Asami 		VOP_STRATEGY(&cbp->cb_buf);
702a56bb8a5SSatoshi Asami 		bn += btodb(rcount);
703a56bb8a5SSatoshi Asami 		addr += rcount;
704a56bb8a5SSatoshi Asami 	}
705a56bb8a5SSatoshi Asami }
706a56bb8a5SSatoshi Asami 
707a56bb8a5SSatoshi Asami /*
708a56bb8a5SSatoshi Asami  * Build a component buffer header.
709a56bb8a5SSatoshi Asami  */
710a56bb8a5SSatoshi Asami static struct ccdbuf *
711a56bb8a5SSatoshi Asami ccdbuffer(cs, bp, bn, addr, bcount)
712a56bb8a5SSatoshi Asami 	register struct ccd_softc *cs;
713a56bb8a5SSatoshi Asami 	struct buf *bp;
714a56bb8a5SSatoshi Asami 	daddr_t bn;
715a56bb8a5SSatoshi Asami 	caddr_t addr;
716a56bb8a5SSatoshi Asami 	long bcount;
717a56bb8a5SSatoshi Asami {
718a56bb8a5SSatoshi Asami 	register struct ccdcinfo *ci;
719a56bb8a5SSatoshi Asami 	register struct ccdbuf *cbp;
720a56bb8a5SSatoshi Asami 	register daddr_t cbn, cboff;
721a56bb8a5SSatoshi Asami 
722a56bb8a5SSatoshi Asami #ifdef DEBUG
723a56bb8a5SSatoshi Asami 	if (ccddebug & CCDB_IO)
724a56bb8a5SSatoshi Asami 		printf("ccdbuffer(%x, %x, %d, %x, %d)\n",
725a56bb8a5SSatoshi Asami 		       cs, bp, bn, addr, bcount);
726a56bb8a5SSatoshi Asami #endif
727a56bb8a5SSatoshi Asami 	/*
728a56bb8a5SSatoshi Asami 	 * Determine which component bn falls in.
729a56bb8a5SSatoshi Asami 	 */
730a56bb8a5SSatoshi Asami 	cbn = bn;
731a56bb8a5SSatoshi Asami 	cboff = 0;
732a56bb8a5SSatoshi Asami 
733a56bb8a5SSatoshi Asami 	/*
734a56bb8a5SSatoshi Asami 	 * Serially concatenated
735a56bb8a5SSatoshi Asami 	 */
736a56bb8a5SSatoshi Asami 	if (cs->sc_ileave == 0) {
737a56bb8a5SSatoshi Asami 		register daddr_t sblk;
738a56bb8a5SSatoshi Asami 
739a56bb8a5SSatoshi Asami 		sblk = 0;
740a56bb8a5SSatoshi Asami 		for (ci = cs->sc_cinfo; cbn >= sblk + ci->ci_size; ci++)
741a56bb8a5SSatoshi Asami 			sblk += ci->ci_size;
742a56bb8a5SSatoshi Asami 		cbn -= sblk;
743a56bb8a5SSatoshi Asami 	}
744a56bb8a5SSatoshi Asami 	/*
745a56bb8a5SSatoshi Asami 	 * Interleaved
746a56bb8a5SSatoshi Asami 	 */
747a56bb8a5SSatoshi Asami 	else {
748a56bb8a5SSatoshi Asami 		register struct ccdiinfo *ii;
749a56bb8a5SSatoshi Asami 		int ccdisk, off;
750a56bb8a5SSatoshi Asami 
751a56bb8a5SSatoshi Asami 		cboff = cbn % cs->sc_ileave;
752a56bb8a5SSatoshi Asami 		cbn /= cs->sc_ileave;
753a56bb8a5SSatoshi Asami 		for (ii = cs->sc_itable; ii->ii_ndisk; ii++)
754a56bb8a5SSatoshi Asami 			if (ii->ii_startblk > cbn)
755a56bb8a5SSatoshi Asami 				break;
756a56bb8a5SSatoshi Asami 		ii--;
757a56bb8a5SSatoshi Asami 		off = cbn - ii->ii_startblk;
758a56bb8a5SSatoshi Asami 		if (ii->ii_ndisk == 1) {
759a56bb8a5SSatoshi Asami 			ccdisk = ii->ii_index[0];
760a56bb8a5SSatoshi Asami 			cbn = ii->ii_startoff + off;
761a56bb8a5SSatoshi Asami 		} else {
762a56bb8a5SSatoshi Asami 			ccdisk = ii->ii_index[off % ii->ii_ndisk];
763a56bb8a5SSatoshi Asami 			cbn = ii->ii_startoff + off / ii->ii_ndisk;
764a56bb8a5SSatoshi Asami 		}
765a56bb8a5SSatoshi Asami 		cbn *= cs->sc_ileave;
766a56bb8a5SSatoshi Asami 		ci = &cs->sc_cinfo[ccdisk];
767a56bb8a5SSatoshi Asami 	}
768a56bb8a5SSatoshi Asami 
769a56bb8a5SSatoshi Asami 	/*
770a56bb8a5SSatoshi Asami 	 * Fill in the component buf structure.
771a56bb8a5SSatoshi Asami 	 */
772a56bb8a5SSatoshi Asami 	cbp = getccdbuf();
773a56bb8a5SSatoshi Asami 	cbp->cb_buf.b_flags = bp->b_flags | B_CALL;
774a56bb8a5SSatoshi Asami 	cbp->cb_buf.b_iodone = (void (*)())ccdiodone;
775a56bb8a5SSatoshi Asami 	cbp->cb_buf.b_proc = bp->b_proc;
776a56bb8a5SSatoshi Asami 	cbp->cb_buf.b_dev = ci->ci_dev;		/* XXX */
777a56bb8a5SSatoshi Asami 	cbp->cb_buf.b_blkno = cbn + cboff;
778a56bb8a5SSatoshi Asami 	cbp->cb_buf.b_data = addr;
779a56bb8a5SSatoshi Asami 	cbp->cb_buf.b_vp = ci->ci_vp;
780a56bb8a5SSatoshi Asami 	if (cs->sc_ileave == 0)
781a56bb8a5SSatoshi Asami 		cbp->cb_buf.b_bcount = dbtob(ci->ci_size - cbn);
782a56bb8a5SSatoshi Asami 	else
783a56bb8a5SSatoshi Asami 		cbp->cb_buf.b_bcount = dbtob(cs->sc_ileave - cboff);
784a56bb8a5SSatoshi Asami 	if (cbp->cb_buf.b_bcount > bcount)
785a56bb8a5SSatoshi Asami 		cbp->cb_buf.b_bcount = bcount;
786a56bb8a5SSatoshi Asami 
787a56bb8a5SSatoshi Asami 	/*
788a56bb8a5SSatoshi Asami 	 * context for ccdiodone
789a56bb8a5SSatoshi Asami 	 */
790a56bb8a5SSatoshi Asami 	cbp->cb_obp = bp;
791a56bb8a5SSatoshi Asami 	cbp->cb_unit = cs - ccd_softc;
792a56bb8a5SSatoshi Asami 	cbp->cb_comp = ci - cs->sc_cinfo;
793a56bb8a5SSatoshi Asami 
794a56bb8a5SSatoshi Asami #ifdef DEBUG
795a56bb8a5SSatoshi Asami 	if (ccddebug & CCDB_IO)
796a56bb8a5SSatoshi Asami 		printf(" dev %x(u%d): cbp %x bn %d addr %x bcnt %d\n",
797a56bb8a5SSatoshi Asami 		       ci->ci_dev, ci-cs->sc_cinfo, cbp, cbp->cb_buf.b_blkno,
798a56bb8a5SSatoshi Asami 		       cbp->cb_buf.b_data, cbp->cb_buf.b_bcount);
799a56bb8a5SSatoshi Asami #endif
800a56bb8a5SSatoshi Asami 	return (cbp);
801a56bb8a5SSatoshi Asami }
802a56bb8a5SSatoshi Asami 
803a56bb8a5SSatoshi Asami static void
804a56bb8a5SSatoshi Asami ccdintr(cs, bp)
805a56bb8a5SSatoshi Asami 	register struct ccd_softc *cs;
806a56bb8a5SSatoshi Asami 	register struct buf *bp;
807a56bb8a5SSatoshi Asami {
808a56bb8a5SSatoshi Asami 
809a56bb8a5SSatoshi Asami #ifdef DEBUG
810a56bb8a5SSatoshi Asami 	if (ccddebug & CCDB_FOLLOW)
811a56bb8a5SSatoshi Asami 		printf("ccdintr(%x, %x)\n", cs, bp);
812a56bb8a5SSatoshi Asami #endif
813a56bb8a5SSatoshi Asami 	/*
814a56bb8a5SSatoshi Asami 	 * Request is done for better or worse, wakeup the top half.
815a56bb8a5SSatoshi Asami 	 */
816a56bb8a5SSatoshi Asami #ifdef WORKING_DISK_STATISTICS		/* XXX !! */
817a56bb8a5SSatoshi Asami 	--cs->sc_nactive;
818a56bb8a5SSatoshi Asami #ifdef DIAGNOSTIC
819a56bb8a5SSatoshi Asami 	if (cs->sc_nactive < 0)
820a56bb8a5SSatoshi Asami 		panic("ccdintr: ccd%d: sc_nactive < 0", cs->sc_unit);
821a56bb8a5SSatoshi Asami #endif
822a56bb8a5SSatoshi Asami 
823a56bb8a5SSatoshi Asami 	if (cs->sc_nactive == 0 && cs->sc_dk >= 0)
824a56bb8a5SSatoshi Asami 		dk_busy &= ~(1 << cs->sc_dk);
825a56bb8a5SSatoshi Asami #endif
826a56bb8a5SSatoshi Asami 	if (bp->b_flags & B_ERROR)
827a56bb8a5SSatoshi Asami 		bp->b_resid = bp->b_bcount;
828a56bb8a5SSatoshi Asami 	biodone(bp);
829a56bb8a5SSatoshi Asami }
830a56bb8a5SSatoshi Asami 
831a56bb8a5SSatoshi Asami /*
832a56bb8a5SSatoshi Asami  * Called at interrupt time.
833a56bb8a5SSatoshi Asami  * Mark the component as done and if all components are done,
834a56bb8a5SSatoshi Asami  * take a ccd interrupt.
835a56bb8a5SSatoshi Asami  */
836a56bb8a5SSatoshi Asami void
837a56bb8a5SSatoshi Asami ccdiodone(cbp)
838a56bb8a5SSatoshi Asami 	struct ccdbuf *cbp;
839a56bb8a5SSatoshi Asami {
840a56bb8a5SSatoshi Asami 	register struct buf *bp = cbp->cb_obp;
841a56bb8a5SSatoshi Asami 	register int unit = cbp->cb_unit;
842a56bb8a5SSatoshi Asami 	int count, s;
843a56bb8a5SSatoshi Asami 
844a56bb8a5SSatoshi Asami 	s = splbio();
845a56bb8a5SSatoshi Asami #ifdef DEBUG
846a56bb8a5SSatoshi Asami 	if (ccddebug & CCDB_FOLLOW)
847a56bb8a5SSatoshi Asami 		printf("ccdiodone(%x)\n", cbp);
848a56bb8a5SSatoshi Asami 	if (ccddebug & CCDB_IO) {
849a56bb8a5SSatoshi Asami 		printf("ccdiodone: bp %x bcount %d resid %d\n",
850a56bb8a5SSatoshi Asami 		       bp, bp->b_bcount, bp->b_resid);
851a56bb8a5SSatoshi Asami 		printf(" dev %x(u%d), cbp %x bn %d addr %x bcnt %d\n",
852a56bb8a5SSatoshi Asami 		       cbp->cb_buf.b_dev, cbp->cb_comp, cbp,
853a56bb8a5SSatoshi Asami 		       cbp->cb_buf.b_blkno, cbp->cb_buf.b_data,
854a56bb8a5SSatoshi Asami 		       cbp->cb_buf.b_bcount);
855a56bb8a5SSatoshi Asami 	}
856a56bb8a5SSatoshi Asami #endif
857a56bb8a5SSatoshi Asami 
858a56bb8a5SSatoshi Asami 	if (cbp->cb_buf.b_flags & B_ERROR) {
859a56bb8a5SSatoshi Asami 		bp->b_flags |= B_ERROR;
860a56bb8a5SSatoshi Asami 		bp->b_error = cbp->cb_buf.b_error ? cbp->cb_buf.b_error : EIO;
861a56bb8a5SSatoshi Asami #ifdef DEBUG
862a56bb8a5SSatoshi Asami 		printf("ccd%d: error %d on component %d\n",
863a56bb8a5SSatoshi Asami 		       unit, bp->b_error, cbp->cb_comp);
864a56bb8a5SSatoshi Asami #endif
865a56bb8a5SSatoshi Asami 	}
866a56bb8a5SSatoshi Asami 	count = cbp->cb_buf.b_bcount;
867a56bb8a5SSatoshi Asami 	putccdbuf(cbp);
868a56bb8a5SSatoshi Asami 
869a56bb8a5SSatoshi Asami 	/*
870a56bb8a5SSatoshi Asami 	 * If all done, "interrupt".
871a56bb8a5SSatoshi Asami 	 */
872a56bb8a5SSatoshi Asami 	bp->b_resid -= count;
873a56bb8a5SSatoshi Asami 	if (bp->b_resid < 0)
874a56bb8a5SSatoshi Asami 		panic("ccdiodone: count");
875a56bb8a5SSatoshi Asami 	if (bp->b_resid == 0)
876a56bb8a5SSatoshi Asami 		ccdintr(&ccd_softc[unit], bp);
877a56bb8a5SSatoshi Asami 	splx(s);
878a56bb8a5SSatoshi Asami }
879a56bb8a5SSatoshi Asami 
880a56bb8a5SSatoshi Asami /* ARGSUSED */
881a56bb8a5SSatoshi Asami int
882a56bb8a5SSatoshi Asami ccdread(dev, uio, flags)
883a56bb8a5SSatoshi Asami 	dev_t dev;
884a56bb8a5SSatoshi Asami 	struct uio *uio;
885a56bb8a5SSatoshi Asami 	int flags;
886a56bb8a5SSatoshi Asami {
887a56bb8a5SSatoshi Asami 	int unit = ccdunit(dev);
888a56bb8a5SSatoshi Asami 	struct ccd_softc *cs;
889a56bb8a5SSatoshi Asami 
890a56bb8a5SSatoshi Asami #ifdef DEBUG
891a56bb8a5SSatoshi Asami 	if (ccddebug & CCDB_FOLLOW)
892a56bb8a5SSatoshi Asami 		printf("ccdread(%x, %x)\n", dev, uio);
893a56bb8a5SSatoshi Asami #endif
894a56bb8a5SSatoshi Asami 	if (unit >= numccd)
895a56bb8a5SSatoshi Asami 		return (ENXIO);
896a56bb8a5SSatoshi Asami 	cs = &ccd_softc[unit];
897a56bb8a5SSatoshi Asami 
898a56bb8a5SSatoshi Asami 	if ((cs->sc_flags & CCDF_INITED) == 0)
899a56bb8a5SSatoshi Asami 		return (ENXIO);
900a56bb8a5SSatoshi Asami 
901a56bb8a5SSatoshi Asami 	/*
902a56bb8a5SSatoshi Asami 	 * XXX: It's not clear that using minphys() is completely safe,
903a56bb8a5SSatoshi Asami 	 * in particular, for raw I/O.  Underlying devices might have some
904a56bb8a5SSatoshi Asami 	 * non-obvious limits, because of the copy to user-space.
905a56bb8a5SSatoshi Asami 	 */
906a56bb8a5SSatoshi Asami 	return (physio(ccdstrategy, NULL, dev, B_READ, minphys, uio));
907a56bb8a5SSatoshi Asami }
908a56bb8a5SSatoshi Asami 
909a56bb8a5SSatoshi Asami /* ARGSUSED */
910a56bb8a5SSatoshi Asami int
911a56bb8a5SSatoshi Asami ccdwrite(dev, uio, flags)
912a56bb8a5SSatoshi Asami 	dev_t dev;
913a56bb8a5SSatoshi Asami 	struct uio *uio;
914a56bb8a5SSatoshi Asami 	int flags;
915a56bb8a5SSatoshi Asami {
916a56bb8a5SSatoshi Asami 	int unit = ccdunit(dev);
917a56bb8a5SSatoshi Asami 	struct ccd_softc *cs;
918a56bb8a5SSatoshi Asami 
919a56bb8a5SSatoshi Asami #ifdef DEBUG
920a56bb8a5SSatoshi Asami 	if (ccddebug & CCDB_FOLLOW)
921a56bb8a5SSatoshi Asami 		printf("ccdwrite(%x, %x)\n", dev, uio);
922a56bb8a5SSatoshi Asami #endif
923a56bb8a5SSatoshi Asami 	if (unit >= numccd)
924a56bb8a5SSatoshi Asami 		return (ENXIO);
925a56bb8a5SSatoshi Asami 	cs = &ccd_softc[unit];
926a56bb8a5SSatoshi Asami 
927a56bb8a5SSatoshi Asami 	if ((cs->sc_flags & CCDF_INITED) == 0)
928a56bb8a5SSatoshi Asami 		return (ENXIO);
929a56bb8a5SSatoshi Asami 
930a56bb8a5SSatoshi Asami 	/*
931a56bb8a5SSatoshi Asami 	 * XXX: It's not clear that using minphys() is completely safe,
932a56bb8a5SSatoshi Asami 	 * in particular, for raw I/O.  Underlying devices might have some
933a56bb8a5SSatoshi Asami 	 * non-obvious limits, because of the copy to user-space.
934a56bb8a5SSatoshi Asami 	 */
935a56bb8a5SSatoshi Asami 	return (physio(ccdstrategy, NULL, dev, B_WRITE, minphys, uio));
936a56bb8a5SSatoshi Asami }
937a56bb8a5SSatoshi Asami 
938a56bb8a5SSatoshi Asami int
939a56bb8a5SSatoshi Asami ccdioctl(dev, cmd, data, flag, p)
940a56bb8a5SSatoshi Asami 	dev_t dev;
941a56bb8a5SSatoshi Asami 	u_long cmd;
942a56bb8a5SSatoshi Asami 	caddr_t data;
943a56bb8a5SSatoshi Asami 	int flag;
944a56bb8a5SSatoshi Asami 	struct proc *p;
945a56bb8a5SSatoshi Asami {
946a56bb8a5SSatoshi Asami 	int unit = ccdunit(dev);
947a56bb8a5SSatoshi Asami 	int i, j, lookedup = 0, error = 0;
948a56bb8a5SSatoshi Asami 	int part, pmask, s;
949a56bb8a5SSatoshi Asami 	struct ccd_softc *cs;
950a56bb8a5SSatoshi Asami 	struct ccd_ioctl *ccio = (struct ccd_ioctl *)data;
951a56bb8a5SSatoshi Asami 	struct ccddevice ccd;
952a56bb8a5SSatoshi Asami 	char **cpp;
953a56bb8a5SSatoshi Asami 	struct vnode **vpp;
954a56bb8a5SSatoshi Asami #ifdef WORKING_DISK_STATISTICS		/* XXX !! */
955a56bb8a5SSatoshi Asami 	extern int dkn;
956a56bb8a5SSatoshi Asami #endif
957a56bb8a5SSatoshi Asami 
958a56bb8a5SSatoshi Asami 	if (unit >= numccd)
959a56bb8a5SSatoshi Asami 		return (ENXIO);
960a56bb8a5SSatoshi Asami 	cs = &ccd_softc[unit];
961a56bb8a5SSatoshi Asami 
962a56bb8a5SSatoshi Asami 	bzero(&ccd, sizeof(ccd));
963a56bb8a5SSatoshi Asami 
964a56bb8a5SSatoshi Asami 	switch (cmd) {
965a56bb8a5SSatoshi Asami 	case CCDIOCSET:
966a56bb8a5SSatoshi Asami 		if (cs->sc_flags & CCDF_INITED)
967a56bb8a5SSatoshi Asami 			return (EBUSY);
968a56bb8a5SSatoshi Asami 
969a56bb8a5SSatoshi Asami 		if ((flag & FWRITE) == 0)
970a56bb8a5SSatoshi Asami 			return (EBADF);
971a56bb8a5SSatoshi Asami 
972a56bb8a5SSatoshi Asami 		if (error = ccdlock(cs))
973a56bb8a5SSatoshi Asami 			return (error);
974a56bb8a5SSatoshi Asami 
975a56bb8a5SSatoshi Asami 		/* Fill in some important bits. */
976a56bb8a5SSatoshi Asami 		ccd.ccd_unit = unit;
977a56bb8a5SSatoshi Asami 		ccd.ccd_interleave = ccio->ccio_ileave;
978a56bb8a5SSatoshi Asami 		ccd.ccd_flags = ccio->ccio_flags & CCDF_USERMASK;
979a56bb8a5SSatoshi Asami 
980a56bb8a5SSatoshi Asami 		/*
981a56bb8a5SSatoshi Asami 		 * Allocate space for and copy in the array of
982a56bb8a5SSatoshi Asami 		 * componet pathnames and device numbers.
983a56bb8a5SSatoshi Asami 		 */
984a56bb8a5SSatoshi Asami 		cpp = malloc(ccio->ccio_ndisks * sizeof(char *),
985a56bb8a5SSatoshi Asami 		    M_DEVBUF, M_WAITOK);
986a56bb8a5SSatoshi Asami 		vpp = malloc(ccio->ccio_ndisks * sizeof(struct vnode *),
987a56bb8a5SSatoshi Asami 		    M_DEVBUF, M_WAITOK);
988a56bb8a5SSatoshi Asami 
989a56bb8a5SSatoshi Asami 		error = copyin((caddr_t)ccio->ccio_disks, (caddr_t)cpp,
990a56bb8a5SSatoshi Asami 		    ccio->ccio_ndisks * sizeof(char **));
991a56bb8a5SSatoshi Asami 		if (error) {
992a56bb8a5SSatoshi Asami 			free(vpp, M_DEVBUF);
993a56bb8a5SSatoshi Asami 			free(cpp, M_DEVBUF);
994a56bb8a5SSatoshi Asami 			ccdunlock(cs);
995a56bb8a5SSatoshi Asami 			return (error);
996a56bb8a5SSatoshi Asami 		}
997a56bb8a5SSatoshi Asami 
998a56bb8a5SSatoshi Asami #ifdef DEBUG
999a56bb8a5SSatoshi Asami 		if (ccddebug & CCDB_INIT)
1000a56bb8a5SSatoshi Asami 			for (i = 0; i < ccio->ccio_ndisks; ++i)
1001a56bb8a5SSatoshi Asami 				printf("ccdioctl: component %d: 0x%x\n",
1002a56bb8a5SSatoshi Asami 				    i, cpp[i]);
1003a56bb8a5SSatoshi Asami #endif
1004a56bb8a5SSatoshi Asami 
1005a56bb8a5SSatoshi Asami 		for (i = 0; i < ccio->ccio_ndisks; ++i) {
1006a56bb8a5SSatoshi Asami #ifdef DEBUG
1007a56bb8a5SSatoshi Asami 			if (ccddebug & CCDB_INIT)
1008a56bb8a5SSatoshi Asami 				printf("ccdioctl: lookedup = %d\n", lookedup);
1009a56bb8a5SSatoshi Asami #endif
1010a56bb8a5SSatoshi Asami 			if (error = ccdlookup(cpp[i], p, &vpp[i])) {
1011a56bb8a5SSatoshi Asami 				for (j = 0; j < lookedup; ++j)
1012a56bb8a5SSatoshi Asami 					(void)vn_close(vpp[j], FREAD|FWRITE,
1013a56bb8a5SSatoshi Asami 					    p->p_ucred, p);
1014a56bb8a5SSatoshi Asami 				free(vpp, M_DEVBUF);
1015a56bb8a5SSatoshi Asami 				free(cpp, M_DEVBUF);
1016a56bb8a5SSatoshi Asami 				ccdunlock(cs);
1017a56bb8a5SSatoshi Asami 				return (error);
1018a56bb8a5SSatoshi Asami 			}
1019a56bb8a5SSatoshi Asami 			++lookedup;
1020a56bb8a5SSatoshi Asami 		}
1021a56bb8a5SSatoshi Asami 		ccd.ccd_cpp = cpp;
1022a56bb8a5SSatoshi Asami 		ccd.ccd_vpp = vpp;
1023a56bb8a5SSatoshi Asami 		ccd.ccd_ndev = ccio->ccio_ndisks;
1024a56bb8a5SSatoshi Asami 
1025a56bb8a5SSatoshi Asami #ifdef WORKING_DISK_STATISTICS		/* XXX !! */
1026a56bb8a5SSatoshi Asami 		/*
1027a56bb8a5SSatoshi Asami 		 * Assign disk index first so that init routine
1028a56bb8a5SSatoshi Asami 		 * can use it (saves having the driver drag around
1029a56bb8a5SSatoshi Asami 		 * the ccddevice pointer just to set up the dk_*
1030a56bb8a5SSatoshi Asami 		 * info in the open routine).
1031a56bb8a5SSatoshi Asami 		 */
1032a56bb8a5SSatoshi Asami 		if (dkn < DK_NDRIVE)
1033a56bb8a5SSatoshi Asami 			ccd.ccd_dk = dkn++;
1034a56bb8a5SSatoshi Asami 		else
1035a56bb8a5SSatoshi Asami 			ccd.ccd_dk = -1;
1036a56bb8a5SSatoshi Asami #endif
1037a56bb8a5SSatoshi Asami 
1038a56bb8a5SSatoshi Asami 		/*
1039a56bb8a5SSatoshi Asami 		 * Initialize the ccd.  Fills in the softc for us.
1040a56bb8a5SSatoshi Asami 		 */
1041a56bb8a5SSatoshi Asami 		if (error = ccdinit(&ccd, cpp, p)) {
1042a56bb8a5SSatoshi Asami #ifdef WORKING_DISK_STATISTICS		/* XXX !! */
1043a56bb8a5SSatoshi Asami 			if (ccd.ccd_dk >= 0)
1044a56bb8a5SSatoshi Asami 				--dkn;
1045a56bb8a5SSatoshi Asami #endif
1046a56bb8a5SSatoshi Asami 			for (j = 0; j < lookedup; ++j)
1047a56bb8a5SSatoshi Asami 				(void)vn_close(vpp[j], FREAD|FWRITE,
1048a56bb8a5SSatoshi Asami 				    p->p_ucred, p);
1049a56bb8a5SSatoshi Asami 			bzero(&ccd_softc[unit], sizeof(struct ccd_softc));
1050a56bb8a5SSatoshi Asami 			free(vpp, M_DEVBUF);
1051a56bb8a5SSatoshi Asami 			free(cpp, M_DEVBUF);
1052a56bb8a5SSatoshi Asami 			ccdunlock(cs);
1053a56bb8a5SSatoshi Asami 			return (error);
1054a56bb8a5SSatoshi Asami 		}
1055a56bb8a5SSatoshi Asami 
1056a56bb8a5SSatoshi Asami 		/*
1057a56bb8a5SSatoshi Asami 		 * The ccd has been successfully initialized, so
1058a56bb8a5SSatoshi Asami 		 * we can place it into the array and read the disklabel.
1059a56bb8a5SSatoshi Asami 		 */
1060a56bb8a5SSatoshi Asami 		bcopy(&ccd, &ccddevs[unit], sizeof(ccd));
1061a56bb8a5SSatoshi Asami 		ccio->ccio_unit = unit;
1062a56bb8a5SSatoshi Asami 		ccio->ccio_size = cs->sc_size;
1063a56bb8a5SSatoshi Asami 		ccdgetdisklabel(dev);
1064a56bb8a5SSatoshi Asami 
1065a56bb8a5SSatoshi Asami 		ccdunlock(cs);
1066a56bb8a5SSatoshi Asami 
1067a56bb8a5SSatoshi Asami 		break;
1068a56bb8a5SSatoshi Asami 
1069a56bb8a5SSatoshi Asami 	case CCDIOCCLR:
1070a56bb8a5SSatoshi Asami 		if ((cs->sc_flags & CCDF_INITED) == 0)
1071a56bb8a5SSatoshi Asami 			return (ENXIO);
1072a56bb8a5SSatoshi Asami 
1073a56bb8a5SSatoshi Asami 		if ((flag & FWRITE) == 0)
1074a56bb8a5SSatoshi Asami 			return (EBADF);
1075a56bb8a5SSatoshi Asami 
1076a56bb8a5SSatoshi Asami 		if (error = ccdlock(cs))
1077a56bb8a5SSatoshi Asami 			return (error);
1078a56bb8a5SSatoshi Asami 
1079a56bb8a5SSatoshi Asami 		/*
1080a56bb8a5SSatoshi Asami 		 * Don't unconfigure if any other partitions are open
1081a56bb8a5SSatoshi Asami 		 * or if both the character and block flavors of this
1082a56bb8a5SSatoshi Asami 		 * partition are open.
1083a56bb8a5SSatoshi Asami 		 */
1084a56bb8a5SSatoshi Asami 		part = DISKPART(dev);
1085a56bb8a5SSatoshi Asami 		pmask = (1 << part);
1086a56bb8a5SSatoshi Asami 		if ((cs->sc_dkdev.dk_openmask & ~pmask) ||
1087a56bb8a5SSatoshi Asami 		    ((cs->sc_dkdev.dk_bopenmask & pmask) &&
1088a56bb8a5SSatoshi Asami 		    (cs->sc_dkdev.dk_copenmask & pmask))) {
1089a56bb8a5SSatoshi Asami 			ccdunlock(cs);
1090a56bb8a5SSatoshi Asami 			return (EBUSY);
1091a56bb8a5SSatoshi Asami 		}
1092a56bb8a5SSatoshi Asami 
1093a56bb8a5SSatoshi Asami 		/*
1094a56bb8a5SSatoshi Asami 		 * Free ccd_softc information and clear entry.
1095a56bb8a5SSatoshi Asami 		 */
1096a56bb8a5SSatoshi Asami 
1097a56bb8a5SSatoshi Asami 		/* Close the components and free their pathnames. */
1098a56bb8a5SSatoshi Asami 		for (i = 0; i < cs->sc_nccdisks; ++i) {
1099a56bb8a5SSatoshi Asami 			/*
1100a56bb8a5SSatoshi Asami 			 * XXX: this close could potentially fail and
1101a56bb8a5SSatoshi Asami 			 * cause Bad Things.  Maybe we need to force
1102a56bb8a5SSatoshi Asami 			 * the close to happen?
1103a56bb8a5SSatoshi Asami 			 */
1104a56bb8a5SSatoshi Asami #ifdef DEBUG
1105a56bb8a5SSatoshi Asami 			if (ccddebug & CCDB_VNODE)
1106a56bb8a5SSatoshi Asami 				vprint("CCDIOCCLR: vnode info",
1107a56bb8a5SSatoshi Asami 				    cs->sc_cinfo[i].ci_vp);
1108a56bb8a5SSatoshi Asami #endif
1109a56bb8a5SSatoshi Asami 			(void)vn_close(cs->sc_cinfo[i].ci_vp, FREAD|FWRITE,
1110a56bb8a5SSatoshi Asami 			    p->p_ucred, p);
1111a56bb8a5SSatoshi Asami 			free(cs->sc_cinfo[i].ci_path, M_DEVBUF);
1112a56bb8a5SSatoshi Asami 		}
1113a56bb8a5SSatoshi Asami 
1114a56bb8a5SSatoshi Asami 		/* Free interleave index. */
1115a56bb8a5SSatoshi Asami 		for (i = 0; cs->sc_itable[i].ii_ndisk; ++i)
1116a56bb8a5SSatoshi Asami 			free(cs->sc_itable[i].ii_index, M_DEVBUF);
1117a56bb8a5SSatoshi Asami 
1118a56bb8a5SSatoshi Asami 		/* Free component info and interleave table. */
1119a56bb8a5SSatoshi Asami 		free(cs->sc_cinfo, M_DEVBUF);
1120a56bb8a5SSatoshi Asami 		free(cs->sc_itable, M_DEVBUF);
1121a56bb8a5SSatoshi Asami 		cs->sc_flags &= ~CCDF_INITED;
1122a56bb8a5SSatoshi Asami 
1123a56bb8a5SSatoshi Asami 		/*
1124a56bb8a5SSatoshi Asami 		 * Free ccddevice information and clear entry.
1125a56bb8a5SSatoshi Asami 		 */
1126a56bb8a5SSatoshi Asami 		free(ccddevs[unit].ccd_cpp, M_DEVBUF);
1127a56bb8a5SSatoshi Asami 		free(ccddevs[unit].ccd_vpp, M_DEVBUF);
1128a56bb8a5SSatoshi Asami 		ccd.ccd_dk = -1;
1129a56bb8a5SSatoshi Asami 		bcopy(&ccd, &ccddevs[unit], sizeof(ccd));
1130a56bb8a5SSatoshi Asami 
1131a56bb8a5SSatoshi Asami 		/* This must be atomic. */
1132a56bb8a5SSatoshi Asami 		s = splhigh();
1133a56bb8a5SSatoshi Asami 		ccdunlock(cs);
1134a56bb8a5SSatoshi Asami 		bzero(cs, sizeof(struct ccd_softc));
1135a56bb8a5SSatoshi Asami 		splx(s);
1136a56bb8a5SSatoshi Asami 
1137a56bb8a5SSatoshi Asami 		break;
1138a56bb8a5SSatoshi Asami 
1139a56bb8a5SSatoshi Asami 	case DIOCGDINFO:
1140a56bb8a5SSatoshi Asami 		if ((cs->sc_flags & CCDF_INITED) == 0)
1141a56bb8a5SSatoshi Asami 			return (ENXIO);
1142a56bb8a5SSatoshi Asami 
1143a56bb8a5SSatoshi Asami 		*(struct disklabel *)data = cs->sc_dkdev.dk_label;
1144a56bb8a5SSatoshi Asami 		break;
1145a56bb8a5SSatoshi Asami 
1146a56bb8a5SSatoshi Asami 	case DIOCGPART:
1147a56bb8a5SSatoshi Asami 		if ((cs->sc_flags & CCDF_INITED) == 0)
1148a56bb8a5SSatoshi Asami 			return (ENXIO);
1149a56bb8a5SSatoshi Asami 
1150a56bb8a5SSatoshi Asami 		((struct partinfo *)data)->disklab = &cs->sc_dkdev.dk_label;
1151a56bb8a5SSatoshi Asami 		((struct partinfo *)data)->part =
1152a56bb8a5SSatoshi Asami 		    &cs->sc_dkdev.dk_label.d_partitions[DISKPART(dev)];
1153a56bb8a5SSatoshi Asami 		break;
1154a56bb8a5SSatoshi Asami 
1155a56bb8a5SSatoshi Asami 	case DIOCWDINFO:
1156a56bb8a5SSatoshi Asami 	case DIOCSDINFO:
1157a56bb8a5SSatoshi Asami 		if ((cs->sc_flags & CCDF_INITED) == 0)
1158a56bb8a5SSatoshi Asami 			return (ENXIO);
1159a56bb8a5SSatoshi Asami 
1160a56bb8a5SSatoshi Asami 		if ((flag & FWRITE) == 0)
1161a56bb8a5SSatoshi Asami 			return (EBADF);
1162a56bb8a5SSatoshi Asami 
1163a56bb8a5SSatoshi Asami 		if (error = ccdlock(cs))
1164a56bb8a5SSatoshi Asami 			return (error);
1165a56bb8a5SSatoshi Asami 
1166a56bb8a5SSatoshi Asami 		cs->sc_flags |= CCDF_LABELLING;
1167a56bb8a5SSatoshi Asami 
1168a56bb8a5SSatoshi Asami 		error = setdisklabel(&cs->sc_dkdev.dk_label,
1169a56bb8a5SSatoshi Asami 		    (struct disklabel *)data, 0, &cs->sc_dkdev.dk_cpulabel);
1170a56bb8a5SSatoshi Asami 		if (error == 0) {
1171a56bb8a5SSatoshi Asami 			if (cmd == DIOCWDINFO)
1172a56bb8a5SSatoshi Asami 				error = writedisklabel(CCDLABELDEV(dev),
1173a56bb8a5SSatoshi Asami 				    ccdstrategy, &cs->sc_dkdev.dk_label,
1174a56bb8a5SSatoshi Asami 				    &cs->sc_dkdev.dk_cpulabel);
1175a56bb8a5SSatoshi Asami 		}
1176a56bb8a5SSatoshi Asami 
1177a56bb8a5SSatoshi Asami 		cs->sc_flags &= ~CCDF_LABELLING;
1178a56bb8a5SSatoshi Asami 
1179a56bb8a5SSatoshi Asami 		ccdunlock(cs);
1180a56bb8a5SSatoshi Asami 
1181a56bb8a5SSatoshi Asami 		if (error)
1182a56bb8a5SSatoshi Asami 			return (error);
1183a56bb8a5SSatoshi Asami 		break;
1184a56bb8a5SSatoshi Asami 
1185a56bb8a5SSatoshi Asami 	case DIOCWLABEL:
1186a56bb8a5SSatoshi Asami 		if ((cs->sc_flags & CCDF_INITED) == 0)
1187a56bb8a5SSatoshi Asami 			return (ENXIO);
1188a56bb8a5SSatoshi Asami 
1189a56bb8a5SSatoshi Asami 		if ((flag & FWRITE) == 0)
1190a56bb8a5SSatoshi Asami 			return (EBADF);
1191a56bb8a5SSatoshi Asami 		if (*(int *)data != 0)
1192a56bb8a5SSatoshi Asami 			cs->sc_flags |= CCDF_WLABEL;
1193a56bb8a5SSatoshi Asami 		else
1194a56bb8a5SSatoshi Asami 			cs->sc_flags &= ~CCDF_WLABEL;
1195a56bb8a5SSatoshi Asami 		break;
1196a56bb8a5SSatoshi Asami 
1197a56bb8a5SSatoshi Asami 	default:
1198a56bb8a5SSatoshi Asami 		return (ENOTTY);
1199a56bb8a5SSatoshi Asami 	}
1200a56bb8a5SSatoshi Asami 
1201a56bb8a5SSatoshi Asami 	return (0);
1202a56bb8a5SSatoshi Asami }
1203a56bb8a5SSatoshi Asami 
1204a56bb8a5SSatoshi Asami int
1205a56bb8a5SSatoshi Asami ccdsize(dev)
1206a56bb8a5SSatoshi Asami 	dev_t dev;
1207a56bb8a5SSatoshi Asami {
1208a56bb8a5SSatoshi Asami 	struct ccd_softc *cs;
1209a56bb8a5SSatoshi Asami 	int part, size;
1210a56bb8a5SSatoshi Asami 
1211a56bb8a5SSatoshi Asami 	if (ccdopen(dev, 0, S_IFBLK, curproc))
1212a56bb8a5SSatoshi Asami 		return (-1);
1213a56bb8a5SSatoshi Asami 
1214a56bb8a5SSatoshi Asami 	cs = &ccd_softc[ccdunit(dev)];
1215a56bb8a5SSatoshi Asami 	part = DISKPART(dev);
1216a56bb8a5SSatoshi Asami 
1217a56bb8a5SSatoshi Asami 	if ((cs->sc_flags & CCDF_INITED) == 0)
1218a56bb8a5SSatoshi Asami 		return (-1);
1219a56bb8a5SSatoshi Asami 
1220a56bb8a5SSatoshi Asami 	if (cs->sc_dkdev.dk_label.d_partitions[part].p_fstype != FS_SWAP)
1221a56bb8a5SSatoshi Asami 		size = -1;
1222a56bb8a5SSatoshi Asami 	else
1223a56bb8a5SSatoshi Asami 		size = cs->sc_dkdev.dk_label.d_partitions[part].p_size;
1224a56bb8a5SSatoshi Asami 
1225a56bb8a5SSatoshi Asami 	if (ccdclose(dev, 0, S_IFBLK, curproc))
1226a56bb8a5SSatoshi Asami 		return (-1);
1227a56bb8a5SSatoshi Asami 
1228a56bb8a5SSatoshi Asami 	return (size);
1229a56bb8a5SSatoshi Asami }
1230a56bb8a5SSatoshi Asami 
1231a56bb8a5SSatoshi Asami int
1232a56bb8a5SSatoshi Asami ccddump(dev, blkno, va, size)
1233a56bb8a5SSatoshi Asami 	dev_t dev;
1234a56bb8a5SSatoshi Asami 	daddr_t blkno;
1235a56bb8a5SSatoshi Asami 	caddr_t va;
1236a56bb8a5SSatoshi Asami 	size_t size;
1237a56bb8a5SSatoshi Asami {
1238a56bb8a5SSatoshi Asami 
1239a56bb8a5SSatoshi Asami 	/* Not implemented. */
1240a56bb8a5SSatoshi Asami 	return ENXIO;
1241a56bb8a5SSatoshi Asami }
1242a56bb8a5SSatoshi Asami 
1243a56bb8a5SSatoshi Asami /*
1244a56bb8a5SSatoshi Asami  * Lookup the provided name in the filesystem.  If the file exists,
1245a56bb8a5SSatoshi Asami  * is a valid block device, and isn't being used by anyone else,
1246a56bb8a5SSatoshi Asami  * set *vpp to the file's vnode.
1247a56bb8a5SSatoshi Asami  */
1248a56bb8a5SSatoshi Asami static int
1249a56bb8a5SSatoshi Asami ccdlookup(path, p, vpp)
1250a56bb8a5SSatoshi Asami 	char *path;
1251a56bb8a5SSatoshi Asami 	struct proc *p;
1252a56bb8a5SSatoshi Asami 	struct vnode **vpp;	/* result */
1253a56bb8a5SSatoshi Asami {
1254a56bb8a5SSatoshi Asami 	struct nameidata nd;
1255a56bb8a5SSatoshi Asami 	struct vnode *vp;
1256a56bb8a5SSatoshi Asami 	struct vattr va;
1257a56bb8a5SSatoshi Asami 	int error;
1258a56bb8a5SSatoshi Asami 
1259a56bb8a5SSatoshi Asami 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, path, p);
1260a56bb8a5SSatoshi Asami 	if (error = vn_open(&nd, FREAD|FWRITE, 0)) {
1261a56bb8a5SSatoshi Asami #ifdef DEBUG
1262a56bb8a5SSatoshi Asami 		if (ccddebug & CCDB_FOLLOW|CCDB_INIT)
1263a56bb8a5SSatoshi Asami 			printf("ccdlookup: vn_open error = %d\n", error);
1264a56bb8a5SSatoshi Asami #endif
1265a56bb8a5SSatoshi Asami 		return (error);
1266a56bb8a5SSatoshi Asami 	}
1267a56bb8a5SSatoshi Asami 	vp = nd.ni_vp;
1268a56bb8a5SSatoshi Asami 
1269a56bb8a5SSatoshi Asami 	if (vp->v_usecount > 1) {
1270a56bb8a5SSatoshi Asami 		VOP_UNLOCK(vp);
1271a56bb8a5SSatoshi Asami 		(void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p);
1272a56bb8a5SSatoshi Asami 		return (EBUSY);
1273a56bb8a5SSatoshi Asami 	}
1274a56bb8a5SSatoshi Asami 
1275a56bb8a5SSatoshi Asami 	if (error = VOP_GETATTR(vp, &va, p->p_ucred, p)) {
1276a56bb8a5SSatoshi Asami #ifdef DEBUG
1277a56bb8a5SSatoshi Asami 		if (ccddebug & CCDB_FOLLOW|CCDB_INIT)
1278a56bb8a5SSatoshi Asami 			printf("ccdlookup: getattr error = %d\n", error);
1279a56bb8a5SSatoshi Asami #endif
1280a56bb8a5SSatoshi Asami 		VOP_UNLOCK(vp);
1281a56bb8a5SSatoshi Asami 		(void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p);
1282a56bb8a5SSatoshi Asami 		return (error);
1283a56bb8a5SSatoshi Asami 	}
1284a56bb8a5SSatoshi Asami 
1285a56bb8a5SSatoshi Asami 	/* XXX: eventually we should handle VREG, too. */
1286a56bb8a5SSatoshi Asami 	if (va.va_type != VBLK) {
1287a56bb8a5SSatoshi Asami 		VOP_UNLOCK(vp);
1288a56bb8a5SSatoshi Asami 		(void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p);
1289a56bb8a5SSatoshi Asami 		return (ENOTBLK);
1290a56bb8a5SSatoshi Asami 	}
1291a56bb8a5SSatoshi Asami 
1292a56bb8a5SSatoshi Asami #ifdef DEBUG
1293a56bb8a5SSatoshi Asami 	if (ccddebug & CCDB_VNODE)
1294a56bb8a5SSatoshi Asami 		vprint("ccdlookup: vnode info", vp);
1295a56bb8a5SSatoshi Asami #endif
1296a56bb8a5SSatoshi Asami 
1297a56bb8a5SSatoshi Asami 	VOP_UNLOCK(vp);
1298a56bb8a5SSatoshi Asami 	*vpp = vp;
1299a56bb8a5SSatoshi Asami 	return (0);
1300a56bb8a5SSatoshi Asami }
1301a56bb8a5SSatoshi Asami 
1302a56bb8a5SSatoshi Asami /*
1303a56bb8a5SSatoshi Asami  * Read the disklabel from the ccd.  If one is not present, fake one
1304a56bb8a5SSatoshi Asami  * up.
1305a56bb8a5SSatoshi Asami  */
1306a56bb8a5SSatoshi Asami static void
1307a56bb8a5SSatoshi Asami ccdgetdisklabel(dev)
1308a56bb8a5SSatoshi Asami 	dev_t dev;
1309a56bb8a5SSatoshi Asami {
1310a56bb8a5SSatoshi Asami 	int unit = ccdunit(dev);
1311a56bb8a5SSatoshi Asami 	struct ccd_softc *cs = &ccd_softc[unit];
1312a56bb8a5SSatoshi Asami 	char *errstring;
1313a56bb8a5SSatoshi Asami 	struct disklabel *lp = &cs->sc_dkdev.dk_label;
1314a56bb8a5SSatoshi Asami 	struct cpu_disklabel *clp = &cs->sc_dkdev.dk_cpulabel;
1315a56bb8a5SSatoshi Asami 	struct ccdgeom *ccg = &cs->sc_geom;
1316a56bb8a5SSatoshi Asami 
1317a56bb8a5SSatoshi Asami 	bzero(lp, sizeof(*lp));
1318a56bb8a5SSatoshi Asami 	bzero(clp, sizeof(*clp));
1319a56bb8a5SSatoshi Asami 
1320a56bb8a5SSatoshi Asami 	lp->d_secperunit = cs->sc_size;
1321a56bb8a5SSatoshi Asami 	lp->d_secsize = ccg->ccg_secsize;
1322a56bb8a5SSatoshi Asami 	lp->d_nsectors = ccg->ccg_nsectors;
1323a56bb8a5SSatoshi Asami 	lp->d_ntracks = ccg->ccg_ntracks;
1324a56bb8a5SSatoshi Asami 	lp->d_ncylinders = ccg->ccg_ncylinders;
1325a56bb8a5SSatoshi Asami 	lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
1326a56bb8a5SSatoshi Asami 
1327a56bb8a5SSatoshi Asami 	strncpy(lp->d_typename, "ccd", sizeof(lp->d_typename));
1328a56bb8a5SSatoshi Asami 	lp->d_type = DTYPE_CCD;
1329a56bb8a5SSatoshi Asami 	strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname));
1330a56bb8a5SSatoshi Asami 	lp->d_rpm = 3600;
1331a56bb8a5SSatoshi Asami 	lp->d_interleave = 1;
1332a56bb8a5SSatoshi Asami 	lp->d_flags = 0;
1333a56bb8a5SSatoshi Asami 
1334a56bb8a5SSatoshi Asami 	lp->d_partitions[RAW_PART].p_offset = 0;
1335a56bb8a5SSatoshi Asami 	lp->d_partitions[RAW_PART].p_size = cs->sc_size;
1336a56bb8a5SSatoshi Asami 	lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
1337a56bb8a5SSatoshi Asami 	lp->d_npartitions = RAW_PART + 1;
1338a56bb8a5SSatoshi Asami 
1339a56bb8a5SSatoshi Asami 	lp->d_magic = DISKMAGIC;
1340a56bb8a5SSatoshi Asami 	lp->d_magic2 = DISKMAGIC;
1341a56bb8a5SSatoshi Asami 	lp->d_checksum = dkcksum(&cs->sc_dkdev.dk_label);
1342a56bb8a5SSatoshi Asami 
1343a56bb8a5SSatoshi Asami 	/*
1344a56bb8a5SSatoshi Asami 	 * Call the generic disklabel extraction routine.
1345a56bb8a5SSatoshi Asami 	 */
1346a56bb8a5SSatoshi Asami 	if (errstring = readdisklabel(CCDLABELDEV(dev), ccdstrategy,
1347a56bb8a5SSatoshi Asami 	    &cs->sc_dkdev.dk_label, &cs->sc_dkdev.dk_cpulabel))
1348a56bb8a5SSatoshi Asami 		ccdmakedisklabel(cs);
1349a56bb8a5SSatoshi Asami 
1350a56bb8a5SSatoshi Asami #ifdef DEBUG
1351a56bb8a5SSatoshi Asami 	/* It's actually extremely common to have unlabeled ccds. */
1352a56bb8a5SSatoshi Asami 	if (ccddebug & CCDB_LABEL)
1353a56bb8a5SSatoshi Asami 		if (errstring != NULL)
1354a56bb8a5SSatoshi Asami 			printf("ccd%d: %s\n", unit, errstring);
1355a56bb8a5SSatoshi Asami #endif
1356a56bb8a5SSatoshi Asami }
1357a56bb8a5SSatoshi Asami 
1358a56bb8a5SSatoshi Asami /*
1359a56bb8a5SSatoshi Asami  * Take care of things one might want to take care of in the event
1360a56bb8a5SSatoshi Asami  * that a disklabel isn't present.
1361a56bb8a5SSatoshi Asami  */
1362a56bb8a5SSatoshi Asami static void
1363a56bb8a5SSatoshi Asami ccdmakedisklabel(cs)
1364a56bb8a5SSatoshi Asami 	struct ccd_softc *cs;
1365a56bb8a5SSatoshi Asami {
1366a56bb8a5SSatoshi Asami 	struct disklabel *lp = &cs->sc_dkdev.dk_label;
1367a56bb8a5SSatoshi Asami 
1368a56bb8a5SSatoshi Asami 	/*
1369a56bb8a5SSatoshi Asami 	 * For historical reasons, if there's no disklabel present
1370a56bb8a5SSatoshi Asami 	 * the raw partition must be marked FS_BSDFFS.
1371a56bb8a5SSatoshi Asami 	 */
1372a56bb8a5SSatoshi Asami 	lp->d_partitions[RAW_PART].p_fstype = FS_BSDFFS;
1373a56bb8a5SSatoshi Asami 
1374a56bb8a5SSatoshi Asami 	strncpy(lp->d_packname, "default label", sizeof(lp->d_packname));
1375a56bb8a5SSatoshi Asami }
1376a56bb8a5SSatoshi Asami 
1377a56bb8a5SSatoshi Asami /*
1378a56bb8a5SSatoshi Asami  * Wait interruptibly for an exclusive lock.
1379a56bb8a5SSatoshi Asami  *
1380a56bb8a5SSatoshi Asami  * XXX
1381a56bb8a5SSatoshi Asami  * Several drivers do this; it should be abstracted and made MP-safe.
1382a56bb8a5SSatoshi Asami  */
1383a56bb8a5SSatoshi Asami static int
1384a56bb8a5SSatoshi Asami ccdlock(cs)
1385a56bb8a5SSatoshi Asami 	struct ccd_softc *cs;
1386a56bb8a5SSatoshi Asami {
1387a56bb8a5SSatoshi Asami 	int error;
1388a56bb8a5SSatoshi Asami 
1389a56bb8a5SSatoshi Asami 	while ((cs->sc_flags & CCDF_LOCKED) != 0) {
1390a56bb8a5SSatoshi Asami 		cs->sc_flags |= CCDF_WANTED;
1391a56bb8a5SSatoshi Asami 		if ((error = tsleep(cs, PRIBIO | PCATCH, "ccdlck", 0)) != 0)
1392a56bb8a5SSatoshi Asami 			return (error);
1393a56bb8a5SSatoshi Asami 	}
1394a56bb8a5SSatoshi Asami 	cs->sc_flags |= CCDF_LOCKED;
1395a56bb8a5SSatoshi Asami 	return (0);
1396a56bb8a5SSatoshi Asami }
1397a56bb8a5SSatoshi Asami 
1398a56bb8a5SSatoshi Asami /*
1399a56bb8a5SSatoshi Asami  * Unlock and wake up any waiters.
1400a56bb8a5SSatoshi Asami  */
1401a56bb8a5SSatoshi Asami static void
1402a56bb8a5SSatoshi Asami ccdunlock(cs)
1403a56bb8a5SSatoshi Asami 	struct ccd_softc *cs;
1404a56bb8a5SSatoshi Asami {
1405a56bb8a5SSatoshi Asami 
1406a56bb8a5SSatoshi Asami 	cs->sc_flags &= ~CCDF_LOCKED;
1407a56bb8a5SSatoshi Asami 	if ((cs->sc_flags & CCDF_WANTED) != 0) {
1408a56bb8a5SSatoshi Asami 		cs->sc_flags &= ~CCDF_WANTED;
1409a56bb8a5SSatoshi Asami 		wakeup(cs);
1410a56bb8a5SSatoshi Asami 	}
1411a56bb8a5SSatoshi Asami }
1412a56bb8a5SSatoshi Asami 
1413a56bb8a5SSatoshi Asami #ifdef DEBUG
1414a56bb8a5SSatoshi Asami static void
1415a56bb8a5SSatoshi Asami printiinfo(ii)
1416a56bb8a5SSatoshi Asami 	struct ccdiinfo *ii;
1417a56bb8a5SSatoshi Asami {
1418a56bb8a5SSatoshi Asami 	register int ix, i;
1419a56bb8a5SSatoshi Asami 
1420a56bb8a5SSatoshi Asami 	for (ix = 0; ii->ii_ndisk; ix++, ii++) {
1421a56bb8a5SSatoshi Asami 		printf(" itab[%d]: #dk %d sblk %d soff %d",
1422a56bb8a5SSatoshi Asami 		       ix, ii->ii_ndisk, ii->ii_startblk, ii->ii_startoff);
1423a56bb8a5SSatoshi Asami 		for (i = 0; i < ii->ii_ndisk; i++)
1424a56bb8a5SSatoshi Asami 			printf(" %d", ii->ii_index[i]);
1425a56bb8a5SSatoshi Asami 		printf("\n");
1426a56bb8a5SSatoshi Asami 	}
1427a56bb8a5SSatoshi Asami }
1428a56bb8a5SSatoshi Asami #endif
1429