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