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