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