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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26
27
28 /*
29 * ATA disk driver
30 *
31 * Handles the standard PCMCIA ATA interface
32 *
33 */
34 #include <sys/errno.h>
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/user.h>
38 #include <sys/buf.h>
39 #include <sys/ioctl.h>
40 #include <sys/file.h>
41 #include <sys/uio.h>
42 #include <sys/fcntl.h>
43 #include <sys/cmn_err.h>
44 #include <sys/kmem.h>
45 #include <sys/sysmacros.h>
46 #include <sys/stat.h>
47 #include <sys/scsi/scsi.h>
48
49 #include <sys/fdio.h>
50
51 #include <sys/errno.h>
52 #include <sys/open.h>
53 #include <sys/varargs.h>
54 #include <sys/fs/pc_label.h>
55
56 #include <sys/hdio.h>
57 #include <sys/dkio.h>
58 #include <sys/dktp/dadkio.h>
59
60 #include <sys/dklabel.h>
61
62 #include <sys/vtoc.h>
63
64 #include <sys/types.h>
65 #include <sys/conf.h>
66 #include <sys/dditypes.h>
67 #include <sys/ddi.h>
68 #include <sys/sunddi.h>
69 #include <sys/dktp/cm.h>
70
71 #include <sys/dktp/fdisk.h>
72
73 #include <sys/fs/pc_label.h>
74
75 #include <sys/pctypes.h>
76
77
78 /*
79 * PCMCIA and DDI related header files
80 */
81 #include <sys/pccard.h>
82
83 #include <sys/pcmcia/pcata.h>
84
85 int pcata_debug = 0;
86
87 static int pcata_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
88 static int pcata_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
89 static int pcata_att1(dev_info_t *dip, ata_soft_t *softp);
90 static int pcata_go(ata_unit_t *unitp);
91 static int pcata_wait(uint32_t port, ushort_t onbits, ushort_t offbits,
92 ata_soft_t *softp);
93 static int pcata_wait1(uint32_t port, ushort_t onbits, ushort_t offbits,
94 int interval, ata_soft_t *softp);
95 static void pcata_wait_complete(ata_soft_t *softp);
96 static uchar_t pcata_drive_type(ata_soft_t *softp, ushort_t *secbuf);
97 static int pcata_setpar(int drive, int heads, int sectors, ata_soft_t *softp);
98 static int pcata_dump(dev_t dev, caddr_t addr, daddr_t blkno, int nblk);
99 static int pcata_print(dev_t dev, char *str);
100 static int pcata_rdrw(dev_t dev, struct uio *uio, int flag);
101 static int pcata_read(dev_t dev, struct uio *uio, cred_t *cred_p);
102 static int pcata_write(dev_t dev, struct uio *uio, cred_t *cred_p);
103 #ifdef ATA_DEBUG
104 static void pcata_print_sttflag(int svalue);
105 #endif
106 static void pcata_clear_queues(ata_unit_t *unitp);
107 static void pcata_nack_packet(struct ata_cmpkt *pktp);
108 static void pcata_iosetup(ata_unit_t *unitp, struct ata_cmpkt *pktp);
109 static int pcata_send_data(ata_unit_t *unitp, int count);
110 static int pcata_get_data(ata_unit_t *unitp, int count);
111
112 struct cb_ops pcata_cb_ops = {
113 pcata_open, /* driver open routine */
114 pcata_close, /* driver close routine */
115 pcata_strategy, /* driver strategy routine */
116 pcata_print, /* driver print routine */
117 pcata_dump, /* driver dump routine */
118 pcata_read, /* driver read routine */
119 pcata_write, /* driver write routine */
120 pcata_ioctl, /* driver ioctl routine */
121 nodev, /* driver devmap routine */
122 nodev, /* driver mmap routine */
123 nodev, /* driver segmap routine */
124 nochpoll, /* driver chpoll routine */
125 pcata_prop_op, /* driver prop_op routine */
126 0, /* driver cb_str - STREAMS only */
127 D_NEW | D_MTSAFE, /* driver compatibility flag */
128 };
129
130 static struct dev_ops ata_ops = {
131 DEVO_REV, /* devo_rev, */
132 0, /* refcnt */
133 pcata_getinfo, /* info */
134 nulldev, /* identify */
135 nulldev, /* probe */
136 pcata_attach, /* attach */
137 pcata_detach, /* detach */
138 nulldev, /* reset */
139 &pcata_cb_ops, /* driver operations */
140 NULL, /* bus operations */
141 NULL, /* power */
142 ddi_quiesce_not_needed, /* quiesce */
143 };
144
145
146
147 void *pcata_soft = NULL;
148
149
150 #include <sys/modctl.h>
151
152 extern struct mod_ops mod_driverops;
153
154 static struct modldrv modldrv = {
155 &mod_driverops, /* Type of module. This one is a driver */
156 "PCMCIA ATA disk controller",
157 &ata_ops, /* driver ops */
158 };
159
160 static struct modlinkage modlinkage = {
161 MODREV_1, (void *)&modldrv, NULL
162 };
163
164 int
_init(void)165 _init(void)
166 {
167 int status;
168
169 status = mod_install(&modlinkage);
170 if (status)
171 return (status);
172
173 status = ddi_soft_state_init(&pcata_soft, sizeof (ata_soft_t), 1);
174
175 return (status);
176 }
177
178
179 int
_fini(void)180 _fini(void)
181 {
182 int status;
183
184 status = mod_remove(&modlinkage);
185 if (!status)
186 ddi_soft_state_fini(&pcata_soft);
187
188 return (status);
189 }
190
191
192 int
_info(struct modinfo * modinfop)193 _info(struct modinfo *modinfop)
194 {
195 return (mod_info(&modlinkage, modinfop));
196 }
197
198 static int
pcata_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)199 pcata_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
200 {
201 int instance = ddi_get_instance(dip);
202 ata_soft_t *softp;
203 int ret;
204
205 /* resume from a checkpoint */
206 if (cmd == DDI_RESUME)
207 return (DDI_SUCCESS);
208
209 if (cmd != DDI_ATTACH) {
210 #ifdef ATA_DEBUG
211 cmn_err(CE_CONT, "_attach returning FAILURE\n");
212 #endif
213 return (DDI_FAILURE);
214 }
215
216 /* Allocate soft state associated with this instance. */
217 ret = ddi_soft_state_zalloc(pcata_soft, ddi_get_instance(dip));
218 if (ret != DDI_SUCCESS) {
219 #ifdef ATA_DEBUG
220 cmn_err(CE_CONT, "_attach: Unable to alloc state\n");
221 #endif
222 return (DDI_FAILURE);
223 }
224
225 softp = ddi_get_soft_state(pcata_soft, instance);
226
227 #ifdef ATA_DEBUG
228 if (pcata_debug & DINIT)
229 cmn_err(CE_CONT, "_attach softp=%p\n", (void *)softp);
230 #endif
231
232 softp->dip = dip;
233 softp->instance = instance;
234 softp->ab_dip = dip;
235 softp->crashbuf = getrbuf(KM_SLEEP);
236 softp->flags = 0;
237 softp->card_state = 0;
238 softp->intr_pending = 0;
239 softp->softint_pending = 0;
240 softp->write_in_progress = 0;
241 softp->blk_open = 0;
242 softp->chr_open = 0;
243 softp->ejected_while_mounted = 0;
244 bzero(softp->lyr_open, sizeof (softp->lyr_open[NUM_PARTS]));
245
246 /*
247 * Initialize to 0 until it is incremented in pcram_check_media
248 */
249 softp->checkmedia_flag = 0;
250 softp->ejected_media_flag = 0;
251 softp->media_state = DKIO_NONE;
252
253 /*
254 * if attach fails, Solaris won't call detach
255 * so we call detach here to release all flagged resources
256 */
257 ret = pcata_att1(dip, softp);
258 if (ret == DDI_FAILURE) {
259 (void) pcata_detach(dip, DDI_DETACH);
260 return (DDI_FAILURE);
261 }
262
263 return (DDI_SUCCESS);
264 }
265
266 static int
pcata_att1(dev_info_t * dip,ata_soft_t * softp)267 pcata_att1(dev_info_t *dip, ata_soft_t *softp)
268 {
269 int ret;
270 client_reg_t client_reg;
271 sockmask_t sockmask;
272 map_log_socket_t map_log_socket;
273 cs_ddi_info_t cs_ddi_info;
274 get_status_t get_status;
275
276
277 /*
278 * create ata_mutex
279 */
280 ret = ddi_get_soft_iblock_cookie(dip, DDI_SOFTINT_MED,
281 &softp->soft_blk_cookie);
282 if (ret != DDI_SUCCESS) {
283 #ifdef ATA_DEBUG
284 cmn_err(CE_CONT, "_attach: unable to get iblock cookie\n");
285 #endif
286 return (ret);
287 }
288
289
290 /*
291 * Setup the mutexii and condition variables.
292 * Initialize the mutex that protects the ATA registers.
293 */
294 mutex_init(&softp->ata_mutex, NULL, MUTEX_DRIVER,
295 (void *)(softp->soft_blk_cookie));
296 mutex_init(&softp->label_mutex, NULL, MUTEX_DRIVER, NULL);
297
298 cv_init(&softp->readywait_cv, NULL, CV_DRIVER, NULL);
299 /* for DKIOCSTATE ioctl() */
300 cv_init(&softp->condvar_mediastate, NULL, CV_DRIVER, NULL);
301 softp->flags |= PCATA_DIDLOCKS;
302
303
304 /*
305 * link in soft interrupt
306 */
307 ret = ddi_add_softintr(dip, DDI_SOFTINT_MED, &softp->softint_id,
308 NULL, NULL, pcata_intr, (caddr_t)softp);
309 if (ret != DDI_SUCCESS) {
310 #ifdef ATA_DEBUG
311 cmn_err(CE_CONT, "_attach: unable to get soft interrupt\n");
312 #endif
313 return (DDI_FAILURE);
314 }
315 softp->flags |= PCATA_SOFTINTROK;
316
317
318 /*
319 * Register with Card Services
320 */
321 client_reg.Attributes =
322 INFO_IO_CLIENT | INFO_CARD_SHARE | INFO_CARD_EXCL;
323
324 client_reg.EventMask =
325 CS_EVENT_CARD_INSERTION |
326 CS_EVENT_CARD_REMOVAL |
327 CS_EVENT_CARD_REMOVAL_LOWP |
328 CS_EVENT_PM_RESUME |
329 CS_EVENT_CLIENT_INFO |
330 CS_EVENT_PM_SUSPEND |
331 CS_EVENT_REGISTRATION_COMPLETE;
332
333 client_reg.event_handler = (csfunction_t *)pcata_event;
334 client_reg.event_callback_args.client_data = softp;
335 client_reg.Version = _VERSION(2, 1);
336 client_reg.dip = dip;
337 (void) strcpy(client_reg.driver_name, pcata_name);
338
339 ret = csx_RegisterClient(&softp->client_handle, &client_reg);
340 if (ret != CS_SUCCESS) {
341 #ifdef ATA_DEBUG
342 cmn_err(CE_CONT, "_attach RegisterClient failed %s\n",
343 pcata_CS_etext(ret));
344 #endif
345 return (DDI_FAILURE);
346 }
347
348 mutex_init(&softp->event_hilock, NULL, MUTEX_DRIVER,
349 *(client_reg.iblk_cookie));
350
351 softp->flags |= PCATA_REGCLIENT;
352
353
354 /*
355 * Get logical socket number and store in softp struct
356 */
357 ret = csx_MapLogSocket(softp->client_handle, &map_log_socket);
358 if (ret != CS_SUCCESS) {
359 #ifdef ATA_DEBUG
360 cmn_err(CE_CONT, "_attach: MapLogSocket failed %s\n",
361 pcata_CS_etext(ret));
362 #endif
363 return (DDI_FAILURE);
364 }
365 softp->sn = map_log_socket.PhySocket;
366
367
368 /*
369 *
370 */
371 cs_ddi_info.Socket = softp->sn;
372 cs_ddi_info.driver_name = pcata_name;
373 cs_ddi_info.dip = dip;
374 cs_ddi_info.instance = softp->instance;
375 if ((ret = csx_CS_DDI_Info(&cs_ddi_info)) != CS_SUCCESS) {
376 #ifdef ATA_DEBUG
377 cmn_err(CE_CONT, "_attach: socket %d CS_DDI_Info failed %s\n",
378 softp->sn, pcata_CS_etext(ret));
379 #endif
380 return (DDI_FAILURE);
381 }
382
383 /*
384 * After the RequestSocketMask call, we start receiving events
385 */
386 sockmask.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL;
387 ret = csx_RequestSocketMask(softp->client_handle, &sockmask);
388 if (ret != CS_SUCCESS) {
389 #ifdef ATA_DEBUG
390 cmn_err(CE_CONT, "_attach: RequestSocketMask failed %s\n",
391 pcata_CS_etext(ret));
392 #endif
393 return (DDI_FAILURE);
394 }
395 softp->flags |= PCATA_REQSOCKMASK;
396
397 /*
398 * We may not get the CARD_READY event
399 * until after we leave this function.
400 */
401 mutex_enter(&softp->event_hilock);
402 softp->card_state |= PCATA_READY_WAIT;
403 mutex_exit(&softp->event_hilock);
404
405 (void) csx_GetStatus(softp->client_handle, &get_status);
406 if (get_status.raw_CardState & CS_STATUS_CARD_INSERTED) {
407
408 /* wait for drive to be initialized */
409 (void) pcata_readywait(softp);
410
411 if ((softp->card_state & PCATA_CARD_INSERTED) == 0 ||
412 (softp->flags & PCATA_READY) == 0) {
413
414 mutex_enter(&softp->ata_mutex);
415 mutex_enter(&softp->event_hilock);
416
417 softp->card_state &= ~PCATA_READY_WAIT;
418
419 mutex_exit(&softp->event_hilock);
420 mutex_exit(&softp->ata_mutex);
421 }
422 }
423
424 /*
425 * Wait for minor node creation before returning
426 */
427 pcata_minor_wait(softp);
428
429 /*
430 * print banner to announce device
431 */
432 ddi_report_dev(dip);
433
434 return (DDI_SUCCESS);
435 }
436
437 static int
pcata_detach(dev_info_t * devi,ddi_detach_cmd_t cmd)438 pcata_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
439 {
440 int instance = ddi_get_instance(devi);
441 ata_soft_t *softp;
442 int ret;
443
444 if (cmd == DDI_SUSPEND)
445 return (DDI_SUCCESS);
446
447 if (cmd != DDI_DETACH)
448 return (DDI_FAILURE);
449
450 softp = ddi_get_soft_state(pcata_soft, instance);
451
452
453 /*
454 * Call the card_removal routine to do any final card cleanup
455 */
456 if (CARD_PRESENT_VALID(softp)) {
457 (void) pcata_card_removal(softp, CS_EVENT_PRI_LOW);
458 }
459
460
461 /*
462 * Release our socket mask - note that we can't do much
463 * if we fail these calls other than to note that
464 * the system will probably panic shortly. Perhaps
465 * we should fail the detach in the case where these
466 * CS calls fail?
467 */
468
469 if (softp->flags & PCATA_REQSOCKMASK) {
470 release_socket_mask_t rsm;
471 ret = csx_ReleaseSocketMask(softp->client_handle, &rsm);
472 if (ret != CS_SUCCESS) {
473 #ifdef ATA_DEBUG
474 cmn_err(CE_CONT, "_detach "
475 "ReleaseSocketMask failed %s\n",
476 pcata_CS_etext(ret));
477 #endif
478 }
479 }
480
481
482 /*
483 * Deregister with Card Services - we will stop getting
484 * events at this point.
485 */
486 if (softp->flags & PCATA_REGCLIENT) {
487 ret = csx_DeregisterClient(softp->client_handle);
488 if (ret != CS_SUCCESS) {
489 #ifdef ATA_DEBUG
490 cmn_err(CE_CONT, "_detach: "
491 "DeregisterClient failed %s\n",
492 pcata_CS_etext(ret));
493 #endif
494 return (DDI_FAILURE);
495
496 }
497 softp->flags &= ~PCATA_REGCLIENT;
498 }
499
500
501 /* unregister the softintrrupt handler */
502 if (softp->flags & PCATA_SOFTINTROK) {
503 ddi_remove_softintr(softp->softint_id);
504 softp->flags &= ~PCATA_SOFTINTROK;
505
506 }
507
508 if (softp->flags & PCATA_DIDLOCKS) {
509
510 /*
511 * XXX/lcl make sure no threads are blocked
512 */
513 mutex_destroy(&softp->ata_mutex);
514 mutex_destroy(&softp->event_hilock);
515 mutex_destroy(&softp->label_mutex);
516 cv_destroy(&softp->readywait_cv);
517 /* for DKIOCSTATE ioctl() */
518 cv_destroy(&softp->condvar_mediastate);
519 softp->flags &= ~PCATA_DIDLOCKS;
520 }
521
522 /* Free various structures and memory here. */
523 if (softp && softp->crashbuf)
524 freerbuf(softp->crashbuf);
525
526 /* Free the soft state structure here */
527 ddi_soft_state_free(pcata_soft, instance);
528
529 #ifdef ATA_DEBUG
530 if (pcata_debug & DPCM)
531 cmn_err(CE_NOTE, "successful detach\n");
532 #endif
533
534 return (DDI_SUCCESS);
535 }
536
537
538 /*
539 * Common controller object interface
540 */
541 /*
542 * initiate a new I/O request
543 * either start it or add it to the request queue
544 */
545 int
pcata_start(ata_unit_t * unitp,buf_t * bp,int blkno)546 pcata_start(ata_unit_t *unitp, buf_t *bp, int blkno)
547 {
548 ata_soft_t *softp = unitp->a_blkp;
549 struct ata_cmpkt *pktp;
550 int ret;
551 int kf = 0;
552
553 ASSERT(mutex_owned(&softp->ata_mutex));
554
555 #ifdef ATA_DEBUG
556 if (pcata_debug & DENT) {
557 cmn_err(CE_CONT, "_start unitp=%p, bp=%p bp->b_private=%p\n",
558 (void *)unitp,
559 (void *)bp,
560 bp->b_private);
561 }
562 #endif
563
564 if (!CARD_PRESENT_VALID(softp))
565 return (CTL_SEND_FAILURE);
566
567 /* XXX/lcl why is this different from CARD_PRESENT_VALID */
568 if (softp->ab_status_flag & ATA_OFFLINE) {
569 return (CTL_SEND_FAILURE);
570 }
571
572 pktp = (struct ata_cmpkt *)kmem_zalloc(sizeof (*pktp), kf);
573 if (!pktp) {
574 cmn_err(CE_NOTE, "_start kmem_zalloc failed\n");
575 return (CTL_SEND_FAILURE);
576 }
577
578 #ifdef ATA_DEBUG
579 if (pcata_debug & DENT)
580 cmn_err(CE_CONT, "_start pktp=%p\n", (void *)pktp);
581 #endif
582
583 if ((bp->b_flags & B_PAGEIO) || (bp->b_flags & B_PHYS))
584 bp_mapin(bp);
585
586 pktp->ac_bytes_per_block = unitp->au_bytes_per_block;
587 pktp->ac_start_v_addr = bp->b_un.b_addr; /* xfer address */
588 pktp->cp_bytexfer = bp->b_bcount;
589 pktp->cp_bp = bp;
590 pktp->cp_ctl_private = unitp;
591 pktp->cp_srtsec = blkno;
592
593 if (bp->b_flags & B_READ) {
594 pktp->ac_direction = AT_IN;
595 pktp->ac_cdb = DCMD_READ;
596 } else {
597 pktp->ac_direction = AT_OUT;
598 pktp->ac_cdb = DCMD_WRITE;
599 }
600
601 /*
602 * b_private is set to 0xBEE by pcata_buf_setup
603 * which is called by an ioctl DIOCTL_RWCMD with a subcommand
604 * of either DADKIO_RWCMD_READ or DADKIO_RWCMD_WRITE
605 *
606 * these commands are used to do I/O through the IOCTL interface
607 *
608 * b_back contains a pointer to the ioctl packet struct (dadkio_rwcmd)
609 */
610 if (bp->b_private == (void *)0xBEE)
611 pktp->cp_passthru = bp->b_back;
612
613 #ifdef ATA_DEBUG
614 if (pcata_debug & DIO) {
615 cmn_err(CE_CONT, "passthru command seen: 0x%p\n",
616 pktp->cp_passthru);
617 }
618 #endif
619
620 pcata_iosetup(unitp, pktp); /* fill a packet */
621 pktp->pkt_forw = 0;
622
623 #ifdef ATA_DEBUG
624 if (pcata_debug & DIO) {
625 cmn_err(CE_CONT, "_start: active: %c head: %c\n",
626 (softp->ab_active == NULL ? 'N' : 'Y'),
627 (softp->ab_head == NULL ? 'N' : 'Y'));
628 }
629 #endif
630
631 if (softp->ab_active == NULL) {
632 /*
633 * The controller is idle.
634 * Put the packet in ab_active....
635 */
636 softp->ab_active = pktp;
637 /*
638 * ... and start it off
639 */
640 ret = PCATA_GO_RETRY;
641 while (ret == PCATA_GO_RETRY) {
642 ret = pcata_go(unitp);
643 }
644 if (ret == DDI_FAILURE) {
645 cmn_err(CE_NOTE, "start_cmd failure \n");
646 softp->ab_active = NULL;
647 return (CTL_SEND_FAILURE);
648 }
649
650 } else {
651 /*
652 * the controller is busy now so put the packet
653 * on ab_head or ab_last.
654 */
655
656 if (softp->ab_head == NULL)
657 softp->ab_head = pktp;
658 else
659 softp->ab_last->pkt_forw = pktp;
660
661 softp->ab_last = pktp;
662 }
663
664 return (CTL_SEND_SUCCESS);
665 }
666
667
668 /*
669 * initiate I/O for packet linked on ab_active
670 */
671 static int
pcata_go(ata_unit_t * unitp)672 pcata_go(ata_unit_t *unitp)
673 {
674 ata_soft_t *softp = unitp->a_blkp;
675 struct ata_cmpkt *pktp = softp->ab_active;
676 uint32_t nbytes;
677 uint32_t start_sec;
678 uint32_t cyl;
679 uint32_t resid;
680 uchar_t head;
681 uchar_t drvheads;
682 uchar_t drvsectors;
683
684 uchar_t ac_devctl;
685 uchar_t ac_sec;
686 uchar_t ac_count;
687 uchar_t ac_lwcyl;
688 uchar_t ac_hicyl;
689 uchar_t ac_hd;
690
691 ASSERT(mutex_owned(&softp->ata_mutex));
692
693 if (pktp == NULL)
694 return (DDI_SUCCESS);
695
696 if (!CARD_PRESENT_VALID(softp)) {
697 pktp->ac_scb = DERR_ABORT;
698 pktp->cp_reason = CPS_CHKERR;
699 return (DDI_FAILURE);
700 }
701
702 #ifdef ATA_DEBUG
703 if (pcata_debug & DENT) {
704 cmn_err(CE_CONT, "_go (%p) altstatus %x error %x\n",
705 (void *)unitp,
706 csx_Get8(softp->handle, AT_ALTSTATUS),
707 csx_Get8(softp->handle, AT_ERROR));
708 cmn_err(CE_CONT, "_go handle=%p\n", softp->handle);
709 }
710 #endif
711
712 /*
713 * calculate drive address based on pktp->cp_srtsec
714 */
715 start_sec = pktp->cp_srtsec;
716 drvheads = unitp->au_hd;
717 drvsectors = unitp->au_sec;
718 resid = start_sec / drvsectors;
719 head = resid % drvheads;
720 cyl = resid / drvheads;
721 nbytes = min(pktp->cp_resid, pktp->ac_bytes_per_block);
722 ac_count = (nbytes >> SCTRSHFT);
723 ac_devctl = unitp->au_ctl_bits;
724 ac_sec = (start_sec % drvsectors) + 1;
725 ac_hd = head | unitp->au_drive_bits;
726 ac_lwcyl = cyl;
727 ac_hicyl = (cyl >> 8);
728
729 #ifdef ATA_DEBUG
730 if (pcata_debug & DIO) {
731 cmn_err(CE_CONT,
732 "_go %s at lba=%d (%uc %uh %us) "
733 "%d sectors cmd=%x ctl=%x\n",
734 (pktp->ac_direction == AT_OUT) ? "WT" : "RD",
735 start_sec, cyl, head, ac_sec,
736 ac_count,
737 pktp->ac_cmd, ac_devctl);
738 }
739 #endif
740
741 if (pcata_wait(AT_ALTSTATUS, ATS_DRDY, ATS_BSY, softp))
742 return (DDI_FAILURE);
743
744 pcata_wait_complete(softp);
745
746 PCIDE_OUTB(softp->handle, AT_DEVCTL, ac_devctl);
747 PCIDE_OUTB(softp->handle, AT_SECT, ac_sec);
748 PCIDE_OUTB(softp->handle, AT_COUNT, ac_count);
749 PCIDE_OUTB(softp->handle, AT_LCYL, ac_lwcyl);
750 PCIDE_OUTB(softp->handle, AT_HCYL, ac_hicyl);
751 PCIDE_OUTB(softp->handle, AT_DRVHD, ac_hd);
752
753 /*
754 * the command should make the controller status show BSY
755 * the ISR intr_hi will not record status while the controller is BSY
756 * therefore set interrupt expected state now
757 * the next time we receive an interrupt and the controller is not BSY
758 * the ISR will do the right thing
759 */
760
761 mutex_enter(&softp->hi_mutex);
762 softp->intr_pending++;
763 if (pktp->ac_direction == AT_OUT)
764 softp->write_in_progress++;
765 csx_Put8(softp->handle, AT_CMD, pktp->ac_cmd);
766 mutex_exit(&softp->hi_mutex);
767
768 /*
769 * If there's data to go along with the command, send it now.
770 */
771 if (pktp->ac_direction == AT_OUT) {
772 if (pcata_send_data(unitp, nbytes) == DDI_FAILURE) {
773 if (pktp->cp_retry >= RETRY_CNT) {
774 pcata_clear_queues(unitp);
775 return (DDI_FAILURE);
776 } else {
777 pktp->cp_retry++;
778 cmn_err(CE_CONT, "_go: write failure,"
779 " retry=%d \n", pktp->cp_retry);
780 cmn_err(CE_CONT,
781 "_go at lba=%d (%uc %uh %us) "
782 "%d sectors cmd=%x ctl=%x \n",
783 start_sec, cyl, head, ac_sec,
784 ac_count,
785 pktp->ac_cmd, ac_devctl);
786 return (PCATA_GO_RETRY);
787 }
788 }
789 }
790
791 return (DDI_SUCCESS);
792 }
793
794 /*
795 * return value
796 * success means go on o next block
797 * failure means continue with current block
798 */
799 static void
pcata_iocmpl(ata_soft_t * softp)800 pcata_iocmpl(ata_soft_t *softp)
801 {
802 struct ata_cmpkt *pktp;
803 ata_unit_t *unitp;
804 int nbytes;
805 int ret;
806 uchar_t status;
807 uchar_t error;
808
809 ASSERT(mutex_owned(&softp->ata_mutex));
810
811 if (!CARD_PRESENT_VALID(softp)) {
812 cmn_err(CE_CONT, "?_iocmpl Device not present\n");
813 return;
814 }
815
816 pktp = softp->ab_active;
817
818 error = pktp->ac_error;
819 status = pktp->ac_status;
820
821 unitp = (ata_unit_t *)pktp->cp_ctl_private;
822
823 /*
824 * If there was an error, quit now
825 * XXX/lcl no retry is attempted?
826 */
827 if ((status & ATS_ERR) || (error & ATE_ABORT)) {
828 #ifdef ATA_DEBUG
829 if (pcata_debug & DIO)
830 cmn_err(CE_CONT,
831 "_iocmpl I/O error status=%04x error=%04x\n",
832 status,
833 error);
834 #endif
835 pktp->cp_reason = CPS_CHKERR;
836 return;
837 }
838
839 nbytes = min(pktp->cp_resid, pktp->ac_bytes_per_block);
840
841 if (pktp->ac_direction == AT_IN) {
842 /*
843 * do the read of the block
844 */
845 ret = pcata_get_data(unitp, nbytes);
846 if (ret == DDI_FAILURE) {
847 /*
848 * If the controller never presented the data
849 * and the error bit isn't set,
850 * there's a real problem. Kill it now.
851 */
852 pcata_clear_queues(unitp);
853 return;
854 }
855 }
856
857 /*
858 * update counts...
859 */
860 pktp->ac_v_addr += nbytes;
861 pktp->cp_resid -= nbytes;
862 pktp->cp_reason = CPS_SUCCESS;
863 pktp->cp_srtsec += (nbytes >> SCTRSHFT);
864
865 /* If last command was a GET_DEFECTS delay a bit */
866 if (pktp->ac_cmd == ATC_READDEFECTS)
867 drv_usecwait(1000);
868 }
869
870 int
pcata_intr_hi(ata_soft_t * softp)871 pcata_intr_hi(ata_soft_t *softp)
872 {
873 /*
874 * In ata there is no hardware support to tell if the interrupt
875 * belongs to ata or not. So no checks necessary here. Later
876 * will check the buffer and see if we have started a transaction.
877 */
878
879 int rval = DDI_INTR_UNCLAIMED;
880 struct ata_cmpkt *pktp;
881 uchar_t status;
882 uchar_t error;
883
884 #ifdef ATA_DEBUG
885 if (pcata_debug & DENT) {
886 cmn_err(CE_CONT,
887 "_intr_hi sn=%d status=%x intr_pending=%d "
888 "softint_pending=%d wr_in_prog=%d\n",
889 softp->sn, csx_Get8(softp->handle, AT_ALTSTATUS),
890 softp->intr_pending, softp->softint_pending,
891 softp->write_in_progress);
892 }
893 #endif
894 mutex_enter(&softp->hi_mutex);
895
896 /*
897 * this test is not redundant (don't remove it)
898 * it is part of card removal processing
899 * and prevents losing interrupt threads
900 */
901 if (!CARD_PRESENT_VALID(softp)) {
902 mutex_exit(&softp->hi_mutex);
903 return (rval);
904 }
905
906 status = csx_Get8(softp->handle, AT_ALTSTATUS);
907
908 /*
909 * this is a shared interrupt
910 * if the controller is NOT busy,
911 * and an interrupt is expected
912 */
913
914 if ((status & ATS_ERR) &&
915 ((status & ATS_BSY) == 0) &&
916 (softp->intr_pending > 0)) {
917 cmn_err(CE_CONT,
918 "?_intr_hi sn=%d status=%x\n",
919 softp->sn, status);
920 /* handle aborted commands */
921 error = csx_Get8(softp->handle, AT_ERROR);
922 if ((error & ATE_ABORT) &&
923 (softp->write_in_progress > 0)) {
924 softp->write_in_progress = 0;
925 }
926 }
927
928 if ((status & ATS_BSY) == 0 &&
929 (softp->write_in_progress == 0) &&
930 (softp->intr_pending > 0)) {
931 /*
932 * Read the status register,
933 * this clears an interrupt from the ata device
934 */
935 status = csx_Get8(softp->handle, AT_STATUS);
936 error = csx_Get8(softp->handle, AT_ERROR);
937 rval = DDI_INTR_CLAIMED;
938 softp->intr_pending--;
939 /*
940 * Make sure the interrupt is cleared, occasionally it is not
941 * cleared by the first status read.
942 */
943 status = csx_Get8(softp->handle, AT_STATUS);
944 /* put the error status in the right place */
945 if ((pktp = softp->ab_active) != 0) {
946 pktp->ac_error = error;
947 pktp->ac_status = status;
948 }
949 }
950 mutex_exit(&softp->hi_mutex);
951
952 #ifdef ATA_DEBUG
953 if (pcata_debug & DENT)
954 cmn_err(CE_CONT,
955 "_intr_hi status=%x error=%x claimed=%d pending=%d\n",
956 status, error,
957 (rval == DDI_INTR_CLAIMED),
958 softp->intr_pending);
959 #endif
960
961 if ((rval == DDI_INTR_CLAIMED) &&
962 (softp->ab_active != NULL)) {
963 mutex_enter(&softp->hi_mutex);
964 softp->softint_pending++;
965 mutex_exit(&softp->hi_mutex);
966 ddi_trigger_softintr(softp->softint_id);
967 }
968
969 return (rval);
970 }
971
972 uint32_t
pcata_intr(char * parm)973 pcata_intr(char *parm)
974 {
975 ata_soft_t *softp = (ata_soft_t *)parm;
976 ata_unit_t *unitp;
977 struct ata_cmpkt *pktp;
978 buf_t *bp;
979 uint32_t nbytes;
980 uint32_t start_sec;
981 uint32_t cyl;
982 uint32_t resid;
983 uchar_t head;
984 uchar_t drvheads;
985 uchar_t drvsectors;
986 uchar_t ac_devctl;
987 uchar_t ac_sec;
988 uchar_t ac_count;
989 int ret;
990
991 #ifdef ATA_DEBUG
992 if (pcata_debug & DENT) {
993 cmn_err(CE_CONT, "_intr entry (%p) sn=%d softint_pending=%d\n",
994 (void *)softp, softp->sn, softp->softint_pending);
995 }
996 #endif
997
998
999 if (softp->softint_pending == 0) {
1000 return (DDI_INTR_UNCLAIMED);
1001 }
1002
1003 mutex_enter(&softp->ata_mutex);
1004
1005 if (softp->ab_active == NULL) {
1006 cmn_err(CE_CONT, "?_intr No outstanding I/O\n");
1007 goto done;
1008 }
1009
1010 /* perform I/O completion */
1011 pcata_iocmpl(softp);
1012
1013 if (!CARD_PRESENT_VALID(softp))
1014 goto done;
1015
1016 /*
1017 * if packet is done (either errors or all bytes transfered)
1018 * pktp points to current packet
1019 * ab_active is cleared
1020 * else
1021 * pktp is null
1022 * ab_active is unchanged
1023 */
1024 pktp = softp->ab_active;
1025 if (pktp != NULL) {
1026 if (pktp->cp_resid == 0 || pktp->cp_reason != CPS_SUCCESS) {
1027 #ifdef ATA_DEBUG
1028 if (pcata_debug & DENT) {
1029 cmn_err(CE_CONT, "_intr retry=%d reason=%d"
1030 " CPS_SUCCESS=%d pkpt=%p cp_resid = %d\n",
1031 pktp->cp_retry, pktp->cp_reason,
1032 CPS_SUCCESS, (void *)pktp,
1033 pktp->cp_resid);
1034 }
1035 #endif
1036 if ((pktp->cp_retry < RETRY_CNT) &&
1037 (pktp->cp_reason != CPS_SUCCESS)) {
1038 pktp->cp_retry++;
1039 unitp = softp->ab_active->cp_ctl_private;
1040
1041 /*
1042 * calculate drive address based on
1043 * pktp->cp_srtsec
1044 */
1045 start_sec = pktp->cp_srtsec;
1046 drvheads = unitp->au_hd;
1047 drvsectors = unitp->au_sec;
1048 resid = start_sec / drvsectors;
1049 head = resid % drvheads;
1050 cyl = resid / drvheads;
1051 nbytes = min(pktp->cp_resid,
1052 pktp->ac_bytes_per_block);
1053 ac_count = (nbytes >> SCTRSHFT);
1054 ac_devctl = unitp->au_ctl_bits;
1055 ac_sec = (start_sec % drvsectors) + 1;
1056
1057 cmn_err(CE_CONT, "_intr I/O failure,"
1058 " retry %d\n", pktp->cp_retry);
1059 cmn_err(CE_CONT,
1060 "_intr %s at lba=%d (%uc %uh %us) "
1061 "%d sectors cmd=%x ctl=%x\n",
1062 (pktp->ac_direction == AT_OUT) ?
1063 "write" : "read",
1064 start_sec, cyl, head, ac_sec,
1065 ac_count,
1066 pktp->ac_cmd, ac_devctl);
1067
1068 pktp = 0;
1069 } else {
1070 /* I/O is complete or an error has occured */
1071 softp->ab_active = NULL;
1072 }
1073 } else {
1074 /* I/O is still in progress */
1075 pktp = 0;
1076 }
1077 }
1078
1079 /*
1080 * packet which caused this interrupt is now complete
1081 */
1082 if (pktp) {
1083 if ((pktp->ac_status & ATS_ERR) || (pktp->ac_error)) {
1084 bioerror(pktp->cp_bp, EIO);
1085 #ifdef ATA_DEBUG
1086 cmn_err(CE_NOTE, "_intr ATA ERROR status=%x error=%x\n",
1087 pktp->ac_status, pktp->ac_error);
1088 #endif
1089 }
1090
1091 bp = pktp->cp_bp;
1092 bp->b_resid = bp->b_bcount - pktp->cp_bytexfer;
1093
1094 /* release the thread for the I/O just completed */
1095 biodone(bp);
1096
1097 kmem_free((void *)pktp, sizeof (*pktp));
1098 }
1099
1100
1101 /* if ab_active is NULL attempt to dequeue next I/O request */
1102 if (softp->ab_active == NULL && softp->ab_head != NULL) {
1103 softp->ab_active = softp->ab_head;
1104 softp->ab_head = softp->ab_head->pkt_forw;
1105
1106 #ifdef ATA_DEBUG
1107 if (pcata_debug & DIO) {
1108 cmn_err(CE_CONT,
1109 "_start_next_cmd current:%p head:%p\n",
1110 (void *)softp->ab_active,
1111 (void *)softp->ab_head);
1112 }
1113 #endif
1114 }
1115
1116 mutex_enter(&softp->hi_mutex);
1117 softp->softint_pending--;
1118 mutex_exit(&softp->hi_mutex);
1119
1120 /* if ab_active is not NULL, attempt to initiate I/O */
1121 if (softp->ab_active != NULL) {
1122 unitp = softp->ab_active->cp_ctl_private;
1123
1124 ret = PCATA_GO_RETRY;
1125 while (ret == PCATA_GO_RETRY) {
1126 ret = pcata_go(unitp);
1127 }
1128 }
1129 goto exit;
1130
1131 done:
1132 mutex_enter(&softp->hi_mutex);
1133 softp->softint_pending--;
1134 mutex_exit(&softp->hi_mutex);
1135 exit:
1136 mutex_exit(&softp->ata_mutex);
1137 #ifdef ATA_DEBUG
1138 if (pcata_debug & DENT)
1139 cmn_err(CE_CONT, "_intr exit (%p)\n", (void *)softp);
1140 #endif
1141 return (DDI_INTR_CLAIMED);
1142 }
1143
1144
1145 /*
1146 * XXX/lcl need determine if all drives or a single drive is to be cleared
1147 * if all drives then eliminate tests for pktp->cp_ctl_private == unitp
1148 * if single drive then examine usage of flag ATA_OFFLINE
1149 */
1150 static void
pcata_clear_queues(ata_unit_t * unitp)1151 pcata_clear_queues(ata_unit_t *unitp)
1152 {
1153 ata_soft_t *softp = unitp->a_blkp;
1154 struct ata_cmpkt *pktp;
1155 buf_t *bp;
1156
1157 ASSERT(mutex_owned(&softp->ata_mutex));
1158
1159 #ifdef ATA_DEBUG
1160 if (pcata_debug & DENT) {
1161 cmn_err(CE_CONT, "_clear_queues (%p)\n", (void *)unitp);
1162 }
1163 #endif
1164 /*
1165 * nack the active request
1166 */
1167 softp->ab_status_flag |= ATA_OFFLINE;
1168
1169 pktp = softp->ab_active;
1170 if (pktp && pktp->cp_ctl_private == unitp)
1171 pcata_nack_packet(pktp);
1172
1173 /*
1174 * now nack all queued requests
1175 */
1176 for (pktp = softp->ab_head; pktp; pktp = pktp->pkt_forw) {
1177 bp = pktp->cp_bp;
1178 if (bp && ((bp->b_flags & B_DONE) == 0)) {
1179 if ((pktp->ac_status & ATS_ERR) || (pktp->ac_error)) {
1180 bioerror(bp, EIO);
1181 }
1182
1183 /* release the thread for the I/O */
1184 biodone(bp);
1185 }
1186 if (pktp->cp_ctl_private == unitp)
1187 pcata_nack_packet(pktp);
1188 }
1189 }
1190
1191 static void
pcata_nack_packet(struct ata_cmpkt * pktp)1192 pcata_nack_packet(struct ata_cmpkt *pktp)
1193 {
1194 #ifdef ATA_DEBUG
1195 if (pcata_debug & DENT)
1196 cmn_err(CE_CONT, "pcata_nack_packet (%p)\n", (void *)pktp);
1197 #endif
1198 if (pktp != NULL) {
1199 pktp->cp_reason = CPS_CHKERR;
1200 pktp->ac_scb = DERR_ABORT;
1201 }
1202 }
1203
1204 /*
1205 * pcata_wait -- wait for a register of a controller to achieve a
1206 * specific state. Arguments are a mask of bits we care about,
1207 * and two sub-masks. To return normally, all the bits in the
1208 * first sub-mask must be ON, all the bits in the second sub-
1209 * mask must be OFF. If 5 seconds pass without the controller
1210 * achieving the desired bit configuration, we return 1, else
1211 * 0.
1212 */
1213 static int
pcata_wait(uint32_t port,ushort_t onbits,ushort_t offbits,ata_soft_t * softp)1214 pcata_wait(uint32_t port, ushort_t onbits, ushort_t offbits, ata_soft_t *softp)
1215 {
1216 register int i;
1217 register ushort_t maskval;
1218 int ival = csx_Get8(softp->handle, port);
1219
1220 for (i = 400000; i && (CARD_PRESENT_VALID(softp)); i--) {
1221 maskval = csx_Get8(softp->handle, port);
1222 if (((maskval & onbits) == onbits) &&
1223 ((maskval & offbits) == 0))
1224 return (0);
1225 drv_usecwait(10);
1226 }
1227 #ifdef ATA_DEBUG
1228 cmn_err(CE_CONT, "_wait timeout: "
1229 "sn=%d port=%x on: 0x%x off: 0x%x ival: 0x%x eval: 0x%x\n",
1230 softp->sn, port, onbits, offbits, ival, maskval);
1231 #endif
1232 return (1);
1233 }
1234
1235
1236 /*
1237 * Similar to pcata_wait but the timeout is much shorter. It is only used
1238 * during initialization when long delays are noticable.
1239 */
1240 static int
pcata_wait1(uint32_t port,ushort_t onbits,ushort_t offbits,int interval,ata_soft_t * softp)1241 pcata_wait1(uint32_t port, ushort_t onbits, ushort_t offbits, int interval,
1242 ata_soft_t *softp)
1243 {
1244 register int i;
1245 register ushort_t maskval;
1246
1247 for (i = interval; i && (CARD_PRESENT_VALID(softp)); i--) {
1248 maskval = csx_Get8(softp->handle, port);
1249 if (((maskval & onbits) == onbits) &&
1250 ((maskval & offbits) == 0))
1251 return (0);
1252 drv_usecwait(10);
1253 }
1254 return (1);
1255 }
1256
1257 /*
1258 * Wait until the command interrupt has been serviced before starting
1259 * another command.
1260 *
1261 */
1262 static void
pcata_wait_complete(ata_soft_t * softp)1263 pcata_wait_complete(ata_soft_t *softp)
1264 {
1265 int i;
1266
1267 for (i = 0; i < PCATA_WAIT_CNT &&
1268 ((softp->intr_pending > 0) || (softp->softint_pending > 0)); i++) {
1269 drv_usecwait(10);
1270 }
1271 }
1272
1273 static int
pcata_send_data(ata_unit_t * unitp,int count)1274 pcata_send_data(ata_unit_t *unitp, int count)
1275 {
1276 ata_soft_t *softp = unitp->a_blkp;
1277 struct ata_cmpkt *pktp = unitp->a_blkp->ab_active;
1278
1279 #ifdef ATA_DEBUG
1280 if (pcata_debug & DENT) {
1281 cmn_err(CE_CONT, "_send_data (%p, %x)\n",
1282 (void *)unitp, count);
1283 }
1284 #endif
1285 if (pcata_wait(AT_ALTSTATUS, ATS_DRQ, 0, softp)) {
1286 cmn_err(CE_CONT, "_send_data - NOT READY\n");
1287 mutex_enter(&softp->hi_mutex);
1288 softp->write_in_progress = 0;
1289 mutex_exit(&softp->hi_mutex);
1290 return (DDI_FAILURE);
1291 }
1292
1293 /*
1294 * copy count bytes from pktp->v_addr to the data port
1295 */
1296 #ifdef ATA_DEBUG
1297 if (pcata_debug & DIO) {
1298 cmn_err(CE_CONT, "_send_data: port=%x addr=0x%p count=0x%x\n",
1299 unitp->a_blkp->ab_data,
1300 (void *)pktp->ac_v_addr,
1301 count);
1302 }
1303 #endif
1304
1305 if (!CARD_PRESENT_VALID(softp)) {
1306 mutex_enter(&softp->hi_mutex);
1307 softp->write_in_progress = 0;
1308 mutex_exit(&softp->hi_mutex);
1309 return (DDI_FAILURE);
1310 }
1311
1312 mutex_enter(&softp->hi_mutex);
1313 csx_RepPut16(softp->handle, (ushort_t *)pktp->ac_v_addr, AT_DATA,
1314 (count >> 1), DDI_DEV_NO_AUTOINCR);
1315 if (softp->write_in_progress > 0)
1316 softp->write_in_progress--;
1317 mutex_exit(&softp->hi_mutex);
1318
1319 #ifdef ATA_DEBUG
1320 if (pcata_debug & DIO) {
1321 cmn_err(CE_CONT, "_send_data: ");
1322 pcata_print_sttflag(csx_Get8(softp->handle, AT_ALTSTATUS));
1323 }
1324
1325 #endif
1326 return (DDI_SUCCESS);
1327 }
1328
1329
1330 static int
pcata_get_data(ata_unit_t * unitp,int count)1331 pcata_get_data(ata_unit_t *unitp, int count)
1332 {
1333 ata_soft_t *softp = unitp->a_blkp;
1334 register struct ata_cmpkt *pktp = unitp->a_blkp->ab_active;
1335
1336 if (pcata_wait(AT_ALTSTATUS, ATS_DRQ, 0, softp)) {
1337 cmn_err(CE_CONT, "_get_data - NOT READY\n");
1338 return (DDI_FAILURE);
1339 }
1340 /*
1341 * copy count bytes from the data port to pktp->ac_v_addr
1342 */
1343
1344 #ifdef ATA_DEBUG
1345 if (pcata_debug & DIO) {
1346 cmn_err(CE_CONT, "_get_data port=%x addr=0x%p count=0x%x\n",
1347 unitp->a_blkp->ab_data, (void *)pktp->ac_v_addr, count);
1348 }
1349 #endif
1350
1351 if (!CARD_PRESENT_VALID(softp))
1352 return (DDI_FAILURE);
1353
1354 csx_RepGet8(softp->handle, (uchar_t *)pktp->ac_v_addr,
1355 AT_DATA, count, DDI_DEV_NO_AUTOINCR);
1356
1357 #ifdef ATA_DEBUG
1358 if (pcata_debug & DIO)
1359 cmn_err(CE_CONT, "_get_data complete\n");
1360 #endif
1361 return (DDI_SUCCESS);
1362 }
1363
1364
1365 int
pcata_getedt(ata_soft_t * softp,int dmax)1366 pcata_getedt(ata_soft_t *softp, int dmax)
1367 {
1368 ushort_t *secbuf;
1369 struct atarpbuf *rpbp;
1370 int drive, dcount;
1371 char buf[41];
1372 int i;
1373
1374 #ifdef ATA_DEBUG
1375 if (pcata_debug & DENT) {
1376 cmn_err(CE_CONT, "_getedt (%p)\n", (void *)softp);
1377 }
1378 #endif
1379 /* toggle reset bit to trigger a software reset */
1380 if (!(CARD_PRESENT_VALID(softp)))
1381 return (DDI_FAILURE);
1382 csx_Put8(softp->handle, AT_DEVCTL, AT_DEVCTL_D3|AT_SRST);
1383
1384 drv_usecwait(1000);
1385 if (!(CARD_PRESENT_VALID(softp)))
1386 return (DDI_FAILURE);
1387
1388 /*
1389 * The interrupt disable command does not work reliably with
1390 * all PC ATA cards. It is better to leave interupts enabled
1391 * and process them as they occur.
1392 */
1393
1394 PCIDE_OUTB(softp->handle, AT_DEVCTL, ENABLE_INTERRUPT);
1395
1396 secbuf = (ushort_t *)kmem_zalloc(NBPSCTR, KM_NOSLEEP);
1397 if (!secbuf) {
1398 return (DDI_FAILURE);
1399 }
1400
1401 for (dcount = drive = 0; drive < dmax; drive++) {
1402 if (!(rpbp = (struct atarpbuf *)kmem_zalloc(
1403 (sizeof (struct atarpbuf) +
1404 sizeof (struct scsi_inquiry)), KM_NOSLEEP))) {
1405 kmem_free(secbuf, NBPSCTR);
1406 return (DDI_FAILURE);
1407 }
1408
1409 /*
1410 * load up with the drive number
1411 */
1412 if (drive == 0) {
1413 PCIDE_OUTB(softp->handle, AT_DRVHD, ATDH_DRIVE0);
1414 } else {
1415 PCIDE_OUTB(softp->handle, AT_DRVHD, ATDH_DRIVE1);
1416 }
1417 PCIDE_OUTB(softp->handle, AT_FEATURE, 0);
1418
1419 softp->ab_dev_type[drive] = pcata_drive_type(softp, secbuf);
1420
1421 if (softp->ab_dev_type[drive] == ATA_DEV_NONE) {
1422 kmem_free(rpbp, (sizeof (struct atarpbuf) +
1423 sizeof (struct scsi_inquiry)));
1424 continue;
1425 }
1426 dcount++;
1427 bcopy((caddr_t)secbuf, (caddr_t)rpbp, sizeof (struct atarpbuf));
1428
1429 mutex_enter(&softp->ata_mutex);
1430 if (!(softp->card_state & PCATA_CARD_INSERTED)) {
1431 kmem_free(rpbp, (sizeof (struct atarpbuf) +
1432 sizeof (struct scsi_inquiry)));
1433 dcount--;
1434 mutex_exit(&softp->ata_mutex);
1435 break;
1436 }
1437
1438 softp->ab_rpbp[drive] = rpbp;
1439
1440 /*
1441 * We need to swap the strings on both platforms.
1442 */
1443 #ifdef _BIG_ENDIAN
1444 pcata_byte_swap((char *)rpbp, sizeof (*rpbp));
1445 #else
1446 pcata_byte_swap(rpbp->atarp_drvser,
1447 sizeof (rpbp->atarp_drvser));
1448 pcata_byte_swap(rpbp->atarp_fw, sizeof (rpbp->atarp_fw));
1449 pcata_byte_swap(rpbp->atarp_model, sizeof (rpbp->atarp_model));
1450 #endif
1451
1452 mutex_exit(&softp->ata_mutex);
1453
1454 #ifdef ATA_DEBUG
1455 if (pcata_debug & DINIT) {
1456 (void) strncpy(buf,
1457 rpbp->atarp_model, sizeof (rpbp->atarp_model));
1458 buf[sizeof (rpbp->atarp_model)-1] = '\0';
1459
1460 /* truncate model */
1461 for (i = sizeof (rpbp->atarp_model) - 2; i && buf[i] == ' ';
1462 i--) {
1463 buf[i] = '\0';
1464 }
1465 cmn_err(CE_CONT, "_getedt model %s, targ %d, stat %x, err %x\n",
1466 buf,
1467 drive,
1468 csx_Get8(softp->handle, AT_STATUS),
1469 csx_Get8(softp->handle, AT_ERROR));
1470 cmn_err(CE_CONT, " cfg 0x%x, cyl %d, hd %d, sec/trk %d\n",
1471 rpbp->atarp_config,
1472 rpbp->atarp_fixcyls,
1473 rpbp->atarp_heads,
1474 rpbp->atarp_sectors);
1475 cmn_err(CE_CONT, " mult1 0x%x, mult2 0x%x, dwcap 0x%x,"
1476 " cap 0x%x\n",
1477 rpbp->atarp_mult1,
1478 rpbp->atarp_mult2,
1479 rpbp->atarp_dwcap,
1480 rpbp->atarp_cap);
1481 cmn_err(CE_CONT, " piomode 0x%x, dmamode 0x%x,"
1482 " advpiomode 0x%x\n",
1483 rpbp->atarp_piomode,
1484 rpbp->atarp_dmamode,
1485 rpbp->atarp_advpiomode);
1486 cmn_err(CE_CONT, " minpio %d, minpioflow %d",
1487 rpbp->atarp_minpio,
1488 rpbp->atarp_minpioflow);
1489 cmn_err(CE_CONT, " valid 0x%x, dwdma 0x%x\n",
1490 rpbp->atarp_validinfo,
1491 rpbp->atarp_dworddma);
1492 }
1493 #endif
1494
1495 if (!(CARD_PRESENT_VALID(softp)))
1496 return (DDI_FAILURE);
1497 (void) csx_Get8(softp->handle, AT_STATUS);
1498 (void) csx_Get8(softp->handle, AT_ERROR);
1499 }
1500
1501 kmem_free(secbuf, NBPSCTR);
1502 if (dcount == 0)
1503 return (DDI_FAILURE);
1504
1505 for (dcount = drive = 0; drive < dmax; drive++) {
1506
1507 if ((rpbp = softp->ab_rpbp[drive]) == NULL) {
1508 continue; /* no drive here */
1509 }
1510
1511 if (softp->ab_dev_type[drive] != ATA_DEV_DISK) {
1512 cmn_err(CE_CONT, "Unknown IDE attachment at 0x%x.\n",
1513 softp->ab_cmd - AT_CMD);
1514 continue;
1515 }
1516
1517 /*
1518 * feed some of the info back in a set_params call.
1519 */
1520 mutex_enter(&softp->ata_mutex);
1521 if (pcata_setpar(drive, rpbp->atarp_heads,
1522 rpbp->atarp_sectors, softp)
1523 == DDI_FAILURE) {
1524 /*
1525 * there should have been a drive here but it
1526 * didn't respond properly. It stayed BUSY.
1527 */
1528 if (softp->ab_rpbp[drive]) {
1529 kmem_free(rpbp,
1530 (sizeof (struct atarpbuf) +
1531 sizeof (struct scsi_inquiry)));
1532 }
1533 softp->ab_rpbp[drive] = NULL;
1534 softp->ab_dev_type[drive] = ATA_DEV_NONE;
1535 mutex_exit(&softp->ata_mutex);
1536 continue;
1537 }
1538 mutex_exit(&softp->ata_mutex);
1539 dcount++;
1540 }
1541
1542 #ifdef ATA_DEBUG
1543 if (pcata_debug)
1544 cmn_err(CE_CONT, "**** probed %d device%s 0x%x\n",
1545 dcount, dcount == 1 ? "." : "s.",
1546 softp->ab_cmd - AT_CMD);
1547 #endif
1548
1549 return (dcount ? DDI_SUCCESS : DDI_FAILURE);
1550 }
1551
1552 /*
1553 * pcata_drive_type()
1554 */
1555 static uchar_t
pcata_drive_type(ata_soft_t * softp,ushort_t * buf)1556 pcata_drive_type(ata_soft_t *softp, ushort_t *buf)
1557 {
1558 struct atarpbuf *rpbp = (struct atarpbuf *)buf;
1559
1560 if (pcata_wait1(AT_ALTSTATUS,
1561 (ATS_DRDY | ATS_DSC), (ATS_BSY | ATS_ERR), 100000, softp))
1562 return (ATA_DEV_NONE);
1563
1564 pcata_wait_complete(softp);
1565
1566 /*
1567 * note: pcata_drive_type is only called by pcata_getedt()
1568 * the drive (master/slave) is selected there
1569 */
1570 /* command also known as IDENTIFY DEVICE */
1571 mutex_enter(&softp->hi_mutex);
1572 softp->intr_pending++;
1573 csx_Put8(softp->handle, AT_CMD, ATC_READPARMS);
1574 mutex_exit(&softp->hi_mutex);
1575
1576 if (pcata_wait1(AT_ALTSTATUS, ATS_DRQ, ATS_BSY, 1000000, softp)) {
1577
1578 #ifdef ATA_DEBUG
1579 if (pcata_debug) {
1580 cmn_err(CE_NOTE, "failed drive did not settle:");
1581 pcata_print_sttflag(csx_Get8(softp->handle, AT_STATUS));
1582 }
1583 #endif
1584 return (ATA_DEV_NONE);
1585 }
1586
1587 csx_RepGet16(softp->handle, (ushort_t *)buf, AT_DATA, NBPSCTR >> 1,
1588 DDI_DEV_NO_AUTOINCR);
1589
1590 #ifdef ATA_DEBUG
1591 if (pcata_debug) {
1592 if ((csx_Get8(softp->handle, AT_STATUS) & ATS_ERR) == 0) {
1593 pcata_byte_swap(rpbp->atarp_model,
1594 sizeof (rpbp->atarp_model));
1595 rpbp->atarp_model[sizeof (rpbp->atarp_model)-1] = '\0';
1596 cmn_err(CE_CONT, "succeeded: %s\n",
1597 rpbp->atarp_model);
1598 pcata_byte_swap(rpbp->atarp_model,
1599 sizeof (rpbp->atarp_model));
1600 } else {
1601 cmn_err(CE_CONT, "failed drive drive read error.\n");
1602 }
1603 }
1604 #endif
1605
1606 /*
1607 * wait for the drive to recognize I've read all the data. some
1608 * drives have been observed to take as much as 3msec to finish
1609 * sending the data; allow 5 msec just in case.
1610 */
1611 if (pcata_wait1(AT_ALTSTATUS, ATS_DRDY, ATS_BSY | ATS_DRQ, 500, softp))
1612 return (ATA_DEV_NONE);
1613
1614 if (!CARD_PRESENT_VALID(softp))
1615 return (ATA_DEV_NONE);
1616
1617 if (csx_Get8(softp->handle, AT_ALTSTATUS) & ATS_ERR)
1618 return (ATA_DEV_NONE);
1619
1620 return (ATA_DEV_DISK);
1621 }
1622
1623
1624 /*
1625 * Drive set params command.
1626 */
1627 static int
pcata_setpar(int drive,int heads,int sectors,ata_soft_t * softp)1628 pcata_setpar(int drive, int heads, int sectors, ata_soft_t *softp)
1629 {
1630
1631 #ifdef ATA_DEBUG
1632 if (pcata_debug & DINIT)
1633 cmn_err(CE_CONT, "_setpar status=0x%x drive=%d heads=%d\n",
1634 csx_Get8(softp->handle, AT_STATUS), drive, heads);
1635 #endif
1636 if (!CARD_PRESENT_VALID(softp))
1637 return (DDI_FAILURE);
1638
1639 if (pcata_wait(AT_ALTSTATUS, ATS_DRDY, ATS_BSY, softp))
1640 return (DDI_FAILURE);
1641
1642 pcata_wait_complete(softp);
1643
1644 PCIDE_OUTB(softp->handle, AT_DRVHD, (heads - 1) |
1645 (drive == 0 ? ATDH_DRIVE0 : ATDH_DRIVE1));
1646 PCIDE_OUTB(softp->handle, AT_COUNT, sectors);
1647
1648 mutex_enter(&softp->hi_mutex);
1649 softp->intr_pending++;
1650 csx_Put8(softp->handle, AT_CMD, ATC_SETPARAM);
1651 mutex_exit(&softp->hi_mutex);
1652
1653 if (pcata_wait(AT_ALTSTATUS, 0, ATS_BSY, softp))
1654 return (DDI_FAILURE);
1655 return (DDI_SUCCESS);
1656 }
1657
1658 void
pcata_byte_swap(char * buf,int n)1659 pcata_byte_swap(char *buf, int n)
1660 {
1661 int i;
1662 char c;
1663
1664 n &= ~1;
1665 for (i = 0; i < n; i += 2) {
1666 c = buf[i];
1667 buf[i] = buf[i + 1];
1668 buf[i + 1] = c;
1669 }
1670 }
1671
1672
1673 int
pcata_set_rw_multiple(ata_soft_t * softp,int drive)1674 pcata_set_rw_multiple(ata_soft_t *softp, int drive)
1675 {
1676 int i;
1677 int laststat;
1678 char size;
1679 char accepted_size = -1;
1680
1681 #ifdef ATA_DEBUG
1682 if (pcata_debug & DENT) {
1683 cmn_err(CE_CONT, "_set_rw_multiple (%p, %d)\n",
1684 (void *)softp, drive);
1685 }
1686 #endif
1687
1688 if (!CARD_PRESENT_VALID(softp))
1689 return (DDI_FAILURE);
1690 /*
1691 * Assume we're going to use read/write multiple until the controller
1692 * says it doesn't understand them.
1693 */
1694 softp->ab_rd_cmd[drive] = ATC_RDMULT;
1695 softp->ab_wr_cmd[drive] = ATC_WRMULT;
1696
1697 /*
1698 * set drive number
1699 */
1700 PCIDE_OUTB(softp->handle, AT_DRVHD, drive == 0 ? ATDH_DRIVE0 :
1701 ATDH_DRIVE1);
1702
1703 for (size = 32; size > 0 && accepted_size == -1 &&
1704 CARD_PRESENT_VALID(softp); size >>= 1) {
1705
1706 if (pcata_wait(AT_ALTSTATUS, ATS_DRDY, ATS_BSY, softp))
1707 return (DDI_FAILURE);
1708
1709 pcata_wait_complete(softp);
1710
1711 /*
1712 * send the command
1713 */
1714 PCIDE_OUTB(softp->handle, AT_COUNT, size);
1715
1716 mutex_enter(&softp->hi_mutex);
1717 softp->intr_pending++;
1718 csx_Put8(softp->handle, AT_CMD, ATC_SETMULT);
1719 mutex_exit(&softp->hi_mutex);
1720
1721 if (pcata_wait(AT_ALTSTATUS, 0, ATS_BSY, softp))
1722 /*
1723 * there should have been a drive here but it
1724 * didn't respond properly. It stayed BUSY.
1725 * complete failure!
1726 */
1727 return (DDI_FAILURE);
1728 /*
1729 * Wait for DRDY or error status
1730 */
1731 for (i = 0; i < ATA_LOOP_CNT && CARD_PRESENT_VALID(softp);
1732 i++) {
1733 if (((laststat = csx_Get8(softp->handle, AT_ALTSTATUS))
1734 & (ATS_DRDY | ATS_ERR)) != 0)
1735 break;
1736 drv_usecwait(10);
1737 }
1738 if (i == ATA_LOOP_CNT)
1739 /*
1740 * Didn't get ready OR error... complete failure!
1741 * there should have been a drive here but it
1742 * didn't respond properly. It didn't set ERR or DRQ.
1743 */
1744 return (DDI_FAILURE);
1745
1746 /*
1747 * See if DRQ or error
1748 */
1749 if (laststat & ATS_ERR) {
1750 /*
1751 * there should have been a drive here but it
1752 * didn't respond properly. There was an error.
1753 * Try the next value.
1754 */
1755 continue;
1756 }
1757 /*
1758 * Got ready.. use the value that worked.
1759 */
1760 accepted_size = size;
1761 }
1762 if (accepted_size == -1) {
1763 /*
1764 * None of the values worked...
1765 * the controller responded correctly though so it probably
1766 * doesn't support the read/write multiple commands.
1767 */
1768
1769 #ifdef ATA_DEBUG
1770 if (pcata_debug & DENT) {
1771 cmn_err(CE_CONT, "Using STD R/W cmds and setting"
1772 "block factor to 1\n");
1773 }
1774 #endif
1775 softp->ab_rd_cmd[drive] = ATC_RDSEC;
1776 softp->ab_wr_cmd[drive] = ATC_WRSEC;
1777 softp->ab_block_factor[drive] = 1;
1778 softp->ab_max_transfer = 1;
1779 return (DDI_SUCCESS);
1780 }
1781 if (accepted_size == 1) {
1782 /*
1783 * OK... Leave it at 1
1784 */
1785 #ifdef ATA_DEBUG
1786 if (pcata_debug & DENT) {
1787 cmn_err(CE_CONT, "setting block factor to 1\n");
1788 }
1789 #endif
1790 softp->ab_block_factor[drive] = accepted_size;
1791 softp->ab_max_transfer = accepted_size;
1792 return (DDI_SUCCESS);
1793 }
1794 accepted_size >>= 1;
1795 /*
1796 * Allow a user specified block factor to override the system chosen
1797 * value. Only allow the user to reduce the value.
1798 * -1 indicates the user didn't specify anything
1799 */
1800 if ((softp->ab_block_factor[drive] != -1) &&
1801 (softp->ab_block_factor[drive] < accepted_size))
1802 accepted_size = softp->ab_block_factor[drive];
1803
1804 if (pcata_wait(AT_ALTSTATUS, ATS_DRDY, ATS_BSY, softp))
1805 return (DDI_FAILURE);
1806
1807 pcata_wait_complete(softp);
1808
1809 PCIDE_OUTB(softp->handle, AT_COUNT, accepted_size);
1810
1811 mutex_enter(&softp->hi_mutex);
1812 softp->intr_pending++;
1813 csx_Put8(softp->handle, AT_CMD, ATC_SETMULT);
1814 mutex_exit(&softp->hi_mutex);
1815
1816 if (pcata_wait(AT_ALTSTATUS, 0, ATS_BSY, softp))
1817 /*
1818 * there should have been a drive here but it
1819 * didn't respond properly. It stayed BUSY.
1820 */
1821 return (DDI_FAILURE);
1822
1823 #ifdef ATA_DEBUG
1824 if (pcata_debug & DENT) {
1825 cmn_err(CE_CONT, "setting block factor for drive %d to %d\n",
1826 drive, accepted_size);
1827 }
1828 #endif
1829
1830 softp->ab_block_factor[drive] = accepted_size;
1831 return (DDI_SUCCESS);
1832 }
1833
1834 static int
pcata_dump(dev_t dev,caddr_t addr,daddr_t blkno,int nblk)1835 pcata_dump(dev_t dev, caddr_t addr, daddr_t blkno, int nblk)
1836 {
1837 ata_soft_t *softp;
1838 buf_t *bp;
1839 void *instance;
1840
1841
1842 if (pcata_getinfo(NULL, DDI_INFO_DEVT2INSTANCE, (void *)dev,
1843 &instance) != DDI_SUCCESS)
1844 return (ENODEV);
1845
1846 softp = ddi_get_soft_state(pcata_soft, (int)(uintptr_t)instance);
1847 if (!softp) {
1848 return (ENXIO);
1849 }
1850
1851 if (!CARD_PRESENT_VALID(softp))
1852 return (ENODEV);
1853
1854 bp = softp->crashbuf;
1855 bp->b_un.b_addr = addr;
1856 bp->b_edev = dev;
1857 bp->b_dev = cmpdev(dev);
1858 bp->b_bcount = nblk * DEV_BSIZE;
1859 bp->b_flags |= B_WRITE | B_PHYS;
1860 bp->b_blkno = blkno;
1861 bp->b_private = 0;
1862
1863 /*
1864 * If pcata_strategy() encounters an exception, or card_removal
1865 * is called, before this is complete, it is possible that
1866 * biodone will be called but the buffer (bp) wont
1867 * be released unless B_ASYNC flag is set. So
1868 * don't set B_ASYNC flag unless you mean it.
1869 */
1870 (void) pcata_strategy(bp);
1871 if (bp->b_error)
1872 return (bp->b_error);
1873
1874 for (;;) {
1875 if (!CARD_PRESENT_VALID(softp))
1876 return (ENODEV);
1877 if (bp->b_flags & B_DONE) {
1878 if (bp->b_flags & B_ERROR)
1879 return (bp->b_error);
1880 else
1881 return (0);
1882 }
1883 drv_usecwait(1000);
1884 }
1885 }
1886
1887 /* ddi print */
1888 static int
pcata_print(dev_t dev,char * str)1889 pcata_print(dev_t dev, char *str)
1890 {
1891 void *instance;
1892 ata_soft_t *softp;
1893
1894
1895 /* get instance number */
1896 if (pcata_getinfo(NULL, DDI_INFO_DEVT2INSTANCE, (void *)dev,
1897 &instance) != DDI_SUCCESS) {
1898 cmn_err(CE_CONT, "_print: pcata_getinfo"
1899 "return ENODEV\n");
1900 return (ENODEV);
1901 }
1902
1903 if (!(softp = ddi_get_soft_state(pcata_soft,
1904 (int)(uintptr_t)instance))) {
1905 return (ENXIO);
1906 }
1907
1908 cmn_err(CE_NOTE, "_print: socket %d %s", softp->sn, str);
1909 return (0);
1910
1911 }
1912
1913 static int
pcata_rdrw(dev_t dev,struct uio * uio,int flag)1914 pcata_rdrw(dev_t dev, struct uio *uio, int flag)
1915 {
1916 return (physio(pcata_strategy, (buf_t *)0, dev, flag, pcata_min, uio));
1917 }
1918
1919
1920
1921 /* ARGSUSED2 */
1922 static int
pcata_read(dev_t dev,struct uio * uio,cred_t * cred_p)1923 pcata_read(dev_t dev, struct uio *uio, cred_t *cred_p)
1924 {
1925 return (pcata_rdrw(dev, uio, B_READ));
1926 }
1927
1928
1929
1930 /* ARGSUSED2 */
1931 static int
pcata_write(dev_t dev,struct uio * uio,cred_t * cred_p)1932 pcata_write(dev_t dev, struct uio *uio, cred_t *cred_p)
1933 {
1934 return (pcata_rdrw(dev, uio, B_WRITE));
1935 }
1936
1937
1938 void
pcata_min(buf_t * bp)1939 pcata_min(buf_t *bp)
1940 {
1941 ata_soft_t *softp;
1942 void *instance;
1943
1944 if (pcata_getinfo(NULL, DDI_INFO_DEVT2INSTANCE, (void *)bp->b_edev,
1945 &instance) != DDI_SUCCESS)
1946 cmn_err(CE_CONT, "Error in pcata_min\n");
1947
1948 softp = ddi_get_soft_state(pcata_soft, (int)(uintptr_t)instance);
1949
1950 if ((ROUNDUP(bp->b_bcount, NBPSCTR) >> SCTRSHFT) >
1951 softp->ab_max_transfer)
1952
1953 bp->b_bcount = softp->ab_max_transfer << SCTRSHFT;
1954 }
1955
1956 static void
pcata_iosetup(ata_unit_t * unitp,struct ata_cmpkt * pktp)1957 pcata_iosetup(ata_unit_t *unitp, struct ata_cmpkt *pktp)
1958 {
1959 uint32_t sec_count;
1960
1961 #ifdef ATA_DEBUG
1962 if (pcata_debug & DENT) {
1963 cmn_err(CE_CONT, "_iosetup (%p, %p)\n",
1964 (void *)unitp, (void *)pktp);
1965 }
1966 #endif
1967
1968 /* check for error retry */
1969 if (pktp->ac_flags & CFLAG_ERROR) {
1970 pktp->ac_bytes_per_block = NBPSCTR;
1971 sec_count = 1;
1972 } else {
1973 /*
1974 * Limit requetst to ab_max_transfer sectors.
1975 * The value is specified by the user in the
1976 * max_transfer property. It must be in the range 1 to 256.
1977 * When max_transfer is 0x100 it is bigger than 8 bits.
1978 * The spec says 0 represents 256 so it should be OK.
1979 */
1980 sec_count = min((pktp->cp_bytexfer >> SCTRSHFT),
1981 unitp->a_blkp->ab_max_transfer);
1982 }
1983 pktp->ac_v_addr = pktp->ac_start_v_addr;
1984 pktp->cp_resid = pktp->cp_bytexfer;
1985 pktp->cp_bytexfer = sec_count << SCTRSHFT;
1986
1987 #ifdef ATA_DEBUG
1988 if (pcata_debug & DIO) {
1989 cmn_err(CE_CONT,
1990 "_iosetup: asking for start 0x%lx count 0x%x\n",
1991 pktp->cp_srtsec, pktp->cp_bytexfer >> SCTRSHFT);
1992 }
1993 #endif
1994 /*
1995 * setup the task file registers
1996 */
1997
1998 if (pktp->cp_passthru) {
1999 switch (((struct dadkio_rwcmd *)(pktp->cp_passthru))->cmd) {
2000 case DADKIO_RWCMD_READ:
2001 pktp->ac_cmd = unitp->au_rd_cmd;
2002 pktp->ac_direction = AT_IN;
2003 break;
2004 case DADKIO_RWCMD_WRITE:
2005 pktp->ac_cmd = unitp->au_wr_cmd;
2006 pktp->ac_direction = AT_OUT;
2007 break;
2008 }
2009 } else {
2010 switch (pktp->ac_cdb) {
2011 case DCMD_READ:
2012 case DCMD_WRITE:
2013 case DCMD_RECAL:
2014 case DCMD_SEEK:
2015 case DCMD_RDVER:
2016 switch (pktp->ac_cdb) {
2017 case DCMD_READ:
2018 pktp->ac_cmd = unitp->au_rd_cmd;
2019 pktp->ac_direction = AT_IN;
2020 break;
2021 case DCMD_WRITE:
2022 pktp->ac_cmd = unitp->au_wr_cmd;
2023 pktp->ac_direction = AT_OUT;
2024 break;
2025 case DCMD_RECAL:
2026 pktp->ac_cmd = ATC_RECAL;
2027 pktp->ac_direction = AT_NO_DATA;
2028 break;
2029 case DCMD_SEEK:
2030 pktp->ac_cmd = ATC_SEEK;
2031 pktp->ac_direction = AT_NO_DATA;
2032 break;
2033 case DCMD_RDVER:
2034 pktp->ac_cmd = ATC_RDVER;
2035 pktp->ac_direction = AT_NO_DATA;
2036 break;
2037 }
2038 break;
2039 default:
2040 cmn_err(CE_CONT, "_iosetup: "
2041 "unrecognized cmd 0x%x\n",
2042 pktp->ac_cdb);
2043 break;
2044 }
2045 }
2046 }
2047
2048
2049 /* ARGSUSED */
2050 int
pcata_spinup(ata_soft_t * softp,int slot)2051 pcata_spinup(ata_soft_t *softp, int slot)
2052 {
2053
2054 if (!(CARD_PRESENT_VALID(softp)))
2055 return (DDI_FAILURE);
2056
2057 if (pcata_wait(AT_ALTSTATUS, ATS_DRDY, ATS_BSY, softp))
2058 return (DDI_FAILURE);
2059
2060 pcata_wait_complete(softp);
2061
2062 /* spin up the drive */
2063 PCIDE_OUTB(softp->handle, AT_DRVHD, ATDH_DRIVE0);
2064
2065 mutex_enter(&softp->hi_mutex);
2066 softp->intr_pending++;
2067 csx_Put8(softp->handle, AT_CMD, ATC_IDLE_IMMED);
2068 mutex_exit(&softp->hi_mutex);
2069
2070 if (pcata_wait(AT_ALTSTATUS,
2071 (ATS_DRDY | ATS_DSC), (ATS_BSY | ATS_ERR), softp)) {
2072 #ifdef ATA_DEBUG
2073 cmn_err(CE_NOTE, "TIMEOUT SPINNING UP: ");
2074 pcata_print_sttflag(csx_Get8(softp->handle, AT_ALTSTATUS));
2075 #endif
2076 return (DDI_FAILURE);
2077 }
2078
2079 pcata_wait_complete(softp);
2080
2081 /* set the R/W multiple value decided at first init time */
2082
2083 PCIDE_OUTB(softp->handle, AT_COUNT, softp->ab_block_factor[0]);
2084
2085 mutex_enter(&softp->hi_mutex);
2086 softp->intr_pending++;
2087 csx_Put8(softp->handle, AT_CMD, ATC_SETMULT);
2088 mutex_exit(&softp->hi_mutex);
2089
2090 if (pcata_wait(AT_STATUS, 0, ATS_BSY, softp)) {
2091 /*
2092 * there should have been a drive here but it
2093 * didn't respond properly. It stayed BUSY.
2094 */
2095 #ifdef ATA_DEBUG
2096 cmn_err(CE_NOTE, "Error Spinning up ATA drive (after CPR)\n");
2097 #endif
2098 return (DDI_FAILURE);
2099 }
2100
2101 return (DDI_SUCCESS);
2102 }
2103
2104 #ifdef ATA_DEBUG
2105 static char *
2106 ata_sttvals[] = { "err", "idx", "corr", "drq", "dsc", "dwf", "drdy", "bsy" };
2107
2108
2109 static void
pcata_print_sttflag(int svalue)2110 pcata_print_sttflag(int svalue)
2111 {
2112 int i;
2113 char buf[80];
2114
2115 (void) sprintf(buf, "_sttflag = 0x%x [ ", svalue);
2116
2117 for (i = 7; i >= 0; i--, svalue <<= 1) {
2118 if (svalue & 0x80) {
2119 (void) strcat(buf, ata_sttvals[i]);
2120 (void) strcat(buf, " ");
2121 }
2122 }
2123 cmn_err(CE_CONT, "%s ]\n", buf);
2124 }
2125 #endif
2126