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