xref: /onnv-gate/usr/src/uts/common/io/pcmcia/pcdisk.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <sys/types.h>
30*0Sstevel@tonic-gate #include <sys/conf.h>
31*0Sstevel@tonic-gate #include <sys/dditypes.h>
32*0Sstevel@tonic-gate #include <sys/ddi.h>
33*0Sstevel@tonic-gate #include <sys/sunddi.h>
34*0Sstevel@tonic-gate 
35*0Sstevel@tonic-gate #include <sys/errno.h>
36*0Sstevel@tonic-gate #include <sys/debug.h>
37*0Sstevel@tonic-gate #include <sys/open.h>
38*0Sstevel@tonic-gate #include <sys/file.h>
39*0Sstevel@tonic-gate #include <sys/cmn_err.h>
40*0Sstevel@tonic-gate #include <sys/varargs.h>
41*0Sstevel@tonic-gate #include <sys/fs/pc_label.h>
42*0Sstevel@tonic-gate 
43*0Sstevel@tonic-gate #include <sys/hdio.h>
44*0Sstevel@tonic-gate #include <sys/dkio.h>
45*0Sstevel@tonic-gate #include <sys/dktp/dadkio.h>
46*0Sstevel@tonic-gate 
47*0Sstevel@tonic-gate #include <sys/dklabel.h>
48*0Sstevel@tonic-gate 
49*0Sstevel@tonic-gate #include <sys/vtoc.h>
50*0Sstevel@tonic-gate 
51*0Sstevel@tonic-gate 
52*0Sstevel@tonic-gate #include <sys/types.h>
53*0Sstevel@tonic-gate #include <sys/conf.h>
54*0Sstevel@tonic-gate #include <sys/dditypes.h>
55*0Sstevel@tonic-gate #include <sys/ddi.h>
56*0Sstevel@tonic-gate #include <sys/sunddi.h>
57*0Sstevel@tonic-gate #include <sys/dktp/cm.h>
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate #include <sys/dktp/fdisk.h>
60*0Sstevel@tonic-gate 
61*0Sstevel@tonic-gate #include <sys/pccard.h>
62*0Sstevel@tonic-gate #include <sys/pcmcia/pcata.h>
63*0Sstevel@tonic-gate 
64*0Sstevel@tonic-gate #define	MIN_SEC_SIZE	512
65*0Sstevel@tonic-gate 
66*0Sstevel@tonic-gate static int pcata_redo_vtoc(ata_soft_t *softp, buf_t *fdiskbp);
67*0Sstevel@tonic-gate static buf_t *pcata_lblk_alloc(dev_t dev);
68*0Sstevel@tonic-gate 
69*0Sstevel@tonic-gate /* Check media insertion/ejection status */
70*0Sstevel@tonic-gate static int pcata_check_media(ata_soft_t *rs, enum dkio_state state);
71*0Sstevel@tonic-gate 
72*0Sstevel@tonic-gate /*
73*0Sstevel@tonic-gate  * Queue a request and call start routine.
74*0Sstevel@tonic-gate  *
75*0Sstevel@tonic-gate  * If the request is not a special buffer request,
76*0Sstevel@tonic-gate  * do validation on it and generate both an absolute
77*0Sstevel@tonic-gate  * block number (which we will leave in b_resid),
78*0Sstevel@tonic-gate  * and a actual block count value (which we will
79*0Sstevel@tonic-gate  * leave in av_back).
80*0Sstevel@tonic-gate  */
81*0Sstevel@tonic-gate 
82*0Sstevel@tonic-gate int
pcata_strategy(buf_t * bp)83*0Sstevel@tonic-gate pcata_strategy(buf_t *bp)
84*0Sstevel@tonic-gate {
85*0Sstevel@tonic-gate 	ata_soft_t	*softp;
86*0Sstevel@tonic-gate 	ata_unit_t	*unitp;
87*0Sstevel@tonic-gate 	void		*instance;
88*0Sstevel@tonic-gate 	daddr_t		blkno;
89*0Sstevel@tonic-gate 	int		part;
90*0Sstevel@tonic-gate 	int		ret;
91*0Sstevel@tonic-gate 
92*0Sstevel@tonic-gate #ifdef ATA_DEBUG
93*0Sstevel@tonic-gate 	if (pcata_debug & DIO)
94*0Sstevel@tonic-gate 		cmn_err(CE_CONT, "_strategy\n");
95*0Sstevel@tonic-gate #endif
96*0Sstevel@tonic-gate 	bp->b_resid = bp->b_bcount;
97*0Sstevel@tonic-gate 
98*0Sstevel@tonic-gate 	if (pcata_getinfo(NULL, DDI_INFO_DEVT2INSTANCE, (void *)bp->b_edev,
99*0Sstevel@tonic-gate 	    &instance) != DDI_SUCCESS) {
100*0Sstevel@tonic-gate 		cmn_err(CE_CONT, "_strategy: pcata_getinfo ENODEV\n");
101*0Sstevel@tonic-gate 		bioerror(bp, ENODEV);
102*0Sstevel@tonic-gate 		biodone(bp);
103*0Sstevel@tonic-gate 		return (0);
104*0Sstevel@tonic-gate 	}
105*0Sstevel@tonic-gate 
106*0Sstevel@tonic-gate 	if (!(softp = ddi_get_soft_state(pcata_soft,
107*0Sstevel@tonic-gate 	    (int)(uintptr_t)instance))) {
108*0Sstevel@tonic-gate 		bioerror(bp, ENXIO);
109*0Sstevel@tonic-gate 		biodone(bp);
110*0Sstevel@tonic-gate 		return (0);
111*0Sstevel@tonic-gate 	}
112*0Sstevel@tonic-gate 
113*0Sstevel@tonic-gate 	if (!(CARD_PRESENT_VALID(softp))) {
114*0Sstevel@tonic-gate #ifdef ATA_DEBUG
115*0Sstevel@tonic-gate 		if (pcata_debug & DIO)
116*0Sstevel@tonic-gate 			cmn_err(CE_CONT, "_strategy card_state = %d bp=%p\n",
117*0Sstevel@tonic-gate 				softp->card_state,
118*0Sstevel@tonic-gate 				(void *)bp);
119*0Sstevel@tonic-gate #endif
120*0Sstevel@tonic-gate 		bioerror(bp, ENXIO);
121*0Sstevel@tonic-gate 		biodone(bp);
122*0Sstevel@tonic-gate 		return (0);
123*0Sstevel@tonic-gate 	}
124*0Sstevel@tonic-gate 
125*0Sstevel@tonic-gate 	if (bp->b_bcount & (NBPSCTR-1)) {
126*0Sstevel@tonic-gate 		bioerror(bp, ENXIO);
127*0Sstevel@tonic-gate 		biodone(bp);
128*0Sstevel@tonic-gate 		return (0);
129*0Sstevel@tonic-gate 	}
130*0Sstevel@tonic-gate 
131*0Sstevel@tonic-gate #ifdef	ATA_DEBUG
132*0Sstevel@tonic-gate 	if (pcata_debug & DIO) {
133*0Sstevel@tonic-gate 		cmn_err(CE_CONT, "_strategy: bp->b_private = %p\n",
134*0Sstevel@tonic-gate 			(void *)bp->b_private);
135*0Sstevel@tonic-gate 		cmn_err(CE_CONT, "_strategy %s request for buf: %p\n",
136*0Sstevel@tonic-gate 			bp->b_flags & B_READ ? "read" : "write", (void *)bp);
137*0Sstevel@tonic-gate 	}
138*0Sstevel@tonic-gate #endif
139*0Sstevel@tonic-gate 
140*0Sstevel@tonic-gate 	mutex_enter(&softp->ata_mutex);
141*0Sstevel@tonic-gate 
142*0Sstevel@tonic-gate 	/*
143*0Sstevel@tonic-gate 	 * pointer to structure for physical drive
144*0Sstevel@tonic-gate 	 */
145*0Sstevel@tonic-gate 	/*
146*0Sstevel@tonic-gate 	 * XXX/lcl since we don't traverse a_forw with some bits from minor
147*0Sstevel@tonic-gate 	 * (aka the UNIT macro) this means only 1 physical disk
148*0Sstevel@tonic-gate 	 * this error occurs everywhere ab_link is used!
149*0Sstevel@tonic-gate 	 */
150*0Sstevel@tonic-gate 	unitp = softp->ab_link;
151*0Sstevel@tonic-gate 	if (!unitp) {
152*0Sstevel@tonic-gate 		mutex_exit(&softp->ata_mutex);
153*0Sstevel@tonic-gate 		bioerror(bp, ENXIO);
154*0Sstevel@tonic-gate 		biodone(bp);
155*0Sstevel@tonic-gate 		return (0);
156*0Sstevel@tonic-gate 	}
157*0Sstevel@tonic-gate 
158*0Sstevel@tonic-gate 	/*
159*0Sstevel@tonic-gate 	 * A normal read/write command.
160*0Sstevel@tonic-gate 	 *
161*0Sstevel@tonic-gate 	 * If the transfer size would take it past the end of the
162*0Sstevel@tonic-gate 	 * partition, trim it down. Also trim it down to a multiple
163*0Sstevel@tonic-gate 	 * of the block size.
164*0Sstevel@tonic-gate 	 */
165*0Sstevel@tonic-gate 	bp->b_flags &= ~(B_DONE|B_ERROR);
166*0Sstevel@tonic-gate 	bp->av_forw = NULL;
167*0Sstevel@tonic-gate 	blkno = bp->b_blkno;
168*0Sstevel@tonic-gate 	part = LPART(bp->b_edev);
169*0Sstevel@tonic-gate 
170*0Sstevel@tonic-gate 
171*0Sstevel@tonic-gate 	/*
172*0Sstevel@tonic-gate 	 * Map block number within partition to absolute
173*0Sstevel@tonic-gate 	 * block number.
174*0Sstevel@tonic-gate 	 */
175*0Sstevel@tonic-gate #ifdef ATA_DEBUG
176*0Sstevel@tonic-gate 	if (pcata_debug & DIO)
177*0Sstevel@tonic-gate 		cmn_err(CE_CONT, "_strategy  "
178*0Sstevel@tonic-gate 			"%c%d: %s block %ld mapped to %ld dev %lx\n",
179*0Sstevel@tonic-gate 			(part > 15 ? 'p' : 's'),
180*0Sstevel@tonic-gate 			(part > 15 ? part - 16 : part),
181*0Sstevel@tonic-gate 			bp->b_flags & B_READ ? "read" : "write",
182*0Sstevel@tonic-gate 			blkno,
183*0Sstevel@tonic-gate 			blkno + unitp->lbl.pmap[part].p_start,
184*0Sstevel@tonic-gate 			bp->b_edev);
185*0Sstevel@tonic-gate #endif
186*0Sstevel@tonic-gate 
187*0Sstevel@tonic-gate 	/* make sure this partition exists */
188*0Sstevel@tonic-gate 	if (unitp->lbl.pmap[part].p_size == 0) {
189*0Sstevel@tonic-gate #ifdef ATA_DEBUG
190*0Sstevel@tonic-gate 		cmn_err(CE_CONT, "_strategy:invalid slice part=%d\n", part);
191*0Sstevel@tonic-gate #endif
192*0Sstevel@tonic-gate 		mutex_exit(&softp->ata_mutex);
193*0Sstevel@tonic-gate 		bioerror(bp, ENXIO);
194*0Sstevel@tonic-gate 		biodone(bp);
195*0Sstevel@tonic-gate 		return (0);
196*0Sstevel@tonic-gate 	}
197*0Sstevel@tonic-gate 
198*0Sstevel@tonic-gate 	/* make sure the I/O begins at a block within the partition */
199*0Sstevel@tonic-gate 	if (blkno < 0 || blkno >= unitp->lbl.pmap[part].p_size) {
200*0Sstevel@tonic-gate #ifdef ATA_DEBUG
201*0Sstevel@tonic-gate 		cmn_err(CE_CONT, "_strategy:block number out of range\n");
202*0Sstevel@tonic-gate #endif
203*0Sstevel@tonic-gate 		mutex_exit(&softp->ata_mutex);
204*0Sstevel@tonic-gate 		bioerror(bp, ENXIO);
205*0Sstevel@tonic-gate 		biodone(bp);
206*0Sstevel@tonic-gate 		return (0);
207*0Sstevel@tonic-gate 	}
208*0Sstevel@tonic-gate 
209*0Sstevel@tonic-gate 	/* XXX/lcl check to make sure I/O doesn't go past end of partition */
210*0Sstevel@tonic-gate 
211*0Sstevel@tonic-gate 	/* put block number into b_resid and number of blocks into av_back */
212*0Sstevel@tonic-gate 	bp->b_resid = bp->b_bcount;
213*0Sstevel@tonic-gate 	bp->av_back = (buf_t *)(ROUNDUP(bp->b_bcount, NBPSCTR) >> SCTRSHFT);
214*0Sstevel@tonic-gate 
215*0Sstevel@tonic-gate 	blkno += unitp->lbl.pmap[part].p_start;
216*0Sstevel@tonic-gate 
217*0Sstevel@tonic-gate 	ret = pcata_start(unitp, bp, blkno);
218*0Sstevel@tonic-gate 	mutex_exit(&softp->ata_mutex);
219*0Sstevel@tonic-gate 
220*0Sstevel@tonic-gate 	if (ret != CTL_SEND_SUCCESS) {
221*0Sstevel@tonic-gate 		bp->b_resid = bp->b_bcount;
222*0Sstevel@tonic-gate #ifdef ATA_DEBUG
223*0Sstevel@tonic-gate 		cmn_err(CE_CONT, "_strategy: ata_start failed bp 0x%p\n",
224*0Sstevel@tonic-gate 			(void *)bp);
225*0Sstevel@tonic-gate #endif
226*0Sstevel@tonic-gate 		bioerror(bp, EIO);
227*0Sstevel@tonic-gate 		biodone(bp);
228*0Sstevel@tonic-gate 		return (0);
229*0Sstevel@tonic-gate 	}
230*0Sstevel@tonic-gate 
231*0Sstevel@tonic-gate 	/*
232*0Sstevel@tonic-gate 	 * If the disk block to be written to is disk block 0, it would
233*0Sstevel@tonic-gate 	 * mean the partition table is changing from underneath us
234*0Sstevel@tonic-gate 	 * we shoud trap and update the in memory image.
235*0Sstevel@tonic-gate 	 * By now the buffer is mapped in and we should be able to
236*0Sstevel@tonic-gate 	 * use the contents as the new fdisk partition.
237*0Sstevel@tonic-gate 	 */
238*0Sstevel@tonic-gate 	if ((bp->b_flags & B_WRITE) && ((bp->b_flags & B_ERROR) != B_ERROR) &&
239*0Sstevel@tonic-gate 		blkno == 0) {
240*0Sstevel@tonic-gate 		if (pcata_redo_vtoc(softp, bp)) {
241*0Sstevel@tonic-gate 			bioerror(bp, EFAULT);
242*0Sstevel@tonic-gate 			biodone(bp);
243*0Sstevel@tonic-gate 			return (0);
244*0Sstevel@tonic-gate 		}
245*0Sstevel@tonic-gate 	}
246*0Sstevel@tonic-gate 
247*0Sstevel@tonic-gate 	return (0);
248*0Sstevel@tonic-gate }
249*0Sstevel@tonic-gate 
250*0Sstevel@tonic-gate /*
251*0Sstevel@tonic-gate  * This routine implements the ioctl calls for the ATA
252*0Sstevel@tonic-gate  */
253*0Sstevel@tonic-gate #define	COPYOUT(a, b, c, f)	\
254*0Sstevel@tonic-gate 	ddi_copyout((caddr_t)(a), (caddr_t)(b), sizeof (c), f)
255*0Sstevel@tonic-gate #define	COPYIN(a, b, c, f)	\
256*0Sstevel@tonic-gate 	ddi_copyin((caddr_t)(a), (caddr_t)(b), sizeof (c), f)
257*0Sstevel@tonic-gate 
258*0Sstevel@tonic-gate /* ARGSUSED3 */
259*0Sstevel@tonic-gate int
pcata_ioctl(dev_t dev,int cmd,intptr_t arg,int flag,cred_t * cred_p,int * rval_p)260*0Sstevel@tonic-gate pcata_ioctl(
261*0Sstevel@tonic-gate 	dev_t dev,
262*0Sstevel@tonic-gate 	int cmd,
263*0Sstevel@tonic-gate 	intptr_t arg,
264*0Sstevel@tonic-gate 	int flag,
265*0Sstevel@tonic-gate 	cred_t *cred_p,
266*0Sstevel@tonic-gate 	int *rval_p)
267*0Sstevel@tonic-gate {
268*0Sstevel@tonic-gate 	uint32_t	data[512 / (sizeof (uint32_t))];
269*0Sstevel@tonic-gate 	void		*instance;
270*0Sstevel@tonic-gate 	ata_soft_t	*softp;
271*0Sstevel@tonic-gate 	ata_unit_t	*unitp;
272*0Sstevel@tonic-gate 	struct dk_cinfo *info;
273*0Sstevel@tonic-gate 	int		i, status;
274*0Sstevel@tonic-gate 	int		err;
275*0Sstevel@tonic-gate 	enum dkio_state	state;
276*0Sstevel@tonic-gate 
277*0Sstevel@tonic-gate #ifdef ATA_DEBUG
278*0Sstevel@tonic-gate 	if (pcata_debug & DIO) cmn_err(CE_CONT, "_ioctl\n");
279*0Sstevel@tonic-gate #endif
280*0Sstevel@tonic-gate 	if (pcata_getinfo(NULL, DDI_INFO_DEVT2INSTANCE, (void *)dev,
281*0Sstevel@tonic-gate 	    &instance) != DDI_SUCCESS)
282*0Sstevel@tonic-gate 		return (ENODEV);
283*0Sstevel@tonic-gate 
284*0Sstevel@tonic-gate 	if (!(softp = ddi_get_soft_state(pcata_soft,
285*0Sstevel@tonic-gate 	    (int)(uintptr_t)instance))) {
286*0Sstevel@tonic-gate 		return (ENXIO);
287*0Sstevel@tonic-gate 	}
288*0Sstevel@tonic-gate 
289*0Sstevel@tonic-gate 
290*0Sstevel@tonic-gate #ifdef ATA_DEBUG
291*0Sstevel@tonic-gate 	if (pcata_debug & DENT) {
292*0Sstevel@tonic-gate 		char    *cmdname;
293*0Sstevel@tonic-gate 
294*0Sstevel@tonic-gate 		switch (cmd) {
295*0Sstevel@tonic-gate 		case DKIOCINFO:		cmdname = "DKIOCINFO       "; break;
296*0Sstevel@tonic-gate 		case DKIOCREMOVABLE:	cmdname = "DKIOCREMOVABLE  "; break;
297*0Sstevel@tonic-gate 		case DKIOCGMEDIAINFO:   cmdname = "DKIOCGMEDIAINFO "; break;
298*0Sstevel@tonic-gate 		case DKIOCGGEOM:	cmdname = "DKIOCGGEOM      "; break;
299*0Sstevel@tonic-gate 		case DKIOCGAPART:	cmdname = "DKIOCGAPART     "; break;
300*0Sstevel@tonic-gate 		case DKIOCSAPART:	cmdname = "DKIOCSAPART     "; break;
301*0Sstevel@tonic-gate 		case DKIOCGVTOC:	cmdname = "DKIOCGVTOC      "; break;
302*0Sstevel@tonic-gate 		case DKIOCSVTOC:	cmdname = "DKIOCSVTOC      "; break;
303*0Sstevel@tonic-gate 		case DKIOCG_VIRTGEOM:	cmdname = "DKIOCG_VIRTGEOM "; break;
304*0Sstevel@tonic-gate 		case DKIOCG_PHYGEOM:	cmdname = "DKIOCG_PHYGEOM  "; break;
305*0Sstevel@tonic-gate 		case DKIOCEJECT:	cmdname = "DKIOCEJECT     *"; break;
306*0Sstevel@tonic-gate 		case DKIOCSGEOM:	cmdname = "DKIOCSGEOM     *"; break;
307*0Sstevel@tonic-gate 		case DKIOCSTATE:	cmdname = "DKIOCSTATE     *"; break;
308*0Sstevel@tonic-gate 		case DKIOCADDBAD:	cmdname = "DKIOCADDBAD    *"; break;
309*0Sstevel@tonic-gate 		case DKIOCGETDEF:	cmdname = "DKIOCGETDEF    *"; break;
310*0Sstevel@tonic-gate 		case DKIOCPARTINFO:	cmdname = "DKIOCPARTINFO  *"; break;
311*0Sstevel@tonic-gate 		case DIOCTL_RWCMD:	cmdname = "DIOCTL_RWCMD    "; break;
312*0Sstevel@tonic-gate 		default:		cmdname = "UNKNOWN        *"; break;
313*0Sstevel@tonic-gate 		}
314*0Sstevel@tonic-gate 		cmn_err(CE_CONT,
315*0Sstevel@tonic-gate 			"_ioctl%d: cmd %x(%s) arg %p softp %p\n",
316*0Sstevel@tonic-gate 			(int)(uintptr_t)instance, cmd, cmdname, (void *)arg,
317*0Sstevel@tonic-gate 			(void *)softp);
318*0Sstevel@tonic-gate 	}
319*0Sstevel@tonic-gate #endif
320*0Sstevel@tonic-gate 
321*0Sstevel@tonic-gate 	/*
322*0Sstevel@tonic-gate 	 * We should process DKIOCSTATE cmd even if CARD is not PRESENT.
323*0Sstevel@tonic-gate 	 * The DKIOCSTATE command should BLOCK if there is no change in state.
324*0Sstevel@tonic-gate 	 * Only when softp->state != state the control returns to the caller.
325*0Sstevel@tonic-gate 	 * This check is done in pcata_check_media().
326*0Sstevel@tonic-gate 	 * There are 3 states for the device.
327*0Sstevel@tonic-gate 	 *	DKIO_NONE
328*0Sstevel@tonic-gate 	 *	DKIO_INSERTED
329*0Sstevel@tonic-gate 	 *	DKIO_EJECTED
330*0Sstevel@tonic-gate 	 * The state transitions are as follows
331*0Sstevel@tonic-gate 	 * DKIO_NONE-DKIO_INSERTED-DKIO_EJECTED-DKIO_NONE-DKIO_INSERTED...
332*0Sstevel@tonic-gate 	 */
333*0Sstevel@tonic-gate 	if (cmd == DKIOCSTATE) {
334*0Sstevel@tonic-gate 		if (ddi_copyin((caddr_t)arg, (caddr_t)&state,
335*0Sstevel@tonic-gate 		    sizeof (state), flag)) {
336*0Sstevel@tonic-gate 			return (EFAULT);
337*0Sstevel@tonic-gate 		}
338*0Sstevel@tonic-gate 
339*0Sstevel@tonic-gate 		/*
340*0Sstevel@tonic-gate 		 * This function is used by the volume management
341*0Sstevel@tonic-gate 		 * to check the pcata card state
342*0Sstevel@tonic-gate 		 */
343*0Sstevel@tonic-gate 		if (err = pcata_check_media(softp, state)) {
344*0Sstevel@tonic-gate 			return (err);
345*0Sstevel@tonic-gate 		}
346*0Sstevel@tonic-gate 
347*0Sstevel@tonic-gate 		if (ddi_copyout((caddr_t)&softp->media_state,
348*0Sstevel@tonic-gate 			(caddr_t)arg, sizeof (softp->media_state), flag)) {
349*0Sstevel@tonic-gate 			return (EFAULT);
350*0Sstevel@tonic-gate 		}
351*0Sstevel@tonic-gate 		return (0);
352*0Sstevel@tonic-gate 	}
353*0Sstevel@tonic-gate 
354*0Sstevel@tonic-gate 	if (!(CARD_PRESENT_VALID(softp))) {
355*0Sstevel@tonic-gate 		return (ENODEV);
356*0Sstevel@tonic-gate 	}
357*0Sstevel@tonic-gate 
358*0Sstevel@tonic-gate 
359*0Sstevel@tonic-gate 	/*
360*0Sstevel@tonic-gate 	 * we can respond to get geom ioctl() only while the driver has
361*0Sstevel@tonic-gate 	 * not completed initialization.
362*0Sstevel@tonic-gate 	 */
363*0Sstevel@tonic-gate 	if ((softp->flags & PCATA_READY) == 0 && cmd != DKIOCG_PHYGEOM) {
364*0Sstevel@tonic-gate 		(void) pcata_readywait(softp);
365*0Sstevel@tonic-gate 		if (!(softp->flags & PCATA_READY))
366*0Sstevel@tonic-gate 			return (EFAULT);
367*0Sstevel@tonic-gate 	}
368*0Sstevel@tonic-gate 
369*0Sstevel@tonic-gate 	ASSERT(softp->ab_link);
370*0Sstevel@tonic-gate 	unitp = softp->ab_link;
371*0Sstevel@tonic-gate 	bzero((caddr_t)data, sizeof (data));
372*0Sstevel@tonic-gate 
373*0Sstevel@tonic-gate 	switch (cmd) {
374*0Sstevel@tonic-gate 	case DKIOCGGEOM:
375*0Sstevel@tonic-gate 	case DKIOCSGEOM:
376*0Sstevel@tonic-gate 	case DKIOCGAPART:
377*0Sstevel@tonic-gate 	case DKIOCSAPART:
378*0Sstevel@tonic-gate 	case DKIOCGVTOC:
379*0Sstevel@tonic-gate 	case DKIOCSVTOC:
380*0Sstevel@tonic-gate 		status = 0;
381*0Sstevel@tonic-gate 		mutex_enter(&softp->label_mutex);
382*0Sstevel@tonic-gate 		status = pcata_lbl_ioctl(dev, cmd, arg, flag);
383*0Sstevel@tonic-gate 		mutex_exit(&softp->label_mutex);
384*0Sstevel@tonic-gate 		return (status);
385*0Sstevel@tonic-gate 	}
386*0Sstevel@tonic-gate 
387*0Sstevel@tonic-gate 	switch (cmd) {
388*0Sstevel@tonic-gate 
389*0Sstevel@tonic-gate 	case DKIOCINFO:
390*0Sstevel@tonic-gate 
391*0Sstevel@tonic-gate 		info = (struct dk_cinfo *)data;
392*0Sstevel@tonic-gate 		/*
393*0Sstevel@tonic-gate 		 * Controller Information
394*0Sstevel@tonic-gate 		 */
395*0Sstevel@tonic-gate 		info->dki_ctype = DKC_PCMCIA_ATA;
396*0Sstevel@tonic-gate 		info->dki_cnum = ddi_get_instance(softp->dip);
397*0Sstevel@tonic-gate 		(void) strcpy(info->dki_cname,
398*0Sstevel@tonic-gate 		    ddi_get_name(ddi_get_parent(softp->dip)));
399*0Sstevel@tonic-gate 
400*0Sstevel@tonic-gate 		/*
401*0Sstevel@tonic-gate 		 * Unit Information
402*0Sstevel@tonic-gate 		 */
403*0Sstevel@tonic-gate 		info->dki_unit = ddi_get_instance(softp->dip);
404*0Sstevel@tonic-gate 		info->dki_slave = 0;
405*0Sstevel@tonic-gate 		(void) strcpy(info->dki_dname, "card");
406*0Sstevel@tonic-gate 		info->dki_flags = DKI_FMTVOL;
407*0Sstevel@tonic-gate 		info->dki_partition = LPART(dev);
408*0Sstevel@tonic-gate 		info->dki_maxtransfer = softp->ab_max_transfer;
409*0Sstevel@tonic-gate 
410*0Sstevel@tonic-gate 		/*
411*0Sstevel@tonic-gate 		 * We can't get from here to there yet
412*0Sstevel@tonic-gate 		 */
413*0Sstevel@tonic-gate 		info->dki_addr = 0;
414*0Sstevel@tonic-gate 		info->dki_space = 0;
415*0Sstevel@tonic-gate 		info->dki_prio = 0;
416*0Sstevel@tonic-gate 		info->dki_vec = 0;
417*0Sstevel@tonic-gate 
418*0Sstevel@tonic-gate 		if (COPYOUT(data, arg, struct dk_cinfo, flag))
419*0Sstevel@tonic-gate 			return (EFAULT);
420*0Sstevel@tonic-gate 		break;
421*0Sstevel@tonic-gate 
422*0Sstevel@tonic-gate 	case DKIOCG_VIRTGEOM:
423*0Sstevel@tonic-gate 	case DKIOCG_PHYGEOM:
424*0Sstevel@tonic-gate 
425*0Sstevel@tonic-gate 		{
426*0Sstevel@tonic-gate 		struct dk_geom dkg;
427*0Sstevel@tonic-gate 		status = 0;
428*0Sstevel@tonic-gate 
429*0Sstevel@tonic-gate 		bzero((caddr_t)&dkg, sizeof (struct dk_geom));
430*0Sstevel@tonic-gate 		mutex_enter(&softp->ata_mutex);
431*0Sstevel@tonic-gate 		unitp = softp->ab_link;
432*0Sstevel@tonic-gate 		if (unitp != 0) {
433*0Sstevel@tonic-gate 			dkg.dkg_ncyl  	= unitp->au_cyl;
434*0Sstevel@tonic-gate 			dkg.dkg_acyl  	= unitp->au_acyl;
435*0Sstevel@tonic-gate 			dkg.dkg_pcyl  	= unitp->au_cyl+unitp->au_acyl;
436*0Sstevel@tonic-gate 			dkg.dkg_nhead 	= unitp->au_hd;
437*0Sstevel@tonic-gate 			dkg.dkg_nsect 	= unitp->au_sec;
438*0Sstevel@tonic-gate 		} else
439*0Sstevel@tonic-gate 			status = EFAULT;
440*0Sstevel@tonic-gate 		mutex_exit(&softp->ata_mutex);
441*0Sstevel@tonic-gate 		if (status)
442*0Sstevel@tonic-gate 			return (EFAULT);
443*0Sstevel@tonic-gate 
444*0Sstevel@tonic-gate 		if (ddi_copyout((caddr_t)&dkg, (caddr_t)arg,
445*0Sstevel@tonic-gate 		    sizeof (struct dk_geom), flag))
446*0Sstevel@tonic-gate 			return (EFAULT);
447*0Sstevel@tonic-gate 		else
448*0Sstevel@tonic-gate 			return (0);
449*0Sstevel@tonic-gate 		}
450*0Sstevel@tonic-gate 
451*0Sstevel@tonic-gate 	case DKIOCGMEDIAINFO:
452*0Sstevel@tonic-gate 
453*0Sstevel@tonic-gate 		{
454*0Sstevel@tonic-gate 		struct dk_minfo media_info;
455*0Sstevel@tonic-gate 		int	secsize;
456*0Sstevel@tonic-gate 
457*0Sstevel@tonic-gate 		media_info.dki_media_type = DK_FIXED_DISK;
458*0Sstevel@tonic-gate 		/*
459*0Sstevel@tonic-gate 		 * atarp_secsize contains the unformatted sector size.
460*0Sstevel@tonic-gate 		 * Using this we determine the actual sector size.
461*0Sstevel@tonic-gate 		 * sector sizes are a multiple of MIN_SEC_SIZE(512).
462*0Sstevel@tonic-gate 		 */
463*0Sstevel@tonic-gate 		secsize = softp->ab_rpbp[0]->atarp_secsiz;
464*0Sstevel@tonic-gate 		secsize = (((secsize)/MIN_SEC_SIZE) * MIN_SEC_SIZE);
465*0Sstevel@tonic-gate 		media_info.dki_lbsize = secsize;
466*0Sstevel@tonic-gate 		media_info.dki_capacity = unitp->au_cyl * unitp->au_hd *
467*0Sstevel@tonic-gate 		    unitp->au_sec;
468*0Sstevel@tonic-gate 		if (ddi_copyout((caddr_t)&media_info, (caddr_t)arg,
469*0Sstevel@tonic-gate 		    sizeof (struct dk_minfo), flag))
470*0Sstevel@tonic-gate 			return (EFAULT);
471*0Sstevel@tonic-gate 		else
472*0Sstevel@tonic-gate 			return (0);
473*0Sstevel@tonic-gate 		}
474*0Sstevel@tonic-gate 
475*0Sstevel@tonic-gate 	case DKIOCREMOVABLE:
476*0Sstevel@tonic-gate 
477*0Sstevel@tonic-gate 		{
478*0Sstevel@tonic-gate 		/*
479*0Sstevel@tonic-gate 		 * Supporting volmgt by returning a constant
480*0Sstevel@tonic-gate 		 *	since PCMCIA is a removable media.
481*0Sstevel@tonic-gate 		 *	Refer to PSARC/1996/004.
482*0Sstevel@tonic-gate 		 */
483*0Sstevel@tonic-gate 		i = 1;
484*0Sstevel@tonic-gate 		if (ddi_copyout((caddr_t)&i, (caddr_t)arg, sizeof (int),
485*0Sstevel@tonic-gate 		    flag)) {
486*0Sstevel@tonic-gate 			return (EFAULT);
487*0Sstevel@tonic-gate 		}
488*0Sstevel@tonic-gate 		break;
489*0Sstevel@tonic-gate 		}
490*0Sstevel@tonic-gate 
491*0Sstevel@tonic-gate 	case DIOCTL_RWCMD:
492*0Sstevel@tonic-gate 		{
493*0Sstevel@tonic-gate 		int	rw;
494*0Sstevel@tonic-gate 		int	status;
495*0Sstevel@tonic-gate 		struct dadkio_rwcmd	rwcmd;
496*0Sstevel@tonic-gate 		struct buf		*bp;
497*0Sstevel@tonic-gate 		struct iovec		aiov;
498*0Sstevel@tonic-gate 		struct uio		auio;
499*0Sstevel@tonic-gate 
500*0Sstevel@tonic-gate #if defined(_MULTI_DATAMODEL)
501*0Sstevel@tonic-gate 		switch (ddi_model_convert_from(flag & FMODELS)) {
502*0Sstevel@tonic-gate 
503*0Sstevel@tonic-gate 		case DDI_MODEL_ILP32: {
504*0Sstevel@tonic-gate 			struct dadkio_rwcmd32	rwcmd32;
505*0Sstevel@tonic-gate 
506*0Sstevel@tonic-gate 			if (ddi_copyin((caddr_t)arg, (caddr_t)&rwcmd32,
507*0Sstevel@tonic-gate 				sizeof (struct dadkio_rwcmd32), flag)) {
508*0Sstevel@tonic-gate 				return (EFAULT);
509*0Sstevel@tonic-gate 			}
510*0Sstevel@tonic-gate 			rwcmd.cmd = rwcmd32.cmd;
511*0Sstevel@tonic-gate 			rwcmd.flags = rwcmd32.flags;
512*0Sstevel@tonic-gate 			rwcmd.blkaddr = (daddr_t)rwcmd32.blkaddr;
513*0Sstevel@tonic-gate 			rwcmd.buflen = rwcmd32.buflen;
514*0Sstevel@tonic-gate 			rwcmd.bufaddr = (caddr_t)(uintptr_t)rwcmd32.bufaddr;
515*0Sstevel@tonic-gate 			break;
516*0Sstevel@tonic-gate 		}
517*0Sstevel@tonic-gate 
518*0Sstevel@tonic-gate 		case DDI_MODEL_NONE:
519*0Sstevel@tonic-gate 			if (ddi_copyin((caddr_t)arg, (caddr_t)&rwcmd,
520*0Sstevel@tonic-gate 				sizeof (struct dadkio_rwcmd), flag)) {
521*0Sstevel@tonic-gate 				return (EFAULT);
522*0Sstevel@tonic-gate 			}
523*0Sstevel@tonic-gate 			break;
524*0Sstevel@tonic-gate 		}
525*0Sstevel@tonic-gate #else	/*  _MULTI_DATAMODEL */
526*0Sstevel@tonic-gate 		if (ddi_copyin((caddr_t)arg, (caddr_t)&rwcmd,
527*0Sstevel@tonic-gate 			sizeof (struct dadkio_rwcmd), flag)) {
528*0Sstevel@tonic-gate 			return (EFAULT);
529*0Sstevel@tonic-gate 		}
530*0Sstevel@tonic-gate #endif	/*  _MULTI_DATAMODEL */
531*0Sstevel@tonic-gate 
532*0Sstevel@tonic-gate 		switch (rwcmd.cmd) {
533*0Sstevel@tonic-gate 		case DADKIO_RWCMD_READ:
534*0Sstevel@tonic-gate 			rw = B_READ;
535*0Sstevel@tonic-gate 			break;
536*0Sstevel@tonic-gate 		case DADKIO_RWCMD_WRITE:
537*0Sstevel@tonic-gate 			rw = B_WRITE;
538*0Sstevel@tonic-gate 			break;
539*0Sstevel@tonic-gate 		default:
540*0Sstevel@tonic-gate 			return (EINVAL);
541*0Sstevel@tonic-gate 		}
542*0Sstevel@tonic-gate 
543*0Sstevel@tonic-gate 		bp		= getrbuf(KM_SLEEP);
544*0Sstevel@tonic-gate 		bp->b_back	= (buf_t *)&rwcmd;	/* ioctl packet */
545*0Sstevel@tonic-gate 		bp->b_private	= (void *)0xBEE;
546*0Sstevel@tonic-gate 
547*0Sstevel@tonic-gate 		bzero((caddr_t)&aiov, sizeof (struct iovec));
548*0Sstevel@tonic-gate 		aiov.iov_base	= rwcmd.bufaddr;
549*0Sstevel@tonic-gate 		aiov.iov_len	= rwcmd.buflen;
550*0Sstevel@tonic-gate 
551*0Sstevel@tonic-gate 		bzero((caddr_t)&auio, sizeof (struct uio));
552*0Sstevel@tonic-gate 		auio.uio_iov	= &aiov;
553*0Sstevel@tonic-gate 		auio.uio_iovcnt	= 1;
554*0Sstevel@tonic-gate 		auio.uio_resid	= rwcmd.buflen;
555*0Sstevel@tonic-gate 		auio.uio_segflg	= flag & FKIOCTL ? UIO_SYSSPACE : UIO_USERSPACE;
556*0Sstevel@tonic-gate 
557*0Sstevel@tonic-gate 		status = physio(pcata_strategy, bp, dev, rw, pcata_min, &auio);
558*0Sstevel@tonic-gate 
559*0Sstevel@tonic-gate 		freerbuf(bp);
560*0Sstevel@tonic-gate 
561*0Sstevel@tonic-gate 		return (status);
562*0Sstevel@tonic-gate 		}
563*0Sstevel@tonic-gate 
564*0Sstevel@tonic-gate 	case DKIOCEJECT:
565*0Sstevel@tonic-gate 		/*
566*0Sstevel@tonic-gate 		 * Since we do not have hardware support for ejecting
567*0Sstevel@tonic-gate 		 * a pcata card, we must not support the generic eject
568*0Sstevel@tonic-gate 		 * ioctl (DKIOCEJECT) which is used for eject(1) command
569*0Sstevel@tonic-gate 		 * because it leads the user to expect behavior that is
570*0Sstevel@tonic-gate 		 * not present.
571*0Sstevel@tonic-gate 		 */
572*0Sstevel@tonic-gate 		return (ENOSYS);
573*0Sstevel@tonic-gate 
574*0Sstevel@tonic-gate 	case HDKIOCSCMD:
575*0Sstevel@tonic-gate 	case HDKIOCGDIAG:
576*0Sstevel@tonic-gate 		break;
577*0Sstevel@tonic-gate 	default:
578*0Sstevel@tonic-gate 		return (ENOTTY);
579*0Sstevel@tonic-gate 	}
580*0Sstevel@tonic-gate 	return (0);
581*0Sstevel@tonic-gate }
582*0Sstevel@tonic-gate 
583*0Sstevel@tonic-gate int
pcata_lbl_ioctl(dev_t dev,int cmd,intptr_t arg,int flag)584*0Sstevel@tonic-gate pcata_lbl_ioctl(dev_t dev, int cmd, intptr_t arg, int flag)
585*0Sstevel@tonic-gate {
586*0Sstevel@tonic-gate 	uint32_t data[512 / (sizeof (uint32_t))];
587*0Sstevel@tonic-gate 	void *instance;
588*0Sstevel@tonic-gate 	ata_soft_t *softp;
589*0Sstevel@tonic-gate 	ata_unit_t *unitp;
590*0Sstevel@tonic-gate 	int i;
591*0Sstevel@tonic-gate 	struct vtoc vtoc;
592*0Sstevel@tonic-gate 
593*0Sstevel@tonic-gate 	if (pcata_getinfo(NULL, DDI_INFO_DEVT2INSTANCE, (void *)dev,
594*0Sstevel@tonic-gate 	    &instance) != DDI_SUCCESS)
595*0Sstevel@tonic-gate 		return (ENODEV);
596*0Sstevel@tonic-gate 
597*0Sstevel@tonic-gate 	if (!(softp = ddi_get_soft_state(pcata_soft,
598*0Sstevel@tonic-gate 	    (int)(uintptr_t)instance))) {
599*0Sstevel@tonic-gate 		return (ENXIO);
600*0Sstevel@tonic-gate 	}
601*0Sstevel@tonic-gate 
602*0Sstevel@tonic-gate 	if (!(CARD_PRESENT_VALID(softp))) {
603*0Sstevel@tonic-gate 		return (ENODEV);
604*0Sstevel@tonic-gate 	}
605*0Sstevel@tonic-gate 
606*0Sstevel@tonic-gate 	ASSERT(softp->ab_link);
607*0Sstevel@tonic-gate 	bzero((caddr_t)data, sizeof (data));
608*0Sstevel@tonic-gate 	unitp    = softp->ab_link;
609*0Sstevel@tonic-gate 
610*0Sstevel@tonic-gate 	switch (cmd) {
611*0Sstevel@tonic-gate 	case DKIOCGGEOM:
612*0Sstevel@tonic-gate 	case DKIOCGAPART:
613*0Sstevel@tonic-gate 	case DKIOCGVTOC:
614*0Sstevel@tonic-gate 		if (pcata_update_vtoc(softp, dev))
615*0Sstevel@tonic-gate 			return (EFAULT);
616*0Sstevel@tonic-gate 	}
617*0Sstevel@tonic-gate 
618*0Sstevel@tonic-gate 	switch (cmd) {
619*0Sstevel@tonic-gate 	case DKIOCGGEOM:
620*0Sstevel@tonic-gate 		{
621*0Sstevel@tonic-gate 		struct dk_geom up;
622*0Sstevel@tonic-gate 
623*0Sstevel@tonic-gate 		pcdsklbl_dgtoug(&up, &unitp->lbl.ondsklbl);
624*0Sstevel@tonic-gate 		if (COPYOUT(&up, arg, struct dk_geom, flag)) {
625*0Sstevel@tonic-gate 			return (EFAULT);
626*0Sstevel@tonic-gate 		}
627*0Sstevel@tonic-gate 		break;
628*0Sstevel@tonic-gate 		}
629*0Sstevel@tonic-gate 
630*0Sstevel@tonic-gate 	case DKIOCSGEOM:
631*0Sstevel@tonic-gate 		i = sizeof (struct dk_geom);
632*0Sstevel@tonic-gate 		if (ddi_copyin((caddr_t)arg, (caddr_t)data, i, flag))
633*0Sstevel@tonic-gate 			return (EFAULT);
634*0Sstevel@tonic-gate 		pcdsklbl_ugtodg((struct dk_geom *)data, &unitp->lbl.ondsklbl);
635*0Sstevel@tonic-gate 		break;
636*0Sstevel@tonic-gate 
637*0Sstevel@tonic-gate 	case DKIOCGAPART:
638*0Sstevel@tonic-gate 		/*
639*0Sstevel@tonic-gate 		 * Return the map for all logical partitions.
640*0Sstevel@tonic-gate 		 */
641*0Sstevel@tonic-gate #if defined(_MULTI_DATAMODEL)
642*0Sstevel@tonic-gate 		switch (ddi_model_convert_from(flag & FMODELS)) {
643*0Sstevel@tonic-gate 		case DDI_MODEL_ILP32: {
644*0Sstevel@tonic-gate 			struct dk_map32 dk_map32[NDKMAP];
645*0Sstevel@tonic-gate 			int	i;
646*0Sstevel@tonic-gate 
647*0Sstevel@tonic-gate 			for (i = 0; i < NDKMAP; i++) {
648*0Sstevel@tonic-gate 				dk_map32[i].dkl_cylno =
649*0Sstevel@tonic-gate 					unitp->lbl.un_map[i].dkl_cylno;
650*0Sstevel@tonic-gate 				dk_map32[i].dkl_nblk =
651*0Sstevel@tonic-gate 					unitp->lbl.un_map[i].dkl_nblk;
652*0Sstevel@tonic-gate 			}
653*0Sstevel@tonic-gate 			i = NDKMAP * sizeof (struct dk_map32);
654*0Sstevel@tonic-gate 			if (ddi_copyout(dk_map32, (caddr_t)arg, i, flag))
655*0Sstevel@tonic-gate 				return (EFAULT);
656*0Sstevel@tonic-gate 			break;
657*0Sstevel@tonic-gate 		}
658*0Sstevel@tonic-gate 
659*0Sstevel@tonic-gate 		case DDI_MODEL_NONE:
660*0Sstevel@tonic-gate 			i = NDKMAP * sizeof (struct dk_map);
661*0Sstevel@tonic-gate 			if (ddi_copyout((caddr_t)unitp->lbl.un_map,
662*0Sstevel@tonic-gate 			    (caddr_t)arg, i, flag))
663*0Sstevel@tonic-gate 				return (EFAULT);
664*0Sstevel@tonic-gate 			break;
665*0Sstevel@tonic-gate 		}
666*0Sstevel@tonic-gate 
667*0Sstevel@tonic-gate #else	/*  _MULTI_DATAMODEL */
668*0Sstevel@tonic-gate 		i = NDKMAP * sizeof (struct dk_map);
669*0Sstevel@tonic-gate 		if (ddi_copyout((caddr_t)unitp->lbl.un_map,
670*0Sstevel@tonic-gate 		    (caddr_t)arg, i, flag))
671*0Sstevel@tonic-gate 			return (EFAULT);
672*0Sstevel@tonic-gate #endif	/*  _MULTI_DATAMODEL */
673*0Sstevel@tonic-gate 		break;
674*0Sstevel@tonic-gate 
675*0Sstevel@tonic-gate 	case DKIOCSAPART:
676*0Sstevel@tonic-gate 		/*
677*0Sstevel@tonic-gate 		 * Set the map for all logical partitions.
678*0Sstevel@tonic-gate 		 */
679*0Sstevel@tonic-gate #if defined(_MULTI_DATAMODEL)
680*0Sstevel@tonic-gate 		switch (ddi_model_convert_from(flag & FMODELS)) {
681*0Sstevel@tonic-gate 		case DDI_MODEL_ILP32: {
682*0Sstevel@tonic-gate 			struct dk_map32 dk_map32[NDKMAP];
683*0Sstevel@tonic-gate 			int	i;
684*0Sstevel@tonic-gate 
685*0Sstevel@tonic-gate 			i = NDKMAP * sizeof (struct dk_map32);
686*0Sstevel@tonic-gate 			if (ddi_copyin((caddr_t)arg, dk_map32, i, flag))
687*0Sstevel@tonic-gate 				return (EFAULT);
688*0Sstevel@tonic-gate 			for (i = 0; i < NDKMAP; i++) {
689*0Sstevel@tonic-gate 				unitp->lbl.un_map[i].dkl_cylno =
690*0Sstevel@tonic-gate 					dk_map32[i].dkl_cylno;
691*0Sstevel@tonic-gate 				unitp->lbl.un_map[i].dkl_nblk =
692*0Sstevel@tonic-gate 					dk_map32[i].dkl_nblk;
693*0Sstevel@tonic-gate 			}
694*0Sstevel@tonic-gate 			i = NDKMAP * sizeof (struct dk_map32);
695*0Sstevel@tonic-gate 			break;
696*0Sstevel@tonic-gate 		}
697*0Sstevel@tonic-gate 
698*0Sstevel@tonic-gate 		case DDI_MODEL_NONE:
699*0Sstevel@tonic-gate 			i = NDKMAP * sizeof (struct dk_map);
700*0Sstevel@tonic-gate 			if (ddi_copyout((caddr_t)unitp->lbl.un_map,
701*0Sstevel@tonic-gate 			    (caddr_t)arg, i, flag))
702*0Sstevel@tonic-gate 				return (EFAULT);
703*0Sstevel@tonic-gate 			break;
704*0Sstevel@tonic-gate 		}
705*0Sstevel@tonic-gate 		break;
706*0Sstevel@tonic-gate #else	/*  _MULTI_DATAMODEL */
707*0Sstevel@tonic-gate 		i = NDKMAP * sizeof (struct dk_map);
708*0Sstevel@tonic-gate 		if (ddi_copyin((caddr_t)arg, (caddr_t)data, i, flag))
709*0Sstevel@tonic-gate 			return (EFAULT);
710*0Sstevel@tonic-gate 		bcopy((caddr_t)data, (caddr_t)unitp->lbl.un_map, i);
711*0Sstevel@tonic-gate 		break;
712*0Sstevel@tonic-gate #endif	/*  _MULTI_DATAMODEL */
713*0Sstevel@tonic-gate 
714*0Sstevel@tonic-gate 	case DKIOCGVTOC:
715*0Sstevel@tonic-gate #if defined(_MULTI_DATAMODEL)
716*0Sstevel@tonic-gate 		switch (ddi_model_convert_from(flag & FMODELS)) {
717*0Sstevel@tonic-gate 		case DDI_MODEL_ILP32: {
718*0Sstevel@tonic-gate 			struct vtoc32 vtoc32;
719*0Sstevel@tonic-gate 
720*0Sstevel@tonic-gate 			pcdsklbl_ondsklabel_to_vtoc(&unitp->lbl, &vtoc);
721*0Sstevel@tonic-gate 			vtoctovtoc32(vtoc, vtoc32);
722*0Sstevel@tonic-gate 			if (ddi_copyout(&vtoc32, (caddr_t)arg,
723*0Sstevel@tonic-gate 			    sizeof (struct vtoc32), flag))
724*0Sstevel@tonic-gate 				return (EFAULT);
725*0Sstevel@tonic-gate 			break;
726*0Sstevel@tonic-gate 		}
727*0Sstevel@tonic-gate 
728*0Sstevel@tonic-gate 		case DDI_MODEL_NONE:
729*0Sstevel@tonic-gate 			pcdsklbl_ondsklabel_to_vtoc(&unitp->lbl, &vtoc);
730*0Sstevel@tonic-gate 			if (ddi_copyout((caddr_t)&vtoc, (caddr_t)arg,
731*0Sstevel@tonic-gate 			    sizeof (struct vtoc), flag))
732*0Sstevel@tonic-gate 				return (EFAULT);
733*0Sstevel@tonic-gate 			break;
734*0Sstevel@tonic-gate 		}
735*0Sstevel@tonic-gate 		return (0);
736*0Sstevel@tonic-gate #else	/*  _MULTI_DATAMODEL */
737*0Sstevel@tonic-gate 		pcdsklbl_ondsklabel_to_vtoc(&unitp->lbl, &vtoc);
738*0Sstevel@tonic-gate 		if (ddi_copyout((caddr_t)&vtoc, (caddr_t)arg,
739*0Sstevel@tonic-gate 		    sizeof (struct vtoc), flag))
740*0Sstevel@tonic-gate 			return (EFAULT);
741*0Sstevel@tonic-gate 		return (0);
742*0Sstevel@tonic-gate #endif	/*  _MULTI_DATAMODEL */
743*0Sstevel@tonic-gate 
744*0Sstevel@tonic-gate 	case DKIOCSVTOC:
745*0Sstevel@tonic-gate #if defined(_MULTI_DATAMODEL)
746*0Sstevel@tonic-gate 		switch (ddi_model_convert_from(flag & FMODELS)) {
747*0Sstevel@tonic-gate 		case DDI_MODEL_ILP32: {
748*0Sstevel@tonic-gate 			struct vtoc32 vtoc32;
749*0Sstevel@tonic-gate 
750*0Sstevel@tonic-gate 			if (ddi_copyin((caddr_t)arg, &vtoc32,
751*0Sstevel@tonic-gate 			    sizeof (struct vtoc32), flag))
752*0Sstevel@tonic-gate 				return (EFAULT);
753*0Sstevel@tonic-gate 			vtoc32tovtoc(vtoc32, vtoc);
754*0Sstevel@tonic-gate 
755*0Sstevel@tonic-gate 			if (pcata_write_dskvtoc(softp, dev, &unitp->lbl, &vtoc))
756*0Sstevel@tonic-gate 				return (EFAULT);
757*0Sstevel@tonic-gate 			break;
758*0Sstevel@tonic-gate 		}
759*0Sstevel@tonic-gate 
760*0Sstevel@tonic-gate 		case DDI_MODEL_NONE:
761*0Sstevel@tonic-gate 			if (ddi_copyin((caddr_t)arg, (caddr_t)&vtoc,
762*0Sstevel@tonic-gate 			    sizeof (struct vtoc), flag))
763*0Sstevel@tonic-gate 				return (EFAULT);
764*0Sstevel@tonic-gate 
765*0Sstevel@tonic-gate 			if (pcata_write_dskvtoc(softp, dev, &unitp->lbl, &vtoc))
766*0Sstevel@tonic-gate 				return (EFAULT);
767*0Sstevel@tonic-gate 
768*0Sstevel@tonic-gate 			break;
769*0Sstevel@tonic-gate 		}
770*0Sstevel@tonic-gate #else	/*  _MULTI_DATAMODEL */
771*0Sstevel@tonic-gate 		if (ddi_copyin((caddr_t)arg, (caddr_t)&vtoc,
772*0Sstevel@tonic-gate 		    sizeof (struct vtoc), flag))
773*0Sstevel@tonic-gate 			return (EFAULT);
774*0Sstevel@tonic-gate 
775*0Sstevel@tonic-gate 		if (pcata_write_dskvtoc(softp, dev, &unitp->lbl, &vtoc))
776*0Sstevel@tonic-gate 			return (EFAULT);
777*0Sstevel@tonic-gate 
778*0Sstevel@tonic-gate 		break;
779*0Sstevel@tonic-gate #endif	/*  _MULTI_DATAMODEL */
780*0Sstevel@tonic-gate 	}
781*0Sstevel@tonic-gate 	return (0);
782*0Sstevel@tonic-gate }
783*0Sstevel@tonic-gate 
784*0Sstevel@tonic-gate /* ARGSUSED */
785*0Sstevel@tonic-gate int
pcata_open(dev_t * dev_p,int flag,int otyp,cred_t * cred_p)786*0Sstevel@tonic-gate pcata_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p)
787*0Sstevel@tonic-gate {
788*0Sstevel@tonic-gate 	register dev_t dev = *dev_p;
789*0Sstevel@tonic-gate 	ata_soft_t *softp;
790*0Sstevel@tonic-gate 	void	*instance;
791*0Sstevel@tonic-gate 	int	i;
792*0Sstevel@tonic-gate 
793*0Sstevel@tonic-gate #ifdef ATA_DEBUG
794*0Sstevel@tonic-gate 	if (pcata_debug & DIO)
795*0Sstevel@tonic-gate 		cmn_err(CE_CONT, "_open: "
796*0Sstevel@tonic-gate 		    "dev_p=%p dev=%x flag=%x otyp=%x cred_p=%p\n",
797*0Sstevel@tonic-gate 		    (void *)dev_p, (int)dev, flag, otyp, (void *)cred_p);
798*0Sstevel@tonic-gate #endif
799*0Sstevel@tonic-gate 	if (pcata_getinfo(NULL, DDI_INFO_DEVT2INSTANCE, (void *) *dev_p,
800*0Sstevel@tonic-gate 	    &instance) != DDI_SUCCESS)
801*0Sstevel@tonic-gate 		return (ENODEV);
802*0Sstevel@tonic-gate 
803*0Sstevel@tonic-gate 	softp = ddi_get_soft_state(pcata_soft, (int)(uintptr_t)instance);
804*0Sstevel@tonic-gate 
805*0Sstevel@tonic-gate 	/*
806*0Sstevel@tonic-gate 	 * open and getinfo may be called before attach completes
807*0Sstevel@tonic-gate 	 */
808*0Sstevel@tonic-gate 	for (i = 0; i < 300; i++) {
809*0Sstevel@tonic-gate 		if (softp->flags & PCATA_READY)
810*0Sstevel@tonic-gate 			break;
811*0Sstevel@tonic-gate 		drv_usecwait(10000);
812*0Sstevel@tonic-gate 	}
813*0Sstevel@tonic-gate 	if (!pcata_readywait(softp))
814*0Sstevel@tonic-gate 		return (ENXIO);
815*0Sstevel@tonic-gate 
816*0Sstevel@tonic-gate #ifdef ATA_DEBUG
817*0Sstevel@tonic-gate 	if (pcata_debug & DIO)
818*0Sstevel@tonic-gate 		cmn_err(CE_CONT,
819*0Sstevel@tonic-gate 		    "_open: part=%d blk_open=%x chr_open=%x lyr_open=%d\n",
820*0Sstevel@tonic-gate 		    LPART(dev), softp->blk_open, softp->chr_open,
821*0Sstevel@tonic-gate 		    softp->lyr_open[LPART(dev)]);
822*0Sstevel@tonic-gate #endif
823*0Sstevel@tonic-gate 
824*0Sstevel@tonic-gate 	mutex_enter(&(softp)->ata_mutex);
825*0Sstevel@tonic-gate 	/*
826*0Sstevel@tonic-gate 	 * Only honor FEXCL.  If a regular open or a layered open
827*0Sstevel@tonic-gate 	 * is still outstanding on the device, the exclusive open
828*0Sstevel@tonic-gate 	 * must fail.
829*0Sstevel@tonic-gate 	 */
830*0Sstevel@tonic-gate 	if (flag & FEXCL) {
831*0Sstevel@tonic-gate 		if ((softp->chr_open & (1 << LPART(dev))) ||
832*0Sstevel@tonic-gate 		    (softp->blk_open & (1 << LPART(dev))) ||
833*0Sstevel@tonic-gate 		    (softp->lyr_open[LPART(dev)])) {
834*0Sstevel@tonic-gate 			mutex_exit(&(softp)->ata_mutex);
835*0Sstevel@tonic-gate 			return (EAGAIN);
836*0Sstevel@tonic-gate 		}
837*0Sstevel@tonic-gate 	}
838*0Sstevel@tonic-gate 
839*0Sstevel@tonic-gate 	switch (otyp) {
840*0Sstevel@tonic-gate 		case OTYP_BLK:
841*0Sstevel@tonic-gate 			softp->blk_open |= (1 << LPART(dev));
842*0Sstevel@tonic-gate 			break;
843*0Sstevel@tonic-gate 		case OTYP_CHR:
844*0Sstevel@tonic-gate 			softp->chr_open |= (1 << LPART(dev));
845*0Sstevel@tonic-gate 			break;
846*0Sstevel@tonic-gate 		case OTYP_LYR:
847*0Sstevel@tonic-gate 			softp->lyr_open[LPART(dev)]++;
848*0Sstevel@tonic-gate 			break;
849*0Sstevel@tonic-gate 		default:
850*0Sstevel@tonic-gate 			mutex_exit(&(softp)->ata_mutex);
851*0Sstevel@tonic-gate 			return (EINVAL);
852*0Sstevel@tonic-gate 	}
853*0Sstevel@tonic-gate 
854*0Sstevel@tonic-gate 	mutex_exit(&(softp)->ata_mutex);
855*0Sstevel@tonic-gate 
856*0Sstevel@tonic-gate 	return (0);
857*0Sstevel@tonic-gate }
858*0Sstevel@tonic-gate 
859*0Sstevel@tonic-gate 
860*0Sstevel@tonic-gate 
861*0Sstevel@tonic-gate /* ARGSUSED */
862*0Sstevel@tonic-gate int
pcata_close(dev_t dev,int flag,int otyp,cred_t * cred_p)863*0Sstevel@tonic-gate pcata_close(dev_t dev, int flag, int otyp, cred_t *cred_p)
864*0Sstevel@tonic-gate {
865*0Sstevel@tonic-gate 	ata_soft_t *softp;
866*0Sstevel@tonic-gate 	int	i;
867*0Sstevel@tonic-gate 	int	lyr_count = 0;
868*0Sstevel@tonic-gate 	void	*instance;
869*0Sstevel@tonic-gate 
870*0Sstevel@tonic-gate #ifdef ATA_DEBUG
871*0Sstevel@tonic-gate 	if (pcata_debug & DIO)
872*0Sstevel@tonic-gate 		cmn_err(CE_CONT, "_close: dev=%x flag=%x otyp=%x cred_p=%p\n",
873*0Sstevel@tonic-gate 		    (int)dev, flag, otyp, (void *)cred_p);
874*0Sstevel@tonic-gate #endif
875*0Sstevel@tonic-gate 
876*0Sstevel@tonic-gate 	if (pcata_getinfo(NULL, DDI_INFO_DEVT2INSTANCE, (void *) dev,
877*0Sstevel@tonic-gate 	    &instance) != DDI_SUCCESS)
878*0Sstevel@tonic-gate 		return (ENODEV);
879*0Sstevel@tonic-gate 
880*0Sstevel@tonic-gate 	softp = ddi_get_soft_state(pcata_soft, (int)(uintptr_t)instance);
881*0Sstevel@tonic-gate 
882*0Sstevel@tonic-gate #ifdef ATA_DEBUG
883*0Sstevel@tonic-gate 	if (pcata_debug & DIO)
884*0Sstevel@tonic-gate 		cmn_err(CE_CONT,
885*0Sstevel@tonic-gate 		    "_close: part=%d blk_open=%x chr_open=%x lyr_open=%d\n",
886*0Sstevel@tonic-gate 		    LPART(dev), softp->blk_open, softp->chr_open,
887*0Sstevel@tonic-gate 		    softp->lyr_open[LPART(dev)]);
888*0Sstevel@tonic-gate #endif
889*0Sstevel@tonic-gate 
890*0Sstevel@tonic-gate 
891*0Sstevel@tonic-gate 	mutex_enter(&(softp)->ata_mutex);
892*0Sstevel@tonic-gate 
893*0Sstevel@tonic-gate 	switch (otyp) {
894*0Sstevel@tonic-gate 		case OTYP_BLK:
895*0Sstevel@tonic-gate 			softp->blk_open &= ~(1 << LPART(dev));
896*0Sstevel@tonic-gate 			break;
897*0Sstevel@tonic-gate 		case OTYP_CHR:
898*0Sstevel@tonic-gate 			softp->chr_open &= ~(1 << LPART(dev));
899*0Sstevel@tonic-gate 			break;
900*0Sstevel@tonic-gate 		case OTYP_LYR:
901*0Sstevel@tonic-gate 			softp->lyr_open[LPART(dev)]--;
902*0Sstevel@tonic-gate 			break;
903*0Sstevel@tonic-gate 			default:
904*0Sstevel@tonic-gate 			mutex_exit(&(softp)->ata_mutex);
905*0Sstevel@tonic-gate 			return (EINVAL);
906*0Sstevel@tonic-gate 	}
907*0Sstevel@tonic-gate 
908*0Sstevel@tonic-gate 	if ((softp->blk_open) || (softp->chr_open)) {
909*0Sstevel@tonic-gate 		/* not done yet */
910*0Sstevel@tonic-gate 		mutex_exit(&(softp)->ata_mutex);
911*0Sstevel@tonic-gate 		return (0);
912*0Sstevel@tonic-gate 	} else {
913*0Sstevel@tonic-gate 		for (i = 0; i < LPART(dev); i++) {
914*0Sstevel@tonic-gate 			if (softp->lyr_open[LPART(dev)] != 0)
915*0Sstevel@tonic-gate 				lyr_count++;
916*0Sstevel@tonic-gate 		}
917*0Sstevel@tonic-gate 
918*0Sstevel@tonic-gate 		if (lyr_count) {
919*0Sstevel@tonic-gate 			/* not done yet */
920*0Sstevel@tonic-gate 			mutex_exit(&(softp)->ata_mutex);
921*0Sstevel@tonic-gate 			return (0);
922*0Sstevel@tonic-gate 		}
923*0Sstevel@tonic-gate 	}
924*0Sstevel@tonic-gate 
925*0Sstevel@tonic-gate 	if (softp->ejected_while_mounted)
926*0Sstevel@tonic-gate 		softp->ejected_while_mounted = 0;
927*0Sstevel@tonic-gate 
928*0Sstevel@tonic-gate 	mutex_exit(&(softp)->ata_mutex);
929*0Sstevel@tonic-gate 
930*0Sstevel@tonic-gate 	return (0);
931*0Sstevel@tonic-gate }
932*0Sstevel@tonic-gate 
933*0Sstevel@tonic-gate static int
pcata_redo_vtoc(ata_soft_t * softp,buf_t * fdiskbp)934*0Sstevel@tonic-gate pcata_redo_vtoc(ata_soft_t *softp, buf_t *fdiskbp)
935*0Sstevel@tonic-gate {
936*0Sstevel@tonic-gate 	struct dk_geom	dkg;
937*0Sstevel@tonic-gate 	ata_unit_t	*unitp;
938*0Sstevel@tonic-gate 	buf_t		*bp;
939*0Sstevel@tonic-gate 	int		status;
940*0Sstevel@tonic-gate 	dev_t		dev;
941*0Sstevel@tonic-gate 
942*0Sstevel@tonic-gate 
943*0Sstevel@tonic-gate 	unitp = softp->ab_link;
944*0Sstevel@tonic-gate 	if (!unitp)
945*0Sstevel@tonic-gate 		return (EFAULT);
946*0Sstevel@tonic-gate 
947*0Sstevel@tonic-gate 	/* given any maj/min convert to fdisk partition 0 */
948*0Sstevel@tonic-gate 	dev = makedevice(getmajor(fdiskbp->b_edev),
949*0Sstevel@tonic-gate 		PCATA_SETMINOR(softp->sn, FDISK_OFFSET));
950*0Sstevel@tonic-gate 
951*0Sstevel@tonic-gate 	if ((bp = pcata_lblk_alloc(dev)) == NULL)
952*0Sstevel@tonic-gate 		return (EFAULT);
953*0Sstevel@tonic-gate 
954*0Sstevel@tonic-gate 	bcopy(fdiskbp->b_un.b_addr, bp->b_un.b_addr, NBPSCTR);
955*0Sstevel@tonic-gate 
956*0Sstevel@tonic-gate 	bzero((caddr_t)&dkg, sizeof (struct dk_geom));
957*0Sstevel@tonic-gate 	dkg.dkg_ncyl  	= unitp->au_cyl;
958*0Sstevel@tonic-gate 	dkg.dkg_nhead 	= unitp->au_hd;
959*0Sstevel@tonic-gate 	dkg.dkg_nsect 	= unitp->au_sec;
960*0Sstevel@tonic-gate 
961*0Sstevel@tonic-gate 	status = pcfdisk_parse(bp, unitp);
962*0Sstevel@tonic-gate 
963*0Sstevel@tonic-gate 	/* release buffer allocated by getrbuf */
964*0Sstevel@tonic-gate 	kmem_free(bp->b_un.b_addr, NBPSCTR);
965*0Sstevel@tonic-gate 	freerbuf(bp);
966*0Sstevel@tonic-gate 
967*0Sstevel@tonic-gate 	if (status == DDI_FAILURE)
968*0Sstevel@tonic-gate 		return (EFAULT);
969*0Sstevel@tonic-gate 	return (0);
970*0Sstevel@tonic-gate }
971*0Sstevel@tonic-gate 
972*0Sstevel@tonic-gate /*
973*0Sstevel@tonic-gate  *
974*0Sstevel@tonic-gate  */
975*0Sstevel@tonic-gate int
pcata_update_vtoc(ata_soft_t * softp,dev_t dev)976*0Sstevel@tonic-gate pcata_update_vtoc(ata_soft_t *softp, dev_t dev)
977*0Sstevel@tonic-gate {
978*0Sstevel@tonic-gate 	ata_unit_t	*unitp;
979*0Sstevel@tonic-gate 	buf_t		*bp;
980*0Sstevel@tonic-gate 	int		status;
981*0Sstevel@tonic-gate 
982*0Sstevel@tonic-gate 	unitp = softp->ab_link;
983*0Sstevel@tonic-gate 	if (!unitp)
984*0Sstevel@tonic-gate 		return (EFAULT);
985*0Sstevel@tonic-gate 
986*0Sstevel@tonic-gate 	/* given any maj/min convert to fdisk partition 0 */
987*0Sstevel@tonic-gate 	dev = makedevice(getmajor(dev),
988*0Sstevel@tonic-gate 		PCATA_SETMINOR(softp->sn, FDISK_OFFSET));
989*0Sstevel@tonic-gate 
990*0Sstevel@tonic-gate 	if ((bp = pcata_lblk_alloc(dev)) == NULL)
991*0Sstevel@tonic-gate 		return (EFAULT);
992*0Sstevel@tonic-gate 
993*0Sstevel@tonic-gate 	/*
994*0Sstevel@tonic-gate 	 * The dev is passed here for use later by the dsklbl_rdvtoc()
995*0Sstevel@tonic-gate 	 * and pcata_dsklbl_read_label() to check for card present before
996*0Sstevel@tonic-gate 	 * calling biowait.
997*0Sstevel@tonic-gate 	 */
998*0Sstevel@tonic-gate 	status = pcfdisk_read(bp, unitp);
999*0Sstevel@tonic-gate 
1000*0Sstevel@tonic-gate 	/* release buffer allocated by getrbuf */
1001*0Sstevel@tonic-gate 	kmem_free(bp->b_un.b_addr, NBPSCTR);
1002*0Sstevel@tonic-gate 	freerbuf(bp);
1003*0Sstevel@tonic-gate 
1004*0Sstevel@tonic-gate 	if (status == DDI_FAILURE)
1005*0Sstevel@tonic-gate 		return (EFAULT);
1006*0Sstevel@tonic-gate 	return (0);
1007*0Sstevel@tonic-gate }
1008*0Sstevel@tonic-gate 
1009*0Sstevel@tonic-gate static buf_t *
pcata_lblk_alloc(dev_t dev)1010*0Sstevel@tonic-gate pcata_lblk_alloc(dev_t dev)
1011*0Sstevel@tonic-gate {
1012*0Sstevel@tonic-gate 	buf_t *bp;
1013*0Sstevel@tonic-gate 	char	*secbuf;
1014*0Sstevel@tonic-gate 
1015*0Sstevel@tonic-gate 	/* allocate memory to hold disk label */
1016*0Sstevel@tonic-gate 	secbuf = kmem_zalloc(NBPSCTR, KM_SLEEP);
1017*0Sstevel@tonic-gate 	if (!secbuf)
1018*0Sstevel@tonic-gate 		return (NULL);
1019*0Sstevel@tonic-gate 
1020*0Sstevel@tonic-gate 	/* allocate a buf_t to manage the disk label block */
1021*0Sstevel@tonic-gate 	bp = getrbuf(KM_SLEEP);
1022*0Sstevel@tonic-gate 	if (!bp) {
1023*0Sstevel@tonic-gate 		kmem_free(secbuf, NBPSCTR);
1024*0Sstevel@tonic-gate 		return (NULL);
1025*0Sstevel@tonic-gate 	}
1026*0Sstevel@tonic-gate 
1027*0Sstevel@tonic-gate 	/* initialize the buf_t */
1028*0Sstevel@tonic-gate 	bp->b_edev = dev;
1029*0Sstevel@tonic-gate 	bp->b_dev  = cmpdev(dev);
1030*0Sstevel@tonic-gate 	bp->b_flags |= B_BUSY;
1031*0Sstevel@tonic-gate 	bp->b_resid = 0;
1032*0Sstevel@tonic-gate 	bp->b_bcount = NBPSCTR;
1033*0Sstevel@tonic-gate 	bp->b_un.b_addr = (caddr_t)secbuf;
1034*0Sstevel@tonic-gate 
1035*0Sstevel@tonic-gate 	return (bp);
1036*0Sstevel@tonic-gate }
1037*0Sstevel@tonic-gate 
1038*0Sstevel@tonic-gate 
1039*0Sstevel@tonic-gate int
pcata_write_dskvtoc(ata_soft_t * softp,dev_t dev,dsk_label_t * lblp,struct vtoc * vtocp)1040*0Sstevel@tonic-gate pcata_write_dskvtoc(ata_soft_t *softp, dev_t dev, dsk_label_t *lblp,
1041*0Sstevel@tonic-gate 		struct vtoc *vtocp)
1042*0Sstevel@tonic-gate {
1043*0Sstevel@tonic-gate 	buf_t *bp;
1044*0Sstevel@tonic-gate 	int	status;
1045*0Sstevel@tonic-gate 
1046*0Sstevel@tonic-gate 	dev = makedevice(getmajor(dev),
1047*0Sstevel@tonic-gate 		PCATA_SETMINOR(softp->sn, FDISK_OFFSET));
1048*0Sstevel@tonic-gate 
1049*0Sstevel@tonic-gate 	if ((bp = pcata_lblk_alloc(dev)) == NULL)
1050*0Sstevel@tonic-gate 		return (EFAULT);
1051*0Sstevel@tonic-gate 
1052*0Sstevel@tonic-gate #ifdef ATA_DEBUG
1053*0Sstevel@tonic-gate 	cmn_err(CE_CONT, "_write_dskvtoc: edev = %lx dev = %x\n",
1054*0Sstevel@tonic-gate 		bp->b_edev,
1055*0Sstevel@tonic-gate 		bp->b_dev);
1056*0Sstevel@tonic-gate #endif
1057*0Sstevel@tonic-gate 
1058*0Sstevel@tonic-gate 
1059*0Sstevel@tonic-gate 	bp->b_edev = dev; /* used by probe_for_card() */
1060*0Sstevel@tonic-gate 	status = pcdsklbl_wrvtoc(lblp, vtocp, bp);
1061*0Sstevel@tonic-gate 
1062*0Sstevel@tonic-gate 	/* release buffer allocated by getrbuf */
1063*0Sstevel@tonic-gate 	kmem_free(bp->b_un.b_addr, NBPSCTR);
1064*0Sstevel@tonic-gate 	freerbuf(bp);
1065*0Sstevel@tonic-gate 
1066*0Sstevel@tonic-gate 	return (status);
1067*0Sstevel@tonic-gate }
1068*0Sstevel@tonic-gate /*
1069*0Sstevel@tonic-gate  *  Check media insertion/ejection status
1070*0Sstevel@tonic-gate  */
1071*0Sstevel@tonic-gate static int
pcata_check_media(ata_soft_t * rs,enum dkio_state state)1072*0Sstevel@tonic-gate pcata_check_media(ata_soft_t *rs, enum dkio_state state)
1073*0Sstevel@tonic-gate {
1074*0Sstevel@tonic-gate 	int		err;
1075*0Sstevel@tonic-gate 	get_status_t	get_status;
1076*0Sstevel@tonic-gate 
1077*0Sstevel@tonic-gate 
1078*0Sstevel@tonic-gate 	mutex_enter(&rs->ata_mutex);
1079*0Sstevel@tonic-gate 
1080*0Sstevel@tonic-gate 	/*
1081*0Sstevel@tonic-gate 	 * Do a CS call to see if the card is present
1082*0Sstevel@tonic-gate 	 */
1083*0Sstevel@tonic-gate 	if ((err = csx_GetStatus(rs->client_handle, &get_status))
1084*0Sstevel@tonic-gate 	    != CS_SUCCESS) {
1085*0Sstevel@tonic-gate 		error2text_t cft;
1086*0Sstevel@tonic-gate 
1087*0Sstevel@tonic-gate 		mutex_exit(&rs->ata_mutex);
1088*0Sstevel@tonic-gate 
1089*0Sstevel@tonic-gate 		cft.item = err;
1090*0Sstevel@tonic-gate 		(void) csx_Error2Text(&cft);
1091*0Sstevel@tonic-gate 		cmn_err(CE_CONT, "pcata_check_media: socket %d "
1092*0Sstevel@tonic-gate 		    "GetStatus failed %s (0x%x)\n",
1093*0Sstevel@tonic-gate 		    rs->sn, cft.text, err);
1094*0Sstevel@tonic-gate 		return (ENXIO);
1095*0Sstevel@tonic-gate 	}
1096*0Sstevel@tonic-gate 
1097*0Sstevel@tonic-gate 	/* Register rs->media_state */
1098*0Sstevel@tonic-gate 	if ((get_status.CardState & CS_EVENT_CARD_INSERTION)) {
1099*0Sstevel@tonic-gate 		rs->media_state = DKIO_INSERTED;
1100*0Sstevel@tonic-gate 	} else {
1101*0Sstevel@tonic-gate 		if (state == DKIO_NONE) {
1102*0Sstevel@tonic-gate 			rs->media_state = DKIO_NONE;
1103*0Sstevel@tonic-gate 		} else {
1104*0Sstevel@tonic-gate 			rs->media_state = DKIO_EJECTED;
1105*0Sstevel@tonic-gate 		}
1106*0Sstevel@tonic-gate 	}
1107*0Sstevel@tonic-gate 
1108*0Sstevel@tonic-gate 
1109*0Sstevel@tonic-gate 	/*
1110*0Sstevel@tonic-gate 	 * XXXX - In order not to modify the volume management
1111*0Sstevel@tonic-gate 	 *	we have to follow the current SCSI CDROM model
1112*0Sstevel@tonic-gate 	 *	for checking media state (broken way, sigh!)
1113*0Sstevel@tonic-gate 	 *		start with state = DKIO_NONE
1114*0Sstevel@tonic-gate 	 *		wait until mediastate = DKIO_INSERTED
1115*0Sstevel@tonic-gate 	 *		wait until mediastate = DKIO_EJECTED
1116*0Sstevel@tonic-gate 	 *		if DKIOCSTATE ioctl() is called second time
1117*0Sstevel@tonic-gate 	 *		with state = DKIO_EJECTED,
1118*0Sstevel@tonic-gate 	 *		   return state = DKIO_NONE
1119*0Sstevel@tonic-gate 	 *		restart with state = DKIO_NONE
1120*0Sstevel@tonic-gate 	 *
1121*0Sstevel@tonic-gate 	 */
1122*0Sstevel@tonic-gate 	if (state != DKIO_NONE) {
1123*0Sstevel@tonic-gate 		if (rs->ejected_media_flag &&
1124*0Sstevel@tonic-gate 		    (rs->media_state == DKIO_EJECTED)) {
1125*0Sstevel@tonic-gate 			rs->media_state = DKIO_NONE;
1126*0Sstevel@tonic-gate 			rs->ejected_media_flag = 0;
1127*0Sstevel@tonic-gate 			mutex_exit(&rs->ata_mutex);
1128*0Sstevel@tonic-gate 			return (0);
1129*0Sstevel@tonic-gate 		}
1130*0Sstevel@tonic-gate 	}
1131*0Sstevel@tonic-gate 
1132*0Sstevel@tonic-gate #ifdef	ATA_DEBUG
1133*0Sstevel@tonic-gate 	if (pcata_debug & DVOLD) {
1134*0Sstevel@tonic-gate 	    cmn_err(CE_CONT, "pcata_check_media: socket %d \n"
1135*0Sstevel@tonic-gate 		"\tWaiting state change: rs->media_state %d state %d\n"
1136*0Sstevel@tonic-gate 		"\tDKIO_NONE %d DKIO_EJECTED %d DKIO_INSERTED %d\n",
1137*0Sstevel@tonic-gate 		rs->sn, rs->media_state, state,
1138*0Sstevel@tonic-gate 		DKIO_NONE, DKIO_EJECTED, DKIO_INSERTED);
1139*0Sstevel@tonic-gate 	}
1140*0Sstevel@tonic-gate #endif
1141*0Sstevel@tonic-gate 
1142*0Sstevel@tonic-gate 	/*
1143*0Sstevel@tonic-gate 	 * wait for Card Detect Change Interrupt handler
1144*0Sstevel@tonic-gate 	 * see either pcata_card_insertion/pcata_card_removal
1145*0Sstevel@tonic-gate 	 * for cv_broadcast
1146*0Sstevel@tonic-gate 	 */
1147*0Sstevel@tonic-gate 	while (rs->media_state == state) {
1148*0Sstevel@tonic-gate 		rs->checkmedia_flag++;
1149*0Sstevel@tonic-gate 		if (cv_wait_sig(&rs->condvar_mediastate,
1150*0Sstevel@tonic-gate 		    &rs->ata_mutex) == 0) {
1151*0Sstevel@tonic-gate 			mutex_exit(&rs->ata_mutex);
1152*0Sstevel@tonic-gate 			return (EINTR);
1153*0Sstevel@tonic-gate 		}
1154*0Sstevel@tonic-gate 	}
1155*0Sstevel@tonic-gate 
1156*0Sstevel@tonic-gate #ifdef	ATA_DEBUG
1157*0Sstevel@tonic-gate 	if (pcata_debug & DVOLD) {
1158*0Sstevel@tonic-gate 		cmn_err(CE_CONT, "pcata_check_media: socket %d \n"
1159*0Sstevel@tonic-gate 		    "\tAfter state change: rs->media_state %d state %d\n"
1160*0Sstevel@tonic-gate 		    "\tDKIO_NONE %d DKIO_EJECTED %d DKIO_INSERTED %d\n",
1161*0Sstevel@tonic-gate 		    rs->sn, rs->media_state, state,
1162*0Sstevel@tonic-gate 		    DKIO_NONE, DKIO_EJECTED, DKIO_INSERTED);
1163*0Sstevel@tonic-gate 	}
1164*0Sstevel@tonic-gate #endif
1165*0Sstevel@tonic-gate 
1166*0Sstevel@tonic-gate 	if (state != DKIO_NONE) {
1167*0Sstevel@tonic-gate 		if (!rs->ejected_media_flag &&
1168*0Sstevel@tonic-gate 		    (rs->media_state == DKIO_EJECTED)) {
1169*0Sstevel@tonic-gate 			rs->ejected_media_flag++;
1170*0Sstevel@tonic-gate 		}
1171*0Sstevel@tonic-gate 	}
1172*0Sstevel@tonic-gate 
1173*0Sstevel@tonic-gate 	mutex_exit(&rs->ata_mutex);
1174*0Sstevel@tonic-gate 
1175*0Sstevel@tonic-gate 	return (0);
1176*0Sstevel@tonic-gate }
1177*0Sstevel@tonic-gate 
1178*0Sstevel@tonic-gate int
pcata_prop_op(dev_t dev,dev_info_t * dip,ddi_prop_op_t prop_op,int mod_flags,char * name,caddr_t valuep,int * lengthp)1179*0Sstevel@tonic-gate pcata_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
1180*0Sstevel@tonic-gate     int mod_flags, char *name, caddr_t valuep, int *lengthp)
1181*0Sstevel@tonic-gate {
1182*0Sstevel@tonic-gate 	int		instance = ddi_get_instance(dip);
1183*0Sstevel@tonic-gate 	ata_soft_t	*softp;
1184*0Sstevel@tonic-gate 	ata_unit_t	*unitp;
1185*0Sstevel@tonic-gate 	uint64_t	nblocks64;
1186*0Sstevel@tonic-gate 
1187*0Sstevel@tonic-gate 	/*
1188*0Sstevel@tonic-gate 	 * Our dynamic properties are all device specific and size oriented.
1189*0Sstevel@tonic-gate 	 * Requests issued under conditions where size is valid are passed
1190*0Sstevel@tonic-gate 	 * to ddi_prop_op_nblocks with the size information, otherwise the
1191*0Sstevel@tonic-gate 	 * request is passed to ddi_prop_op.
1192*0Sstevel@tonic-gate 	 */
1193*0Sstevel@tonic-gate 	softp = ddi_get_soft_state(pcata_soft, instance);
1194*0Sstevel@tonic-gate 	if ((dev == DDI_DEV_T_ANY) || (softp == NULL) ||
1195*0Sstevel@tonic-gate 	    !(CARD_PRESENT_VALID(softp)) ||
1196*0Sstevel@tonic-gate 	    ((unitp = softp->ab_link) == NULL)) {
1197*0Sstevel@tonic-gate 		return (ddi_prop_op(dev, dip, prop_op, mod_flags,
1198*0Sstevel@tonic-gate 		    name, valuep, lengthp));
1199*0Sstevel@tonic-gate 	} else {
1200*0Sstevel@tonic-gate 		/* get nblocks value */
1201*0Sstevel@tonic-gate 		nblocks64 = (ulong_t)unitp->lbl.pmap[LPART(dev)].p_size;
1202*0Sstevel@tonic-gate 
1203*0Sstevel@tonic-gate 		return (ddi_prop_op_nblocks(dev, dip, prop_op, mod_flags,
1204*0Sstevel@tonic-gate 		    name, valuep, lengthp, nblocks64));
1205*0Sstevel@tonic-gate 	}
1206*0Sstevel@tonic-gate }
1207