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