Annotation of src/sys/dev/ic/wdc.c, Revision 1.15
1.15 ! mycroft 1: /* $NetBSD: wdc.c,v 1.14 1998/01/15 02:23:43 cgd Exp $ */
1.2 bouyer 2:
3: /*
4: * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved.
5: *
6: * DMA and multi-sector PIO handling are derived from code contributed by
7: * Onno van der Linden.
8: *
9: * Atapi support added by Manuel Bouyer.
10: *
1.12 cgd 11: * Bus_space-ified by Christopher G. Demetriou.
12: *
1.2 bouyer 13: * Redistribution and use in source and binary forms, with or without
14: * modification, are permitted provided that the following conditions
15: * are met:
16: * 1. Redistributions of source code must retain the above copyright
17: * notice, this list of conditions and the following disclaimer.
18: * 2. Redistributions in binary form must reproduce the above copyright
19: * notice, this list of conditions and the following disclaimer in the
20: * documentation and/or other materials provided with the distribution.
21: * 3. All advertising materials mentioning features or use of this software
22: * must display the following acknowledgement:
23: * This product includes software developed by Charles M. Hannum.
24: * 4. The name of the author may not be used to endorse or promote products
25: * derived from this software without specific prior written permission.
26: *
27: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
28: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
29: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
31: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
32: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
36: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37: */
38:
1.12 cgd 39: /*
40: * CODE UNTESTED IN THE CURRENT REVISION:
41: * * DMA
42: * * 32-bit data port access.
43: */
44:
1.2 bouyer 45: #include <sys/param.h>
46: #include <sys/systm.h>
47: #include <sys/kernel.h>
48: #include <sys/conf.h>
49: #include <sys/file.h>
50: #include <sys/stat.h>
51: #include <sys/ioctl.h>
52: #include <sys/buf.h>
53: #include <sys/uio.h>
54: #include <sys/malloc.h>
55: #include <sys/device.h>
56: #include <sys/disklabel.h>
57: #include <sys/disk.h>
58: #include <sys/syslog.h>
59: #include <sys/proc.h>
60:
61: #include <vm/vm.h>
62:
63: #include <machine/intr.h>
64: #include <machine/bus.h>
65:
1.12 cgd 66: #include <dev/ic/wdcreg.h>
67: #include <dev/ic/wdcvar.h>
68: #include <dev/ata/wdlink.h>
1.2 bouyer 69: #include "atapibus.h"
1.12 cgd 70: #include "wdc.h"
1.2 bouyer 71:
72: #if NATAPIBUS > 0
73: #include <dev/scsipi/scsipi_all.h>
1.12 cgd 74: #include <dev/scsipi/atapi_all.h>
1.2 bouyer 75: #include <dev/scsipi/atapiconf.h>
76: #endif
77:
78: #define WAITTIME (10 * hz) /* time to wait for a completion */
79: /* this is a lot for hard drives, but not for cdroms */
80: #define RECOVERYTIME hz/2
81: #define WDCDELAY 100
82: #define WDCNDELAY 100000 /* delay = 100us; so 10s for a controller state change */
83: #if 0
84: /* If you enable this, it will report any delays more than 100us * N long. */
85: #define WDCNDELAY_DEBUG 50
86: #endif
87:
88: #define WDIORETRIES 5 /* number of retries before giving up */
89:
90: #define WDPART(dev) DISKPART(dev)
91:
92: LIST_HEAD(xfer_free_list, wdc_xfer) xfer_free_list;
93:
1.12 cgd 94: int wdc_init_controller __P((struct wdc_softc *,
95: const struct wdc_attachment_data *));
1.2 bouyer 96: void wdcstart __P((struct wdc_softc *));
1.12 cgd 97: int wdcreset __P((struct wdc_softc *, int));
1.2 bouyer 98: #define VERBOSE 1
99: #define SILENT 0
100: void wdcrestart __P((void *arg));
101: void wdcunwedge __P((struct wdc_softc *));
102: void wdctimeout __P((void *arg));
1.12 cgd 103: int wdccontrol __P((struct wdc_softc*, struct wd_link *));
1.2 bouyer 104: void wdc_free_xfer __P((struct wdc_xfer *));
105: void wdcerror __P((struct wdc_softc*, char *));
106: void wdcbit_bucket __P(( struct wdc_softc *, int));
107: #if NWD > 0
1.12 cgd 108: int wdprint __P((void *, const char *));
109: int wdsetctlr __P((struct wd_link *));
110: int wdc_ata_intr __P((struct wdc_softc *,struct wdc_xfer *));
1.2 bouyer 111: void wdc_ata_start __P((struct wdc_softc *,struct wdc_xfer *));
112: void wdc_ata_done __P((struct wdc_softc *, struct wdc_xfer *));
113: #endif /* NWD > 0 */
114: #if NATAPIBUS > 0
115: void wdc_atapi_minphys __P((struct buf *bp));
116: void wdc_atapi_start __P((struct wdc_softc *,struct wdc_xfer *));
1.12 cgd 117: int wdc_atapi_intr __P((struct wdc_softc *, struct wdc_xfer *));
1.2 bouyer 118: void wdc_atapi_done __P((struct wdc_softc *, struct wdc_xfer *));
1.12 cgd 119: int wdc_atapi_send_command_packet __P((struct scsipi_xfer *sc_xfer));
1.2 bouyer 120: #define MAX_SIZE MAXPHYS /* XXX */
121: #endif
122:
1.8 bouyer 123: #ifdef ATAPI_DEBUG2
1.2 bouyer 124: static int wdc_nxfer;
125: #endif
126:
127: #ifdef WDDEBUG
128: #define WDDEBUG_PRINT(args) printf args
129: #else
130: #define WDDEBUG_PRINT(args)
131: #endif
132:
133: #if NATAPIBUS > 0
134: static struct scsipi_adapter wdc_switch = {
135: wdc_atapi_send_command_packet,
136: wdc_atapi_minphys,
137: 0,
138: 0
139: };
140: #endif
141:
1.12 cgd 142: /*
143: * wdc_init_controller: Does a quick probe/init of the controller.
144: *
145: * Return values:
146: * 0 No controller present (as far as it can tell).
147: * >0 Controller present and seemingly functional.
148: * <0 Controller present, but not working correctly.
149: */
1.2 bouyer 150: int
1.12 cgd 151: wdc_init_controller(wdc, adp)
152: struct wdc_softc *wdc;
153: const struct wdc_attachment_data *adp;
154: {
155: bus_space_tag_t iot;
156: bus_space_handle_t ioh;
1.2 bouyer 157:
1.12 cgd 158: iot = wdc->sc_iot;
159: ioh = wdc->sc_ioh;
1.2 bouyer 160:
1.7 bouyer 161: if (wdcreset(wdc, SILENT) != 0) {
1.2 bouyer 162: /*
1.12 cgd 163: * If the reset failed, there is no master. test for
164: * ATAPI signature on the slave device. If no ATAPI
165: * slave, wait 5s and retry a reset.
1.2 bouyer 166: */
1.12 cgd 167: bus_space_write_1(iot, ioh, wd_sdh, WDSD_IBM | 0x10); /*slave*/
168: if (bus_space_read_1(iot, ioh, wd_cyl_lo) == 0x14 &&
169: bus_space_read_1(iot, ioh, wd_cyl_hi) == 0xeb) {
1.7 bouyer 170: wdc->sc_flags |= WDCF_ONESLAVE;
171: goto drivefound;
172: } else {
1.2 bouyer 173: delay(500000);
174: if (wdcreset(wdc, SILENT) != 0)
1.12 cgd 175: return (0);
1.2 bouyer 176: }
1.7 bouyer 177: }
1.9 fvdl 178: delay(1000);
1.12 cgd 179:
180: /*
181: * Reset succeeded. Test for ATAPI signature on both master
182: * and slave.
183: */
184: if (bus_space_read_1(iot, ioh, wd_cyl_lo) == 0x14 &&
185: bus_space_read_1(iot, ioh, wd_cyl_hi) == 0xeb)
1.7 bouyer 186: goto drivefound;
1.12 cgd 187: bus_space_write_1(iot, ioh, wd_sdh, WDSD_IBM | 0x10);
188: if (bus_space_read_1(iot, ioh, wd_cyl_lo) == 0x14 &&
189: bus_space_read_1(iot, ioh, wd_cyl_hi) == 0xeb) {
1.2 bouyer 190: wdc->sc_flags |= WDCF_ONESLAVE;
1.7 bouyer 191: goto drivefound;
1.2 bouyer 192: }
1.12 cgd 193:
194: /*
195: * Test non-ATAPI registers. Error register not writable,
196: * but all of cyllo is.
197: */
198: bus_space_write_1(iot, ioh, wd_sdh, WDSD_IBM);
199: bus_space_write_1(iot, ioh, wd_error, 0x58);
200: bus_space_write_1(iot, ioh, wd_cyl_lo, 0xa5);
201: if (bus_space_read_1(iot, ioh, wd_error) != 0x58 &&
202: bus_space_read_1(iot, ioh, wd_cyl_lo) == 0xa5)
203: goto drivefound;
204:
205: /*
206: * If no drives found, but the resets succeeded, we claim to
207: * have the controller, at least.
208: */
209: return (1);
210:
1.7 bouyer 211: drivefound:
1.2 bouyer 212: /* Select drive 0 or ATAPI slave device */
213: if (wdc->sc_flags & WDCF_ONESLAVE)
1.12 cgd 214: bus_space_write_1(iot, ioh, wd_sdh, WDSD_IBM | 0x10);
1.2 bouyer 215: else
1.12 cgd 216: bus_space_write_1(iot, ioh, wd_sdh, WDSD_IBM);
1.2 bouyer 217:
218: /* Wait for controller to become ready. */
219: if (wait_for_unbusy(wdc) < 0)
1.12 cgd 220: return (-1);
1.2 bouyer 221:
222: /* Start drive diagnostics. */
1.12 cgd 223: bus_space_write_1(iot, ioh, wd_command, WDCC_DIAGNOSE);
1.2 bouyer 224:
225: /* Wait for command to complete. */
226: if (wait_for_unbusy(wdc) < 0)
1.12 cgd 227: return (-1);
1.2 bouyer 228:
229: return 1;
230: }
231:
1.12 cgd 232: int
233: wdcprobe(adp)
234: const struct wdc_attachment_data *adp;
235: {
236: struct wdc_softc _wdc, *wdc = &_wdc; /* XXX EWWWWW! */
237: int rv;
238:
239: bzero(wdc, sizeof *wdc);
240: strcpy(wdc->sc_dev.dv_xname, "wdcprobe");
241: wdc->sc_adp = adp;
242:
243: rv = wdc_init_controller(wdc, adp);
244:
245: if (rv < 0)
246: rv = 1;
247: return (rv);
248: }
249:
1.2 bouyer 250: void
1.12 cgd 251: wdcattach(wdc, adp)
252: struct wdc_softc *wdc;
253: const struct wdc_attachment_data *adp;
1.2 bouyer 254: {
255: #if NWD > 0
256: int drive;
257: #endif
258:
1.12 cgd 259: wdc->sc_adp = adp;
260: if (wdc_init_controller(wdc, adp) <= 0) {
1.15 ! mycroft 261: printf("%s: controller wouldn't initialize properly\n",
! 262: wdc->sc_dev.dv_xname);
1.12 cgd 263: return;
264: }
265:
1.2 bouyer 266: TAILQ_INIT(&wdc->sc_xfer);
267:
1.12 cgd 268: if (wdc->sc_cap & WDC_CAPABILITY_DMA)
269: (*wdc->sc_dma_setup)(wdc->sc_dma_arg);
1.2 bouyer 270:
1.8 bouyer 271: #ifdef ATAPI_DEBUG2
1.2 bouyer 272: wdc_nxfer = 0;
273: #endif
274:
275: #if NATAPIBUS > 0
276: /*
277: * Attach an ATAPI bus, if configured.
278: */
279: wdc->ab_link = malloc(sizeof(struct scsipi_link), M_DEVBUF, M_NOWAIT);
280: if (wdc->ab_link == NULL) {
1.12 cgd 281: printf("%s: can't allocate ATAPI link\n",
282: wdc->sc_dev.dv_xname);
1.2 bouyer 283: return;
284: }
285: bzero(wdc->ab_link,sizeof(struct scsipi_link));
286: wdc->ab_link->type = BUS_ATAPI;
287: wdc->ab_link->openings = 1;
288: wdc->ab_link->scsipi_atapi.type = ATAPI;
289: wdc->ab_link->scsipi_atapi.channel = 0;
290: wdc->ab_link->adapter_softc = (caddr_t)wdc;
291: wdc->ab_link->adapter = &wdc_switch;
1.12 cgd 292: (void)config_found(&wdc->sc_dev, (void *)wdc->ab_link, NULL);
1.2 bouyer 293: #endif /* NATAPIBUS > 0 */
294: #if NWD > 0
295: /*
296: * Attach standard IDE/ESDI/etc. disks to the controller.
297: */
298: for (drive = 0; drive < 2; drive++) {
1.4 bouyer 299: /* if a disk is already present, skip */
300: if ((wdc->sc_drives_mask & (1 << drive)) != 0) {
301: continue;
302: }
1.2 bouyer 303: /* controller active while autoconf */
304: wdc->sc_flags |= WDCF_ACTIVE;
305:
306: if (wdccommandshort(wdc, drive, WDCC_RECAL) != 0 ||
307: wait_for_ready(wdc) != 0) {
308: wdc->d_link[drive] = NULL;
309: wdc->sc_flags &= ~WDCF_ACTIVE;
310: } else {
311: wdc->sc_flags &= ~WDCF_ACTIVE;
312: wdc->d_link[drive] = malloc(sizeof(struct wd_link),
313: M_DEVBUF, M_NOWAIT);
314: if (wdc->d_link[drive] == NULL) {
315: printf("%s: can't allocate link for drive %d\n",
1.12 cgd 316: wdc->sc_dev.dv_xname, drive);
1.2 bouyer 317: continue;
318: }
319: bzero(wdc->d_link[drive],sizeof(struct wd_link));
320: wdc->d_link[drive]->type = ATA;
321: wdc->d_link[drive]->wdc_softc =(caddr_t) wdc;
322: wdc->d_link[drive]->drive = drive;
1.12 cgd 323: if (wdc->sc_cap & WDC_CAPABILITY_DMA)
1.2 bouyer 324: wdc->d_link[drive]->sc_mode = WDM_DMA;
325: else
326: wdc->d_link[drive]->sc_mode = 0;
327:
1.4 bouyer 328: wdc->sc_drives_mask |= (1 << drive);
1.12 cgd 329: (void)config_found(&wdc->sc_dev,
330: (void *)wdc->d_link[drive], wdprint);
1.2 bouyer 331: }
332: }
333: #endif /* NWD > 0 */
1.10 mikel 334: /* explicitly select an existing drive, to avoid spurious interrupts */
1.7 bouyer 335: if (wdc->sc_flags & WDCF_ONESLAVE)
1.12 cgd 336: bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_sdh, WDSD_IBM | 0x10); /* slave */
1.7 bouyer 337: else
1.12 cgd 338: bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_sdh, WDSD_IBM); /* master */
1.8 bouyer 339: /*
340: * Reset controller. The probe, with some combinations of ATA/ATAPI
1.10 mikel 341: * devices keep it in a mostly working, but strange state (with busy
1.8 bouyer 342: * led on)
343: */
344: wdcreset(wdc, VERBOSE);
1.2 bouyer 345: }
346:
347: /*
348: * Start I/O on a controller. This does the calculation, and starts a read or
349: * write operation. Called to from wdstart() to start a transfer, from
350: * wdcintr() to continue a multi-sector transfer or start the next transfer, or
351: * wdcrestart() after recovering from an error.
352: */
353: void
354: wdcstart(wdc)
355: struct wdc_softc *wdc;
356: {
357: struct wdc_xfer *xfer;
358:
359: if ((wdc->sc_flags & WDCF_ACTIVE) != 0 ) {
360: WDDEBUG_PRINT(("wdcstart: already active\n"));
361: return; /* controller aleady active */
362: }
363: #ifdef DIAGNOSTIC
364: if ((wdc->sc_flags & WDCF_IRQ_WAIT) != 0)
365: panic("wdcstart: controller waiting for irq\n");
366: #endif
367: /* is there a xfer ? */
368: xfer = wdc->sc_xfer.tqh_first;
369: if (xfer == NULL) {
370: #ifdef ATAPI_DEBUG2
371: printf("wdcstart: null xfer\n");
372: #endif
373: /*
374: * XXX
375: * This is a kluge. See comments in wd_get_parms().
376: */
377: if ((wdc->sc_flags & WDCF_WANTED) != 0) {
1.8 bouyer 378: #ifdef ATAPI_DEBUG2
1.2 bouyer 379: printf("WDCF_WANTED\n");
380: #endif
381: wdc->sc_flags &= ~WDCF_WANTED;
382: wakeup(wdc);
383: }
384: return;
385: }
386: wdc->sc_flags |= WDCF_ACTIVE;
387: #ifdef ATAPI_DEBUG2
388: printf("wdcstart: drive %d\n", (int)xfer->d_link->drive);
389: #endif
1.12 cgd 390: bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_sdh, WDSD_IBM | xfer->d_link->drive << 4);
1.2 bouyer 391: #if NATAPIBUS > 0 && NWD > 0
392: if (xfer->c_flags & C_ATAPI) {
393: #ifdef ATAPI_DEBUG_WDC
394: printf("wdcstart: atapi\n");
395: #endif
396: wdc_atapi_start(wdc,xfer);
397: } else
398: wdc_ata_start(wdc,xfer);
399: #else /* NATAPIBUS > 0 && NWD > 0 */
400: #if NATAPIBUS > 0
401: #ifdef ATAPI_DEBUG_WDC
402: printf("wdcstart: atapi\n");
403: #endif
404: wdc_atapi_start(wdc,xfer);
405: #endif /* NATAPIBUS > */
406: #if NWD > 0
407: wdc_ata_start(wdc,xfer);
408: #endif /* NWD > 0 */
409: #endif /* NATAPIBUS > 0 && NWD > 0 */
410: }
411:
412: #if NWD > 0
413: int
414: wdprint(aux, wdc)
415: void *aux;
416: const char *wdc;
417: {
418: struct wd_link *d_link = aux;
419:
420: if (!wdc)
421: printf(" drive %d", d_link->drive);
422: return QUIET;
423: }
424:
425: void
426: wdc_ata_start(wdc, xfer)
427: struct wdc_softc *wdc;
428: struct wdc_xfer *xfer;
429: {
430: struct wd_link *d_link;
431: struct buf *bp = xfer->c_bp;
432: int nblks;
433:
434: d_link=xfer->d_link;
435:
436: if (wdc->sc_errors >= WDIORETRIES) {
437: wderror(d_link, bp, "wdc_ata_start hard error");
438: xfer->c_flags |= C_ERROR;
439: wdc_ata_done(wdc, xfer);
440: return;
441: }
442:
443: /* Do control operations specially. */
444: if (d_link->sc_state < READY) {
445: /*
446: * Actually, we want to be careful not to mess with the control
447: * state if the device is currently busy, but we can assume
448: * that we never get to this point if that's the case.
449: */
450: if (wdccontrol(wdc, d_link) == 0) {
451: /* The drive is busy. Wait. */
452: return;
453: }
454: }
455:
456: /*
457: * WDCF_ERROR is set by wdcunwedge() and wdcintr() when an error is
458: * encountered. If we are in multi-sector mode, then we switch to
459: * single-sector mode and retry the operation from the start.
460: */
461: if (wdc->sc_flags & WDCF_ERROR) {
462: wdc->sc_flags &= ~WDCF_ERROR;
463: if ((wdc->sc_flags & WDCF_SINGLE) == 0) {
464: wdc->sc_flags |= WDCF_SINGLE;
465: xfer->c_skip = 0;
466: }
467: }
468:
469:
470: /* When starting a transfer... */
471: if (xfer->c_skip == 0) {
472: daddr_t blkno;
473:
474: WDDEBUG_PRINT(("\n%s: wdc_ata_start %s %d@%d; map ",
475: wdc->sc_dev.dv_xname,
476: (xfer->c_flags & B_READ) ? "read" : "write",
477: xfer->c_bcount, xfer->c_blkno));
478:
479: blkno = xfer->c_blkno+xfer->c_p_offset;
480: xfer->c_blkno = blkno / (d_link->sc_lp->d_secsize / DEV_BSIZE);
481: } else {
482: WDDEBUG_PRINT((" %d)%x", xfer->c_skip,
1.12 cgd 483: bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_altsts)));
1.2 bouyer 484: }
485:
486: /*
487: * When starting a multi-sector transfer, or doing single-sector
488: * transfers...
489: */
490: if (xfer->c_skip == 0 || (wdc->sc_flags & WDCF_SINGLE) != 0 ||
491: d_link->sc_mode == WDM_DMA) {
492: daddr_t blkno = xfer->c_blkno;
493: long cylin, head, sector;
494: int command;
495:
496: if ((wdc->sc_flags & WDCF_SINGLE) != 0)
497: nblks = 1;
498: else if (d_link->sc_mode != WDM_DMA)
499: nblks = xfer->c_bcount / d_link->sc_lp->d_secsize;
500: else
501: nblks =
502: min(xfer->c_bcount / d_link->sc_lp->d_secsize, 8);
503:
504: /* Check for bad sectors and adjust transfer, if necessary. */
505: if ((d_link->sc_lp->d_flags & D_BADSECT) != 0
506: #ifdef B_FORMAT
507: && (bp->b_flags & B_FORMAT) == 0
508: #endif
509: ) {
510: long blkdiff;
511: int i;
512:
513: for (i = 0;
514: (blkdiff = d_link->sc_badsect[i]) != -1; i++) {
515: blkdiff -= blkno;
516: if (blkdiff < 0)
517: continue;
518: if (blkdiff == 0) {
519: /* Replace current block of transfer. */
520: blkno =
521: d_link->sc_lp->d_secperunit -
522: d_link->sc_lp->d_nsectors - i - 1;
523: }
524: if (blkdiff < nblks) {
525: /* Bad block inside transfer. */
526: wdc->sc_flags |= WDCF_SINGLE;
527: nblks = 1;
528: }
529: break;
530: }
1.10 mikel 531: /* Transfer is okay now. */
1.2 bouyer 532: }
533:
534: if ((d_link->sc_params.wdp_capabilities & WD_CAP_LBA) != 0) {
535: sector = (blkno >> 0) & 0xff;
536: cylin = (blkno >> 8) & 0xffff;
537: head = (blkno >> 24) & 0xf;
538: head |= WDSD_LBA;
539: } else {
540: sector = blkno % d_link->sc_lp->d_nsectors;
541: sector++; /* Sectors begin with 1, not 0. */
542: blkno /= d_link->sc_lp->d_nsectors;
543: head = blkno % d_link->sc_lp->d_ntracks;
544: blkno /= d_link->sc_lp->d_ntracks;
545: cylin = blkno;
546: head |= WDSD_CHS;
547: }
548:
549: if (d_link->sc_mode == WDM_PIOSINGLE ||
550: (wdc->sc_flags & WDCF_SINGLE) != 0)
551: xfer->c_nblks = 1;
552: else if (d_link->sc_mode == WDM_PIOMULTI)
553: xfer->c_nblks = min(nblks, d_link->sc_multiple);
554: else
555: xfer->c_nblks = nblks;
556: xfer->c_nbytes = xfer->c_nblks * d_link->sc_lp->d_secsize;
557:
558: #ifdef B_FORMAT
559: if (bp->b_flags & B_FORMAT) {
560: sector = d_link->sc_lp->d_gap3;
561: nblks = d_link->sc_lp->d_nsectors;
562: command = WDCC_FORMAT;
563: } else
564: #endif
565: switch (d_link->sc_mode) {
566: case WDM_DMA:
567: command = (xfer->c_flags & B_READ) ?
568: WDCC_READDMA : WDCC_WRITEDMA;
569: /* Start the DMA channel. */
1.12 cgd 570: (*wdc->sc_dma_start)(wdc->sc_dma_arg,
571: xfer->databuf + xfer->c_skip, xfer->c_nbytes,
572: xfer->c_flags & B_READ);
1.2 bouyer 573: break;
574:
575: case WDM_PIOMULTI:
576: command = (xfer->c_flags & B_READ) ?
577: WDCC_READMULTI : WDCC_WRITEMULTI;
578: break;
579:
580: case WDM_PIOSINGLE:
581: command = (xfer->c_flags & B_READ) ?
582: WDCC_READ : WDCC_WRITE;
583: break;
584:
585: default:
586: #ifdef DIAGNOSTIC
587: panic("bad wd mode");
588: #endif
589: return;
590: }
591:
592: /* Initiate command! */
593: if (wdccommand(wdc, d_link, command, d_link->drive,
594: cylin, head, sector, nblks) != 0) {
595: wderror(d_link, NULL,
596: "wdc_ata_start: timeout waiting for unbusy");
597: wdcunwedge(wdc);
598: return;
599: }
600:
1.12 cgd 601: WDDEBUG_PRINT(("sector %lu cylin %lu head %lu addr %p sts %x\n",
1.2 bouyer 602: sector, cylin, head, xfer->databuf,
1.12 cgd 603: bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_altsts)));
1.2 bouyer 604:
605: } else if (xfer->c_nblks > 1) {
606: /* The number of blocks in the last stretch may be smaller. */
607: nblks = xfer->c_bcount / d_link->sc_lp->d_secsize;
608: if (xfer->c_nblks > nblks) {
609: xfer->c_nblks = nblks;
610: xfer->c_nbytes = xfer->c_bcount;
611: }
612: }
613:
614: /* If this was a write and not using DMA, push the data. */
615: if (d_link->sc_mode != WDM_DMA &&
616: (xfer->c_flags & (B_READ|B_WRITE)) == B_WRITE) {
617: if (wait_for_drq(wdc) < 0) {
618: wderror(d_link, NULL,
619: "wdc_ata_start: timeout waiting for drq");
620: wdcunwedge(wdc);
621: return;
622: }
623:
1.12 cgd 624: if ((wdc->sc_cap & WDC_CAPABILITY_DATA32) == 0)
625: bus_space_write_multi_2(wdc->sc_iot, wdc->sc_ioh,
626: wd_data, xfer->databuf + xfer->c_skip,
1.2 bouyer 627: xfer->c_nbytes >> 1);
628: else
1.12 cgd 629: bus_space_write_multi_4(wdc->sc_iot, wdc->sc_ioh,
630: wd_data, xfer->databuf + xfer->c_skip,
1.2 bouyer 631: xfer->c_nbytes >> 2);
632: }
633:
634: wdc->sc_flags |= WDCF_IRQ_WAIT;
635: WDDEBUG_PRINT(("wdc_ata_start: timeout "));
636: timeout(wdctimeout, wdc, WAITTIME);
637: WDDEBUG_PRINT(("done\n"));
638: }
639:
640: int
641: wdc_ata_intr(wdc,xfer)
642: struct wdc_softc *wdc;
643: struct wdc_xfer *xfer;
644: {
645: struct wd_link *d_link;
646:
647: d_link = xfer->d_link;
648:
649: if (wait_for_unbusy(wdc) < 0) {
650: wdcerror(wdc, "wdcintr: timeout waiting for unbusy");
1.5 bouyer 651: return 0;
1.2 bouyer 652: }
653:
1.8 bouyer 654: wdc->sc_flags &= ~WDCF_IRQ_WAIT;
1.2 bouyer 655: untimeout(wdctimeout, wdc);
656:
657: /* Is it not a transfer, but a control operation? */
658: if (d_link->sc_state < READY) {
659: if (wdccontrol(wdc, d_link) == 0) {
660: /* The drive is busy. Wait. */
661: return 1;
662: }
663: WDDEBUG_PRINT(("wdc_ata_start from wdc_ata_intr(open) flags 0x%x\n",
1.12 cgd 664: wdc->sc_flags));
1.2 bouyer 665: wdc_ata_start(wdc,xfer);
666: return 1;
667: }
668:
669: /* Turn off the DMA channel. */
670: if (d_link->sc_mode == WDM_DMA)
1.12 cgd 671: (*wdc->sc_dma_finish)(wdc->sc_dma_arg);
1.2 bouyer 672:
673: /* Have we an error? */
674: if (wdc->sc_status & WDCS_ERR) {
675: #ifdef WDDEBUG
676: wderror(d_link, NULL, "wdc_ata_start");
677: #endif
678: if ((wdc->sc_flags & WDCF_SINGLE) == 0) {
679: wdc->sc_flags |= WDCF_ERROR;
680: goto restart;
681: }
682:
683: #ifdef B_FORMAT
684: if (bp->b_flags & B_FORMAT)
685: goto bad;
686: #endif
687:
688: if (++wdc->sc_errors < WDIORETRIES) {
689: if (wdc->sc_errors == (WDIORETRIES + 1) / 2) {
690: #if 0
691: wderror(wd, NULL, "wedgie");
692: #endif
693: wdcunwedge(wdc);
694: return 1;
695: }
696: goto restart;
697: }
698: wderror(d_link, xfer->c_bp, "wdc_ata_intr hard error");
699:
700: #ifdef B_FORMAT
701: bad:
702: #endif
703: xfer->c_flags |= C_ERROR;
704: goto done;
705: }
706:
707: /* If this was a read and not using DMA, fetch the data. */
708: if (d_link->sc_mode != WDM_DMA &&
709: (xfer->c_flags & (B_READ|B_WRITE)) == B_READ) {
710: if ((wdc->sc_status & (WDCS_DRDY | WDCS_DSC | WDCS_DRQ))
711: != (WDCS_DRDY | WDCS_DSC | WDCS_DRQ)) {
712: wderror(d_link, NULL, "wdcintr: read intr before drq");
713: wdcunwedge(wdc);
714: return 1;
715: }
716:
717: /* Pull in data. */
1.12 cgd 718: if ((wdc->sc_cap & WDC_CAPABILITY_DATA32) == 0)
719: bus_space_read_multi_2(wdc->sc_iot, wdc->sc_ioh,
720: wd_data, xfer->databuf + xfer->c_skip,
721: xfer->c_nbytes >> 1);
1.2 bouyer 722: else
1.12 cgd 723: bus_space_read_multi_4(wdc->sc_iot, wdc->sc_ioh,
724: wd_data, xfer->databuf + xfer->c_skip,
725: xfer->c_nbytes >> 2);
1.2 bouyer 726: }
727:
728: /* If we encountered any abnormalities, flag it as a soft error. */
729: if (wdc->sc_errors > 0 ||
730: (wdc->sc_status & WDCS_CORR) != 0) {
731: wderror(d_link, xfer->c_bp, "soft error (corrected)");
732: wdc->sc_errors = 0;
733: }
734:
735: /* Adjust pointers for the next block, if any. */
736: xfer->c_blkno += xfer->c_nblks;
737: xfer->c_skip += xfer->c_nbytes;
738: xfer->c_bcount -= xfer->c_nbytes;
739:
740: /* See if this transfer is complete. */
741: if (xfer->c_bcount > 0)
742: goto restart;
743:
744: done:
745: /* Done with this transfer, with or without error. */
746: wdc_ata_done(wdc, xfer);
1.5 bouyer 747: return 1;
1.2 bouyer 748:
749: restart:
750: /* Start the next operation */
751: WDDEBUG_PRINT(("wdc_ata_start from wdcintr flags 0x%x\n",
752: wdc->sc_flags));
753: wdc_ata_start(wdc, xfer);
754:
755: return 1;
756: }
757:
758: void
759: wdc_ata_done(wdc, xfer)
760: struct wdc_softc *wdc;
761: struct wdc_xfer *xfer;
762: {
763: struct buf *bp = xfer->c_bp;
764: struct wd_link *d_link = xfer->d_link;
765: int s;
766:
767: WDDEBUG_PRINT(("wdc_ata_done\n"));
768:
769: /* remove this command from xfer queue */
770: s = splbio();
771: TAILQ_REMOVE(&wdc->sc_xfer, xfer, c_xferchain);
772: wdc->sc_flags &= ~(WDCF_SINGLE | WDCF_ERROR | WDCF_ACTIVE);
773: wdc->sc_errors = 0;
774: if (bp) {
775: if (xfer->c_flags & C_ERROR) {
776: bp->b_flags |= B_ERROR;
777: bp->b_error = EIO;
778: }
779: bp->b_resid = xfer->c_bcount;
780: wddone(d_link, bp);
781: biodone(bp);
782: } else {
783: wakeup(xfer->databuf);
784: }
785: xfer->c_skip = 0;
786: wdc_free_xfer(xfer);
787: d_link->openings++;
788: wdstart((void*)d_link->wd_softc);
789: WDDEBUG_PRINT(("wdcstart from wdc_ata_done, flags 0x%x\n",
790: wdc->sc_flags));
791: wdcstart(wdc);
792: splx(s);
793: }
794:
795: /*
796: * Get the drive parameters, if ESDI or ATA, or create fake ones for ST506.
797: */
798: int
799: wdc_get_parms(wdc, d_link)
800: struct wdc_softc * wdc;
801: struct wd_link *d_link;
802: {
803: int i;
804: char tb[DEV_BSIZE];
805: int s, error;
806:
807: /*
808: * XXX
809: * The locking done here, and the length of time this may keep the rest
810: * of the system suspended, is a kluge. This should be rewritten to
811: * set up a transfer and queue it through wdstart(), but it's called
812: * infrequently enough that this isn't a pressing matter.
813: */
814:
815: s = splbio();
816:
817: while ((wdc->sc_flags & WDCF_ACTIVE) != 0) {
818: wdc->sc_flags |= WDCF_WANTED;
819: if ((error = tsleep(wdc, PRIBIO | PCATCH, "wdprm", 0)) != 0) {
820: splx(s);
821: return error;
822: }
823: }
824:
825: wdc->sc_flags |= WDCF_ACTIVE;
826:
827: if (wdccommandshort(wdc, d_link->drive, WDCC_IDENTIFY) != 0 ||
828: wait_for_drq(wdc) != 0) {
829: /*
830: * We `know' there's a drive here; just assume it's old.
831: * This geometry is only used to read the MBR and print a
832: * (false) attach message.
833: */
834: strncpy(d_link->sc_lp->d_typename, "ST506",
835: sizeof d_link->sc_lp->d_typename);
836: d_link->sc_lp->d_type = DTYPE_ST506;
837:
838: strncpy(d_link->sc_params.wdp_model, "unknown",
839: sizeof d_link->sc_params.wdp_model);
840: d_link->sc_params.wdp_config = WD_CFG_FIXED;
841: d_link->sc_params.wdp_cylinders = 1024;
842: d_link->sc_params.wdp_heads = 8;
843: d_link->sc_params.wdp_sectors = 17;
844: d_link->sc_params.wdp_maxmulti = 0;
845: d_link->sc_params.wdp_usedmovsd = 0;
846: d_link->sc_params.wdp_capabilities = 0;
847: } else {
848: strncpy(d_link->sc_lp->d_typename, "ESDI/IDE",
849: sizeof d_link->sc_lp->d_typename);
850: d_link->sc_lp->d_type = DTYPE_ESDI;
851:
852: /* Read in parameter block. */
1.12 cgd 853: bus_space_read_multi_2(wdc->sc_iot, wdc->sc_ioh, wd_data,
854: (u_int16_t *)tb, sizeof(tb) >> 1);
1.2 bouyer 855: bcopy(tb, &d_link->sc_params, sizeof(struct wdparams));
856:
857: /* Shuffle string byte order. */
858: for (i = 0; i < sizeof(d_link->sc_params.wdp_model); i += 2) {
859: u_short *p;
860: p = (u_short *)(d_link->sc_params.wdp_model + i);
861: *p = ntohs(*p);
862: }
863: }
864:
865: /* Clear any leftover interrupt. */
1.12 cgd 866: (void) bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_status);
1.2 bouyer 867:
868: /* Restart the queue. */
869: WDDEBUG_PRINT(("wdcstart from wdc_get_parms flags 0x%x\n",
870: wdc->sc_flags));
871: wdc->sc_flags &= ~WDCF_ACTIVE;
872: wdcstart(wdc);
873:
874: splx(s);
875: return 0;
876: }
877:
878: /*
879: * Implement operations needed before read/write.
880: * Returns 0 if operation still in progress, 1 if completed.
881: */
882: int
883: wdccontrol(wdc, d_link)
884: struct wdc_softc *wdc;
885: struct wd_link *d_link;
886: {
887: WDDEBUG_PRINT(("wdccontrol\n"));
888:
889: switch (d_link->sc_state) {
890: case RECAL: /* Set SDH, step rate, do recal. */
891: if (wdccommandshort(wdc, d_link->drive, WDCC_RECAL) != 0) {
892: wderror(d_link, NULL, "wdccontrol: recal failed (1)");
893: goto bad;
894: }
895: d_link->sc_state = RECAL_WAIT;
896: break;
897:
898: case RECAL_WAIT:
899: if (wdc->sc_status & WDCS_ERR) {
900: wderror(d_link, NULL, "wdccontrol: recal failed (2)");
901: goto bad;
902: }
903: /* fall through */
904:
905: case GEOMETRY:
906: if ((d_link->sc_params.wdp_capabilities & WD_CAP_LBA) != 0)
907: goto multimode;
908: if (wdsetctlr(d_link) != 0) {
909: /* Already printed a message. */
910: goto bad;
911: }
912: d_link->sc_state = GEOMETRY_WAIT;
913: break;
914:
915: case GEOMETRY_WAIT:
916: if (wdc->sc_status & WDCS_ERR) {
917: wderror(d_link, NULL, "wdccontrol: geometry failed");
918: goto bad;
919: }
920: /* fall through */
921:
922: case MULTIMODE:
923: multimode:
924: if (d_link->sc_mode != WDM_PIOMULTI)
925: goto ready;
1.12 cgd 926: bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_seccnt, d_link->sc_multiple);
1.2 bouyer 927: if (wdccommandshort(wdc, d_link->drive,
928: WDCC_SETMULTI) != 0) {
929: wderror(d_link, NULL,
930: "wdccontrol: setmulti failed (1)");
931: goto bad;
932: }
933: d_link->sc_state = MULTIMODE_WAIT;
934: break;
935:
936: case MULTIMODE_WAIT:
937: if (wdc->sc_status & WDCS_ERR) {
938: wderror(d_link, NULL,
939: "wdccontrol: setmulti failed (2)");
940: goto bad;
941: }
942: /* fall through */
943:
944: case READY:
945: ready:
946: wdc->sc_errors = 0;
947: d_link->sc_state = READY;
948: /*
949: * The rest of the initialization can be done by normal means.
950: */
951: return 1;
952:
953: bad:
954: wdcunwedge(wdc);
955: return 0;
956: }
957:
958: wdc->sc_flags |= WDCF_IRQ_WAIT;
959: timeout(wdctimeout, wdc, WAITTIME);
960: return 0;
961: }
962:
963: #endif /* NWD > 0 */
964:
965:
966: /*
967: * Interrupt routine for the controller. Acknowledge the interrupt, check for
968: * errors on the current operation, mark it done if necessary, and start the
969: * next request. Also check for a partially done transfer, and continue with
970: * the next chunk if so.
971: */
972: int
973: wdcintr(arg)
974: void *arg;
975: {
976: struct wdc_softc *wdc = arg;
977: struct wdc_xfer *xfer;
978:
979: if ((wdc->sc_flags & WDCF_IRQ_WAIT) == 0) {
980: /* Clear the pending interrupt and abort. */
1.12 cgd 981: u_char s = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_status);
1.2 bouyer 982:
983: #ifdef ATAPI_DEBUG_WDC
1.12 cgd 984: u_char e = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_error);
985: u_char i = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_seccnt);
1.2 bouyer 986: printf("wdcintr: inactive controller, "
987: "punting st=%02x er=%02x irr=%02x\n", s, e, i);
988: #else
1.12 cgd 989: bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_error);
990: bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_seccnt);
1.2 bouyer 991: #endif
992:
993: if (s & WDCS_DRQ) {
1.12 cgd 994: int len = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_cyl_lo) +
995: 256 * bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_cyl_hi);
1.2 bouyer 996: #ifdef ATAPI_DEBUG_WDC
997: printf ("wdcintr: clearing up %d bytes\n", len);
998: #endif
999: wdcbit_bucket (wdc, len);
1000: }
1001: return 0;
1002: }
1003:
1004: WDDEBUG_PRINT(("wdcintr\n"));
1005:
1006: xfer = wdc->sc_xfer.tqh_first;
1007: #if NATAPIBUS > 0 && NWD > 0
1008: if (xfer->c_flags & C_ATAPI) {
1.5 bouyer 1009: return wdc_atapi_intr(wdc,xfer);
1.2 bouyer 1010: } else
1011: return wdc_ata_intr(wdc,xfer);
1012: #else /* NATAPIBUS > 0 && NWD > 0 */
1013: #if NATAPIBUS > 0
1.5 bouyer 1014: return wdc_atapi_intr(wdc,xfer);
1.2 bouyer 1015: #endif /* NATAPIBUS > 0 */
1016: #if NWD > 0
1017: return wdc_ata_intr(wdc,xfer);
1018: #endif /* NWD > 0 */
1019: #endif /* NATAPIBUS > 0 && NWD > 0 */
1020: }
1021:
1022: int
1023: wdcreset(wdc, verb)
1024: struct wdc_softc *wdc;
1025: int verb;
1026: {
1027:
1028: /* Reset the device. */
1.12 cgd 1029: bus_space_write_1(wdc->sc_auxiot, wdc->sc_auxioh, wd_aux_ctlr,
1030: WDCTL_RST | WDCTL_IDS);
1.2 bouyer 1031: delay(1000);
1.12 cgd 1032: bus_space_write_1(wdc->sc_auxiot, wdc->sc_auxioh, wd_aux_ctlr,
1033: WDCTL_IDS);
1.2 bouyer 1034: delay(1000);
1.12 cgd 1035: (void) bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_error);
1036: bus_space_write_1(wdc->sc_auxiot, wdc->sc_auxioh, wd_aux_ctlr,
1037: WDCTL_4BIT);
1.2 bouyer 1038:
1039: if (wait_for_unbusy(wdc) < 0) {
1040: if (verb)
1041: printf("%s: reset failed\n", wdc->sc_dev.dv_xname);
1042: return 1;
1043: }
1044:
1045: return 0;
1046: }
1047:
1048: void
1049: wdcrestart(arg)
1050: void *arg;
1051: {
1052: struct wdc_softc *wdc = arg;
1053: int s;
1054:
1055: s = splbio();
1056: wdcstart(wdc);
1057: splx(s);
1058: }
1059:
1060: /*
1061: * Unwedge the controller after an unexpected error. We do this by resetting
1062: * it, marking all drives for recalibration, and stalling the queue for a short
1063: * period to give the reset time to finish.
1064: * NOTE: We use a timeout here, so this routine must not be called during
1065: * autoconfig or dump.
1066: */
1067: void
1068: wdcunwedge(wdc)
1069: struct wdc_softc *wdc;
1070: {
1071: int unit;
1072:
1073: #ifdef ATAPI_DEBUG
1074: printf("wdcunwedge\n");
1075: #endif
1076:
1077: untimeout(wdctimeout, wdc);
1078: wdc->sc_flags &= ~WDCF_IRQ_WAIT;
1079: (void) wdcreset(wdc, VERBOSE);
1080:
1081: /* Schedule recalibrate for all drives on this controller. */
1082: for (unit = 0; unit < 2; unit++) {
1.8 bouyer 1083: if (!wdc->d_link[unit])
1084: wdccommandshort(wdc, unit, ATAPI_SOFT_RESET);
1085: else if (wdc->d_link[unit]->sc_state > RECAL)
1.2 bouyer 1086: wdc->d_link[unit]->sc_state = RECAL;
1087: }
1088:
1089: wdc->sc_flags |= WDCF_ERROR;
1090: ++wdc->sc_errors;
1091:
1092: /* Wake up in a little bit and restart the operation. */
1093: WDDEBUG_PRINT(("wdcrestart from wdcunwedge\n"));
1094: wdc->sc_flags &= ~WDCF_ACTIVE;
1095: timeout(wdcrestart, wdc, RECOVERYTIME);
1096: }
1097:
1098: int
1099: wdcwait(wdc, mask)
1100: struct wdc_softc *wdc;
1101: int mask;
1102: {
1103: int timeout = 0;
1104: u_char status;
1105: #ifdef WDCNDELAY_DEBUG
1106: extern int cold;
1107: #endif
1108:
1.12 cgd 1109: WDDEBUG_PRINT(("wdcwait\n"));
1.2 bouyer 1110:
1111: for (;;) {
1.12 cgd 1112: wdc->sc_status = status = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_status);
1.2 bouyer 1113: /*
1114: * XXX
1115: * If a single slave ATAPI device is attached, it may
1116: * have released the bus. Select it and try again.
1117: */
1118: if (status == 0xff && wdc->sc_flags & WDCF_ONESLAVE) {
1.12 cgd 1119: bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_sdh, WDSD_IBM | 0x10);
1120: wdc->sc_status = status = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_status);
1.2 bouyer 1121: }
1122: if ((status & WDCS_BSY) == 0 && (status & mask) == mask)
1123: break;
1124: if (++timeout > WDCNDELAY) {
1.3 bouyer 1125: #ifdef ATAPI_DEBUG
1.12 cgd 1126: printf("wdcwait: timeout, status %x error %x\n", status, bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_error));
1.2 bouyer 1127: #endif
1128: return -1;
1129: }
1130: delay(WDCDELAY);
1131: }
1132: if (status & WDCS_ERR) {
1.12 cgd 1133: wdc->sc_error = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_error);
1.2 bouyer 1134: return WDCS_ERR;
1135: }
1136: #ifdef WDCNDELAY_DEBUG
1137: /* After autoconfig, there should be no long delays. */
1138: if (!cold && timeout > WDCNDELAY_DEBUG) {
1139: struct wdc_xfer *xfer = wdc->sc_xfer.tqh_first;
1140: if (xfer == NULL)
1141: printf("%s: warning: busy-wait took %dus\n",
1142: wdc->sc_dev.dv_xname, WDCDELAY * timeout);
1143: else
1144: printf("%s(%s): warning: busy-wait took %dus\n",
1145: wdc->sc_dev.dv_xname,
1146: ((struct device*)xfer->d_link->wd_softc)->dv_xname,
1147: WDCDELAY * timeout);
1148: }
1149: #endif
1150: return 0;
1151: }
1152:
1153: void
1154: wdctimeout(arg)
1155: void *arg;
1156: {
1157: struct wdc_softc *wdc = (struct wdc_softc *)arg;
1.8 bouyer 1158: struct wdc_xfer *xfer = wdc->sc_xfer.tqh_first;
1.2 bouyer 1159: int s;
1160:
1161: WDDEBUG_PRINT(("wdctimeout\n"));
1162:
1163: s = splbio();
1164: if ((wdc->sc_flags & WDCF_IRQ_WAIT) != 0) {
1.8 bouyer 1165: wdcerror(wdc, "lost interrupt");
1166: printf("\ttype: %s\n", (xfer->c_flags & C_ATAPI) ? "atapi":"ata");
1167: printf("\tc_bcount: %d\n", xfer->c_bcount);
1168: printf("\tc_skip: %d\n", xfer->c_skip);
1169: wdcintr(wdc);
1.2 bouyer 1170: wdc->sc_flags &= ~WDCF_IRQ_WAIT;
1171: wdcunwedge(wdc);
1172: } else
1173: wdcerror(wdc, "missing untimeout");
1174: splx(s);
1175: }
1176:
1177: /*
1178: * Wait for the drive to become ready and send a command.
1179: * Return -1 if busy for too long or 0 otherwise.
1180: * Assumes interrupts are blocked.
1181: */
1182: int
1183: wdccommand(wdc, d_link, command, drive, cylin, head, sector, count)
1184: struct wdc_softc *wdc;
1185: struct wd_link *d_link;
1186: int command;
1187: int drive, cylin, head, sector, count;
1188: {
1189: int stat;
1190:
1191: WDDEBUG_PRINT(("wdccommand drive %d\n", drive));
1192:
1193: #if defined(DIAGNOSTIC) && defined(WDCDEBUG)
1194: if ((wdc->sc_flags & WDCF_ACTIVE) == 0)
1195: printf("wdccommand: controler not active (drive %d)\n", drive);
1196: #endif
1197:
1198: /* Select drive, head, and addressing mode. */
1.12 cgd 1199: bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_sdh, WDSD_IBM | (drive << 4) | head);
1.2 bouyer 1200:
1201: /* Wait for it to become ready to accept a command. */
1202: if (command == WDCC_IDP || d_link->type == ATAPI)
1203: stat = wait_for_unbusy(wdc);
1204: else
1205: stat = wdcwait(wdc, WDCS_DRDY);
1206:
1207: if (stat < 0) {
1208: #ifdef ATAPI_DEBUG
1209: printf("wdcommand: xfer failed (wait_for_unbusy) status %d\n",
1210: stat);
1211: #endif
1212: return -1;
1213: }
1214:
1215: /* Load parameters. */
1216: if (d_link->type == ATA && d_link->sc_lp->d_type == DTYPE_ST506)
1.12 cgd 1217: bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_precomp, d_link->sc_lp->d_precompcyl / 4);
1.2 bouyer 1218: else
1.12 cgd 1219: bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_features, 0);
1220: bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_cyl_lo, cylin);
1221: bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_cyl_hi, cylin >> 8);
1222: bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_sector, sector);
1223: bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_seccnt, count);
1.2 bouyer 1224:
1225: /* Send command. */
1.12 cgd 1226: bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_command, command);
1.2 bouyer 1227:
1228: return 0;
1229: }
1230:
1231: /*
1232: * Simplified version of wdccommand().
1233: */
1234: int
1235: wdccommandshort(wdc, drive, command)
1236: struct wdc_softc *wdc;
1237: int drive;
1238: int command;
1239: {
1240:
1241: WDDEBUG_PRINT(("wdccommandshort\n"));
1242:
1243: #if defined(DIAGNOSTIC) && defined(WDCDEBUG)
1244: if ((wdc->sc_flags & WDCF_ACTIVE) == 0)
1.10 mikel 1245: printf("wdccommandshort: controller not active (drive %d)\n",
1.2 bouyer 1246: drive);
1247: #endif
1248:
1249: /* Select drive. */
1.12 cgd 1250: bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_sdh, WDSD_IBM | (drive << 4));
1.2 bouyer 1251:
1252: if (wdcwait(wdc, WDCS_DRDY) < 0)
1253: return -1;
1254:
1.12 cgd 1255: bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_command, command);
1.2 bouyer 1256:
1257: return 0;
1258: }
1259:
1260: void
1261: wdc_exec_xfer(wdc, d_link, xfer)
1262: struct wdc_softc *wdc;
1263: struct wd_link *d_link;
1264: struct wdc_xfer *xfer;
1265: {
1266: int s;
1267:
1268: WDDEBUG_PRINT(("wdc_exec_xfer\n"));
1269:
1270: s = splbio();
1271:
1272: /* insert at the end of command list */
1.12 cgd 1273: TAILQ_INSERT_TAIL(&wdc->sc_xfer,xfer , c_xferchain);
1.2 bouyer 1274: WDDEBUG_PRINT(("wdcstart from wdc_exec_xfer, flags 0x%x\n",
1275: wdc->sc_flags));
1276: wdcstart(wdc);
1277: xfer->c_flags |= C_NEEDDONE; /* we can now call upper level done() */
1278: splx(s);
1279: }
1280:
1281: struct wdc_xfer *
1282: wdc_get_xfer(flags)
1283: int flags;
1284: {
1285: struct wdc_xfer *xfer;
1286: int s;
1287:
1288: s = splbio();
1289: if ((xfer = xfer_free_list.lh_first) != NULL) {
1290: LIST_REMOVE(xfer, free_list);
1291: splx(s);
1292: #ifdef DIAGNOSTIC
1293: if ((xfer->c_flags & C_INUSE) != 0)
1294: panic("wdc_get_xfer: xfer already in use\n");
1295: #endif
1296: } else {
1297: splx(s);
1.8 bouyer 1298: #ifdef ATAPI_DEBUG2
1.2 bouyer 1299: printf("wdc:making xfer %d\n",wdc_nxfer);
1300: #endif
1301: xfer = malloc(sizeof(*xfer), M_DEVBUF,
1302: ((flags & IDE_NOSLEEP) != 0 ? M_NOWAIT : M_WAITOK));
1303: if (xfer == NULL)
1304: return 0;
1305:
1306: #ifdef DIAGNOSTIC
1307: xfer->c_flags &= ~C_INUSE;
1308: #endif
1.8 bouyer 1309: #ifdef ATAPI_DEBUG2
1.2 bouyer 1310: wdc_nxfer++;
1311: #endif
1312: }
1313: #ifdef DIAGNOSTIC
1314: if ((xfer->c_flags & C_INUSE) != 0)
1315: panic("wdc_get_xfer: xfer already in use\n");
1316: #endif
1317: bzero(xfer,sizeof(struct wdc_xfer));
1318: xfer->c_flags = C_INUSE;
1319: return xfer;
1320: }
1321:
1322: void
1323: wdc_free_xfer(xfer)
1324: struct wdc_xfer *xfer;
1325: {
1326: int s;
1327:
1328: s = splbio();
1329: xfer->c_flags &= ~C_INUSE;
1330: LIST_INSERT_HEAD(&xfer_free_list, xfer, free_list);
1331: splx(s);
1332: }
1333:
1334: void
1335: wdcerror(wdc, msg)
1336: struct wdc_softc *wdc;
1337: char *msg;
1338: {
1339: struct wdc_xfer *xfer = wdc->sc_xfer.tqh_first;
1340: if (xfer == NULL)
1341: printf("%s: %s\n", wdc->sc_dev.dv_xname, msg);
1342: else
1343: printf("%s(%d): %s\n", wdc->sc_dev.dv_xname,
1344: xfer->d_link->drive, msg);
1345: }
1346:
1347: /*
1348: * the bit bucket
1349: */
1350: void
1351: wdcbit_bucket(wdc, size)
1352: struct wdc_softc *wdc;
1353: int size;
1354: {
1355:
1.12 cgd 1356: for (; size >= 2; size -= 2)
1357: (void)bus_space_read_2(wdc->sc_iot, wdc->sc_ioh, wd_data);
1358: if (size)
1359: (void)bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_data);
1.2 bouyer 1360: }
1361:
1362:
1363: #if NATAPIBUS > 0
1364:
1365: void
1366: wdc_atapi_minphys (struct buf *bp)
1367: {
1368: if(bp->b_bcount > MAX_SIZE)
1369: bp->b_bcount = MAX_SIZE;
1370: minphys(bp);
1371: }
1372:
1373:
1374: void
1375: wdc_atapi_start(wdc, xfer)
1376: struct wdc_softc *wdc;
1377: struct wdc_xfer *xfer;
1378: {
1379: struct scsipi_xfer *sc_xfer = xfer->atapi_cmd;
1380:
1381: #ifdef ATAPI_DEBUG_WDC
1382: printf("wdc_atapi_start, acp flags %x \n",sc_xfer->flags);
1383: #endif
1384: if (wdc->sc_errors >= WDIORETRIES) {
1385: if ((wdc->sc_status & WDCS_ERR) == 0) {
1386: sc_xfer->error = XS_DRIVER_STUFFUP; /* XXX do we know more ? */
1387: } else {
1388: sc_xfer->error = XS_SENSE;
1.12 cgd 1389: sc_xfer->sense.atapi_sense = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_error);
1.2 bouyer 1390: }
1391: wdc_atapi_done(wdc, xfer);
1392: return;
1393: }
1394: if (wait_for_unbusy(wdc) != 0) {
1395: if ((wdc->sc_status & WDCS_ERR) == 0) {
1396: printf("wdc_atapi_start: not ready, st = %02x\n",
1397: wdc->sc_status);
1398: sc_xfer->error = XS_SELTIMEOUT;
1399: }
1400: #if 0 /* don't get the sense yet, as this may be just UNIT ATTENTION */
1401: else {
1402: #ifdef ATAPI_DEBUG_WDC
1403: printf("wdc_atapi_start: sense %02x\n", wdc->sc_error);
1404: #endif
1405: sc_xfer->error = XS_SENSE;
1406: sc_xfer->sense.atapi_sense = wdc->sc_error;
1407: }
1408: wdc_atapi_done(wdc, xfer);
1409: return;
1410: #endif
1411: }
1412:
1.12 cgd 1413: /*
1414: * Limit length to what can be stuffed into the cylinder register
1415: * (16 bits). Some CD-ROMs seem to interpret '0' as 65536,
1416: * but not all devices do that and it's not obvious from the
1417: * ATAPI spec that that behaviour should be expected. If more
1418: * data is necessary, multiple data transfer phases will be done.
1419: */
1.2 bouyer 1420: if (wdccommand(wdc, (struct wd_link*)xfer->d_link, ATAPI_PACKET_COMMAND,
1.12 cgd 1421: sc_xfer->sc_link->scsipi_atapi.drive,
1422: sc_xfer->datalen <= 0xffff ? sc_xfer->datalen : 0xffff,
1.2 bouyer 1423: 0, 0, 0) != 0) {
1.10 mikel 1424: printf("wdc_atapi_start: can't send atapi packet command\n");
1.2 bouyer 1425: sc_xfer->error = XS_DRIVER_STUFFUP;
1426: wdc_atapi_done(wdc, xfer);
1427: return;
1428: }
1429: if ((sc_xfer->sc_link->scsipi_atapi.cap & 0x0300) != ACAP_DRQ_INTR) {
1430: int i, phase;
1431: for (i=20000; i>0; --i) {
1.12 cgd 1432: phase = (bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_ireason) &
1.2 bouyer 1433: (WDCI_CMD | WDCI_IN)) |
1.12 cgd 1434: (bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_status) & WDCS_DRQ);
1.2 bouyer 1435: if (phase == PHASE_CMDOUT)
1436: break;
1437: delay(10);
1438: }
1439: if (phase != PHASE_CMDOUT ) {
1.10 mikel 1440: printf("wdc_atapi_start: timeout waiting PHASE_CMDOUT");
1.2 bouyer 1441: sc_xfer->error = XS_SELTIMEOUT;
1442: wdc_atapi_done(wdc, xfer);
1443: return;
1444: }
1.12 cgd 1445: bus_space_write_multi_2(wdc->sc_iot, wdc->sc_ioh, wd_data,
1446: (u_int16_t *)sc_xfer->cmd, sc_xfer->cmdlen >> 1);
1.2 bouyer 1447: }
1448: wdc->sc_flags |= WDCF_IRQ_WAIT;
1449:
1450: #ifdef ATAPI_DEBUG2
1451: printf("wdc_atapi_start: timeout\n");
1452: #endif
1453: timeout(wdctimeout, wdc, WAITTIME);
1454: return;
1455: }
1456:
1457:
1458: int
1459: wdc_atapi_get_params(ab_link, drive, id)
1460: struct scsipi_link *ab_link;
1461: u_int8_t drive;
1462: struct atapi_identify *id;
1463: {
1464: struct wdc_softc *wdc = (void*)ab_link->adapter_softc;
1465: int status, len, excess = 0;
1466: int s, error;
1467:
1.4 bouyer 1468: /* if a disk is already present, skip */
1469: if ((wdc->sc_drives_mask & (1 << drive)) != 0) {
1.2 bouyer 1470: #ifdef ATAPI_DEBUG_PROBE
1.4 bouyer 1471: printf("wdc_atapi_get_params: drive %d present\n", drive);
1.2 bouyer 1472: #endif
1473: return 0;
1474: }
1475:
1476: /*
1477: * If there is only one ATAPI slave on the bus,don't probe
1478: * drive 0 (master)
1479: */
1480:
1481: if (wdc->sc_flags & WDCF_ONESLAVE && drive != 1)
1482: return 0;
1483:
1484: #ifdef ATAPI_DEBUG_PROBE
1485: printf("wdc_atapi_get_params: probing drive %d\n", drive);
1486: #endif
1487:
1488: /*
1489: * XXX
1490: * The locking done here, and the length of time this may keep the rest
1491: * of the system suspended, is a kluge. This should be rewritten to
1492: * set up a transfer and queue it through wdstart(), but it's called
1493: * infrequently enough that this isn't a pressing matter.
1494: */
1495:
1496: s = splbio();
1497:
1498: while ((wdc->sc_flags & WDCF_ACTIVE) != 0) {
1499: wdc->sc_flags |= WDCF_WANTED;
1500: if ((error = tsleep(wdc, PRIBIO | PCATCH, "atprm", 0)) != 0) {
1501: splx(s);
1502: return error;
1503: }
1504: }
1505:
1506: wdc->sc_flags |= WDCF_ACTIVE;
1507: error = 1;
1508: (void)wdcreset(wdc, VERBOSE);
1509: if ((status = wdccommand(wdc, (struct wd_link*)(&(ab_link->scsipi_atapi)),
1510: ATAPI_SOFT_RESET, drive, 0, 0, 0, 0)) != 0) {
1511: #ifdef ATAPI_DEBUG
1512: printf("wdc_atapi_get_params: ATAPI_SOFT_RESET"
1513: "failed for drive %d: status %d error %d\n",
1514: drive, status, wdc->sc_error);
1515: #endif
1516: error = 0;
1517: goto end;
1518: }
1519: if ((status = wait_for_unbusy(wdc)) != 0) {
1520: #ifdef ATAPI_DEBUG
1521: printf("wdc_atapi_get_params: wait_for_unbusy failed "
1522: "for drive %d: status %d error %d\n",
1523: drive, status, wdc->sc_error);
1524: #endif
1525: error = 0;
1526: goto end;
1527: }
1528:
1529: if (wdccommand(wdc, (struct wd_link*)(&(ab_link->scsipi_atapi)),
1530: ATAPI_IDENTIFY_DEVICE, drive, sizeof(struct atapi_identify),
1531: 0, 0, 0) != 0 ||
1532: atapi_ready(wdc) != 0) {
1533: #ifdef ATAPI_DEBUG_PROBE
1534: printf("ATAPI_IDENTIFY_DEVICE failed for drive %d\n", drive);
1535: #endif
1536: error = 0;
1537: goto end;
1538: }
1.12 cgd 1539: len = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_cyl_lo) + 256 *
1540: bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_cyl_hi);
1.2 bouyer 1541: if (len != sizeof(struct atapi_identify)) {
1542: printf("Warning drive %d returned %d/%d of "
1543: "indentify device data\n", drive, len,
1544: sizeof(struct atapi_identify));
1545: excess = len - sizeof(struct atapi_identify);
1546: if (excess < 0)
1547: excess = 0;
1548: }
1.12 cgd 1549: bus_space_read_multi_2(wdc->sc_iot, wdc->sc_ioh, wd_data,
1550: (u_int16_t *)id, sizeof(struct atapi_identify) >> 1);
1.2 bouyer 1551: wdcbit_bucket(wdc, excess);
1.4 bouyer 1552: wdc->sc_drives_mask |= (1 << drive);
1.2 bouyer 1553:
1554: end: /* Restart the queue. */
1555: WDDEBUG_PRINT(("wdcstart from wdc_atapi_get_parms flags 0x%x\n",
1556: wdc->sc_flags));
1557: wdc->sc_flags &= ~WDCF_ACTIVE;
1558: wdcstart(wdc);
1559: splx(s);
1560: return error;
1561: }
1562:
1563: int
1564: wdc_atapi_send_command_packet(sc_xfer)
1565: struct scsipi_xfer *sc_xfer;
1566: {
1567: struct scsipi_link *sc_link = sc_xfer->sc_link;
1568: struct wdc_softc *wdc = (void*)sc_link->adapter_softc;
1569: struct wdc_xfer *xfer;
1570: int flags = sc_xfer->flags;
1.8 bouyer 1571:
1.2 bouyer 1572: if (flags & SCSI_POLL) { /* should use the queue and wdc_atapi_start */
1573: struct wdc_xfer xfer_s;
1574: int i, s;
1575:
1576: s = splbio();
1577: #ifdef ATAPI_DEBUG_WDC
1578: printf("wdc_atapi_send_cmd: "
1579: "flags 0x%x drive %d cmdlen %d datalen %d",
1580: sc_xfer->flags, sc_link->scsipi_atapi.drive, sc_xfer->cmdlen,
1581: sc_xfer->datalen);
1582: #endif
1583: xfer = &xfer_s;
1584: bzero(xfer, sizeof(xfer_s));
1585: xfer->c_flags = C_INUSE|C_ATAPI|flags;
1586: xfer->d_link = (struct wd_link *)(&sc_link->scsipi_atapi);
1587: xfer->c_bp = sc_xfer->bp;
1588: xfer->atapi_cmd = sc_xfer;
1589: xfer->c_blkno = 0;
1590: xfer->databuf = sc_xfer->data;
1591: xfer->c_bcount = sc_xfer->datalen;
1.12 cgd 1592:
1.2 bouyer 1593: if (wait_for_unbusy (wdc) != 0) {
1594: if ((wdc->sc_status & WDCS_ERR) == 0) {
1595: printf("wdc_atapi_send_command: not ready, "
1596: "st = %02x\n", wdc->sc_status);
1597: sc_xfer->error = XS_SELTIMEOUT;
1598: } else {
1599: sc_xfer->error = XS_SENSE;
1600: sc_xfer->sense.atapi_sense = wdc->sc_error;
1601: }
1602: splx(s);
1603: return COMPLETE;
1604: }
1605:
1.12 cgd 1606: /*
1607: * Limit length to what can be stuffed into the cylinder
1608: * register (16 bits). Some CD-ROMs seem to interpret '0'
1609: * as 65536, but not all devices do that and it's not
1610: * obvious from the ATAPI spec that that behaviour should
1611: * be expected. If more data is necessary, multiple data
1612: * transfer phases will be done.
1613: */
1.2 bouyer 1614: if (wdccommand(wdc, (struct wd_link*)(&sc_link->scsipi_atapi),
1.12 cgd 1615: ATAPI_PACKET_COMMAND, sc_link->scsipi_atapi.drive,
1616: sc_xfer->datalen <= 0xffff ? sc_xfer->datalen : 0xffff,
1.2 bouyer 1617: 0, 0, 0) != 0) {
1.10 mikel 1618: printf("can't send atapi packet command\n");
1.2 bouyer 1619: sc_xfer->error = XS_DRIVER_STUFFUP;
1620: splx(s);
1621: return COMPLETE;
1622: }
1623:
1624: /* Wait for cmd i/o phase. */
1625: for (i = 20000; i > 0; --i) {
1626: int phase;
1.12 cgd 1627: phase = (bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_ireason) &
1.2 bouyer 1628: (WDCI_CMD | WDCI_IN)) |
1.12 cgd 1629: (bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_status) & WDCS_DRQ);
1.2 bouyer 1630: if (phase == PHASE_CMDOUT)
1631: break;
1632: delay(10);
1633: }
1634: #ifdef ATAPI_DEBUG_WDC
1635: printf("Wait for cmd i/o phase: i = %d\n", i);
1636: #endif
1637:
1.12 cgd 1638: bus_space_write_multi_2(wdc->sc_iot, wdc->sc_ioh, wd_data,
1639: (u_int16_t *)sc_xfer->cmd, sc_xfer->cmdlen >> 1);
1.2 bouyer 1640:
1641: /* Wait for data i/o phase. */
1642: for ( i= 20000; i > 0; --i) {
1643: int phase;
1.12 cgd 1644: phase = (bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_ireason) &
1.2 bouyer 1645: (WDCI_CMD | WDCI_IN)) |
1.12 cgd 1646: (bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_status) & WDCS_DRQ);
1.2 bouyer 1647: if (phase != PHASE_CMDOUT)
1648: break;
1649: delay(10);
1650: }
1651:
1652: #ifdef ATAPI_DEBUG_WDC
1653: printf("Wait for data i/o phase: i = %d\n", i);
1654: #endif
1.8 bouyer 1655: wdc->sc_flags |= WDCF_IRQ_WAIT;
1.5 bouyer 1656: while ((sc_xfer->flags & ITSDONE) == 0) {
1657: wdc_atapi_intr(wdc, xfer);
1.2 bouyer 1658: for (i = 2000; i > 0; --i)
1.12 cgd 1659: if ((bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_status)
1.2 bouyer 1660: & WDCS_DRQ) == 0)
1661: break;
1662: #ifdef ATAPI_DEBUG_WDC
1663: printf("wdc_atapi_intr: i = %d\n", i);
1664: #endif
1665: }
1666: wdc->sc_flags &= ~(WDCF_IRQ_WAIT | WDCF_SINGLE | WDCF_ERROR);
1667: wdc->sc_errors = 0;
1668: xfer->c_skip = 0;
1669: splx(s);
1670: return COMPLETE;
1671: } else { /* POLLED */
1672: xfer = wdc_get_xfer(flags & SCSI_NOSLEEP ? IDE_NOSLEEP : 0);
1673: if (xfer == NULL) {
1674: return TRY_AGAIN_LATER;
1675: }
1676: xfer->c_flags |= C_ATAPI|sc_xfer->flags;
1677: xfer->d_link = (struct wd_link*)(&sc_link->scsipi_atapi);
1678: xfer->c_bp = sc_xfer->bp;
1679: xfer->atapi_cmd = sc_xfer;
1680: xfer->c_blkno = 0;
1681: xfer->databuf = sc_xfer->data;
1682: xfer->c_bcount = sc_xfer->datalen;
1683: wdc_exec_xfer(wdc, xfer->d_link, xfer);
1684: #ifdef ATAPI_DEBUG_WDC
1685: printf("wdc_atapi_send_command_packet: wdc_exec_xfer, flags 0x%x\n",
1686: sc_xfer->flags);
1687: #endif
1688: return (sc_xfer->flags & ITSDONE) ? COMPLETE : SUCCESSFULLY_QUEUED;
1689: }
1690: }
1691:
1692: int
1693: wdc_atapi_intr(wdc, xfer)
1694: struct wdc_softc *wdc;
1695: struct wdc_xfer *xfer;
1696: {
1697: struct scsipi_xfer *sc_xfer = xfer->atapi_cmd;
1698: int len, phase, i, retries=0;
1699: int err, st, ire;
1700:
1701: #ifdef ATAPI_DEBUG2
1702: printf("wdc_atapi_intr: %s\n", wdc->sc_dev.dv_xname);
1703: #endif
1704:
1705: if (wait_for_unbusy(wdc) < 0) {
1706: if ((wdc->sc_status & WDCS_ERR) == 0) {
1707: printf("wdc_atapi_intr: controller busy\n");
1.5 bouyer 1708: return 0;
1.2 bouyer 1709: } else {
1710: sc_xfer->error = XS_SENSE;
1711: sc_xfer->sense.atapi_sense = wdc->sc_error;
1712: }
1713: #ifdef ATAPI_DEBUG_WDC
1714: printf("wdc_atapi_intr: wdc_atapi_done(), error %d\n",
1715: sc_xfer->error);
1716: #endif
1717: wdc_atapi_done(wdc, xfer);
1718: return 0;
1719: }
1720:
1721:
1722: again:
1.12 cgd 1723: len = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_cyl_lo) +
1724: 256 * bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_cyl_hi);
1.2 bouyer 1725:
1.12 cgd 1726: st = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_status);
1727: err = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_error);
1728: ire = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_ireason);
1.2 bouyer 1729:
1730: phase = (ire & (WDCI_CMD | WDCI_IN)) | (st & WDCS_DRQ);
1731: #ifdef ATAPI_DEBUG_WDC
1732: printf("wdc_atapi_intr: len %d st %d err %d ire %d :",
1733: len, st, err, ire);
1734: #endif
1735: switch (phase) {
1736: case PHASE_CMDOUT:
1737: /* send packet command */
1738: #ifdef ATAPI_DEBUG_WDC
1739: printf("PHASE_CMDOUT\n");
1740: #endif
1741:
1742: #ifdef ATAPI_DEBUG_WDC
1743: {
1744: int i;
1745: char *c = (char *)sc_xfer->cmd;
1746: printf("wdc_atapi_intr: cmd ");
1747: for (i = 0; i < sc_xfer->cmdlen; i++)
1748: printf("%x ", c[i]);
1749: printf("\n");
1750: }
1751: #endif
1752:
1.12 cgd 1753: bus_space_write_multi_2(wdc->sc_iot, wdc->sc_ioh, wd_data,
1754: (u_int16_t *)sc_xfer->cmd, sc_xfer->cmdlen >> 1);
1.2 bouyer 1755: return 1;
1756:
1757: case PHASE_DATAOUT:
1758: /* write data */
1759: #ifdef ATAPI_DEBUG_WDC
1760: printf("PHASE_DATAOUT\n");
1761: #endif
1762: if ((sc_xfer->flags & SCSI_DATA_OUT) == 0) {
1763: printf("wdc_atapi_intr: bad data phase\n");
1764: sc_xfer->error = XS_DRIVER_STUFFUP;
1.5 bouyer 1765: return 0;
1.2 bouyer 1766: }
1767: if (xfer->c_bcount < len) {
1768: printf("wdc_atapi_intr: warning: write only "
1769: "%d of %d requested bytes\n", xfer->c_bcount, len);
1.12 cgd 1770: bus_space_write_multi_2(wdc->sc_iot, wdc->sc_ioh,
1771: wd_data, xfer->databuf + xfer->c_skip,
1772: xfer->c_bcount >> 1);
1773: for (i = xfer->c_bcount; i < len; i += 2)
1774: bus_space_write_2(wdc->sc_iot, wdc->sc_ioh,
1775: wd_data, 0);
1.8 bouyer 1776: xfer->c_skip += xfer->c_bcount;
1.2 bouyer 1777: xfer->c_bcount = 0;
1778: } else {
1.12 cgd 1779: bus_space_write_multi_2(wdc->sc_iot, wdc->sc_ioh,
1780: wd_data, xfer->databuf + xfer->c_skip, len >> 1);
1.2 bouyer 1781: xfer->c_skip += len;
1782: xfer->c_bcount -= len;
1783: }
1.8 bouyer 1784: return 1;
1.2 bouyer 1785:
1786: case PHASE_DATAIN:
1787: /* Read data */
1788: #ifdef ATAPI_DEBUG_WDC
1789: printf("PHASE_DATAIN\n");
1790: #endif
1791: if ((sc_xfer->flags & SCSI_DATA_IN) == 0) {
1792: printf("wdc_atapi_intr: bad data phase\n");
1793: sc_xfer->error = XS_DRIVER_STUFFUP;
1.5 bouyer 1794: return 0;
1.2 bouyer 1795: }
1796: if (xfer->c_bcount < len) {
1797: printf("wdc_atapi_intr: warning: reading only "
1798: "%d of %d bytes\n", xfer->c_bcount, len);
1.12 cgd 1799: bus_space_read_multi_2(wdc->sc_iot, wdc->sc_ioh,
1800: wd_data, xfer->databuf + xfer->c_skip,
1801: xfer->c_bcount >> 1);
1.2 bouyer 1802: wdcbit_bucket(wdc, len - xfer->c_bcount);
1.8 bouyer 1803: xfer->c_skip += xfer->c_bcount;
1.2 bouyer 1804: xfer->c_bcount = 0;
1805: } else {
1.12 cgd 1806: bus_space_read_multi_2(wdc->sc_iot, wdc->sc_ioh,
1807: wd_data, xfer->databuf + xfer->c_skip, len >> 1);
1.2 bouyer 1808: xfer->c_skip += len;
1809: xfer->c_bcount -=len;
1810: }
1.8 bouyer 1811: return 1;
1.2 bouyer 1812:
1813: case PHASE_ABORTED:
1814: case PHASE_COMPLETED:
1815: #ifdef ATAPI_DEBUG_WDC
1816: printf("PHASE_COMPLETED\n");
1817: #endif
1818: if (st & WDCS_ERR) {
1819: sc_xfer->error = XS_SENSE;
1.12 cgd 1820: sc_xfer->sense.atapi_sense = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_error);
1.2 bouyer 1821: }
1822: #ifdef ATAPI_DEBUG_WDC
1823: if (xfer->c_bcount != 0) {
1824: printf("wdc_atapi_intr warning: bcount value "
1825: "is %d after io\n", xfer->c_bcount);
1826: }
1827: #endif
1828: break;
1829:
1830: default:
1831: if (++retries<500) {
1832: DELAY(100);
1833: goto again;
1834: }
1835: printf("wdc_atapi_intr: unknown phase %d\n", phase);
1836: if (st & WDCS_ERR) {
1837: sc_xfer->error = XS_SENSE;
1.12 cgd 1838: sc_xfer->sense.atapi_sense = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_error);
1.2 bouyer 1839: } else {
1840: sc_xfer->error = XS_DRIVER_STUFFUP;
1841: }
1842: }
1843:
1844: #ifdef ATAPI_DEBUG_WDC
1845: printf("wdc_atapi_intr: wdc_atapi_done() (end), error %d\n",
1846: sc_xfer->error);
1847: #endif
1848: wdc_atapi_done(wdc, xfer);
1.5 bouyer 1849: return (1);
1.2 bouyer 1850: }
1851:
1852:
1853: void
1854: wdc_atapi_done(wdc, xfer)
1855: struct wdc_softc *wdc;
1856: struct wdc_xfer *xfer;
1857: {
1858: struct scsipi_xfer *sc_xfer = xfer->atapi_cmd;
1859: int s;
1860: int need_done = xfer->c_flags & C_NEEDDONE;
1861:
1862: #ifdef ATAPI_DEBUG
1863: printf("wdc_atapi_done: flags 0x%x\n", (u_int)xfer->c_flags);
1864: #endif
1865: sc_xfer->resid = xfer->c_bcount;
1.8 bouyer 1866: wdc->sc_flags &= ~WDCF_IRQ_WAIT;
1.2 bouyer 1867:
1868: /* remove this command from xfer queue */
1869: wdc->sc_errors = 0;
1870: xfer->c_skip = 0;
1871: if ((xfer->c_flags & SCSI_POLL) == 0) {
1872: s = splbio();
1873: untimeout(wdctimeout, wdc);
1874: TAILQ_REMOVE(&wdc->sc_xfer, xfer, c_xferchain);
1875: wdc->sc_flags &= ~(WDCF_SINGLE | WDCF_ERROR | WDCF_ACTIVE);
1876: wdc_free_xfer(xfer);
1877: sc_xfer->flags |= ITSDONE;
1878: if (need_done) {
1879: #ifdef ATAPI_DEBUG
1880: printf("wdc_atapi_done: scsipi_done\n");
1881: #endif
1882: scsipi_done(sc_xfer);
1883: }
1884: #ifdef WDDEBUG
1885: printf("wdcstart from wdc_atapi_intr, flags 0x%x\n",
1886: wdc->sc_flags);
1887: #endif
1888: wdcstart(wdc);
1889: splx(s);
1.8 bouyer 1890: } else {
1.2 bouyer 1891: wdc->sc_flags &= ~(WDCF_SINGLE | WDCF_ERROR | WDCF_ACTIVE);
1.8 bouyer 1892: sc_xfer->flags |= ITSDONE;
1893: }
1.2 bouyer 1894: }
1895:
1896: #endif /* NATAPIBUS > 0 */
CVSweb <webmaster@jp.NetBSD.org>