xref: /onnv-gate/usr/src/uts/common/io/pcmcia/pcata.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 2004 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/errno.h>
30*0Sstevel@tonic-gate #include <sys/param.h>
31*0Sstevel@tonic-gate #include <sys/systm.h>
32*0Sstevel@tonic-gate #include <sys/user.h>
33*0Sstevel@tonic-gate #include <sys/buf.h>
34*0Sstevel@tonic-gate #include <sys/ioctl.h>
35*0Sstevel@tonic-gate #include <sys/file.h>
36*0Sstevel@tonic-gate #include <sys/uio.h>
37*0Sstevel@tonic-gate #include <sys/fcntl.h>
38*0Sstevel@tonic-gate #include <sys/cmn_err.h>
39*0Sstevel@tonic-gate #include <sys/kmem.h>
40*0Sstevel@tonic-gate #include <sys/sysmacros.h>
41*0Sstevel@tonic-gate #include <sys/stat.h>
42*0Sstevel@tonic-gate #include <sys/scsi/scsi.h>
43*0Sstevel@tonic-gate 
44*0Sstevel@tonic-gate #include <sys/fdio.h>
45*0Sstevel@tonic-gate 
46*0Sstevel@tonic-gate #include <sys/errno.h>
47*0Sstevel@tonic-gate #include <sys/open.h>
48*0Sstevel@tonic-gate #include <sys/varargs.h>
49*0Sstevel@tonic-gate #include <sys/fs/pc_label.h>
50*0Sstevel@tonic-gate 
51*0Sstevel@tonic-gate #include <sys/hdio.h>
52*0Sstevel@tonic-gate #include <sys/dkio.h>
53*0Sstevel@tonic-gate 
54*0Sstevel@tonic-gate #include <sys/dklabel.h>
55*0Sstevel@tonic-gate 
56*0Sstevel@tonic-gate #include <sys/vtoc.h>
57*0Sstevel@tonic-gate 
58*0Sstevel@tonic-gate #include <sys/types.h>
59*0Sstevel@tonic-gate #include <sys/conf.h>
60*0Sstevel@tonic-gate #include <sys/dditypes.h>
61*0Sstevel@tonic-gate #include <sys/dktp/cm.h>
62*0Sstevel@tonic-gate 
63*0Sstevel@tonic-gate #include <sys/dktp/fdisk.h>
64*0Sstevel@tonic-gate 
65*0Sstevel@tonic-gate #include <sys/fs/pc_label.h>
66*0Sstevel@tonic-gate 
67*0Sstevel@tonic-gate /*
68*0Sstevel@tonic-gate  * PCMCIA and DDI related header files
69*0Sstevel@tonic-gate  */
70*0Sstevel@tonic-gate #include <sys/pccard.h>
71*0Sstevel@tonic-gate #include <sys/ddi.h>
72*0Sstevel@tonic-gate #include <sys/sunddi.h>
73*0Sstevel@tonic-gate 
74*0Sstevel@tonic-gate #include <sys/pcmcia/pcata.h>
75*0Sstevel@tonic-gate 
76*0Sstevel@tonic-gate int pcata_event(event_t event, int priority, event_callback_args_t *eca);
77*0Sstevel@tonic-gate static int pcata_create_device_node(ata_soft_t *softp);
78*0Sstevel@tonic-gate static int pcata_initchild(ata_soft_t *softp, int targ);
79*0Sstevel@tonic-gate static int pcata_drive_setup(ata_soft_t *softp);
80*0Sstevel@tonic-gate static void pcata_drive_unsetup(ata_soft_t *softp);
81*0Sstevel@tonic-gate static int pcata_card_insertion(ata_soft_t *softp);
82*0Sstevel@tonic-gate 
83*0Sstevel@tonic-gate event2text_t event2text = {
84*0Sstevel@tonic-gate 	0, 0, 0, NULL };
85*0Sstevel@tonic-gate 
86*0Sstevel@tonic-gate char	*pcata_name = PCATA_NAME;		/* Global not local */
87*0Sstevel@tonic-gate 
88*0Sstevel@tonic-gate 
89*0Sstevel@tonic-gate /*
90*0Sstevel@tonic-gate  * pcata_event - this is the event handler
91*0Sstevel@tonic-gate  */
92*0Sstevel@tonic-gate 
93*0Sstevel@tonic-gate int
pcata_event(event_t event,int priority,event_callback_args_t * eca)94*0Sstevel@tonic-gate pcata_event(event_t event, int priority, event_callback_args_t *eca)
95*0Sstevel@tonic-gate {
96*0Sstevel@tonic-gate 	ata_soft_t *softp = eca->client_data;
97*0Sstevel@tonic-gate 	int	retcode = CS_UNSUPPORTED_EVENT;
98*0Sstevel@tonic-gate 
99*0Sstevel@tonic-gate #ifdef  ATA_DEBUG
100*0Sstevel@tonic-gate 	if (pcata_debug & DPCM) {
101*0Sstevel@tonic-gate 		event2text.event = event;
102*0Sstevel@tonic-gate 
103*0Sstevel@tonic-gate 		(void) csx_Event2Text(&event2text);
104*0Sstevel@tonic-gate 		cmn_err(CE_CONT, "_event (0x%x) %s priority 0x%x\n",
105*0Sstevel@tonic-gate 		    event,
106*0Sstevel@tonic-gate 		    event2text.text,
107*0Sstevel@tonic-gate 		    priority);
108*0Sstevel@tonic-gate 	}
109*0Sstevel@tonic-gate #endif
110*0Sstevel@tonic-gate 
111*0Sstevel@tonic-gate 
112*0Sstevel@tonic-gate 	/*
113*0Sstevel@tonic-gate 	 * Find out which event we got and do the appropriate thing
114*0Sstevel@tonic-gate 	 */
115*0Sstevel@tonic-gate 	switch (event) {
116*0Sstevel@tonic-gate 	case CS_EVENT_REGISTRATION_COMPLETE:
117*0Sstevel@tonic-gate 		retcode = CS_SUCCESS;
118*0Sstevel@tonic-gate 		break;
119*0Sstevel@tonic-gate 	case CS_EVENT_CARD_INSERTION:
120*0Sstevel@tonic-gate 		/* if this is NOT low priority, ignore it */
121*0Sstevel@tonic-gate 		if ((priority & CS_EVENT_PRI_LOW) == 0)
122*0Sstevel@tonic-gate 			break;
123*0Sstevel@tonic-gate 
124*0Sstevel@tonic-gate 		mutex_enter(&softp->event_hilock);
125*0Sstevel@tonic-gate 		softp->card_state = PCATA_WAITINIT;
126*0Sstevel@tonic-gate 		mutex_exit(&softp->event_hilock);
127*0Sstevel@tonic-gate 
128*0Sstevel@tonic-gate 		retcode = pcata_card_insertion(softp);
129*0Sstevel@tonic-gate 		if (retcode == CS_SUCCESS) {
130*0Sstevel@tonic-gate 			if (pcata_drive_setup(softp) != DDI_SUCCESS) {
131*0Sstevel@tonic-gate 				retcode = CS_GENERAL_FAILURE;
132*0Sstevel@tonic-gate 			}
133*0Sstevel@tonic-gate 		}
134*0Sstevel@tonic-gate 		mutex_enter(&softp->event_hilock);
135*0Sstevel@tonic-gate 		softp->card_state &= ~PCATA_WAITINIT;
136*0Sstevel@tonic-gate 		/* kick start any threads that were blocked */
137*0Sstevel@tonic-gate 		cv_broadcast(&softp->readywait_cv);
138*0Sstevel@tonic-gate 		mutex_exit(&softp->event_hilock);
139*0Sstevel@tonic-gate 
140*0Sstevel@tonic-gate 		break;
141*0Sstevel@tonic-gate 		/*
142*0Sstevel@tonic-gate 		 * Note that we get two CS_EVENT_CARD_REMOVAL events -
143*0Sstevel@tonic-gate 		 * one at high priority and the other at low priority.
144*0Sstevel@tonic-gate 		 * This is determined by the setting of the
145*0Sstevel@tonic-gate 		 * CS_EVENT_CARD_REMOVAL_LOWP bit in either of the
146*0Sstevel@tonic-gate 		 * event masks.
147*0Sstevel@tonic-gate 		 * (See the call to RegisterClient).
148*0Sstevel@tonic-gate 		 * We handle the CS_EVENT_PM_SUSPEND event the same
149*0Sstevel@tonic-gate 		 * way that we handle a CS_EVENT_CARD_REMOVAL event
150*0Sstevel@tonic-gate 		 * since if we're being asked to suspend, then we
151*0Sstevel@tonic-gate 		 * can't tell if the same card is inserted after
152*0Sstevel@tonic-gate 		 * a resume.
153*0Sstevel@tonic-gate 		 */
154*0Sstevel@tonic-gate 	case CS_EVENT_CARD_REMOVAL:
155*0Sstevel@tonic-gate 		retcode = pcata_card_removal(softp, priority);
156*0Sstevel@tonic-gate 		break;
157*0Sstevel@tonic-gate 
158*0Sstevel@tonic-gate 	case CS_EVENT_PM_SUSPEND:
159*0Sstevel@tonic-gate 		break;
160*0Sstevel@tonic-gate 	}
161*0Sstevel@tonic-gate 
162*0Sstevel@tonic-gate 	return (retcode);
163*0Sstevel@tonic-gate }
164*0Sstevel@tonic-gate 
165*0Sstevel@tonic-gate 
166*0Sstevel@tonic-gate /*
167*0Sstevel@tonic-gate  * at card insertion allocate I/O addresses
168*0Sstevel@tonic-gate  */
169*0Sstevel@tonic-gate int
pcata_ci_ioaddr(ata_soft_t * softp)170*0Sstevel@tonic-gate pcata_ci_ioaddr(ata_soft_t *softp)
171*0Sstevel@tonic-gate {
172*0Sstevel@tonic-gate 	pcata_cis_vars_t	*cis_vars = &softp->cis_vars;
173*0Sstevel@tonic-gate 	pcata_cftable_t		*cftable = NULL;
174*0Sstevel@tonic-gate 	pcata_cftable_t		*cft;
175*0Sstevel@tonic-gate 	io_req_t		io_req;
176*0Sstevel@tonic-gate 	int			ret;
177*0Sstevel@tonic-gate 
178*0Sstevel@tonic-gate 	/*
179*0Sstevel@tonic-gate 	 * Read CIS and setup the variables.
180*0Sstevel@tonic-gate 	 */
181*0Sstevel@tonic-gate 	ret = pcata_parse_cis(softp, &cftable);
182*0Sstevel@tonic-gate 	if (ret != CS_SUCCESS) {
183*0Sstevel@tonic-gate 		cmn_err(CE_CONT, "_ci_ioaddr "
184*0Sstevel@tonic-gate 			"socket %d unable to get CIS information\n",
185*0Sstevel@tonic-gate 			softp->sn);
186*0Sstevel@tonic-gate 		pcata_destroy_cftable_list(&cftable);
187*0Sstevel@tonic-gate 		return (ret);
188*0Sstevel@tonic-gate 	}
189*0Sstevel@tonic-gate 
190*0Sstevel@tonic-gate 	/*
191*0Sstevel@tonic-gate 	 * Parse CIS data
192*0Sstevel@tonic-gate 	 */
193*0Sstevel@tonic-gate 	cft = cftable;
194*0Sstevel@tonic-gate 	while (cft) {
195*0Sstevel@tonic-gate 		/* skip config index 0 (memory mapped config) */
196*0Sstevel@tonic-gate 		if (cft->p.config_index) {
197*0Sstevel@tonic-gate 			/*
198*0Sstevel@tonic-gate 			 * Allocate IO resources.
199*0Sstevel@tonic-gate 			 */
200*0Sstevel@tonic-gate 			io_req.Attributes1	= IO_DATA_PATH_WIDTH_16;
201*0Sstevel@tonic-gate 			io_req.IOAddrLines	= cft->p.addr_lines;
202*0Sstevel@tonic-gate 			io_req.BasePort1.base	= (cft->p.ata_base[0] & 0xfff0);
203*0Sstevel@tonic-gate 			io_req.NumPorts1	= cft->p.ata_length[0];
204*0Sstevel@tonic-gate 
205*0Sstevel@tonic-gate 			io_req.Attributes2	= 0;
206*0Sstevel@tonic-gate 			io_req.NumPorts2	= 0;
207*0Sstevel@tonic-gate 			if (cft->p.ranges == 2) {
208*0Sstevel@tonic-gate 				io_req.Attributes2	= IO_DATA_PATH_WIDTH_16;
209*0Sstevel@tonic-gate 				io_req.NumPorts2	= cft->p.ata_length[1];
210*0Sstevel@tonic-gate 				io_req.BasePort2.base	=
211*0Sstevel@tonic-gate 				    (cft->p.ata_base[1] & 0xfff0);
212*0Sstevel@tonic-gate 			}
213*0Sstevel@tonic-gate 
214*0Sstevel@tonic-gate 			ret = csx_RequestIO(softp->client_handle, &io_req);
215*0Sstevel@tonic-gate 			if (ret == CS_SUCCESS) {
216*0Sstevel@tonic-gate 				/* found a good IO range */
217*0Sstevel@tonic-gate 				break;
218*0Sstevel@tonic-gate 			}
219*0Sstevel@tonic-gate 		}
220*0Sstevel@tonic-gate 		cft = cft->next;
221*0Sstevel@tonic-gate 	}
222*0Sstevel@tonic-gate 
223*0Sstevel@tonic-gate 
224*0Sstevel@tonic-gate 	/*
225*0Sstevel@tonic-gate 	 * save all the CIS data
226*0Sstevel@tonic-gate 	 */
227*0Sstevel@tonic-gate 	if (cft) {
228*0Sstevel@tonic-gate 		cis_vars->ata_base[0]	= cft->p.ata_base[0] & 0xfff0;
229*0Sstevel@tonic-gate 		cis_vars->ata_length[0]	= cft->p.ata_length[0];
230*0Sstevel@tonic-gate 		cis_vars->addr_lines	= cft->p.addr_lines;
231*0Sstevel@tonic-gate 		cis_vars->ata_vcc	= cft->p.ata_vcc;
232*0Sstevel@tonic-gate 		cis_vars->ata_vpp1	= cft->p.ata_vpp1;
233*0Sstevel@tonic-gate 		cis_vars->ata_vpp2	= cft->p.ata_vpp2;
234*0Sstevel@tonic-gate 		cis_vars->pin		= cft->p.pin;
235*0Sstevel@tonic-gate 		cis_vars->config_index	= cft->p.config_index;
236*0Sstevel@tonic-gate 		if (cft->p.ranges == 2) {
237*0Sstevel@tonic-gate 			cis_vars->ata_base[1]	= cft->p.ata_base[1] & 0xfff0;
238*0Sstevel@tonic-gate 			cis_vars->ata_length[1]	= cft->p.ata_length[1];
239*0Sstevel@tonic-gate 		}
240*0Sstevel@tonic-gate 	}
241*0Sstevel@tonic-gate 
242*0Sstevel@tonic-gate 	/* release config table entries list */
243*0Sstevel@tonic-gate 	pcata_destroy_cftable_list(&cftable);
244*0Sstevel@tonic-gate 
245*0Sstevel@tonic-gate 	/*
246*0Sstevel@tonic-gate 	 * if we could not find a usable set of address
247*0Sstevel@tonic-gate 	 */
248*0Sstevel@tonic-gate 	if (!cft) {
249*0Sstevel@tonic-gate 		cmn_err(CE_CONT, "socket %d RequestIO failed %s\n",
250*0Sstevel@tonic-gate 			softp->sn, pcata_CS_etext(ret));
251*0Sstevel@tonic-gate 		return (CS_GENERAL_FAILURE);
252*0Sstevel@tonic-gate 	}
253*0Sstevel@tonic-gate 
254*0Sstevel@tonic-gate 	softp->handle = io_req.BasePort1.handle;
255*0Sstevel@tonic-gate 	softp->flags |= PCATA_REQUESTIO;
256*0Sstevel@tonic-gate 
257*0Sstevel@tonic-gate #ifdef	ATA_DEBUG
258*0Sstevel@tonic-gate 	if (pcata_debug & DINIT) {
259*0Sstevel@tonic-gate 		cmn_err(CE_CONT,
260*0Sstevel@tonic-gate 			"\npresent mask: 0x%x\n"
261*0Sstevel@tonic-gate 			"PRR pin mask: 0x%x\n"
262*0Sstevel@tonic-gate 			"major_revision: 0x%x\n"
263*0Sstevel@tonic-gate 			"minor_revision: 0x%x\n"
264*0Sstevel@tonic-gate 			"manufacturer_id: 0x%x\n"
265*0Sstevel@tonic-gate 			"card_id: 0x%x\n"
266*0Sstevel@tonic-gate 			"config_base: 0x%x\n"
267*0Sstevel@tonic-gate 			"config_index: 0x%x\n",
268*0Sstevel@tonic-gate 			cis_vars->present, cis_vars->pin,
269*0Sstevel@tonic-gate 			cis_vars->major_revision,
270*0Sstevel@tonic-gate 			cis_vars->minor_revision,
271*0Sstevel@tonic-gate 			cis_vars->manufacturer_id,
272*0Sstevel@tonic-gate 			cis_vars->card_id,
273*0Sstevel@tonic-gate 			cis_vars->config_base,
274*0Sstevel@tonic-gate 			cis_vars->config_index);
275*0Sstevel@tonic-gate 
276*0Sstevel@tonic-gate 		cmn_err(CE_CONT,
277*0Sstevel@tonic-gate 			"\nata_vcc: %u\n"
278*0Sstevel@tonic-gate 			"ata_vpp1: %u\n"
279*0Sstevel@tonic-gate 			"ata_vpp2: %u\n"
280*0Sstevel@tonic-gate 			"addr_lines: %u\n"
281*0Sstevel@tonic-gate 			"ata_base[0]:   %u\n"
282*0Sstevel@tonic-gate 			"ata_length[0]: %u\n"
283*0Sstevel@tonic-gate 			"ata_base[1]:   %u\n"
284*0Sstevel@tonic-gate 			"ata_length[1]: %u\n",
285*0Sstevel@tonic-gate 			cis_vars->ata_vcc,
286*0Sstevel@tonic-gate 			cis_vars->ata_vpp1,
287*0Sstevel@tonic-gate 			cis_vars->ata_vpp2,
288*0Sstevel@tonic-gate 			cis_vars->addr_lines,
289*0Sstevel@tonic-gate 			cis_vars->ata_base[0],
290*0Sstevel@tonic-gate 			cis_vars->ata_length[0],
291*0Sstevel@tonic-gate 			cis_vars->ata_base[1],
292*0Sstevel@tonic-gate 			cis_vars->ata_length[1]);
293*0Sstevel@tonic-gate 	}
294*0Sstevel@tonic-gate #endif
295*0Sstevel@tonic-gate #ifdef ATA_DEBUG
296*0Sstevel@tonic-gate 	if (pcata_debug & DPCM) {
297*0Sstevel@tonic-gate 		cmn_err(CE_CONT, "ports assigned: 0x%p+%u & 0x%p+%u\n",
298*0Sstevel@tonic-gate 			(void *)io_req.BasePort1.handle,
299*0Sstevel@tonic-gate 			io_req.NumPorts1,
300*0Sstevel@tonic-gate 			(void *)io_req.BasePort2.handle,
301*0Sstevel@tonic-gate 			io_req.NumPorts2);
302*0Sstevel@tonic-gate 		cmn_err(CE_CONT,
303*0Sstevel@tonic-gate 			"_ci_ioaddr: socket %d base_0 0x%x len_0 0x%x"
304*0Sstevel@tonic-gate 			" base_1 0x%x len_1 0x%x\n",
305*0Sstevel@tonic-gate 			softp->sn,
306*0Sstevel@tonic-gate 			cis_vars->ata_base[0], cis_vars->ata_length[0],
307*0Sstevel@tonic-gate 			cis_vars->ata_base[0], cis_vars->ata_length[1]);
308*0Sstevel@tonic-gate 	}
309*0Sstevel@tonic-gate #endif
310*0Sstevel@tonic-gate 	return (CS_SUCCESS);
311*0Sstevel@tonic-gate }
312*0Sstevel@tonic-gate 
313*0Sstevel@tonic-gate /*
314*0Sstevel@tonic-gate  * The card must be inserted before some things can be done
315*0Sstevel@tonic-gate  * 1) determine the I/O address space
316*0Sstevel@tonic-gate  * 2) determine the IRQ
317*0Sstevel@tonic-gate  * 3) configure the card
318*0Sstevel@tonic-gate  */
319*0Sstevel@tonic-gate static int
pcata_card_insertion(ata_soft_t * softp)320*0Sstevel@tonic-gate pcata_card_insertion(ata_soft_t *softp)
321*0Sstevel@tonic-gate {
322*0Sstevel@tonic-gate 	get_status_t		get_status;
323*0Sstevel@tonic-gate 	pcata_cis_vars_t	*cis_vars = &softp->cis_vars;
324*0Sstevel@tonic-gate 	irq_req_t		irq_req;
325*0Sstevel@tonic-gate 	config_req_t		config_req;
326*0Sstevel@tonic-gate 	modify_config_t		modify_config;
327*0Sstevel@tonic-gate 	int			ret;
328*0Sstevel@tonic-gate 	int			i;
329*0Sstevel@tonic-gate 
330*0Sstevel@tonic-gate #ifdef  ATA_DEBUG
331*0Sstevel@tonic-gate 	if (pcata_debug & DPCM)
332*0Sstevel@tonic-gate 		cmn_err(CE_CONT, "_card_insertion: socket %d\n",
333*0Sstevel@tonic-gate 			softp->sn);
334*0Sstevel@tonic-gate #endif
335*0Sstevel@tonic-gate 
336*0Sstevel@tonic-gate 	mutex_enter(&softp->ata_mutex);
337*0Sstevel@tonic-gate 
338*0Sstevel@tonic-gate 	/*
339*0Sstevel@tonic-gate 	 * Allocate io address space
340*0Sstevel@tonic-gate 	 */
341*0Sstevel@tonic-gate 	if ((softp->flags & PCATA_REQUESTIO) == 0) {
342*0Sstevel@tonic-gate 		ret = pcata_ci_ioaddr(softp);
343*0Sstevel@tonic-gate 		if (ret != CS_SUCCESS) {
344*0Sstevel@tonic-gate 			mutex_exit(&softp->ata_mutex);
345*0Sstevel@tonic-gate 			return (ret);
346*0Sstevel@tonic-gate 		}
347*0Sstevel@tonic-gate 	}
348*0Sstevel@tonic-gate 
349*0Sstevel@tonic-gate 	/*
350*0Sstevel@tonic-gate 	 * Allocate an IRQ.
351*0Sstevel@tonic-gate 	 */
352*0Sstevel@tonic-gate 	softp->intr_pending = 0;
353*0Sstevel@tonic-gate 	irq_req.Attributes = IRQ_TYPE_EXCLUSIVE;
354*0Sstevel@tonic-gate 	irq_req.irq_handler = (csfunction_t *)pcata_intr_hi;
355*0Sstevel@tonic-gate 	irq_req.irq_handler_arg = (caddr_t)softp;
356*0Sstevel@tonic-gate 	if (!(softp->flags & PCATA_REQUESTIRQ)) {
357*0Sstevel@tonic-gate 		ret = csx_RequestIRQ(softp->client_handle, &irq_req);
358*0Sstevel@tonic-gate 		if (ret != CS_SUCCESS) {
359*0Sstevel@tonic-gate #ifdef  ATA_DEBUG
360*0Sstevel@tonic-gate 			cmn_err(CE_CONT, "socket %d RequestIRQ failed %s\n",
361*0Sstevel@tonic-gate 				softp->sn, pcata_CS_etext(ret));
362*0Sstevel@tonic-gate #endif
363*0Sstevel@tonic-gate 			mutex_exit(&softp->ata_mutex);
364*0Sstevel@tonic-gate 			return (ret);
365*0Sstevel@tonic-gate 		}
366*0Sstevel@tonic-gate 		softp->flags |= PCATA_REQUESTIRQ;
367*0Sstevel@tonic-gate 	}
368*0Sstevel@tonic-gate 
369*0Sstevel@tonic-gate 	/*
370*0Sstevel@tonic-gate 	 * Initialize high level interrupt mutex.
371*0Sstevel@tonic-gate 	 */
372*0Sstevel@tonic-gate 	if (!(softp->flags & PCATA_DIDLOCKS2)) {
373*0Sstevel@tonic-gate 		mutex_init(&softp->hi_mutex, NULL,
374*0Sstevel@tonic-gate 		    MUTEX_DRIVER, *(irq_req.iblk_cookie));
375*0Sstevel@tonic-gate 		softp->flags |= PCATA_DIDLOCKS2;
376*0Sstevel@tonic-gate 	}
377*0Sstevel@tonic-gate 
378*0Sstevel@tonic-gate 	/*
379*0Sstevel@tonic-gate 	 * Configure the card.
380*0Sstevel@tonic-gate 	 */
381*0Sstevel@tonic-gate 	config_req.Attributes	= 0;
382*0Sstevel@tonic-gate 	config_req.Vcc		= cis_vars->ata_vcc;
383*0Sstevel@tonic-gate 	config_req.Vpp1		= cis_vars->ata_vpp1;
384*0Sstevel@tonic-gate 	config_req.Vpp2		= cis_vars->ata_vpp2;
385*0Sstevel@tonic-gate 	config_req.IntType	= SOCKET_INTERFACE_MEMORY_AND_IO;
386*0Sstevel@tonic-gate 	config_req.ConfigBase	= cis_vars->config_base;
387*0Sstevel@tonic-gate 	config_req.Status	= 0;
388*0Sstevel@tonic-gate 	config_req.Pin		= cis_vars->pin;
389*0Sstevel@tonic-gate 	config_req.Copy		= 0;
390*0Sstevel@tonic-gate 	config_req.ConfigIndex	= cis_vars->config_index;
391*0Sstevel@tonic-gate 	config_req.Present	= cis_vars->present;
392*0Sstevel@tonic-gate 
393*0Sstevel@tonic-gate 	if (!(softp->flags & PCATA_REQUESTCONFIG)) {
394*0Sstevel@tonic-gate 
395*0Sstevel@tonic-gate 		ret = csx_RequestConfiguration(
396*0Sstevel@tonic-gate 			softp->client_handle,
397*0Sstevel@tonic-gate 			&config_req);
398*0Sstevel@tonic-gate 		if (ret != CS_SUCCESS) {
399*0Sstevel@tonic-gate #ifdef  ATA_DEBUG
400*0Sstevel@tonic-gate 			cmn_err(CE_CONT,
401*0Sstevel@tonic-gate 				"socket %d RequestConfiguration failed %s\n",
402*0Sstevel@tonic-gate 				softp->sn,
403*0Sstevel@tonic-gate 				pcata_CS_etext(ret));
404*0Sstevel@tonic-gate #endif
405*0Sstevel@tonic-gate 			mutex_exit(&softp->ata_mutex);
406*0Sstevel@tonic-gate 			return (ret);
407*0Sstevel@tonic-gate 		}
408*0Sstevel@tonic-gate 		softp->flags |= PCATA_REQUESTCONFIG;
409*0Sstevel@tonic-gate 	}
410*0Sstevel@tonic-gate 
411*0Sstevel@tonic-gate #ifdef  ATA_DEBUG
412*0Sstevel@tonic-gate 	if (pcata_debug & DPCM)
413*0Sstevel@tonic-gate 		cmn_err(CE_CONT, "_card_insertion: configuration complete\n");
414*0Sstevel@tonic-gate #endif
415*0Sstevel@tonic-gate 
416*0Sstevel@tonic-gate 	mutex_exit(&softp->ata_mutex);
417*0Sstevel@tonic-gate 	mutex_enter(&softp->event_hilock);
418*0Sstevel@tonic-gate 	softp->card_state = PCATA_WAIT_FOR_READY;
419*0Sstevel@tonic-gate 	mutex_exit(&softp->event_hilock);
420*0Sstevel@tonic-gate 
421*0Sstevel@tonic-gate 	/*
422*0Sstevel@tonic-gate 	 * check the disk (every .05 sec) to see if it is ready
423*0Sstevel@tonic-gate 	 */
424*0Sstevel@tonic-gate 	for (i = 0; i < PCATA_READY_TIMEOUT; i += 50000) {
425*0Sstevel@tonic-gate 		(void) csx_GetStatus(softp->client_handle, &get_status);
426*0Sstevel@tonic-gate 		if (get_status.CardState & CS_EVENT_CARD_READY)
427*0Sstevel@tonic-gate 			break;
428*0Sstevel@tonic-gate 		drv_usecwait(50000);
429*0Sstevel@tonic-gate 	}
430*0Sstevel@tonic-gate 
431*0Sstevel@tonic-gate 	if ((get_status.CardState & CS_EVENT_CARD_READY) == 0) {
432*0Sstevel@tonic-gate 		/* the disk is NOT ready */
433*0Sstevel@tonic-gate 		return (CS_GENERAL_FAILURE);
434*0Sstevel@tonic-gate 	}
435*0Sstevel@tonic-gate 
436*0Sstevel@tonic-gate 	mutex_enter(&softp->ata_mutex);
437*0Sstevel@tonic-gate 
438*0Sstevel@tonic-gate 	/*
439*0Sstevel@tonic-gate 	 * create the device tree
440*0Sstevel@tonic-gate 	 */
441*0Sstevel@tonic-gate 	if (!(softp->flags & PCATA_MAKEDEVICENODE)) {
442*0Sstevel@tonic-gate 		if (pcata_create_device_node(softp) != CS_SUCCESS) {
443*0Sstevel@tonic-gate 			mutex_enter(&softp->event_hilock);
444*0Sstevel@tonic-gate 			cv_broadcast(&softp->readywait_cv);
445*0Sstevel@tonic-gate 			mutex_exit(&softp->event_hilock);
446*0Sstevel@tonic-gate 			mutex_exit(&softp->ata_mutex);
447*0Sstevel@tonic-gate 			return (CS_GENERAL_FAILURE);
448*0Sstevel@tonic-gate 		}
449*0Sstevel@tonic-gate 		softp->flags |= PCATA_MAKEDEVICENODE;
450*0Sstevel@tonic-gate 	}
451*0Sstevel@tonic-gate 
452*0Sstevel@tonic-gate 	/*
453*0Sstevel@tonic-gate 	 * enable interrupts thru the CSX context
454*0Sstevel@tonic-gate 	 */
455*0Sstevel@tonic-gate 	bzero((caddr_t)&modify_config, sizeof (modify_config_t));
456*0Sstevel@tonic-gate 	modify_config.Socket = softp->sn;
457*0Sstevel@tonic-gate 	modify_config.Attributes =
458*0Sstevel@tonic-gate 	    CONF_IRQ_CHANGE_VALID | CONF_ENABLE_IRQ_STEERING;
459*0Sstevel@tonic-gate 	ret = csx_ModifyConfiguration(softp->client_handle, &modify_config);
460*0Sstevel@tonic-gate 	if (ret != CS_SUCCESS) {
461*0Sstevel@tonic-gate 		cmn_err(CE_CONT, "ModifyConfiguration failed %s\n",
462*0Sstevel@tonic-gate 		    pcata_CS_etext(ret));
463*0Sstevel@tonic-gate 		mutex_exit(&softp->ata_mutex);
464*0Sstevel@tonic-gate 		return (CS_GENERAL_FAILURE);
465*0Sstevel@tonic-gate 	}
466*0Sstevel@tonic-gate 
467*0Sstevel@tonic-gate 	mutex_enter(&softp->event_hilock);
468*0Sstevel@tonic-gate 	softp->card_state &= ~PCATA_WAIT_FOR_READY;
469*0Sstevel@tonic-gate 	softp->card_state |= PCATA_CARD_IS_READY;
470*0Sstevel@tonic-gate 	softp->card_state |= PCATA_CARD_INSERTED;
471*0Sstevel@tonic-gate 	cv_broadcast(&softp->readywait_cv);
472*0Sstevel@tonic-gate 	mutex_exit(&softp->event_hilock);
473*0Sstevel@tonic-gate 
474*0Sstevel@tonic-gate 	/* XXXX - for Volume Manager */
475*0Sstevel@tonic-gate 	if (softp->checkmedia_flag) {
476*0Sstevel@tonic-gate 		softp->checkmedia_flag = 0;
477*0Sstevel@tonic-gate 		softp->media_state = DKIO_INSERTED;
478*0Sstevel@tonic-gate 		cv_broadcast(&softp->condvar_mediastate);
479*0Sstevel@tonic-gate #ifdef	ATA_DEBUG
480*0Sstevel@tonic-gate 		if (pcata_debug & DVOLD) {
481*0Sstevel@tonic-gate 			cmn_err(CE_CONT, "pcata_card_insertion: socket %d \n"
482*0Sstevel@tonic-gate 			    "\tdoing cv_broadcast - "
483*0Sstevel@tonic-gate 			    "softp->media_state of DKIO_INSERTED\n", softp->sn);
484*0Sstevel@tonic-gate 		}
485*0Sstevel@tonic-gate #endif
486*0Sstevel@tonic-gate 	}
487*0Sstevel@tonic-gate 
488*0Sstevel@tonic-gate 	mutex_exit(&softp->ata_mutex);
489*0Sstevel@tonic-gate 	return (CS_SUCCESS);
490*0Sstevel@tonic-gate }
491*0Sstevel@tonic-gate 
492*0Sstevel@tonic-gate /*
493*0Sstevel@tonic-gate  * this function may be called by several different threads simultaneously
494*0Sstevel@tonic-gate  * the normal calling sequence is
495*0Sstevel@tonic-gate  */
496*0Sstevel@tonic-gate int
pcata_readywait(ata_soft_t * softp)497*0Sstevel@tonic-gate pcata_readywait(ata_soft_t *softp)
498*0Sstevel@tonic-gate {
499*0Sstevel@tonic-gate 	mutex_enter(&softp->event_hilock);
500*0Sstevel@tonic-gate 
501*0Sstevel@tonic-gate 	if (softp->card_state & PCATA_WAITINIT)
502*0Sstevel@tonic-gate 		cv_wait(&softp->readywait_cv, &softp->event_hilock);
503*0Sstevel@tonic-gate 
504*0Sstevel@tonic-gate 	mutex_exit(&softp->event_hilock);
505*0Sstevel@tonic-gate 	return (softp->card_state & PCATA_CARD_IS_READY);
506*0Sstevel@tonic-gate }
507*0Sstevel@tonic-gate 
508*0Sstevel@tonic-gate /*
509*0Sstevel@tonic-gate  * Wait for minor nodes to be created before returning from attach,
510*0Sstevel@tonic-gate  * with a 5 sec. timeout to avoid hangs should an error occur.
511*0Sstevel@tonic-gate  */
512*0Sstevel@tonic-gate void
pcata_minor_wait(ata_soft_t * softp)513*0Sstevel@tonic-gate pcata_minor_wait(ata_soft_t *softp)
514*0Sstevel@tonic-gate {
515*0Sstevel@tonic-gate 	clock_t	timeout;
516*0Sstevel@tonic-gate 
517*0Sstevel@tonic-gate 	timeout = ddi_get_lbolt() + drv_usectohz(5000000);
518*0Sstevel@tonic-gate 	mutex_enter(&softp->event_hilock);
519*0Sstevel@tonic-gate 	while ((softp->flags & PCATA_MAKEDEVICENODE) == 0) {
520*0Sstevel@tonic-gate 		if (cv_timedwait(&softp->readywait_cv, &softp->event_hilock,
521*0Sstevel@tonic-gate 		    timeout) == (clock_t)-1)
522*0Sstevel@tonic-gate 			break;
523*0Sstevel@tonic-gate 	}
524*0Sstevel@tonic-gate 	mutex_exit(&softp->event_hilock);
525*0Sstevel@tonic-gate }
526*0Sstevel@tonic-gate 
527*0Sstevel@tonic-gate 
528*0Sstevel@tonic-gate int
pcata_card_removal(ata_soft_t * softp,int priority)529*0Sstevel@tonic-gate pcata_card_removal(ata_soft_t *softp, int priority)
530*0Sstevel@tonic-gate {
531*0Sstevel@tonic-gate 	int	ret;
532*0Sstevel@tonic-gate 
533*0Sstevel@tonic-gate #ifdef ATA_DEBUG
534*0Sstevel@tonic-gate 	if (pcata_debug & DENT)
535*0Sstevel@tonic-gate 		cmn_err(CE_CONT, "_card_removal: priority=%x\n",
536*0Sstevel@tonic-gate 		    priority);
537*0Sstevel@tonic-gate #endif
538*0Sstevel@tonic-gate 
539*0Sstevel@tonic-gate 	mutex_enter(&softp->event_hilock);
540*0Sstevel@tonic-gate 	softp->card_state &= ~(PCATA_CARD_INSERTED | PCATA_WAIT_FOR_READY);
541*0Sstevel@tonic-gate 	softp->flags &= ~PCATA_READY;
542*0Sstevel@tonic-gate 	mutex_exit(&softp->event_hilock);
543*0Sstevel@tonic-gate 
544*0Sstevel@tonic-gate 	/*
545*0Sstevel@tonic-gate 	 * If we're being called at high priority, we can't do much more
546*0Sstevel@tonic-gate 	 * than note that the card went away.
547*0Sstevel@tonic-gate 	 */
548*0Sstevel@tonic-gate 	if (priority & CS_EVENT_PRI_HIGH)
549*0Sstevel@tonic-gate 		return (CS_SUCCESS);
550*0Sstevel@tonic-gate 
551*0Sstevel@tonic-gate 	mutex_enter(&softp->ata_mutex);
552*0Sstevel@tonic-gate 
553*0Sstevel@tonic-gate 	/*
554*0Sstevel@tonic-gate 	 * If the device was open at the time the card was removed
555*0Sstevel@tonic-gate 	 * we set the ejected_while_mounted flag until all instances of the
556*0Sstevel@tonic-gate 	 * device are closed.
557*0Sstevel@tonic-gate 	 * If the device is mounted by vold it will remain open when
558*0Sstevel@tonic-gate 	 * the card is removed. If the card is inserted again it will
559*0Sstevel@tonic-gate 	 * be mounted again by vold.
560*0Sstevel@tonic-gate 	 */
561*0Sstevel@tonic-gate 	if ((softp->blk_open) || (softp->chr_open))
562*0Sstevel@tonic-gate 		softp->ejected_while_mounted = 1;
563*0Sstevel@tonic-gate 	else {
564*0Sstevel@tonic-gate 		int i;
565*0Sstevel@tonic-gate 		for (i = 0; i < NUM_PARTS; i++) {
566*0Sstevel@tonic-gate 			if (softp->lyr_open[i] != 0)
567*0Sstevel@tonic-gate 				softp->ejected_while_mounted = 1;
568*0Sstevel@tonic-gate 		}
569*0Sstevel@tonic-gate 	}
570*0Sstevel@tonic-gate 
571*0Sstevel@tonic-gate 	if (softp->ejected_while_mounted) {
572*0Sstevel@tonic-gate 		cmn_err(CE_WARN, "socket%d "
573*0Sstevel@tonic-gate 				"Card is ejected & "
574*0Sstevel@tonic-gate 				"Data integrity is not guaranteed",
575*0Sstevel@tonic-gate 				softp->sn);
576*0Sstevel@tonic-gate 	}
577*0Sstevel@tonic-gate 
578*0Sstevel@tonic-gate 	/* XXXX - for Volume Manager */
579*0Sstevel@tonic-gate 	if (softp->checkmedia_flag) {
580*0Sstevel@tonic-gate 		softp->checkmedia_flag = 0;
581*0Sstevel@tonic-gate 		softp->media_state = DKIO_EJECTED;
582*0Sstevel@tonic-gate 		cv_broadcast(&softp->condvar_mediastate);
583*0Sstevel@tonic-gate #ifdef	ATA_DEBUG
584*0Sstevel@tonic-gate 		if (pcata_debug & DVOLD) {
585*0Sstevel@tonic-gate 			cmn_err(CE_CONT,
586*0Sstevel@tonic-gate 			    "pcata_card_removal: socket %d \n"
587*0Sstevel@tonic-gate 			    "\tdoing cv_broadcast - "
588*0Sstevel@tonic-gate 			    "softp->media_state of DKIO_EJECTED\n",
589*0Sstevel@tonic-gate 			    softp->sn);
590*0Sstevel@tonic-gate 		}
591*0Sstevel@tonic-gate #endif
592*0Sstevel@tonic-gate 	}
593*0Sstevel@tonic-gate 
594*0Sstevel@tonic-gate 	if (softp->flags & PCATA_REQUESTCONFIG) {
595*0Sstevel@tonic-gate 		/*
596*0Sstevel@tonic-gate 		 * Release card configuration.
597*0Sstevel@tonic-gate 		 */
598*0Sstevel@tonic-gate 		release_config_t release_config;
599*0Sstevel@tonic-gate 		if ((ret = csx_ReleaseConfiguration(softp->client_handle,
600*0Sstevel@tonic-gate 			&release_config)) != CS_SUCCESS) {
601*0Sstevel@tonic-gate 
602*0Sstevel@tonic-gate 			cmn_err(CE_CONT, "socket %d ReleaseConfiguration failed"
603*0Sstevel@tonic-gate 				"%s\n",
604*0Sstevel@tonic-gate 				softp->sn, pcata_CS_etext(ret));
605*0Sstevel@tonic-gate 		} /* ReleaseConfiguration */
606*0Sstevel@tonic-gate 
607*0Sstevel@tonic-gate 		softp->flags &= ~PCATA_REQUESTCONFIG;
608*0Sstevel@tonic-gate 	} /* PCATA_REQUESTCONFIG */
609*0Sstevel@tonic-gate 
610*0Sstevel@tonic-gate 	if (softp->flags & PCATA_REQUESTIRQ) {
611*0Sstevel@tonic-gate 		irq_req_t irq_req;
612*0Sstevel@tonic-gate 		/*
613*0Sstevel@tonic-gate 		 * Release allocated IRQ resources.
614*0Sstevel@tonic-gate 		 */
615*0Sstevel@tonic-gate 		ret = csx_ReleaseIRQ(softp->client_handle, &irq_req);
616*0Sstevel@tonic-gate 		if (ret != CS_SUCCESS) {
617*0Sstevel@tonic-gate 			cmn_err(CE_CONT, "socket %d ReleaseIRQ failed %s\n",
618*0Sstevel@tonic-gate 				softp->sn, pcata_CS_etext(ret));
619*0Sstevel@tonic-gate 		} /* ReleaseIRQ */
620*0Sstevel@tonic-gate 		softp->flags &= ~PCATA_REQUESTIRQ;
621*0Sstevel@tonic-gate 
622*0Sstevel@tonic-gate 	} /* PCATA_REQUESTIRQ */
623*0Sstevel@tonic-gate 
624*0Sstevel@tonic-gate 	if (softp->flags & PCATA_DIDLOCKS2) {
625*0Sstevel@tonic-gate 		mutex_destroy(&softp->hi_mutex);
626*0Sstevel@tonic-gate 		softp->flags &= ~PCATA_DIDLOCKS2;
627*0Sstevel@tonic-gate 	}
628*0Sstevel@tonic-gate 
629*0Sstevel@tonic-gate 
630*0Sstevel@tonic-gate 	if (softp->flags & PCATA_REQUESTIO) {
631*0Sstevel@tonic-gate 		/*
632*0Sstevel@tonic-gate 		 * Release allocated IO resources.
633*0Sstevel@tonic-gate 		 */
634*0Sstevel@tonic-gate 		io_req_t io_req;
635*0Sstevel@tonic-gate 		if ((ret = csx_ReleaseIO(softp->client_handle,
636*0Sstevel@tonic-gate 			&io_req)) != CS_SUCCESS) {
637*0Sstevel@tonic-gate 			cmn_err(CE_CONT, "socket %d"
638*0Sstevel@tonic-gate 				"ReleaseIO failed %s\n",
639*0Sstevel@tonic-gate 				softp->sn, pcata_CS_etext(ret));
640*0Sstevel@tonic-gate 		} /* ReleaseIO */
641*0Sstevel@tonic-gate 		softp->flags &= ~PCATA_REQUESTIO;
642*0Sstevel@tonic-gate 	} /* PCATA_REQUESTIO */
643*0Sstevel@tonic-gate 
644*0Sstevel@tonic-gate 	/*
645*0Sstevel@tonic-gate 	 * Remove all the device nodes.  We don't have to explictly
646*0Sstevel@tonic-gate 	 * specify the names if we want Card Services to remove
647*0Sstevel@tonic-gate 	 * all of the devices.
648*0Sstevel@tonic-gate 	 * Note that when you call RemoveDeviceNode with the Action
649*0Sstevel@tonic-gate 	 * argument set to REMOVE_ALL_DEVICE_NODES, the
650*0Sstevel@tonic-gate 	 * NumDevNodes must be zero.
651*0Sstevel@tonic-gate 	 */
652*0Sstevel@tonic-gate 	if (softp->flags & PCATA_MAKEDEVICENODE) {
653*0Sstevel@tonic-gate 		remove_device_node_t remove_device_node;
654*0Sstevel@tonic-gate 
655*0Sstevel@tonic-gate 		remove_device_node.Action = REMOVE_ALL_DEVICE_NODES;
656*0Sstevel@tonic-gate 		remove_device_node.NumDevNodes = 0;
657*0Sstevel@tonic-gate 
658*0Sstevel@tonic-gate 		if ((ret = csx_RemoveDeviceNode(softp->client_handle,
659*0Sstevel@tonic-gate 		    &remove_device_node)) != CS_SUCCESS) {
660*0Sstevel@tonic-gate 			cmn_err(CE_CONT, "_card_removal: socket %d "
661*0Sstevel@tonic-gate 			    "RemoveDeviceNode failed %s\n",
662*0Sstevel@tonic-gate 			    softp->sn, pcata_CS_etext(ret));
663*0Sstevel@tonic-gate 		} /* RemoveDeviceNode */
664*0Sstevel@tonic-gate 		softp->flags &= ~PCATA_MAKEDEVICENODE;
665*0Sstevel@tonic-gate 	} /* PCATA_MAKEDEVICENODE */
666*0Sstevel@tonic-gate 
667*0Sstevel@tonic-gate 	pcata_drive_unsetup(softp);
668*0Sstevel@tonic-gate 	mutex_exit(&softp->ata_mutex);
669*0Sstevel@tonic-gate 
670*0Sstevel@tonic-gate 	mutex_enter(&softp->event_hilock);
671*0Sstevel@tonic-gate 	cv_broadcast(&softp->readywait_cv);
672*0Sstevel@tonic-gate 	mutex_exit(&softp->event_hilock);
673*0Sstevel@tonic-gate 	return (CS_SUCCESS);
674*0Sstevel@tonic-gate }
675*0Sstevel@tonic-gate 
676*0Sstevel@tonic-gate static void
pcata_drive_unsetup(ata_soft_t * softp)677*0Sstevel@tonic-gate pcata_drive_unsetup(ata_soft_t *softp)
678*0Sstevel@tonic-gate {
679*0Sstevel@tonic-gate 	ata_unit_t	*unitp;
680*0Sstevel@tonic-gate 	struct ata_cmpkt *pktp;
681*0Sstevel@tonic-gate 	int drive;
682*0Sstevel@tonic-gate 	buf_t		*bp;
683*0Sstevel@tonic-gate 
684*0Sstevel@tonic-gate 	/*
685*0Sstevel@tonic-gate 	 * free ab_active
686*0Sstevel@tonic-gate 	 */
687*0Sstevel@tonic-gate 	if ((pktp = softp->ab_active) != NULL) {
688*0Sstevel@tonic-gate 		bp = pktp->cp_bp;
689*0Sstevel@tonic-gate 		if (bp && ((bp->b_flags & B_DONE) == 0)) {
690*0Sstevel@tonic-gate 			bioerror(bp, ENXIO);
691*0Sstevel@tonic-gate 			biodone(bp);
692*0Sstevel@tonic-gate 		}
693*0Sstevel@tonic-gate 		kmem_free((void *)pktp, sizeof (*pktp));
694*0Sstevel@tonic-gate 		softp->ab_active = NULL;
695*0Sstevel@tonic-gate 	}
696*0Sstevel@tonic-gate 
697*0Sstevel@tonic-gate 	/* release any packets queued on the controller */
698*0Sstevel@tonic-gate 	while ((pktp = softp->ab_head) != NULL) {
699*0Sstevel@tonic-gate 		softp->ab_head = pktp->pkt_forw;
700*0Sstevel@tonic-gate 		bp = pktp->cp_bp;
701*0Sstevel@tonic-gate 		if (bp && ((bp->b_flags & B_DONE) == 0)) {
702*0Sstevel@tonic-gate 			/* first free the packets */
703*0Sstevel@tonic-gate 			bioerror(bp, ENXIO);
704*0Sstevel@tonic-gate 			biodone(bp);
705*0Sstevel@tonic-gate 		}
706*0Sstevel@tonic-gate 		kmem_free((void *)pktp, sizeof (*pktp));
707*0Sstevel@tonic-gate 	}
708*0Sstevel@tonic-gate 
709*0Sstevel@tonic-gate 	/* release the unit structures */
710*0Sstevel@tonic-gate 	while ((unitp = softp->ab_link) != NULL) {
711*0Sstevel@tonic-gate 		softp->ab_link = unitp->a_forw;
712*0Sstevel@tonic-gate 		kmem_free(unitp, sizeof (ata_unit_t));
713*0Sstevel@tonic-gate 	}
714*0Sstevel@tonic-gate 
715*0Sstevel@tonic-gate 	/*
716*0Sstevel@tonic-gate 	 * now free the atarpbuf memory
717*0Sstevel@tonic-gate 	 * It is poor code practice to use artificial number of drives,
718*0Sstevel@tonic-gate 	 * but we need to be consistant with the rest of the code, hence the
719*0Sstevel@tonic-gate 	 * drive=1 value.
720*0Sstevel@tonic-gate 	 */
721*0Sstevel@tonic-gate 	for (drive = 0; drive < 1; drive++) {
722*0Sstevel@tonic-gate 		if (softp->ab_rpbp[drive]) {
723*0Sstevel@tonic-gate 			kmem_free(softp->ab_rpbp[drive],
724*0Sstevel@tonic-gate 				(sizeof (struct atarpbuf) +
725*0Sstevel@tonic-gate 				sizeof (struct scsi_inquiry)));
726*0Sstevel@tonic-gate 			softp->ab_rpbp[drive] = NULL;
727*0Sstevel@tonic-gate 		}
728*0Sstevel@tonic-gate 	}
729*0Sstevel@tonic-gate }
730*0Sstevel@tonic-gate 
731*0Sstevel@tonic-gate 
732*0Sstevel@tonic-gate /*
733*0Sstevel@tonic-gate  * pcata_parse_cis - gets CIS information to configure the card.
734*0Sstevel@tonic-gate  *
735*0Sstevel@tonic-gate  * returns: CS_SUCCESS - if CIS information retreived correctly
736*0Sstevel@tonic-gate  *	    CS_OUT_OF_RESOURCE - if no memory for cftable entry
737*0Sstevel@tonic-gate  *	    {various CS return codes} - if problem getting CIS information
738*0Sstevel@tonic-gate  */
739*0Sstevel@tonic-gate int
pcata_parse_cis(ata_soft_t * softp,pcata_cftable_t ** cftable)740*0Sstevel@tonic-gate pcata_parse_cis(ata_soft_t *softp, pcata_cftable_t **cftable)
741*0Sstevel@tonic-gate {
742*0Sstevel@tonic-gate 
743*0Sstevel@tonic-gate 
744*0Sstevel@tonic-gate 	pcata_cis_vars_t *cis_vars = &softp->cis_vars;
745*0Sstevel@tonic-gate 	cistpl_config_t cistpl_config;
746*0Sstevel@tonic-gate 	cistpl_cftable_entry_t cistpl_cftable_entry;
747*0Sstevel@tonic-gate 	struct cistpl_cftable_entry_io_t *io = &cistpl_cftable_entry.io;
748*0Sstevel@tonic-gate 	cistpl_vers_1_t cistpl_vers_1;
749*0Sstevel@tonic-gate 	tuple_t tuple;
750*0Sstevel@tonic-gate 	pcata_cftable_t *cft, *ocft, *dcft, default_cftable;
751*0Sstevel@tonic-gate 	int ret, last_config_index;
752*0Sstevel@tonic-gate 	cistpl_manfid_t cistpl_manfid;
753*0Sstevel@tonic-gate 
754*0Sstevel@tonic-gate 	dcft = &default_cftable;
755*0Sstevel@tonic-gate 
756*0Sstevel@tonic-gate 	/*
757*0Sstevel@tonic-gate 	 * Clear the PCATA_VALID_IO_INFO flags here.
758*0Sstevel@tonic-gate 	 * These will be set if necessary as we parse the CIS and
759*0Sstevel@tonic-gate 	 * check the manufacturer specific overrides later on.
760*0Sstevel@tonic-gate 	 */
761*0Sstevel@tonic-gate 	softp->flags &= ~PCATA_VALID_IO_INFO;
762*0Sstevel@tonic-gate 
763*0Sstevel@tonic-gate 
764*0Sstevel@tonic-gate 	/*
765*0Sstevel@tonic-gate 	 * Clear the CIS information structure.
766*0Sstevel@tonic-gate 	 */
767*0Sstevel@tonic-gate 	bzero((caddr_t)cis_vars, sizeof (pcata_cis_vars_t));
768*0Sstevel@tonic-gate 
769*0Sstevel@tonic-gate 	/*
770*0Sstevel@tonic-gate 	 * CISTPL_CONFIG processing. Search for the first config tuple
771*0Sstevel@tonic-gate 	 * so that we can get a pointer to the card's configuration
772*0Sstevel@tonic-gate 	 * registers. If this tuple is not found, there's no point
773*0Sstevel@tonic-gate 	 * in searching for anything else.
774*0Sstevel@tonic-gate 	 */
775*0Sstevel@tonic-gate 	tuple.Attributes = 0;
776*0Sstevel@tonic-gate 	tuple.DesiredTuple = CISTPL_CONFIG;
777*0Sstevel@tonic-gate 	if ((ret = csx_GetFirstTuple(softp->client_handle,
778*0Sstevel@tonic-gate 	    &tuple)) != CS_SUCCESS) {
779*0Sstevel@tonic-gate 		cmn_err(CE_CONT, "_parse_cis: socket %d CISTPL_CONFIG "
780*0Sstevel@tonic-gate 		    "tuple not found\n", softp->sn);
781*0Sstevel@tonic-gate 		return (ret);
782*0Sstevel@tonic-gate 	} /* GetFirstTuple */
783*0Sstevel@tonic-gate 
784*0Sstevel@tonic-gate 	/*
785*0Sstevel@tonic-gate 	 * We shouldn't ever fail parsing this tuple.  If we do,
786*0Sstevel@tonic-gate 	 * there's probably an internal error in the CIS parser.
787*0Sstevel@tonic-gate 	 */
788*0Sstevel@tonic-gate 	ret = csx_Parse_CISTPL_CONFIG(softp->client_handle, &tuple,
789*0Sstevel@tonic-gate 		&cistpl_config);
790*0Sstevel@tonic-gate 	if (ret != CS_SUCCESS) {
791*0Sstevel@tonic-gate 		return (ret);
792*0Sstevel@tonic-gate 	}
793*0Sstevel@tonic-gate 
794*0Sstevel@tonic-gate 	/*
795*0Sstevel@tonic-gate 	 * This is the last CISTPL_CFTABLE_ENTRY tuple index that
796*0Sstevel@tonic-gate 	 * we need to look at.
797*0Sstevel@tonic-gate 	 */
798*0Sstevel@tonic-gate 	last_config_index = cistpl_config.last;
799*0Sstevel@tonic-gate 
800*0Sstevel@tonic-gate 	if (cistpl_config.nr) {
801*0Sstevel@tonic-gate 		cis_vars->config_base = cistpl_config.base;
802*0Sstevel@tonic-gate 		cis_vars->present = cistpl_config.present;
803*0Sstevel@tonic-gate 	} else {
804*0Sstevel@tonic-gate 		cmn_err(CE_CONT, "_parse_cis: socket %d"
805*0Sstevel@tonic-gate 			"CISTPL_CONFIG no configuration registers"
806*0Sstevel@tonic-gate 			"found\n", softp->sn);
807*0Sstevel@tonic-gate 		return (CS_BAD_CIS);
808*0Sstevel@tonic-gate 	} /* if (cistpl_config.nr) */
809*0Sstevel@tonic-gate 
810*0Sstevel@tonic-gate 	/*
811*0Sstevel@tonic-gate 	 * CISTPL_VERS_1 processing. The information from this tuple is
812*0Sstevel@tonic-gate 	 * mainly used for display purposes.
813*0Sstevel@tonic-gate 	 */
814*0Sstevel@tonic-gate 	tuple.Attributes = 0;
815*0Sstevel@tonic-gate 	tuple.DesiredTuple = CISTPL_VERS_1;
816*0Sstevel@tonic-gate 	ret = csx_GetFirstTuple(softp->client_handle, &tuple);
817*0Sstevel@tonic-gate 	if (ret != CS_SUCCESS) {
818*0Sstevel@tonic-gate 		/*
819*0Sstevel@tonic-gate 		 * It's OK not to find the tuple if it's not in the CIS, but
820*0Sstevel@tonic-gate 		 *	this test will catch other errors.
821*0Sstevel@tonic-gate 		 */
822*0Sstevel@tonic-gate 		if (ret != CS_NO_MORE_ITEMS) {
823*0Sstevel@tonic-gate 			return (ret);
824*0Sstevel@tonic-gate 		}
825*0Sstevel@tonic-gate 	} else {
826*0Sstevel@tonic-gate 		/*
827*0Sstevel@tonic-gate 		 * We shouldn't ever fail parsing this tuple.  If we do,
828*0Sstevel@tonic-gate 		 * there's probably an internal error in the CIS parser.
829*0Sstevel@tonic-gate 		 */
830*0Sstevel@tonic-gate 		if ((ret = csx_Parse_CISTPL_VERS_1(softp->client_handle,
831*0Sstevel@tonic-gate 		    &tuple, &cistpl_vers_1)) != CS_SUCCESS) {
832*0Sstevel@tonic-gate 
833*0Sstevel@tonic-gate 			return (ret);
834*0Sstevel@tonic-gate 		} else {
835*0Sstevel@tonic-gate 			int	i;
836*0Sstevel@tonic-gate 
837*0Sstevel@tonic-gate 			cis_vars->major_revision = cistpl_vers_1.major;
838*0Sstevel@tonic-gate 			cis_vars->minor_revision = cistpl_vers_1.minor;
839*0Sstevel@tonic-gate 
840*0Sstevel@tonic-gate 
841*0Sstevel@tonic-gate 			/*
842*0Sstevel@tonic-gate 			 * The first byte of the unused prod_strings will be
843*0Sstevel@tonic-gate 			 * NULL since we did a bzero(cis_vars) above.
844*0Sstevel@tonic-gate 			 */
845*0Sstevel@tonic-gate 			for (i = 0; i < cistpl_vers_1.ns; i++)
846*0Sstevel@tonic-gate 				(void) strcpy(cis_vars->prod_strings[i],
847*0Sstevel@tonic-gate 					cistpl_vers_1.pi[i]);
848*0Sstevel@tonic-gate 
849*0Sstevel@tonic-gate 		} /* csx_Parse_CISTPL_VERS_1 */
850*0Sstevel@tonic-gate 	} /* GetFirstTuple */
851*0Sstevel@tonic-gate 
852*0Sstevel@tonic-gate 	/*
853*0Sstevel@tonic-gate 	 * CISTPL_CFTABLE_ENTRY processing. Search for the first config tuple
854*0Sstevel@tonic-gate 	 * so that we can get a card configuration. If this tuple is not
855*0Sstevel@tonic-gate 	 * found, there's no point in searching for anything else.
856*0Sstevel@tonic-gate 	 */
857*0Sstevel@tonic-gate 	tuple.Attributes = 0;
858*0Sstevel@tonic-gate 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
859*0Sstevel@tonic-gate 	if ((ret = csx_GetFirstTuple(softp->client_handle,
860*0Sstevel@tonic-gate 	    &tuple)) != CS_SUCCESS) {
861*0Sstevel@tonic-gate 		cmn_err(CE_CONT,
862*0Sstevel@tonic-gate 			"_parse_cis: socket %d CISTPL_CFTABLE_ENTRY "
863*0Sstevel@tonic-gate 				"tuple not found\n", softp->sn);
864*0Sstevel@tonic-gate 		return (ret);
865*0Sstevel@tonic-gate 	} /* GetFirstTuple */
866*0Sstevel@tonic-gate 
867*0Sstevel@tonic-gate 	/*
868*0Sstevel@tonic-gate 	 * Clear the default values.
869*0Sstevel@tonic-gate 	 */
870*0Sstevel@tonic-gate 	bzero((caddr_t)dcft, sizeof (pcata_cftable_t));
871*0Sstevel@tonic-gate 
872*0Sstevel@tonic-gate 
873*0Sstevel@tonic-gate 	/*
874*0Sstevel@tonic-gate 	 * Some cards don't provide enough information
875*0Sstevel@tonic-gate 	 * in their CIS to allow us to configure them
876*0Sstevel@tonic-gate 	 * using CIS information alone, so we have to
877*0Sstevel@tonic-gate 	 * set some default values here.
878*0Sstevel@tonic-gate 	 */
879*0Sstevel@tonic-gate 	dcft->p.ata_vcc = 50;
880*0Sstevel@tonic-gate 
881*0Sstevel@tonic-gate 
882*0Sstevel@tonic-gate 	/*
883*0Sstevel@tonic-gate 	 * Loop through the CISTPL_CFTABLE_ENTRY tuple until we find a
884*0Sstevel@tonic-gate 	 * valid configuration.
885*0Sstevel@tonic-gate 	 */
886*0Sstevel@tonic-gate 	do {
887*0Sstevel@tonic-gate 
888*0Sstevel@tonic-gate 		ocft = kmem_zalloc(sizeof (pcata_cftable_t), KM_NOSLEEP);
889*0Sstevel@tonic-gate 		if (!ocft) {
890*0Sstevel@tonic-gate 			return (CS_OUT_OF_RESOURCE);
891*0Sstevel@tonic-gate 		}
892*0Sstevel@tonic-gate 		bzero((caddr_t)ocft, sizeof (pcata_cftable_t));
893*0Sstevel@tonic-gate 
894*0Sstevel@tonic-gate 		if (!*cftable) {
895*0Sstevel@tonic-gate 			*cftable = ocft;
896*0Sstevel@tonic-gate 			cft = ocft;
897*0Sstevel@tonic-gate 			cft->prev = NULL;
898*0Sstevel@tonic-gate 		} else {
899*0Sstevel@tonic-gate 			cft->next = ocft;
900*0Sstevel@tonic-gate 			cft->next->prev = cft;
901*0Sstevel@tonic-gate 			cft = cft->next;
902*0Sstevel@tonic-gate 		}
903*0Sstevel@tonic-gate 
904*0Sstevel@tonic-gate 		cft->next = NULL;
905*0Sstevel@tonic-gate 
906*0Sstevel@tonic-gate 		bzero((caddr_t)&cistpl_cftable_entry,
907*0Sstevel@tonic-gate 			sizeof (struct cistpl_cftable_entry_t));
908*0Sstevel@tonic-gate 
909*0Sstevel@tonic-gate 		/*
910*0Sstevel@tonic-gate 		 * We shouldn't ever fail parsing this tuple.  If we do,
911*0Sstevel@tonic-gate 		 * there's probably an internal error in the CIS parser.
912*0Sstevel@tonic-gate 		 */
913*0Sstevel@tonic-gate 		if ((ret = csx_Parse_CISTPL_CFTABLE_ENTRY(
914*0Sstevel@tonic-gate 			softp->client_handle, &tuple,
915*0Sstevel@tonic-gate 			&cistpl_cftable_entry)) != CS_SUCCESS) {
916*0Sstevel@tonic-gate 			return (ret);
917*0Sstevel@tonic-gate 
918*0Sstevel@tonic-gate 		} else {
919*0Sstevel@tonic-gate 			int default_cftable;
920*0Sstevel@tonic-gate 
921*0Sstevel@tonic-gate 			/*
922*0Sstevel@tonic-gate 			 * See if this tuple has default values that we
923*0Sstevel@tonic-gate 			 * should save. If so, copy the default values
924*0Sstevel@tonic-gate 			 * that we've seen so far into the current cftable
925*0Sstevel@tonic-gate 			 * structure.
926*0Sstevel@tonic-gate 			 */
927*0Sstevel@tonic-gate 			if (cistpl_cftable_entry.flags &
928*0Sstevel@tonic-gate 				CISTPL_CFTABLE_TPCE_DEFAULT) {
929*0Sstevel@tonic-gate 				default_cftable = 1;
930*0Sstevel@tonic-gate 			} else {
931*0Sstevel@tonic-gate 				default_cftable = 0;
932*0Sstevel@tonic-gate 			}
933*0Sstevel@tonic-gate 
934*0Sstevel@tonic-gate 			bcopy((caddr_t)&dcft->p, (caddr_t)&cft->p,
935*0Sstevel@tonic-gate 				sizeof (pcata_cftable_params_t));
936*0Sstevel@tonic-gate 
937*0Sstevel@tonic-gate 			cft->p.config_index = cistpl_cftable_entry.index;
938*0Sstevel@tonic-gate 
939*0Sstevel@tonic-gate 
940*0Sstevel@tonic-gate 			if (cistpl_cftable_entry.flags &
941*0Sstevel@tonic-gate 				CISTPL_CFTABLE_TPCE_IF) {
942*0Sstevel@tonic-gate 				cft->p.pin = cistpl_cftable_entry.pin;
943*0Sstevel@tonic-gate 			if (default_cftable)
944*0Sstevel@tonic-gate 				dcft->p.pin = cistpl_cftable_entry.pin;
945*0Sstevel@tonic-gate 			}
946*0Sstevel@tonic-gate 
947*0Sstevel@tonic-gate 
948*0Sstevel@tonic-gate 			if (cistpl_cftable_entry.flags &
949*0Sstevel@tonic-gate 				CISTPL_CFTABLE_TPCE_FS_PWR) {
950*0Sstevel@tonic-gate 				struct cistpl_cftable_entry_pd_t *pd;
951*0Sstevel@tonic-gate 
952*0Sstevel@tonic-gate 				pd = &cistpl_cftable_entry.pd;
953*0Sstevel@tonic-gate 
954*0Sstevel@tonic-gate 				if (pd->flags &
955*0Sstevel@tonic-gate 					CISTPL_CFTABLE_TPCE_FS_PWR_VCC) {
956*0Sstevel@tonic-gate 					if (pd->pd_vcc.nomV_flags &
957*0Sstevel@tonic-gate 						CISTPL_CFTABLE_PD_EXISTS) {
958*0Sstevel@tonic-gate 						cft->p.ata_vcc =
959*0Sstevel@tonic-gate 							pd->pd_vcc.nomV;
960*0Sstevel@tonic-gate 						if (default_cftable)
961*0Sstevel@tonic-gate 							dcft->p.ata_vcc =
962*0Sstevel@tonic-gate 								pd->pd_vcc.nomV;
963*0Sstevel@tonic-gate 					} /* CISTPL_CFTABLE_PD_EXISTS */
964*0Sstevel@tonic-gate 				} /* CISTPL_CFTABLE_TPCE_FS_PWR_VCC */
965*0Sstevel@tonic-gate 
966*0Sstevel@tonic-gate 				if (pd->flags &
967*0Sstevel@tonic-gate 					CISTPL_CFTABLE_TPCE_FS_PWR_VPP1) {
968*0Sstevel@tonic-gate 					if (pd->pd_vpp1.nomV_flags &
969*0Sstevel@tonic-gate 						CISTPL_CFTABLE_PD_EXISTS) {
970*0Sstevel@tonic-gate 						cft->p.ata_vpp1 =
971*0Sstevel@tonic-gate 							pd->pd_vpp1.nomV;
972*0Sstevel@tonic-gate 						if (default_cftable)
973*0Sstevel@tonic-gate 							dcft->p.ata_vpp1 =
974*0Sstevel@tonic-gate 							    pd->pd_vpp1.nomV;
975*0Sstevel@tonic-gate 					} /* CISTPL_CFTABLE_PD_EXISTS */
976*0Sstevel@tonic-gate 				} /* CISTPL_CFTABLE_TPCE_FS_PWR_VPP1 */
977*0Sstevel@tonic-gate 
978*0Sstevel@tonic-gate 				if (pd->flags &
979*0Sstevel@tonic-gate 					CISTPL_CFTABLE_TPCE_FS_PWR_VPP2) {
980*0Sstevel@tonic-gate 					if (pd->pd_vpp2.nomV_flags &
981*0Sstevel@tonic-gate 						CISTPL_CFTABLE_PD_EXISTS) {
982*0Sstevel@tonic-gate 						cft->p.ata_vpp2 =
983*0Sstevel@tonic-gate 							pd->pd_vpp2.nomV;
984*0Sstevel@tonic-gate 						if (default_cftable)
985*0Sstevel@tonic-gate 							dcft->p.ata_vpp2 =
986*0Sstevel@tonic-gate 							    pd->pd_vpp2.nomV;
987*0Sstevel@tonic-gate 					} /* CISTPL_CFTABLE_PD_EXISTS */
988*0Sstevel@tonic-gate 				} /* CISTPL_CFTABLE_TPCE_FS_PWR_VPP2 */
989*0Sstevel@tonic-gate 
990*0Sstevel@tonic-gate 			} /* CISTPL_CFTABLE_TPCE_FS_PWR */
991*0Sstevel@tonic-gate 
992*0Sstevel@tonic-gate 			if (cistpl_cftable_entry.flags &
993*0Sstevel@tonic-gate 				CISTPL_CFTABLE_TPCE_FS_IO) {
994*0Sstevel@tonic-gate 				softp->flags |= PCATA_VALID_IO_INFO;
995*0Sstevel@tonic-gate 				cft->p.addr_lines = io->addr_lines;
996*0Sstevel@tonic-gate 				if (default_cftable)
997*0Sstevel@tonic-gate 					dcft->p.addr_lines = io->addr_lines;
998*0Sstevel@tonic-gate 
999*0Sstevel@tonic-gate 				if (io->ranges) {
1000*0Sstevel@tonic-gate 
1001*0Sstevel@tonic-gate 					cft->p.ranges = io->ranges;
1002*0Sstevel@tonic-gate #ifdef ATA_DEBUG
1003*0Sstevel@tonic-gate 					if (pcata_debug & DPCM)
1004*0Sstevel@tonic-gate 						cmn_err(CE_CONT,
1005*0Sstevel@tonic-gate 						"CS says ranges present: %d\n",
1006*0Sstevel@tonic-gate 						io->ranges);
1007*0Sstevel@tonic-gate #endif
1008*0Sstevel@tonic-gate 
1009*0Sstevel@tonic-gate 					cft->p.ata_base[0] =
1010*0Sstevel@tonic-gate 						(uint32_t)io->range[0].addr;
1011*0Sstevel@tonic-gate 					cft->p.ata_length[0] =
1012*0Sstevel@tonic-gate 						(uint32_t)io->range[0].length;
1013*0Sstevel@tonic-gate 
1014*0Sstevel@tonic-gate 					if (io->ranges == 2) {
1015*0Sstevel@tonic-gate 						cft->p.ata_base[1] =
1016*0Sstevel@tonic-gate 						    (uint32_t)io->range[1].addr;
1017*0Sstevel@tonic-gate 						cft->p.ata_length[1] =
1018*0Sstevel@tonic-gate 						    (uint32_t)io->range[1].
1019*0Sstevel@tonic-gate 						    length;
1020*0Sstevel@tonic-gate 					}
1021*0Sstevel@tonic-gate 					if (default_cftable) {
1022*0Sstevel@tonic-gate 						dcft->p.ata_base[0] =
1023*0Sstevel@tonic-gate 						(uint32_t)io->range[0].addr;
1024*0Sstevel@tonic-gate 						dcft->p.ata_length[0] =
1025*0Sstevel@tonic-gate 						(uint32_t)io->range[0].length;
1026*0Sstevel@tonic-gate 						if (io->ranges == 2) {
1027*0Sstevel@tonic-gate 							dcft->p.ata_base[1] =
1028*0Sstevel@tonic-gate 							(uint32_t)
1029*0Sstevel@tonic-gate 							    io->range[1].addr;
1030*0Sstevel@tonic-gate 							dcft->p.ata_length[1] =
1031*0Sstevel@tonic-gate 							(uint32_t)
1032*0Sstevel@tonic-gate 							    io->range[1].length;
1033*0Sstevel@tonic-gate 						}
1034*0Sstevel@tonic-gate 					}
1035*0Sstevel@tonic-gate #ifdef ATA_DEBUG
1036*0Sstevel@tonic-gate 					if (pcata_debug & DPCM) {
1037*0Sstevel@tonic-gate 						cmn_err(CE_CONT,
1038*0Sstevel@tonic-gate 						"CS 1st io range: 0x%x+%d\n",
1039*0Sstevel@tonic-gate 						(uint32_t)io->range[0].addr,
1040*0Sstevel@tonic-gate 						(uint32_t)io->range[0].length);
1041*0Sstevel@tonic-gate 						cmn_err(CE_CONT,
1042*0Sstevel@tonic-gate 						"CS 2nd io range: 0x%x+%d\n",
1043*0Sstevel@tonic-gate 						(uint32_t)io->range[1].addr,
1044*0Sstevel@tonic-gate 						(uint32_t)io->range[1].length);
1045*0Sstevel@tonic-gate 					}
1046*0Sstevel@tonic-gate #endif
1047*0Sstevel@tonic-gate 				} else {
1048*0Sstevel@tonic-gate 				/*
1049*0Sstevel@tonic-gate 				 * If there's no IO ranges for this
1050*0Sstevel@tonic-gate 				 * configuration, then we need to calculate
1051*0Sstevel@tonic-gate 				 * the length of the IO space by using the
1052*0Sstevel@tonic-gate 				 * number of IO address lines value.
1053*0Sstevel@tonic-gate 				 * Or we can set the base to zero and the
1054*0Sstevel@tonic-gate 				 * length to 0xf.
1055*0Sstevel@tonic-gate 				 */
1056*0Sstevel@tonic-gate 
1057*0Sstevel@tonic-gate 					if (!(cistpl_cftable_entry.io.flags &
1058*0Sstevel@tonic-gate 					    CISTPL_CFTABLE_TPCE_FS_IO_RANGE)) {
1059*0Sstevel@tonic-gate 						cft->p.ata_length[0] =
1060*0Sstevel@tonic-gate 						    (1 << cft->p.addr_lines);
1061*0Sstevel@tonic-gate 					} /* CISTPL_CFTABLE_TPCE_FS_IO_RANGE */
1062*0Sstevel@tonic-gate 				} /* io->ranges */
1063*0Sstevel@tonic-gate 			} /* CISTPL_CFTABLE_TPCE_FS_IO */
1064*0Sstevel@tonic-gate 
1065*0Sstevel@tonic-gate 		} /* csx_Parse_CISTPL_CFTABLE_ENTRY */
1066*0Sstevel@tonic-gate 	} while ((cistpl_cftable_entry.index != last_config_index) &&
1067*0Sstevel@tonic-gate 		((ret = csx_GetNextTuple(softp->client_handle,
1068*0Sstevel@tonic-gate 	    &tuple)) == CS_SUCCESS));
1069*0Sstevel@tonic-gate 
1070*0Sstevel@tonic-gate #ifdef	ATA_DEBUG
1071*0Sstevel@tonic-gate if (pcata_debug) {
1072*0Sstevel@tonic-gate 	pcata_cftable_t *cft;
1073*0Sstevel@tonic-gate 
1074*0Sstevel@tonic-gate 	cmn_err(CE_CONT, "====== socket %d unsorted cftable ======\n",
1075*0Sstevel@tonic-gate 		(int)softp->sn);
1076*0Sstevel@tonic-gate 	for (cft = *cftable; cft; cft = cft->next) {
1077*0Sstevel@tonic-gate 		cmn_err(CE_CONT,
1078*0Sstevel@tonic-gate 			"\n====== cftable entry ======\n"
1079*0Sstevel@tonic-gate 			"desireability: 0x%x\n"
1080*0Sstevel@tonic-gate 			" config_index: 0x%x\n"
1081*0Sstevel@tonic-gate 			"   addr_lines: 0x%x\n"
1082*0Sstevel@tonic-gate 			"    length[0]: 0x%x\n"
1083*0Sstevel@tonic-gate 			"    length[1]: 0x%x\n"
1084*0Sstevel@tonic-gate 			"          pin: 0x%x\n",
1085*0Sstevel@tonic-gate 			(int)cft->desireability, (int)cft->p.config_index,
1086*0Sstevel@tonic-gate 			(int)cft->p.addr_lines, cft->p.ata_length[0],
1087*0Sstevel@tonic-gate 			cft->p.ata_length[1], (int)cft->p.pin);
1088*0Sstevel@tonic-gate 
1089*0Sstevel@tonic-gate 		cmn_err(CE_CONT,
1090*0Sstevel@tonic-gate 			"\n      ata_vcc: %d\n"
1091*0Sstevel@tonic-gate 			"     ata_vpp1: %d\n"
1092*0Sstevel@tonic-gate 			"     ata_vpp2: %d\n"
1093*0Sstevel@tonic-gate 			"  ata_base[0]: 0x%p\n"
1094*0Sstevel@tonic-gate 			"  ata_base[1]: 0x%p\n"
1095*0Sstevel@tonic-gate 			"====\n",
1096*0Sstevel@tonic-gate 			(int)cft->p.ata_vcc, (int)cft->p.ata_vpp1,
1097*0Sstevel@tonic-gate 			(int)cft->p.ata_vpp2,
1098*0Sstevel@tonic-gate 			(void *)(uintptr_t)cft->p.ata_base[0],
1099*0Sstevel@tonic-gate 			(void *)(uintptr_t)cft->p.ata_base[1]);
1100*0Sstevel@tonic-gate 	}
1101*0Sstevel@tonic-gate 
1102*0Sstevel@tonic-gate }
1103*0Sstevel@tonic-gate #endif
1104*0Sstevel@tonic-gate 
1105*0Sstevel@tonic-gate 	/*
1106*0Sstevel@tonic-gate 	 * If GetNextTuple gave us any error code other than
1107*0Sstevel@tonic-gate 	 * CS_NO_MORE_ITEMS, it means that there is probably
1108*0Sstevel@tonic-gate 	 * an internal error in the CIS parser.
1109*0Sstevel@tonic-gate 	 */
1110*0Sstevel@tonic-gate 	if ((ret != CS_SUCCESS) && (ret != CS_NO_MORE_ITEMS)) {
1111*0Sstevel@tonic-gate 
1112*0Sstevel@tonic-gate 		return (ret);	/* this is a real error */
1113*0Sstevel@tonic-gate 
1114*0Sstevel@tonic-gate 	}
1115*0Sstevel@tonic-gate 	/*
1116*0Sstevel@tonic-gate 	 * CISTPL_FUNCID and CISTPL_FUNCE processing
1117*0Sstevel@tonic-gate 	 */
1118*0Sstevel@tonic-gate 	tuple.Attributes = 0;
1119*0Sstevel@tonic-gate 	tuple.DesiredTuple = CISTPL_FUNCID;
1120*0Sstevel@tonic-gate 	if ((ret = csx_GetFirstTuple(softp->client_handle,
1121*0Sstevel@tonic-gate 	    &tuple)) != CS_SUCCESS) {
1122*0Sstevel@tonic-gate 		/*
1123*0Sstevel@tonic-gate 		 * It's OK not to find the tuple if it's not in the CIS, but
1124*0Sstevel@tonic-gate 		 * this test will catch other errors.
1125*0Sstevel@tonic-gate 		 */
1126*0Sstevel@tonic-gate 		if (ret != CS_NO_MORE_ITEMS) {
1127*0Sstevel@tonic-gate 			return (ret);
1128*0Sstevel@tonic-gate 		}
1129*0Sstevel@tonic-gate 	} else {
1130*0Sstevel@tonic-gate 
1131*0Sstevel@tonic-gate 		do {
1132*0Sstevel@tonic-gate 			cistpl_funcid_t cistpl_funcid;
1133*0Sstevel@tonic-gate 			cistpl_funce_t cistpl_funce;
1134*0Sstevel@tonic-gate 
1135*0Sstevel@tonic-gate 			bzero((caddr_t)&cistpl_funcid,
1136*0Sstevel@tonic-gate 				sizeof (struct cistpl_funcid_t));
1137*0Sstevel@tonic-gate 
1138*0Sstevel@tonic-gate 			if ((ret = csx_Parse_CISTPL_FUNCID(
1139*0Sstevel@tonic-gate 				softp->client_handle,
1140*0Sstevel@tonic-gate 				&tuple, &cistpl_funcid)) != CS_SUCCESS) {
1141*0Sstevel@tonic-gate 				return (ret);
1142*0Sstevel@tonic-gate 			}
1143*0Sstevel@tonic-gate 
1144*0Sstevel@tonic-gate 
1145*0Sstevel@tonic-gate 			tuple.DesiredTuple = CISTPL_FUNCE;
1146*0Sstevel@tonic-gate 			while ((ret = csx_GetNextTuple(softp->client_handle,
1147*0Sstevel@tonic-gate 				&tuple)) == CS_SUCCESS) {
1148*0Sstevel@tonic-gate 				bzero((caddr_t)&cistpl_funce,
1149*0Sstevel@tonic-gate 					sizeof (cistpl_funce_t));
1150*0Sstevel@tonic-gate 
1151*0Sstevel@tonic-gate 				/*
1152*0Sstevel@tonic-gate 				 * Function extention parsing needs to be added
1153*0Sstevel@tonic-gate 				 * for pcata in cardservices.  Function
1154*0Sstevel@tonic-gate 				 * extention is required by spec but not used
1155*0Sstevel@tonic-gate 				 * in the code.
1156*0Sstevel@tonic-gate 				 */
1157*0Sstevel@tonic-gate 
1158*0Sstevel@tonic-gate 				if ((ret = csx_Parse_CISTPL_FUNCE(
1159*0Sstevel@tonic-gate 					softp->client_handle,
1160*0Sstevel@tonic-gate 					&tuple, &cistpl_funce,
1161*0Sstevel@tonic-gate 					cistpl_funcid.function)) ==
1162*0Sstevel@tonic-gate 						CS_SUCCESS) {
1163*0Sstevel@tonic-gate 					cmn_err(CE_WARN, "have funce!!!!!\n");
1164*0Sstevel@tonic-gate 
1165*0Sstevel@tonic-gate 					}
1166*0Sstevel@tonic-gate 			}
1167*0Sstevel@tonic-gate 			tuple.DesiredTuple = CISTPL_FUNCID;
1168*0Sstevel@tonic-gate 		} while ((ret = csx_GetNextTuple(softp->client_handle,
1169*0Sstevel@tonic-gate 			&tuple)) == CS_SUCCESS);
1170*0Sstevel@tonic-gate 	} /* GetFirstTuple */
1171*0Sstevel@tonic-gate 
1172*0Sstevel@tonic-gate 	/*
1173*0Sstevel@tonic-gate 	 * CISTPL_MANFID processing. The information from this tuple is
1174*0Sstevel@tonic-gate 	 *	used to augment the information we get from the
1175*0Sstevel@tonic-gate 	 *	CISTPL_FUNCID and CISTPL_FUNCE tuples.
1176*0Sstevel@tonic-gate 	 */
1177*0Sstevel@tonic-gate 	tuple.Attributes = 0;
1178*0Sstevel@tonic-gate 	tuple.DesiredTuple = CISTPL_MANFID;
1179*0Sstevel@tonic-gate 	if ((ret = csx_GetFirstTuple(softp->client_handle,
1180*0Sstevel@tonic-gate 	    &tuple)) != CS_SUCCESS) {
1181*0Sstevel@tonic-gate 		/*
1182*0Sstevel@tonic-gate 		 * It's OK not to find the tuple if it's not in the CIS, but
1183*0Sstevel@tonic-gate 		 *	this test will catch other errors.
1184*0Sstevel@tonic-gate 		 */
1185*0Sstevel@tonic-gate 		if (ret != CS_NO_MORE_ITEMS) {
1186*0Sstevel@tonic-gate 			cmn_err(CE_CONT, " %x \n", ret);
1187*0Sstevel@tonic-gate 			return (ret);
1188*0Sstevel@tonic-gate 		}
1189*0Sstevel@tonic-gate 	} else {
1190*0Sstevel@tonic-gate 		if ((ret = csx_Parse_CISTPL_MANFID(softp->client_handle,
1191*0Sstevel@tonic-gate 			&tuple, &cistpl_manfid)) != CS_SUCCESS) {
1192*0Sstevel@tonic-gate 			return (ret);
1193*0Sstevel@tonic-gate 		} else {
1194*0Sstevel@tonic-gate 			cis_vars->manufacturer_id = cistpl_manfid.manf;
1195*0Sstevel@tonic-gate 			cis_vars->card_id = cistpl_manfid.card;
1196*0Sstevel@tonic-gate 		} /* csx_Parse_CISTPL_MANFID */
1197*0Sstevel@tonic-gate 
1198*0Sstevel@tonic-gate 
1199*0Sstevel@tonic-gate 
1200*0Sstevel@tonic-gate 	} /* GetFirstTuple */
1201*0Sstevel@tonic-gate 
1202*0Sstevel@tonic-gate 	return (CS_SUCCESS);
1203*0Sstevel@tonic-gate }
1204*0Sstevel@tonic-gate 
1205*0Sstevel@tonic-gate 
1206*0Sstevel@tonic-gate void
pcata_destroy_cftable_list(pcata_cftable_t ** cftable)1207*0Sstevel@tonic-gate pcata_destroy_cftable_list(pcata_cftable_t **cftable)
1208*0Sstevel@tonic-gate {
1209*0Sstevel@tonic-gate 	pcata_cftable_t *cft, *ocft = NULL;
1210*0Sstevel@tonic-gate 
1211*0Sstevel@tonic-gate 	cft = *cftable;
1212*0Sstevel@tonic-gate 
1213*0Sstevel@tonic-gate 	while (cft) {
1214*0Sstevel@tonic-gate 	    ocft = cft;
1215*0Sstevel@tonic-gate 	    cft = cft->next;
1216*0Sstevel@tonic-gate 	}
1217*0Sstevel@tonic-gate 
1218*0Sstevel@tonic-gate 	while (ocft) {
1219*0Sstevel@tonic-gate 	    cft = ocft->prev;
1220*0Sstevel@tonic-gate 	    kmem_free(ocft, sizeof (pcata_cftable_t));
1221*0Sstevel@tonic-gate 	    ocft = cft;
1222*0Sstevel@tonic-gate 	}
1223*0Sstevel@tonic-gate 
1224*0Sstevel@tonic-gate 	*cftable = NULL;
1225*0Sstevel@tonic-gate }
1226*0Sstevel@tonic-gate 
1227*0Sstevel@tonic-gate 
1228*0Sstevel@tonic-gate 
1229*0Sstevel@tonic-gate char	*
pcata_CS_etext(int ret)1230*0Sstevel@tonic-gate pcata_CS_etext(int ret)
1231*0Sstevel@tonic-gate {
1232*0Sstevel@tonic-gate 	static error2text_t cft;
1233*0Sstevel@tonic-gate 
1234*0Sstevel@tonic-gate 	cft.item = ret;
1235*0Sstevel@tonic-gate 	(void) csx_Error2Text(&cft);
1236*0Sstevel@tonic-gate 
1237*0Sstevel@tonic-gate 	return (cft.text);
1238*0Sstevel@tonic-gate }
1239*0Sstevel@tonic-gate 
1240*0Sstevel@tonic-gate 
1241*0Sstevel@tonic-gate /*
1242*0Sstevel@tonic-gate  * pcata_getinfo() - this routine translates the dip info dev_t and
1243*0Sstevel@tonic-gate  * 	vice versa.
1244*0Sstevel@tonic-gate  *
1245*0Sstevel@tonic-gate  *	Returns:	DDI_SUCCESS, if successful.
1246*0Sstevel@tonic-gate  *			DDI_FAILURE, if unsuccessful.
1247*0Sstevel@tonic-gate  */
1248*0Sstevel@tonic-gate /* ARGSUSED */
1249*0Sstevel@tonic-gate int
pcata_getinfo(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** result)1250*0Sstevel@tonic-gate pcata_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
1251*0Sstevel@tonic-gate {
1252*0Sstevel@tonic-gate 	ata_soft_t *softp;
1253*0Sstevel@tonic-gate 	int		ret;
1254*0Sstevel@tonic-gate 	cs_ddi_info_t cs_ddi_info;
1255*0Sstevel@tonic-gate 
1256*0Sstevel@tonic-gate 	switch (cmd) {
1257*0Sstevel@tonic-gate 	case DDI_INFO_DEVT2DEVINFO:
1258*0Sstevel@tonic-gate 	case DDI_INFO_DEVT2INSTANCE:
1259*0Sstevel@tonic-gate 
1260*0Sstevel@tonic-gate 		cs_ddi_info.Socket = PCATA_SOCKET((dev_t)arg);
1261*0Sstevel@tonic-gate 		cs_ddi_info.driver_name = pcata_name;
1262*0Sstevel@tonic-gate 		ret = csx_CS_DDI_Info(&cs_ddi_info);
1263*0Sstevel@tonic-gate 		if (ret != CS_SUCCESS) {
1264*0Sstevel@tonic-gate #ifdef ATA_DEBUG
1265*0Sstevel@tonic-gate 			cmn_err(CE_CONT, "_getinfo: "
1266*0Sstevel@tonic-gate 				"socket %d CS_DD_Info failed %s (0x%x)\n",
1267*0Sstevel@tonic-gate 				cs_ddi_info.Socket,
1268*0Sstevel@tonic-gate 				pcata_CS_etext(ret),
1269*0Sstevel@tonic-gate 				ret);
1270*0Sstevel@tonic-gate #endif
1271*0Sstevel@tonic-gate 			return (DDI_FAILURE);
1272*0Sstevel@tonic-gate 		}
1273*0Sstevel@tonic-gate 
1274*0Sstevel@tonic-gate 		switch (cmd) {
1275*0Sstevel@tonic-gate 		case DDI_INFO_DEVT2DEVINFO:
1276*0Sstevel@tonic-gate 			softp = ddi_get_soft_state(pcata_soft,
1277*0Sstevel@tonic-gate 				cs_ddi_info.instance);
1278*0Sstevel@tonic-gate 			*result = NULL;
1279*0Sstevel@tonic-gate 			if (softp) {
1280*0Sstevel@tonic-gate 				*result = softp->dip;
1281*0Sstevel@tonic-gate 			}
1282*0Sstevel@tonic-gate 			break;
1283*0Sstevel@tonic-gate 		case DDI_INFO_DEVT2INSTANCE:
1284*0Sstevel@tonic-gate 			*result = (void *)(uintptr_t)cs_ddi_info.instance;
1285*0Sstevel@tonic-gate 			break;
1286*0Sstevel@tonic-gate 		} /* switch */
1287*0Sstevel@tonic-gate 		break;
1288*0Sstevel@tonic-gate 	default:
1289*0Sstevel@tonic-gate 		return (DDI_FAILURE);
1290*0Sstevel@tonic-gate 	}
1291*0Sstevel@tonic-gate 	return (DDI_SUCCESS);
1292*0Sstevel@tonic-gate }
1293*0Sstevel@tonic-gate 
1294*0Sstevel@tonic-gate static int
pcata_initchild(ata_soft_t * softp,int targ)1295*0Sstevel@tonic-gate pcata_initchild(ata_soft_t *softp, int targ)
1296*0Sstevel@tonic-gate {
1297*0Sstevel@tonic-gate 	ata_unit_t	*unitp;
1298*0Sstevel@tonic-gate 
1299*0Sstevel@tonic-gate 	ASSERT(mutex_owned(&softp->ata_mutex));
1300*0Sstevel@tonic-gate 
1301*0Sstevel@tonic-gate #ifdef ATA_DEBUG
1302*0Sstevel@tonic-gate 	if (pcata_debug & DENT) {
1303*0Sstevel@tonic-gate 		cmn_err(CE_CONT, "_initchild(%p, %d)\n",
1304*0Sstevel@tonic-gate 			(void *)softp, targ);
1305*0Sstevel@tonic-gate 	}
1306*0Sstevel@tonic-gate #endif
1307*0Sstevel@tonic-gate 
1308*0Sstevel@tonic-gate 	if (softp->ab_rpbp[targ] == NULL)
1309*0Sstevel@tonic-gate 		return (DDI_NOT_WELL_FORMED);
1310*0Sstevel@tonic-gate 
1311*0Sstevel@tonic-gate 	unitp = (ata_unit_t *)kmem_zalloc(sizeof (*unitp), KM_NOSLEEP);
1312*0Sstevel@tonic-gate 	if (!unitp) {
1313*0Sstevel@tonic-gate 		return (DDI_NOT_WELL_FORMED);
1314*0Sstevel@tonic-gate 	}
1315*0Sstevel@tonic-gate 
1316*0Sstevel@tonic-gate 	unitp->a_blkp		= softp;
1317*0Sstevel@tonic-gate 	unitp->a_forw		= softp->ab_link;
1318*0Sstevel@tonic-gate 	softp->ab_link		= unitp;
1319*0Sstevel@tonic-gate 
1320*0Sstevel@tonic-gate 	unitp->au_targ		= (char)targ;
1321*0Sstevel@tonic-gate 	unitp->au_drive_bits	= (targ == 0 ? ATDH_DRIVE0 : ATDH_DRIVE1);
1322*0Sstevel@tonic-gate 	unitp->au_rpbuf		= softp->ab_rpbp[targ];
1323*0Sstevel@tonic-gate 	unitp->au_acyl		= 2;
1324*0Sstevel@tonic-gate 	unitp->au_cyl		= unitp->au_rpbuf->atarp_fixcyls +
1325*0Sstevel@tonic-gate 	    unitp->au_rpbuf->atarp_remcyls -
1326*0Sstevel@tonic-gate 	    unitp->au_acyl;
1327*0Sstevel@tonic-gate 	unitp->au_hd		= unitp->au_rpbuf->atarp_heads;
1328*0Sstevel@tonic-gate 	unitp->au_sec		= unitp->au_rpbuf->atarp_sectors;
1329*0Sstevel@tonic-gate 	unitp->au_ctl_bits	= AT_DEVCTL_D3;
1330*0Sstevel@tonic-gate 	unitp->au_block_factor	= softp->ab_block_factor[targ];
1331*0Sstevel@tonic-gate 	unitp->au_rd_cmd	= softp->ab_rd_cmd[targ];
1332*0Sstevel@tonic-gate 	unitp->au_wr_cmd	= softp->ab_wr_cmd[targ];
1333*0Sstevel@tonic-gate 
1334*0Sstevel@tonic-gate 	unitp->au_bytes_per_block = unitp->au_block_factor << SCTRSHFT;
1335*0Sstevel@tonic-gate 
1336*0Sstevel@tonic-gate #ifdef	ATA_DEBUG
1337*0Sstevel@tonic-gate 	if (pcata_debug & DINIT)
1338*0Sstevel@tonic-gate 		cmn_err(CE_CONT, "_initchild: "
1339*0Sstevel@tonic-gate 			"targ = %d cyl = %d acyl = %d head = %d sec = %d\n",
1340*0Sstevel@tonic-gate 			targ,
1341*0Sstevel@tonic-gate 			unitp->au_cyl,
1342*0Sstevel@tonic-gate 			unitp->au_acyl,
1343*0Sstevel@tonic-gate 			unitp->au_hd,
1344*0Sstevel@tonic-gate 			unitp->au_sec);
1345*0Sstevel@tonic-gate #endif
1346*0Sstevel@tonic-gate 
1347*0Sstevel@tonic-gate 	return (DDI_SUCCESS);
1348*0Sstevel@tonic-gate }
1349*0Sstevel@tonic-gate 
1350*0Sstevel@tonic-gate static int
pcata_drive_setup(ata_soft_t * softp)1351*0Sstevel@tonic-gate pcata_drive_setup(ata_soft_t *softp)
1352*0Sstevel@tonic-gate {
1353*0Sstevel@tonic-gate 	major_t		devmajor;
1354*0Sstevel@tonic-gate 	int		ret;
1355*0Sstevel@tonic-gate 
1356*0Sstevel@tonic-gate 	devmajor = ddi_name_to_major(pcata_name);
1357*0Sstevel@tonic-gate 
1358*0Sstevel@tonic-gate #ifdef ATA_DEBUG
1359*0Sstevel@tonic-gate 	if (pcata_debug & DPCM) {
1360*0Sstevel@tonic-gate 		cmn_err(CE_CONT, "_drive_setup(%p)\n", (void *)softp);
1361*0Sstevel@tonic-gate 	}
1362*0Sstevel@tonic-gate #endif
1363*0Sstevel@tonic-gate 
1364*0Sstevel@tonic-gate 	if (!(CARD_PRESENT_VALID(softp))) {
1365*0Sstevel@tonic-gate 		goto err;
1366*0Sstevel@tonic-gate 	}
1367*0Sstevel@tonic-gate 
1368*0Sstevel@tonic-gate 	/* setup card */
1369*0Sstevel@tonic-gate 	softp->ab_block_factor[0]	= 1;
1370*0Sstevel@tonic-gate 	softp->ab_block_factor[1]	= 1;
1371*0Sstevel@tonic-gate 	softp->ab_max_transfer		= 0x100;
1372*0Sstevel@tonic-gate 	softp->ab_status_flag		= 0;
1373*0Sstevel@tonic-gate 
1374*0Sstevel@tonic-gate 	/*
1375*0Sstevel@tonic-gate 	 * port addresses
1376*0Sstevel@tonic-gate 	 */
1377*0Sstevel@tonic-gate 	softp->ab_data			= AT_DATA;
1378*0Sstevel@tonic-gate 	softp->ab_error			= AT_ERROR;
1379*0Sstevel@tonic-gate 	softp->ab_feature		= AT_FEATURE;
1380*0Sstevel@tonic-gate 	softp->ab_count			= AT_COUNT;
1381*0Sstevel@tonic-gate 	softp->ab_sect			= AT_SECT;
1382*0Sstevel@tonic-gate 	softp->ab_lcyl			= AT_LCYL;
1383*0Sstevel@tonic-gate 	softp->ab_hcyl			= AT_HCYL;
1384*0Sstevel@tonic-gate 	softp->ab_drvhd			= AT_DRVHD;
1385*0Sstevel@tonic-gate 	softp->ab_status		= AT_STATUS;
1386*0Sstevel@tonic-gate 	softp->ab_cmd			= AT_CMD;
1387*0Sstevel@tonic-gate 
1388*0Sstevel@tonic-gate 	softp->ab_altstatus		= AT_ALTSTATUS;
1389*0Sstevel@tonic-gate 	softp->ab_devctl		= AT_DEVCTL;
1390*0Sstevel@tonic-gate 	softp->ab_drvaddr		= AT_DRVADDR;
1391*0Sstevel@tonic-gate 
1392*0Sstevel@tonic-gate 	/*
1393*0Sstevel@tonic-gate 	 * Future work second arg should not be hard coded (# of drives per
1394*0Sstevel@tonic-gate 	 * socket).
1395*0Sstevel@tonic-gate 	 * Right now in PCMCIA we have one disk per target,
1396*0Sstevel@tonic-gate 	 * if and when we have disks that have multiple targets
1397*0Sstevel@tonic-gate 	 * in the same socket (unlikely) then we will have multiple
1398*0Sstevel@tonic-gate 	 * disks per socket.
1399*0Sstevel@tonic-gate 	 */
1400*0Sstevel@tonic-gate 
1401*0Sstevel@tonic-gate 	if (pcata_getedt(softp, 1) == DDI_FAILURE) {
1402*0Sstevel@tonic-gate 		goto err;
1403*0Sstevel@tonic-gate 	}
1404*0Sstevel@tonic-gate 
1405*0Sstevel@tonic-gate 	softp->ab_block_factor[0] = (-1);
1406*0Sstevel@tonic-gate 	if (pcata_set_rw_multiple(softp, 0)) {
1407*0Sstevel@tonic-gate 		goto err;
1408*0Sstevel@tonic-gate 	}
1409*0Sstevel@tonic-gate 
1410*0Sstevel@tonic-gate 	mutex_enter(&softp->ata_mutex);
1411*0Sstevel@tonic-gate 	ret = pcata_initchild(softp, 0);
1412*0Sstevel@tonic-gate 	mutex_exit(&softp->ata_mutex);
1413*0Sstevel@tonic-gate 	if (ret != DDI_SUCCESS)
1414*0Sstevel@tonic-gate 		goto err;
1415*0Sstevel@tonic-gate 
1416*0Sstevel@tonic-gate 	if (pcata_spinup(softp, 0) != DDI_SUCCESS) {
1417*0Sstevel@tonic-gate 		goto err;
1418*0Sstevel@tonic-gate 	}
1419*0Sstevel@tonic-gate 
1420*0Sstevel@tonic-gate 	if (!(softp->ab_link)) {
1421*0Sstevel@tonic-gate 		goto err;
1422*0Sstevel@tonic-gate 	}
1423*0Sstevel@tonic-gate 	/*
1424*0Sstevel@tonic-gate 	 * Initialise the Partition table so that pcata_strategy can
1425*0Sstevel@tonic-gate 	 * successfully read the actual vtoc information.
1426*0Sstevel@tonic-gate 	 */
1427*0Sstevel@tonic-gate 	pcinit_pmap(softp->ab_link);
1428*0Sstevel@tonic-gate 
1429*0Sstevel@tonic-gate 	if (pcata_update_vtoc(softp, makedevice(devmajor,
1430*0Sstevel@tonic-gate 	    PCATA_SETMINOR(softp->sn, FDISK_OFFSET)))) {
1431*0Sstevel@tonic-gate 		goto err;
1432*0Sstevel@tonic-gate 	}
1433*0Sstevel@tonic-gate 
1434*0Sstevel@tonic-gate 	mutex_enter(&softp->event_hilock);
1435*0Sstevel@tonic-gate 	softp->flags |= PCATA_READY;
1436*0Sstevel@tonic-gate 	cv_broadcast(&softp->readywait_cv);
1437*0Sstevel@tonic-gate 	mutex_exit(&softp->event_hilock);
1438*0Sstevel@tonic-gate 	return (DDI_SUCCESS);
1439*0Sstevel@tonic-gate err:
1440*0Sstevel@tonic-gate 	mutex_enter(&softp->event_hilock);
1441*0Sstevel@tonic-gate 	cv_broadcast(&softp->readywait_cv);
1442*0Sstevel@tonic-gate 	mutex_exit(&softp->event_hilock);
1443*0Sstevel@tonic-gate 	return (DDI_FAILURE);
1444*0Sstevel@tonic-gate }
1445*0Sstevel@tonic-gate 
1446*0Sstevel@tonic-gate /* probably want to replace this with struct devnode_desc */
1447*0Sstevel@tonic-gate 
1448*0Sstevel@tonic-gate static struct driver_minor_data {
1449*0Sstevel@tonic-gate 	char	*name;
1450*0Sstevel@tonic-gate 	int	minor;
1451*0Sstevel@tonic-gate 	int	type;
1452*0Sstevel@tonic-gate } id_minor_data[] = {
1453*0Sstevel@tonic-gate 		{ "a",		0,	S_IFBLK},
1454*0Sstevel@tonic-gate 		{ "b",		1,	S_IFBLK},
1455*0Sstevel@tonic-gate 		{ "c",		2,	S_IFBLK},
1456*0Sstevel@tonic-gate 		{ "d",		3,	S_IFBLK},
1457*0Sstevel@tonic-gate 		{ "e",		4,	S_IFBLK},
1458*0Sstevel@tonic-gate 		{ "f",		5,	S_IFBLK},
1459*0Sstevel@tonic-gate 		{ "g",		6,	S_IFBLK},
1460*0Sstevel@tonic-gate 		{ "h",		7,	S_IFBLK},
1461*0Sstevel@tonic-gate 		{ "i",		8,	S_IFBLK},
1462*0Sstevel@tonic-gate 		{ "j",		9,	S_IFBLK},
1463*0Sstevel@tonic-gate 		{ "k",		10,	S_IFBLK},
1464*0Sstevel@tonic-gate 		{ "l",		11,	S_IFBLK},
1465*0Sstevel@tonic-gate 		{ "m",		12,	S_IFBLK},
1466*0Sstevel@tonic-gate 		{ "n",		13,	S_IFBLK},
1467*0Sstevel@tonic-gate 		{ "o",		14,	S_IFBLK},
1468*0Sstevel@tonic-gate 		{ "p",		15,	S_IFBLK},
1469*0Sstevel@tonic-gate 		{ "q",		16,	S_IFBLK},
1470*0Sstevel@tonic-gate 		{ "r",		17,	S_IFBLK},
1471*0Sstevel@tonic-gate 		{ "s",		18,	S_IFBLK},
1472*0Sstevel@tonic-gate 		{ "t",		19,	S_IFBLK},
1473*0Sstevel@tonic-gate 		{ "u",		20,	S_IFBLK},
1474*0Sstevel@tonic-gate 
1475*0Sstevel@tonic-gate 		{ "a,raw",	0,	S_IFCHR},
1476*0Sstevel@tonic-gate 		{ "b,raw",	1,	S_IFCHR},
1477*0Sstevel@tonic-gate 		{ "c,raw",	2,	S_IFCHR},
1478*0Sstevel@tonic-gate 		{ "d,raw",	3,	S_IFCHR},
1479*0Sstevel@tonic-gate 		{ "e,raw",	4,	S_IFCHR},
1480*0Sstevel@tonic-gate 		{ "f,raw",	5,	S_IFCHR},
1481*0Sstevel@tonic-gate 		{ "g,raw",	6,	S_IFCHR},
1482*0Sstevel@tonic-gate 		{ "h,raw",	7,	S_IFCHR},
1483*0Sstevel@tonic-gate 		{ "i,raw",	8,	S_IFCHR},
1484*0Sstevel@tonic-gate 		{ "j,raw",	9,	S_IFCHR},
1485*0Sstevel@tonic-gate 		{ "k,raw",	10,	S_IFCHR},
1486*0Sstevel@tonic-gate 		{ "l,raw",	11,	S_IFCHR},
1487*0Sstevel@tonic-gate 		{ "m,raw",	12,	S_IFCHR},
1488*0Sstevel@tonic-gate 		{ "n,raw",	13,	S_IFCHR},
1489*0Sstevel@tonic-gate 		{ "o,raw",	14,	S_IFCHR},
1490*0Sstevel@tonic-gate 		{ "p,raw",	15,	S_IFCHR},
1491*0Sstevel@tonic-gate 		{ "q,raw",	16,	S_IFCHR},
1492*0Sstevel@tonic-gate 		{ "r,raw",	17,	S_IFCHR},
1493*0Sstevel@tonic-gate 		{ "s,raw",	18,	S_IFCHR},
1494*0Sstevel@tonic-gate 		{ "t,raw",	19,	S_IFCHR},
1495*0Sstevel@tonic-gate 		{ "u,raw",	20,	S_IFCHR},
1496*0Sstevel@tonic-gate };
1497*0Sstevel@tonic-gate 
1498*0Sstevel@tonic-gate 
1499*0Sstevel@tonic-gate /*
1500*0Sstevel@tonic-gate  * create the device nodes
1501*0Sstevel@tonic-gate  */
1502*0Sstevel@tonic-gate static int
pcata_create_device_node(ata_soft_t * softp)1503*0Sstevel@tonic-gate pcata_create_device_node(ata_soft_t *softp)
1504*0Sstevel@tonic-gate {
1505*0Sstevel@tonic-gate 	struct driver_minor_data *dmdp;
1506*0Sstevel@tonic-gate 	devnode_desc_t		*dnd;
1507*0Sstevel@tonic-gate 	make_device_node_t	make_device_node;
1508*0Sstevel@tonic-gate 	int			ret;
1509*0Sstevel@tonic-gate 
1510*0Sstevel@tonic-gate 	make_device_node.Action = CREATE_DEVICE_NODE;
1511*0Sstevel@tonic-gate 
1512*0Sstevel@tonic-gate 
1513*0Sstevel@tonic-gate 	make_device_node.NumDevNodes =
1514*0Sstevel@tonic-gate 	    sizeof (id_minor_data)/sizeof (*id_minor_data);
1515*0Sstevel@tonic-gate 
1516*0Sstevel@tonic-gate 	make_device_node.devnode_desc =
1517*0Sstevel@tonic-gate 		kmem_zalloc(sizeof (devnode_desc_t) *
1518*0Sstevel@tonic-gate 		make_device_node.NumDevNodes, KM_SLEEP);
1519*0Sstevel@tonic-gate 
1520*0Sstevel@tonic-gate 
1521*0Sstevel@tonic-gate #ifdef ATA_DEBUG
1522*0Sstevel@tonic-gate 	if (pcata_debug & DIO) {
1523*0Sstevel@tonic-gate 		cmn_err(CE_CONT, "_create_device_nodes socket=%d\n",
1524*0Sstevel@tonic-gate 			softp->sn);
1525*0Sstevel@tonic-gate 	}
1526*0Sstevel@tonic-gate #endif
1527*0Sstevel@tonic-gate 
1528*0Sstevel@tonic-gate 	for (dnd = make_device_node.devnode_desc, dmdp = id_minor_data;
1529*0Sstevel@tonic-gate 			dmdp < (id_minor_data +
1530*0Sstevel@tonic-gate 			    sizeof (id_minor_data) / sizeof (id_minor_data[0]));
1531*0Sstevel@tonic-gate 			dmdp++, dnd++) {
1532*0Sstevel@tonic-gate 		dnd->name = dmdp->name;
1533*0Sstevel@tonic-gate 
1534*0Sstevel@tonic-gate 		/*
1535*0Sstevel@tonic-gate 		 * Later on need to incorporate the target number
1536*0Sstevel@tonic-gate 		 * Right now in PCMCIA we have one disk per target,
1537*0Sstevel@tonic-gate 		 * if and when we have disks that have multiple targets
1538*0Sstevel@tonic-gate 		 * in the same socket (unlikely) then we will have multiple
1539*0Sstevel@tonic-gate 		 * disks per socket.
1540*0Sstevel@tonic-gate 		 */
1541*0Sstevel@tonic-gate 
1542*0Sstevel@tonic-gate 		dnd->minor_num = PCATA_SETMINOR(softp->sn, dmdp->minor);
1543*0Sstevel@tonic-gate 
1544*0Sstevel@tonic-gate #ifdef ATA_DEBUG
1545*0Sstevel@tonic-gate 		if (pcata_debug & DMKDEV) {
1546*0Sstevel@tonic-gate 			cmn_err(CE_CONT,
1547*0Sstevel@tonic-gate 				"_create_device_node: "
1548*0Sstevel@tonic-gate 				"socket %d minor = %d minor_num = %d\n",
1549*0Sstevel@tonic-gate 				    softp->sn, dmdp->minor, dnd->minor_num);
1550*0Sstevel@tonic-gate 		}
1551*0Sstevel@tonic-gate #endif
1552*0Sstevel@tonic-gate 		dnd->node_type = DDI_NT_BLOCK;
1553*0Sstevel@tonic-gate 		dnd->spec_type = dmdp->type;
1554*0Sstevel@tonic-gate 	}
1555*0Sstevel@tonic-gate 
1556*0Sstevel@tonic-gate 
1557*0Sstevel@tonic-gate 	ret = csx_MakeDeviceNode(softp->client_handle, &make_device_node);
1558*0Sstevel@tonic-gate 	if (ret != CS_SUCCESS) {
1559*0Sstevel@tonic-gate 		cmn_err(CE_CONT, "_create_device_node "
1560*0Sstevel@tonic-gate 			"socket %d MakeDeviceNode failed %s (0x%x)\n",
1561*0Sstevel@tonic-gate 			    softp->sn, pcata_CS_etext(ret), ret);
1562*0Sstevel@tonic-gate 	}
1563*0Sstevel@tonic-gate 
1564*0Sstevel@tonic-gate 	/*
1565*0Sstevel@tonic-gate 	 * We don't need this structure anymore since we've
1566*0Sstevel@tonic-gate 	 * created the devices.  If we need to keep
1567*0Sstevel@tonic-gate 	 * track of the devices that we've created
1568*0Sstevel@tonic-gate 	 * for some reason, then you' want to keep
1569*0Sstevel@tonic-gate 	 * this structure and the make_device_node_t
1570*0Sstevel@tonic-gate 	 * structure around in a global data area.
1571*0Sstevel@tonic-gate 	 */
1572*0Sstevel@tonic-gate 	kmem_free(make_device_node.devnode_desc,
1573*0Sstevel@tonic-gate 		sizeof (devnode_desc_t) * make_device_node.NumDevNodes);
1574*0Sstevel@tonic-gate 
1575*0Sstevel@tonic-gate 	make_device_node.devnode_desc = NULL;
1576*0Sstevel@tonic-gate 	return (ret);
1577*0Sstevel@tonic-gate }
1578