Annotation of src/sys/dev/ic/wdc.c, Revision 1.309
1.309 ! andvar 1: /* $NetBSD: wdc.c,v 1.308 2021/10/05 08:01:05 rin Exp $ */
1.31 bouyer 2:
3: /*
1.137 bouyer 4: * Copyright (c) 1998, 2001, 2003 Manuel Bouyer. All rights reserved.
1.31 bouyer 5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: *
15: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25: */
1.2 bouyer 26:
1.27 mycroft 27: /*-
1.220 mycroft 28: * Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc.
1.27 mycroft 29: * All rights reserved.
1.2 bouyer 30: *
1.27 mycroft 31: * This code is derived from software contributed to The NetBSD Foundation
32: * by Charles M. Hannum, by Onno van der Linden and by Manuel Bouyer.
1.12 cgd 33: *
1.2 bouyer 34: * Redistribution and use in source and binary forms, with or without
35: * modification, are permitted provided that the following conditions
36: * are met:
37: * 1. Redistributions of source code must retain the above copyright
38: * notice, this list of conditions and the following disclaimer.
39: * 2. Redistributions in binary form must reproduce the above copyright
40: * notice, this list of conditions and the following disclaimer in the
41: * documentation and/or other materials provided with the distribution.
42: *
1.27 mycroft 43: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
44: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
45: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
46: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
47: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
48: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
49: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
50: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
51: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
52: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
53: * POSSIBILITY OF SUCH DAMAGE.
1.2 bouyer 54: */
55:
1.12 cgd 56: /*
57: * CODE UNTESTED IN THE CURRENT REVISION:
58: */
1.100 lukem 59:
60: #include <sys/cdefs.h>
1.309 ! andvar 61: __KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.308 2021/10/05 08:01:05 rin Exp $");
1.12 cgd 62:
1.247 dyoung 63: #include "opt_ata.h"
1.263 bouyer 64: #include "opt_wdc.h"
1.31 bouyer 65:
1.2 bouyer 66: #include <sys/param.h>
67: #include <sys/systm.h>
68: #include <sys/kernel.h>
69: #include <sys/conf.h>
70: #include <sys/buf.h>
1.31 bouyer 71: #include <sys/device.h>
1.2 bouyer 72: #include <sys/malloc.h>
1.302 jdolecek 73: #include <sys/kmem.h>
1.2 bouyer 74: #include <sys/syslog.h>
75: #include <sys/proc.h>
76:
1.249 ad 77: #include <sys/intr.h>
78: #include <sys/bus.h>
1.2 bouyer 79:
1.17 sakamoto 80: #ifndef __BUS_SPACE_HAS_STREAM_METHODS
1.31 bouyer 81: #define bus_space_write_multi_stream_2 bus_space_write_multi_2
82: #define bus_space_write_multi_stream_4 bus_space_write_multi_4
83: #define bus_space_read_multi_stream_2 bus_space_read_multi_2
84: #define bus_space_read_multi_stream_4 bus_space_read_multi_4
1.246 sborrill 85: #define bus_space_read_stream_2 bus_space_read_2
86: #define bus_space_read_stream_4 bus_space_read_4
87: #define bus_space_write_stream_2 bus_space_write_2
88: #define bus_space_write_stream_4 bus_space_write_4
1.17 sakamoto 89: #endif /* __BUS_SPACE_HAS_STREAM_METHODS */
1.16 sakamoto 90:
1.103 bouyer 91: #include <dev/ata/atavar.h>
1.31 bouyer 92: #include <dev/ata/atareg.h>
1.239 bouyer 93: #include <dev/ata/satareg.h>
94: #include <dev/ata/satavar.h>
1.12 cgd 95: #include <dev/ic/wdcreg.h>
96: #include <dev/ic/wdcvar.h>
1.31 bouyer 97:
1.137 bouyer 98: #include "locators.h"
99:
1.2 bouyer 100: #include "atapibus.h"
1.106 bouyer 101: #include "wd.h"
1.240 bouyer 102: #include "sata.h"
1.2 bouyer 103:
1.31 bouyer 104: #define WDCDELAY 100 /* 100 microseconds */
105: #define WDCNDELAY_RST (WDC_RESET_WAIT * 1000 / WDCDELAY)
1.2 bouyer 106: #if 0
1.31 bouyer 107: /* If you enable this, it will report any delays more than WDCDELAY * N long. */
1.2 bouyer 108: #define WDCNDELAY_DEBUG 50
109: #endif
110:
1.284 jdolecek 111: /* When polling wait that much and then kpause for 1/hz seconds */
1.219 perry 112: #define WDCDELAY_POLL 1 /* ms */
1.137 bouyer 113:
114: /* timeout for the control commands */
115: #define WDC_CTRL_DELAY 10000 /* 10s, for the recall command */
116:
1.224 bouyer 117: /*
118: * timeout when waiting for BSY to deassert when probing.
119: * set to 5s. From the standards this could be up to 31, but we can't
1.261 snj 120: * wait that much at boot time, and 5s seems to be enough.
1.224 bouyer 121: */
122: #define WDC_PROBE_WAIT 5
123:
124:
1.106 bouyer 125: #if NWD > 0
1.103 bouyer 126: extern const struct ata_bustype wdc_ata_bustype; /* in ata_wdc.c */
1.106 bouyer 127: #else
128: /* A fake one, the autoconfig will print "wd at foo ... not configured */
129: const struct ata_bustype wdc_ata_bustype = {
1.291 maya 130: .bustype_type = SCSIPI_BUSTYPE_ATA,
1.290 maya 131: .ata_bio = NULL,
1.291 maya 132: .ata_reset_drive = NULL,
1.290 maya 133: .ata_reset_channel = wdc_reset_channel,
134: .ata_exec_command = wdc_exec_command,
135: .ata_get_params = NULL,
136: .ata_addref = NULL,
137: .ata_delref = NULL,
138: .ata_killpending = NULL,
139: .ata_recovery = NULL,
1.106 bouyer 140: };
141: #endif
1.102 bouyer 142:
1.213 thorpej 143: /* Flags to wdcreset(). */
144: #define RESET_POLL 1
1.284 jdolecek 145: #define RESET_SLEEP 0 /* wdcreset() will use kpause() */
1.213 thorpej 146:
147: static int wdcprobe1(struct ata_channel *, int);
148: static int wdcreset(struct ata_channel *, int);
1.222 christos 149: static void __wdcerror(struct ata_channel *, const char *);
1.205 thorpej 150: static int __wdcwait_reset(struct ata_channel *, int, int);
151: static void __wdccommand_done(struct ata_channel *, struct ata_xfer *);
1.308 rin 152: static int __wdccommand_poll(struct ata_channel *, struct ata_xfer *);
1.205 thorpej 153: static void __wdccommand_done_end(struct ata_channel *, struct ata_xfer *);
154: static void __wdccommand_kill_xfer(struct ata_channel *,
1.182 bouyer 155: struct ata_xfer *, int);
1.284 jdolecek 156: static int __wdccommand_start(struct ata_channel *, struct ata_xfer *);
1.205 thorpej 157: static int __wdccommand_intr(struct ata_channel *, struct ata_xfer *, int);
1.284 jdolecek 158: static int __wdcwait(struct ata_channel *, int, int, int, int *);
1.31 bouyer 159:
1.213 thorpej 160: static void wdc_datain_pio(struct ata_channel *, int, void *, size_t);
161: static void wdc_dataout_pio(struct ata_channel *, int, void *, size_t);
1.31 bouyer 162: #define DEBUG_INTR 0x01
163: #define DEBUG_XFERS 0x02
164: #define DEBUG_STATUS 0x04
165: #define DEBUG_FUNCS 0x08
166: #define DEBUG_PROBE 0x10
1.74 enami 167: #define DEBUG_DETACH 0x20
1.87 bouyer 168: #define DEBUG_DELAY 0x40
1.204 thorpej 169: #ifdef ATADEBUG
170: extern int atadebug_mask; /* init'ed in ata.c */
1.31 bouyer 171: int wdc_nxfer = 0;
1.204 thorpej 172: #define ATADEBUG_PRINT(args, level) if (atadebug_mask & (level)) printf args
1.2 bouyer 173: #else
1.204 thorpej 174: #define ATADEBUG_PRINT(args, level)
1.2 bouyer 175: #endif
176:
1.162 thorpej 177: /*
1.176 thorpej 178: * Initialize the "shadow register" handles for a standard wdc controller.
179: */
180: void
1.284 jdolecek 181: wdc_init_shadow_regs(struct wdc_regs *wdr)
1.176 thorpej 182: {
1.205 thorpej 183: wdr->cmd_iohs[wd_status] = wdr->cmd_iohs[wd_command];
184: wdr->cmd_iohs[wd_features] = wdr->cmd_iohs[wd_error];
185: }
186:
187: /*
188: * Allocate a wdc_regs array, based on the number of channels.
189: */
190: void
191: wdc_allocate_regs(struct wdc_softc *wdc)
192: {
193:
1.207 thorpej 194: wdc->regs = malloc(wdc->sc_atac.atac_nchannels *
195: sizeof(struct wdc_regs), M_DEVBUF, M_WAITOK);
1.176 thorpej 196: }
197:
1.240 bouyer 198: #if NSATA > 0
1.239 bouyer 199: /*
200: * probe drives on SATA controllers with standard SATA registers:
201: * bring the PHYs online, read the drive signature and set drive flags
202: * appropriately.
203: */
204: void
205: wdc_sataprobe(struct ata_channel *chp)
206: {
1.297 jdolecek 207: struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.239 bouyer 208: struct wdc_regs *wdr = CHAN_TO_WDC_REGS(chp);
1.279 martin 209: uint8_t st = 0, sc __unused, sn __unused, cl, ch;
1.284 jdolecek 210: int i;
1.239 bouyer 211:
1.274 bouyer 212: KASSERT(chp->ch_ndrives == 0 || chp->ch_drive != NULL);
1.239 bouyer 213:
1.284 jdolecek 214: /* do this before we take lock */
215:
216: ata_channel_lock(chp);
217:
1.242 bouyer 218: /* reset the PHY and bring online */
219: switch (sata_reset_interface(chp, wdr->sata_iot, wdr->sata_control,
1.278 bouyer 220: wdr->sata_status, AT_WAIT)) {
1.239 bouyer 221: case SStatus_DET_DEV:
1.258 sborrill 222: /* wait 5s for BSY to clear */
223: for (i = 0; i < WDC_PROBE_WAIT * hz; i++) {
224: bus_space_write_1(wdr->cmd_iot,
225: wdr->cmd_iohs[wd_sdh], 0, WDSD_IBM);
226: delay(10); /* 400ns delay */
227: st = bus_space_read_1(wdr->cmd_iot,
228: wdr->cmd_iohs[wd_status], 0);
229: if ((st & WDCS_BSY) == 0)
230: break;
1.284 jdolecek 231: ata_delay(chp, 1, "sataprb", AT_WAIT);
1.258 sborrill 232: }
233: if (i == WDC_PROBE_WAIT * hz)
234: aprint_error_dev(chp->ch_atac->atac_dev,
235: "BSY never cleared, status 0x%02x\n", st);
236: sc = bus_space_read_1(wdr->cmd_iot,
1.239 bouyer 237: wdr->cmd_iohs[wd_seccnt], 0);
1.258 sborrill 238: sn = bus_space_read_1(wdr->cmd_iot,
1.239 bouyer 239: wdr->cmd_iohs[wd_sector], 0);
1.258 sborrill 240: cl = bus_space_read_1(wdr->cmd_iot,
1.239 bouyer 241: wdr->cmd_iohs[wd_cyl_lo], 0);
1.258 sborrill 242: ch = bus_space_read_1(wdr->cmd_iot,
1.239 bouyer 243: wdr->cmd_iohs[wd_cyl_hi], 0);
1.258 sborrill 244: ATADEBUG_PRINT(("%s: port %d: sc=0x%x sn=0x%x "
1.239 bouyer 245: "cl=0x%x ch=0x%x\n",
1.253 cube 246: device_xname(chp->ch_atac->atac_dev), chp->ch_channel,
1.258 sborrill 247: sc, sn, cl, ch), DEBUG_PROBE);
1.307 rin 248: if (atabus_alloc_drives(chp, wdc->wdc_maxdrives) != 0) {
249: ata_channel_unlock(chp);
1.274 bouyer 250: return;
1.307 rin 251: }
1.239 bouyer 252: /*
1.258 sborrill 253: * sc and sn are supposed to be 0x1 for ATAPI, but in some
1.239 bouyer 254: * cases we get wrong values here, so ignore it.
255: */
256: if (cl == 0x14 && ch == 0xeb)
1.274 bouyer 257: chp->ch_drive[0].drive_type = ATA_DRIVET_ATAPI;
1.239 bouyer 258: else
1.274 bouyer 259: chp->ch_drive[0].drive_type = ATA_DRIVET_ATA;
1.239 bouyer 260:
1.241 bouyer 261: /*
262: * issue a reset in case only the interface part of the drive
263: * is up
264: */
265: if (wdcreset(chp, RESET_SLEEP) != 0)
1.274 bouyer 266: chp->ch_drive[0].drive_type = ATA_DRIVET_NONE;
1.239 bouyer 267: break;
268:
269: default:
1.242 bouyer 270: break;
1.239 bouyer 271: }
1.284 jdolecek 272:
273: ata_channel_unlock(chp);
1.239 bouyer 274: }
1.240 bouyer 275: #endif /* NSATA > 0 */
1.239 bouyer 276:
277:
1.162 thorpej 278: /* Test to see controller with at last one attached drive is there.
279: * Returns a bit for each possible drive found (0x01 for drive 0,
280: * 0x02 for drive 1).
281: * Logic:
282: * - If a status register is at 0xff, assume there is no drive here
283: * (ISA has pull-up resistors). Similarly if the status register has
284: * the value we last wrote to the bus (for IDE interfaces without pullups).
285: * If no drive at all -> return.
286: * - reset the controller, wait for it to complete (may take up to 31s !).
287: * If timeout -> return.
288: * - test ATA/ATAPI signatures. If at last one drive found -> return.
289: * - try an ATA command on the master.
290: */
1.137 bouyer 291:
1.239 bouyer 292: void
1.205 thorpej 293: wdc_drvprobe(struct ata_channel *chp)
1.137 bouyer 294: {
1.257 pooka 295: struct ataparams params; /* XXX: large struct */
1.207 thorpej 296: struct atac_softc *atac = chp->ch_atac;
297: struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.205 thorpej 298: struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
1.145 christos 299: u_int8_t st0 = 0, st1 = 0;
1.284 jdolecek 300: int i, j, error, tfd;
1.137 bouyer 301:
1.293 martin 302: ata_channel_lock(chp);
1.294 christos 303: if (atabus_alloc_drives(chp, wdc->wdc_maxdrives) != 0) {
304: ata_channel_unlock(chp);
1.274 bouyer 305: return;
1.294 christos 306: }
1.164 thorpej 307: if (wdcprobe1(chp, 0) == 0) {
308: /* No drives, abort the attach here. */
1.274 bouyer 309: atabus_free_drives(chp);
1.293 martin 310: ata_channel_unlock(chp);
1.164 thorpej 311: return;
1.161 thorpej 312: }
1.137 bouyer 313:
314: /* for ATA/OLD drives, wait for DRDY, 3s timeout */
315: for (i = 0; i < mstohz(3000); i++) {
1.263 bouyer 316: /*
317: * select drive 1 first, so that master is selected on
318: * exit from the loop
319: */
1.274 bouyer 320: if (chp->ch_ndrives > 1 &&
321: chp->ch_drive[1].drive_type == ATA_DRIVET_ATA) {
1.263 bouyer 322: if (wdc->select)
323: wdc->select(chp,1);
324: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh],
325: 0, WDSD_IBM | 0x10);
326: delay(10); /* 400ns delay */
327: st1 = bus_space_read_1(wdr->cmd_iot,
328: wdr->cmd_iohs[wd_status], 0);
329: }
1.274 bouyer 330: if (chp->ch_drive[0].drive_type == ATA_DRIVET_ATA) {
1.207 thorpej 331: if (wdc->select)
1.174 bouyer 332: wdc->select(chp,0);
1.205 thorpej 333: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh],
1.174 bouyer 334: 0, WDSD_IBM);
335: delay(10); /* 400ns delay */
1.205 thorpej 336: st0 = bus_space_read_1(wdr->cmd_iot,
337: wdr->cmd_iohs[wd_status], 0);
1.174 bouyer 338: }
1.219 perry 339:
340:
1.274 bouyer 341: if ((chp->ch_drive[0].drive_type != ATA_DRIVET_ATA ||
342: (st0 & WDCS_DRDY)) &&
343: (chp->ch_ndrives < 2 ||
344: chp->ch_drive[1].drive_type != ATA_DRIVET_ATA ||
345: (st1 & WDCS_DRDY)))
1.137 bouyer 346: break;
1.263 bouyer 347: #ifdef WDC_NO_IDS
1.304 skrll 348: /* cannot kpause here (can't enable IPL_BIO interrupts),
1.263 bouyer 349: * delay instead
350: */
351: delay(1000000 / hz);
352: #else
1.284 jdolecek 353: ata_delay(chp, 1, "atadrdy", AT_WAIT);
1.265 bouyer 354: #endif
1.264 christos 355: }
1.274 bouyer 356: if ((st0 & WDCS_DRDY) == 0 &&
357: chp->ch_drive[0].drive_type != ATA_DRIVET_ATAPI)
358: chp->ch_drive[0].drive_type = ATA_DRIVET_NONE;
359: if (chp->ch_ndrives > 1 && (st1 & WDCS_DRDY) == 0 &&
360: chp->ch_drive[1].drive_type != ATA_DRIVET_ATAPI)
361: chp->ch_drive[1].drive_type = ATA_DRIVET_NONE;
1.284 jdolecek 362: ata_channel_unlock(chp);
1.137 bouyer 363:
1.204 thorpej 364: ATADEBUG_PRINT(("%s:%d: wait DRDY st0 0x%x st1 0x%x\n",
1.253 cube 365: device_xname(atac->atac_dev),
1.169 thorpej 366: chp->ch_channel, st0, st1), DEBUG_PROBE);
1.137 bouyer 367:
368: /* Wait a bit, some devices are weird just after a reset. */
369: delay(5000);
370:
1.274 bouyer 371: for (i = 0; i < chp->ch_ndrives; i++) {
1.238 itohy 372: #if NATA_DMA
1.137 bouyer 373: /*
1.282 skrll 374: * Init error counter so that an error within the first xfers
1.137 bouyer 375: * will trigger a downgrade
376: */
1.306 skrll 377: chp->ch_drive[i].n_dmaerrs = NERRS_MAX - 1;
1.238 itohy 378: #endif
1.137 bouyer 379:
380: /* If controller can't do 16bit flag the drives as 32bit */
1.207 thorpej 381: if ((atac->atac_cap &
1.212 thorpej 382: (ATAC_CAP_DATA16 | ATAC_CAP_DATA32)) == ATAC_CAP_DATA32) {
1.284 jdolecek 383: ata_channel_lock(chp);
1.274 bouyer 384: chp->ch_drive[i].drive_flags |= ATA_DRIVE_CAP32;
1.284 jdolecek 385: ata_channel_unlock(chp);
1.212 thorpej 386: }
1.274 bouyer 387: if (chp->ch_drive[i].drive_type == ATA_DRIVET_NONE)
1.137 bouyer 388: continue;
389:
1.144 briggs 390: /* Shortcut in case we've been shutdown */
1.205 thorpej 391: if (chp->ch_flags & ATACH_SHUTDOWN)
1.164 thorpej 392: return;
1.144 briggs 393:
1.216 bouyer 394: /*
395: * Issue an identify, to try to detect ghosts.
396: * Note that we can't use interrupts here, because if there
397: * is no devices, we will get a command aborted without
398: * interrupts.
399: */
400: error = ata_get_params(&chp->ch_drive[i],
401: AT_WAIT | AT_POLL, ¶ms);
1.137 bouyer 402: if (error != CMD_OK) {
1.284 jdolecek 403: ata_channel_lock(chp);
404: ata_delay(chp, 1000, "atacnf", AT_WAIT);
405: ata_channel_unlock(chp);
1.144 briggs 406:
407: /* Shortcut in case we've been shutdown */
1.205 thorpej 408: if (chp->ch_flags & ATACH_SHUTDOWN)
1.164 thorpej 409: return;
1.144 briggs 410:
1.137 bouyer 411: error = ata_get_params(&chp->ch_drive[i],
1.216 bouyer 412: AT_WAIT | AT_POLL, ¶ms);
1.137 bouyer 413: }
1.274 bouyer 414: if (error != CMD_OK) {
1.204 thorpej 415: ATADEBUG_PRINT(("%s:%d:%d: IDENTIFY failed (%d)\n",
1.253 cube 416: device_xname(atac->atac_dev),
1.169 thorpej 417: chp->ch_channel, i, error), DEBUG_PROBE);
1.284 jdolecek 418: ata_channel_lock(chp);
1.274 bouyer 419: if (chp->ch_drive[i].drive_type != ATA_DRIVET_ATA ||
420: (wdc->cap & WDC_CAPABILITY_PREATA) == 0) {
421: chp->ch_drive[i].drive_type = ATA_DRIVET_NONE;
1.284 jdolecek 422: ata_channel_unlock(chp);
1.137 bouyer 423: continue;
1.274 bouyer 424: }
1.137 bouyer 425: /*
426: * Pre-ATA drive ?
427: * Test registers writability (Error register not
428: * writable, but cyllo is), then try an ATA command.
429: */
1.203 thorpej 430: if (wdc->select)
1.169 thorpej 431: wdc->select(chp,i);
1.205 thorpej 432: bus_space_write_1(wdr->cmd_iot,
433: wdr->cmd_iohs[wd_sdh], 0, WDSD_IBM | (i << 4));
1.137 bouyer 434: delay(10); /* 400ns delay */
1.205 thorpej 435: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_error],
1.157 fvdl 436: 0, 0x58);
1.205 thorpej 437: bus_space_write_1(wdr->cmd_iot,
438: wdr->cmd_iohs[wd_cyl_lo], 0, 0xa5);
439: if (bus_space_read_1(wdr->cmd_iot,
440: wdr->cmd_iohs[wd_error], 0) == 0x58 ||
441: bus_space_read_1(wdr->cmd_iot,
442: wdr->cmd_iohs[wd_cyl_lo], 0) != 0xa5) {
1.204 thorpej 443: ATADEBUG_PRINT(("%s:%d:%d: register "
1.137 bouyer 444: "writability failed\n",
1.253 cube 445: device_xname(atac->atac_dev),
1.169 thorpej 446: chp->ch_channel, i), DEBUG_PROBE);
1.274 bouyer 447: chp->ch_drive[i].drive_type = ATA_DRIVET_NONE;
1.284 jdolecek 448: ata_channel_unlock(chp);
1.155 bouyer 449: continue;
1.137 bouyer 450: }
1.284 jdolecek 451: if (wdc_wait_for_ready(chp, 10000, 0, &tfd) ==
452: WDCWAIT_TOUT) {
1.204 thorpej 453: ATADEBUG_PRINT(("%s:%d:%d: not ready\n",
1.253 cube 454: device_xname(atac->atac_dev),
1.169 thorpej 455: chp->ch_channel, i), DEBUG_PROBE);
1.274 bouyer 456: chp->ch_drive[i].drive_type = ATA_DRIVET_NONE;
1.284 jdolecek 457: ata_channel_unlock(chp);
1.137 bouyer 458: continue;
459: }
1.205 thorpej 460: bus_space_write_1(wdr->cmd_iot,
461: wdr->cmd_iohs[wd_command], 0, WDCC_RECAL);
1.137 bouyer 462: delay(10); /* 400ns delay */
1.284 jdolecek 463: if (wdc_wait_for_ready(chp, 10000, 0, &tfd) ==
464: WDCWAIT_TOUT) {
1.204 thorpej 465: ATADEBUG_PRINT(("%s:%d:%d: WDCC_RECAL failed\n",
1.253 cube 466: device_xname(atac->atac_dev),
1.169 thorpej 467: chp->ch_channel, i), DEBUG_PROBE);
1.274 bouyer 468: chp->ch_drive[i].drive_type = ATA_DRIVET_NONE;
1.284 jdolecek 469: ata_channel_unlock(chp);
1.155 bouyer 470: } else {
1.274 bouyer 471: for (j = 0; j < chp->ch_ndrives; j++) {
472: if (chp->ch_drive[i].drive_type !=
473: ATA_DRIVET_NONE) {
474: chp->ch_drive[j].drive_type =
475: ATA_DRIVET_OLD;
476: }
477: }
1.284 jdolecek 478: ata_channel_unlock(chp);
1.137 bouyer 479: }
480: }
481: }
1.164 thorpej 482: }
483:
1.2 bouyer 484: int
1.284 jdolecek 485: wdcprobe(struct wdc_regs *wdr)
1.12 cgd 486: {
1.292 tsutsui 487:
488: return wdcprobe_with_reset(wdr, NULL);
489: }
490:
491: int
492: wdcprobe_with_reset(struct wdc_regs *wdr,
493: void (*do_reset)(struct ata_channel *, int))
494: {
1.302 jdolecek 495: struct wdc_softc *wdc;
496: struct ata_channel *ch;
1.284 jdolecek 497: int rv;
498:
1.302 jdolecek 499: wdc = kmem_zalloc(sizeof(*wdc), KM_SLEEP);
500: ch = kmem_zalloc(sizeof(*ch), KM_SLEEP);
501:
502: ata_channel_init(ch);
503: ch->ch_atac = &wdc->sc_atac;
504: wdc->regs = wdr;
1.284 jdolecek 505:
1.292 tsutsui 506: /* check the MD reset method */
1.302 jdolecek 507: wdc->reset = (do_reset != NULL) ? do_reset : wdc_do_reset;
508:
509: ata_channel_lock(ch);
510: rv = wdcprobe1(ch, 1);
511: ata_channel_unlock(ch);
1.284 jdolecek 512:
1.302 jdolecek 513: ata_channel_destroy(ch);
1.284 jdolecek 514:
1.302 jdolecek 515: kmem_free(ch, sizeof(*ch));
516: kmem_free(wdc, sizeof(*wdc));
1.163 thorpej 517:
1.284 jdolecek 518: return rv;
1.137 bouyer 519: }
520:
1.167 thorpej 521: static int
1.205 thorpej 522: wdcprobe1(struct ata_channel *chp, int poll)
1.137 bouyer 523: {
1.207 thorpej 524: struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.205 thorpej 525: struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
1.279 martin 526: u_int8_t st0 = 0, st1 = 0, sc __unused, sn __unused, cl, ch;
1.31 bouyer 527: u_int8_t ret_value = 0x03;
528: u_int8_t drive;
1.247 dyoung 529: /* XXX if poll, wdc_probe_count is 0. */
1.224 bouyer 530: int wdc_probe_count =
1.247 dyoung 531: poll ? (WDC_PROBE_WAIT / WDCDELAY)
532: : (WDC_PROBE_WAIT * hz);
1.31 bouyer 533:
534: /*
535: * Sanity check to see if the wdc channel responds at all.
536: */
537:
1.207 thorpej 538: if ((wdc->cap & WDC_CAPABILITY_NO_EXTRA_RESETS) == 0) {
1.224 bouyer 539: while (wdc_probe_count-- > 0) {
540: if (wdc->select)
541: wdc->select(chp,0);
1.107 dbj 542:
1.224 bouyer 543: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh],
544: 0, WDSD_IBM);
545: delay(10); /* 400ns delay */
546: st0 = bus_space_read_1(wdr->cmd_iot,
547: wdr->cmd_iohs[wd_status], 0);
1.137 bouyer 548:
1.224 bouyer 549: if (wdc->select)
550: wdc->select(chp,1);
1.219 perry 551:
1.224 bouyer 552: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh],
553: 0, WDSD_IBM | 0x10);
554: delay(10); /* 400ns delay */
555: st1 = bus_space_read_1(wdr->cmd_iot,
556: wdr->cmd_iohs[wd_status], 0);
557: if ((st0 & WDCS_BSY) == 0)
558: break;
559: }
1.43 kenh 560:
1.204 thorpej 561: ATADEBUG_PRINT(("%s:%d: before reset, st0=0x%x, st1=0x%x\n",
1.280 msaitoh 562: __func__, chp->ch_channel, st0, st1), DEBUG_PROBE);
1.43 kenh 563:
1.142 bouyer 564: if (st0 == 0xff || st0 == WDSD_IBM)
1.43 kenh 565: ret_value &= ~0x01;
1.142 bouyer 566: if (st1 == 0xff || st1 == (WDSD_IBM | 0x10))
1.43 kenh 567: ret_value &= ~0x02;
1.125 mycroft 568: /* Register writability test, drive 0. */
569: if (ret_value & 0x01) {
1.207 thorpej 570: if (wdc->select)
1.169 thorpej 571: wdc->select(chp,0);
1.205 thorpej 572: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh],
1.157 fvdl 573: 0, WDSD_IBM);
1.205 thorpej 574: bus_space_write_1(wdr->cmd_iot,
575: wdr->cmd_iohs[wd_cyl_lo], 0, 0x02);
576: cl = bus_space_read_1(wdr->cmd_iot,
577: wdr->cmd_iohs[wd_cyl_lo], 0);
1.174 bouyer 578: if (cl != 0x02) {
1.204 thorpej 579: ATADEBUG_PRINT(("%s:%d drive 0 wd_cyl_lo: "
1.174 bouyer 580: "got 0x%x != 0x02\n",
1.280 msaitoh 581: __func__, chp->ch_channel, cl),
1.174 bouyer 582: DEBUG_PROBE);
1.125 mycroft 583: ret_value &= ~0x01;
1.174 bouyer 584: }
1.205 thorpej 585: bus_space_write_1(wdr->cmd_iot,
586: wdr->cmd_iohs[wd_cyl_lo], 0, 0x01);
587: cl = bus_space_read_1(wdr->cmd_iot,
588: wdr->cmd_iohs[wd_cyl_lo], 0);
1.174 bouyer 589: if (cl != 0x01) {
1.204 thorpej 590: ATADEBUG_PRINT(("%s:%d drive 0 wd_cyl_lo: "
1.174 bouyer 591: "got 0x%x != 0x01\n",
1.280 msaitoh 592: __func__, chp->ch_channel, cl),
1.174 bouyer 593: DEBUG_PROBE);
1.125 mycroft 594: ret_value &= ~0x01;
1.174 bouyer 595: }
1.205 thorpej 596: bus_space_write_1(wdr->cmd_iot,
597: wdr->cmd_iohs[wd_sector], 0, 0x01);
598: cl = bus_space_read_1(wdr->cmd_iot,
599: wdr->cmd_iohs[wd_sector], 0);
1.174 bouyer 600: if (cl != 0x01) {
1.204 thorpej 601: ATADEBUG_PRINT(("%s:%d drive 0 wd_sector: "
1.174 bouyer 602: "got 0x%x != 0x01\n",
1.280 msaitoh 603: __func__, chp->ch_channel, cl),
1.174 bouyer 604: DEBUG_PROBE);
1.125 mycroft 605: ret_value &= ~0x01;
1.174 bouyer 606: }
1.205 thorpej 607: bus_space_write_1(wdr->cmd_iot,
608: wdr->cmd_iohs[wd_sector], 0, 0x02);
609: cl = bus_space_read_1(wdr->cmd_iot,
610: wdr->cmd_iohs[wd_sector], 0);
1.174 bouyer 611: if (cl != 0x02) {
1.204 thorpej 612: ATADEBUG_PRINT(("%s:%d drive 0 wd_sector: "
1.174 bouyer 613: "got 0x%x != 0x02\n",
1.280 msaitoh 614: __func__, chp->ch_channel, cl),
1.174 bouyer 615: DEBUG_PROBE);
1.125 mycroft 616: ret_value &= ~0x01;
1.174 bouyer 617: }
1.205 thorpej 618: cl = bus_space_read_1(wdr->cmd_iot,
619: wdr->cmd_iohs[wd_cyl_lo], 0);
1.174 bouyer 620: if (cl != 0x01) {
1.204 thorpej 621: ATADEBUG_PRINT(("%s:%d drive 0 wd_cyl_lo(2): "
1.174 bouyer 622: "got 0x%x != 0x01\n",
1.280 msaitoh 623: __func__, chp->ch_channel, cl),
1.174 bouyer 624: DEBUG_PROBE);
1.131 mycroft 625: ret_value &= ~0x01;
1.174 bouyer 626: }
1.125 mycroft 627: }
628: /* Register writability test, drive 1. */
629: if (ret_value & 0x02) {
1.207 thorpej 630: if (wdc->select)
1.169 thorpej 631: wdc->select(chp,1);
1.205 thorpej 632: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh],
1.157 fvdl 633: 0, WDSD_IBM | 0x10);
1.205 thorpej 634: bus_space_write_1(wdr->cmd_iot,
635: wdr->cmd_iohs[wd_cyl_lo], 0, 0x02);
636: cl = bus_space_read_1(wdr->cmd_iot,
637: wdr->cmd_iohs[wd_cyl_lo], 0);
1.174 bouyer 638: if (cl != 0x02) {
1.204 thorpej 639: ATADEBUG_PRINT(("%s:%d drive 1 wd_cyl_lo: "
1.174 bouyer 640: "got 0x%x != 0x02\n",
1.280 msaitoh 641: __func__, chp->ch_channel, cl),
1.174 bouyer 642: DEBUG_PROBE);
1.125 mycroft 643: ret_value &= ~0x02;
1.174 bouyer 644: }
1.205 thorpej 645: bus_space_write_1(wdr->cmd_iot,
646: wdr->cmd_iohs[wd_cyl_lo], 0, 0x01);
647: cl = bus_space_read_1(wdr->cmd_iot,
648: wdr->cmd_iohs[wd_cyl_lo], 0);
1.174 bouyer 649: if (cl != 0x01) {
1.204 thorpej 650: ATADEBUG_PRINT(("%s:%d drive 1 wd_cyl_lo: "
1.174 bouyer 651: "got 0x%x != 0x01\n",
1.280 msaitoh 652: __func__, chp->ch_channel, cl),
1.174 bouyer 653: DEBUG_PROBE);
1.125 mycroft 654: ret_value &= ~0x02;
1.174 bouyer 655: }
1.205 thorpej 656: bus_space_write_1(wdr->cmd_iot,
657: wdr->cmd_iohs[wd_sector], 0, 0x01);
658: cl = bus_space_read_1(wdr->cmd_iot,
659: wdr->cmd_iohs[wd_sector], 0);
1.174 bouyer 660: if (cl != 0x01) {
1.204 thorpej 661: ATADEBUG_PRINT(("%s:%d drive 1 wd_sector: "
1.174 bouyer 662: "got 0x%x != 0x01\n",
1.280 msaitoh 663: __func__, chp->ch_channel, cl),
1.174 bouyer 664: DEBUG_PROBE);
1.125 mycroft 665: ret_value &= ~0x02;
1.174 bouyer 666: }
1.205 thorpej 667: bus_space_write_1(wdr->cmd_iot,
668: wdr->cmd_iohs[wd_sector], 0, 0x02);
669: cl = bus_space_read_1(wdr->cmd_iot,
670: wdr->cmd_iohs[wd_sector], 0);
1.174 bouyer 671: if (cl != 0x02) {
1.204 thorpej 672: ATADEBUG_PRINT(("%s:%d drive 1 wd_sector: "
1.174 bouyer 673: "got 0x%x != 0x02\n",
1.280 msaitoh 674: __func__, chp->ch_channel, cl),
1.174 bouyer 675: DEBUG_PROBE);
1.125 mycroft 676: ret_value &= ~0x02;
1.174 bouyer 677: }
1.205 thorpej 678: cl = bus_space_read_1(wdr->cmd_iot,
679: wdr->cmd_iohs[wd_cyl_lo], 0);
1.174 bouyer 680: if (cl != 0x01) {
1.204 thorpej 681: ATADEBUG_PRINT(("%s:%d drive 1 wd_cyl_lo(2): "
1.174 bouyer 682: "got 0x%x != 0x01\n",
1.280 msaitoh 683: __func__, chp->ch_channel, cl),
1.174 bouyer 684: DEBUG_PROBE);
1.131 mycroft 685: ret_value &= ~0x02;
1.174 bouyer 686: }
1.125 mycroft 687: }
1.137 bouyer 688:
1.174 bouyer 689: if (ret_value == 0) {
1.137 bouyer 690: return 0;
1.174 bouyer 691: }
1.62 bouyer 692: }
1.31 bouyer 693:
1.181 bouyer 694: #if 0 /* XXX this break some ATA or ATAPI devices */
1.174 bouyer 695: /*
696: * reset bus. Also send an ATAPI_RESET to devices, in case there are
697: * ATAPI device out there which don't react to the bus reset
698: */
699: if (ret_value & 0x01) {
1.207 thorpej 700: if (wdc->select)
1.174 bouyer 701: wdc->select(chp,0);
1.205 thorpej 702: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh],
1.174 bouyer 703: 0, WDSD_IBM);
1.205 thorpej 704: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_command], 0,
1.174 bouyer 705: ATAPI_SOFT_RESET);
706: }
707: if (ret_value & 0x02) {
1.207 thorpej 708: if (wdc->select)
1.174 bouyer 709: wdc->select(chp,0);
1.205 thorpej 710: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh],
1.174 bouyer 711: 0, WDSD_IBM | 0x10);
1.205 thorpej 712: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_command], 0,
1.174 bouyer 713: ATAPI_SOFT_RESET);
714: }
1.156 bouyer 715:
1.175 bouyer 716: delay(5000);
1.181 bouyer 717: #endif
1.175 bouyer 718:
1.225 bouyer 719: wdc->reset(chp, RESET_POLL);
1.137 bouyer 720: DELAY(2000);
1.205 thorpej 721: (void) bus_space_read_1(wdr->cmd_iot, wdr->cmd_iohs[wd_error], 0);
1.275 rkujawa 722:
1.305 skrll 723: if (! (wdc->cap & WDC_CAPABILITY_NO_AUXCTL))
724: bus_space_write_1(wdr->ctl_iot, wdr->ctl_ioh, wd_aux_ctlr,
1.275 rkujawa 725: WDCTL_4BIT);
726:
1.263 bouyer 727: #ifdef WDC_NO_IDS
728: ret_value = __wdcwait_reset(chp, ret_value, RESET_POLL);
729: #else
1.137 bouyer 730: ret_value = __wdcwait_reset(chp, ret_value, poll);
1.263 bouyer 731: #endif
1.283 msaitoh 732: ATADEBUG_PRINT(("%s:%d: after reset, ret_value=%#x\n",
1.280 msaitoh 733: __func__, chp->ch_channel, ret_value), DEBUG_PROBE);
1.12 cgd 734:
1.137 bouyer 735: /* if reset failed, there's nothing here */
1.263 bouyer 736: if (ret_value == 0) {
1.137 bouyer 737: return 0;
1.263 bouyer 738: }
1.67 bouyer 739:
1.12 cgd 740: /*
1.167 thorpej 741: * Test presence of drives. First test register signatures looking
742: * for ATAPI devices. If it's not an ATAPI and reset said there may
743: * be something here assume it's ATA or OLD. Ghost will be killed
744: * later in attach routine.
1.12 cgd 745: */
1.274 bouyer 746: for (drive = 0; drive < wdc->wdc_maxdrives; drive++) {
1.137 bouyer 747: if ((ret_value & (0x01 << drive)) == 0)
748: continue;
1.207 thorpej 749: if (wdc->select)
1.169 thorpej 750: wdc->select(chp,drive);
1.205 thorpej 751: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], 0,
1.137 bouyer 752: WDSD_IBM | (drive << 4));
753: delay(10); /* 400ns delay */
754: /* Save registers contents */
1.205 thorpej 755: sc = bus_space_read_1(wdr->cmd_iot,
756: wdr->cmd_iohs[wd_seccnt], 0);
757: sn = bus_space_read_1(wdr->cmd_iot,
758: wdr->cmd_iohs[wd_sector], 0);
759: cl = bus_space_read_1(wdr->cmd_iot,
760: wdr->cmd_iohs[wd_cyl_lo], 0);
761: ch = bus_space_read_1(wdr->cmd_iot,
762: wdr->cmd_iohs[wd_cyl_hi], 0);
1.137 bouyer 763:
1.204 thorpej 764: ATADEBUG_PRINT(("%s:%d:%d: after reset, sc=0x%x sn=0x%x "
1.280 msaitoh 765: "cl=0x%x ch=0x%x\n", __func__, chp->ch_channel, drive, sc,
766: sn, cl, ch), DEBUG_PROBE);
1.31 bouyer 767: /*
1.266 jakllsch 768: * sc & sn are supposed to be 0x1 for ATAPI but in some cases
1.137 bouyer 769: * we get wrong values here, so ignore it.
1.31 bouyer 770: */
1.274 bouyer 771: if (chp->ch_drive != NULL) {
772: if (cl == 0x14 && ch == 0xeb) {
773: chp->ch_drive[drive].drive_type = ATA_DRIVET_ATAPI;
774: } else {
775: chp->ch_drive[drive].drive_type = ATA_DRIVET_ATA;
776: }
1.137 bouyer 777: }
1.31 bouyer 778: }
1.263 bouyer 779: /*
780: * Select an existing drive before lowering spl, some WDC_NO_IDS
781: * devices incorrectly assert IRQ on nonexistent slave
782: */
783: if (ret_value & 0x01) {
784: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], 0,
785: WDSD_IBM);
786: (void)bus_space_read_1(wdr->cmd_iot,
787: wdr->cmd_iohs[wd_status], 0);
788: }
1.219 perry 789: return (ret_value);
1.137 bouyer 790: }
1.31 bouyer 791:
1.137 bouyer 792: void
1.205 thorpej 793: wdcattach(struct ata_channel *chp)
1.137 bouyer 794: {
1.207 thorpej 795: struct atac_softc *atac = chp->ch_atac;
796: struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.32 bouyer 797:
1.274 bouyer 798: KASSERT(wdc->wdc_maxdrives > 0 && wdc->wdc_maxdrives <= WDC_MAXDRIVES);
1.205 thorpej 799:
1.191 mycroft 800: /* default data transfer methods */
1.210 thorpej 801: if (wdc->datain_pio == NULL)
1.191 mycroft 802: wdc->datain_pio = wdc_datain_pio;
1.210 thorpej 803: if (wdc->dataout_pio == NULL)
1.191 mycroft 804: wdc->dataout_pio = wdc_dataout_pio;
1.225 bouyer 805: /* default reset method */
806: if (wdc->reset == NULL)
807: wdc->reset = wdc_do_reset;
1.191 mycroft 808:
1.137 bouyer 809: /* initialise global data */
1.208 thorpej 810: if (atac->atac_bustype_ata == NULL)
811: atac->atac_bustype_ata = &wdc_ata_bustype;
1.207 thorpej 812: if (atac->atac_probe == NULL)
813: atac->atac_probe = wdc_drvprobe;
1.208 thorpej 814: #if NATAPIBUS > 0
815: if (atac->atac_atapibus_attach == NULL)
816: atac->atac_atapibus_attach = wdc_atapibus_attach;
817: #endif
1.198 thorpej 818:
1.210 thorpej 819: ata_channel_attach(chp);
1.74 enami 820: }
821:
1.250 dyoung 822: void
823: wdc_childdetached(device_t self, device_t child)
824: {
825: struct atac_softc *atac = device_private(self);
826: struct ata_channel *chp;
827: int i;
828:
829: for (i = 0; i < atac->atac_nchannels; i++) {
830: chp = atac->atac_channels[i];
831: if (child == chp->atabus) {
832: chp->atabus = NULL;
833: return;
834: }
835: }
836: }
837:
1.137 bouyer 838: int
1.250 dyoung 839: wdcdetach(device_t self, int flags)
1.137 bouyer 840: {
1.250 dyoung 841: struct atac_softc *atac = device_private(self);
1.205 thorpej 842: struct ata_channel *chp;
1.207 thorpej 843: struct scsipi_adapter *adapt = &atac->atac_atapi_adapter._generic;
1.137 bouyer 844: int i, error = 0;
845:
1.207 thorpej 846: for (i = 0; i < atac->atac_nchannels; i++) {
847: chp = atac->atac_channels[i];
1.250 dyoung 848: if (chp->atabus == NULL)
849: continue;
1.204 thorpej 850: ATADEBUG_PRINT(("wdcdetach: %s: detaching %s\n",
1.253 cube 851: device_xname(atac->atac_dev), device_xname(chp->atabus)),
1.207 thorpej 852: DEBUG_DETACH);
1.251 dyoung 853: if ((error = config_detach(chp->atabus, flags)) != 0)
854: return error;
1.284 jdolecek 855: ata_channel_detach(chp);
1.137 bouyer 856: }
1.252 dyoung 857: if (adapt->adapt_refcnt != 0)
858: return EBUSY;
1.251 dyoung 859: return 0;
1.137 bouyer 860: }
861:
1.31 bouyer 862: /* restart an interrupted I/O */
863: void
1.163 thorpej 864: wdcrestart(void *v)
1.31 bouyer 865: {
1.205 thorpej 866: struct ata_channel *chp = v;
1.31 bouyer 867: int s;
1.2 bouyer 868:
1.31 bouyer 869: s = splbio();
1.202 thorpej 870: atastart(chp);
1.31 bouyer 871: splx(s);
1.2 bouyer 872: }
1.219 perry 873:
1.2 bouyer 874:
1.31 bouyer 875: /*
876: * Interrupt routine for the controller. Acknowledge the interrupt, check for
877: * errors on the current operation, mark it done if necessary, and start the
878: * next request. Also check for a partially done transfer, and continue with
879: * the next chunk if so.
880: */
1.12 cgd 881: int
1.163 thorpej 882: wdcintr(void *arg)
1.12 cgd 883: {
1.205 thorpej 884: struct ata_channel *chp = arg;
1.207 thorpej 885: struct atac_softc *atac = chp->ch_atac;
886: struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.205 thorpej 887: struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
1.165 thorpej 888: struct ata_xfer *xfer;
1.76 bouyer 889: int ret;
1.12 cgd 890:
1.253 cube 891: if (!device_is_active(atac->atac_dev)) {
1.204 thorpej 892: ATADEBUG_PRINT(("wdcintr: deactivated controller\n"),
1.80 enami 893: DEBUG_INTR);
894: return (0);
895: }
1.284 jdolecek 896:
1.303 bouyer 897: if ((chp->ch_flags & ATACH_IRQ_WAIT) == 0)
1.287 jdolecek 898: goto ignore;
899:
1.284 jdolecek 900: xfer = ata_queue_get_active_xfer(chp);
901: if (xfer == NULL) {
1.204 thorpej 902: ATADEBUG_PRINT(("wdcintr: inactive controller\n"), DEBUG_INTR);
1.285 jdolecek 903: ignore:
1.113 bouyer 904: /* try to clear the pending interrupt anyway */
1.205 thorpej 905: (void)bus_space_read_1(wdr->cmd_iot,
906: wdr->cmd_iohs[wd_status], 0);
1.80 enami 907: return (0);
1.31 bouyer 908: }
1.12 cgd 909:
1.285 jdolecek 910: /*
1.286 jdolecek 911: * On some controllers (e.g. some PCI-IDE) setting the WDCTL_IDS bit
1.285 jdolecek 912: * actually has no effect, and interrupt is triggered regardless.
913: * Ignore polled commands here, they are processed separately.
914: */
915: if (ISSET(xfer->c_flags, C_POLL)) {
916: ATADEBUG_PRINT(("%s: polled xfer ignored\n", __func__),
917: DEBUG_INTR);
918: goto ignore;
919: }
920:
1.204 thorpej 921: ATADEBUG_PRINT(("wdcintr\n"), DEBUG_INTR);
1.284 jdolecek 922: KASSERT(xfer != NULL);
923:
1.238 itohy 924: #if NATA_DMA || NATA_PIOBM
1.205 thorpej 925: if (chp->ch_flags & ATACH_DMA_WAIT) {
1.169 thorpej 926: wdc->dma_status =
927: (*wdc->dma_finish)(wdc->dma_arg, chp->ch_channel,
1.185 bouyer 928: xfer->c_drive, WDC_DMAEND_END);
1.169 thorpej 929: if (wdc->dma_status & WDC_DMAST_NOIRQ) {
1.84 bouyer 930: /* IRQ not for us, not detected by DMA engine */
931: return 0;
932: }
1.205 thorpej 933: chp->ch_flags &= ~ATACH_DMA_WAIT;
1.84 bouyer 934: }
1.238 itohy 935: #endif
1.287 jdolecek 936: chp->ch_flags &= ~ATACH_IRQ_WAIT;
1.289 jdolecek 937: KASSERT(xfer->ops != NULL && xfer->ops->c_intr != NULL);
938: ret = xfer->ops->c_intr(chp, xfer, 1);
1.287 jdolecek 939: if (ret == 0) /* irq was not for us, still waiting for irq */
940: chp->ch_flags |= ATACH_IRQ_WAIT;
1.76 bouyer 941: return (ret);
1.12 cgd 942: }
943:
1.31 bouyer 944: /* Put all disk in RESET state */
1.125 mycroft 945: void
1.274 bouyer 946: wdc_reset_drive(struct ata_drive_datas *drvp, int flags, uint32_t *sigp)
1.2 bouyer 947: {
1.205 thorpej 948: struct ata_channel *chp = drvp->chnl_softc;
1.207 thorpej 949:
1.289 jdolecek 950: ata_channel_lock_owned(chp);
951:
1.274 bouyer 952: KASSERT(sigp == NULL);
953:
1.211 thorpej 954: ATADEBUG_PRINT(("wdc_reset_drive %s:%d for drive %d\n",
1.253 cube 955: device_xname(chp->ch_atac->atac_dev), chp->ch_channel,
956: drvp->drive), DEBUG_FUNCS);
1.182 bouyer 957:
1.289 jdolecek 958: ata_thread_run(chp, flags, ATACH_TH_RESET, ATACH_NODRIVE);
1.182 bouyer 959: }
960:
1.183 bouyer 961: void
1.205 thorpej 962: wdc_reset_channel(struct ata_channel *chp, int flags)
1.182 bouyer 963: {
1.284 jdolecek 964: struct ata_xfer *xfer;
1.289 jdolecek 965:
966: ata_channel_lock_owned(chp);
967:
1.238 itohy 968: #if NATA_DMA || NATA_PIOBM
1.207 thorpej 969: struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.238 itohy 970: #endif
1.184 bouyer 971:
1.287 jdolecek 972: chp->ch_flags &= ~ATACH_IRQ_WAIT;
973:
1.186 bouyer 974: /*
1.284 jdolecek 975: * if the current command is on an ATAPI device, issue a
1.186 bouyer 976: * ATAPI_SOFT_RESET
977: */
1.289 jdolecek 978: xfer = ata_queue_get_active_xfer_locked(chp);
1.284 jdolecek 979:
1.186 bouyer 980: if (xfer && xfer->c_chp == chp && (xfer->c_flags & C_ATAPI)) {
981: wdccommandshort(chp, xfer->c_drive, ATAPI_SOFT_RESET);
1.284 jdolecek 982: ata_delay(chp, 1000, "atardl", flags);
1.186 bouyer 983: }
984:
1.184 bouyer 985: /* reset the channel */
1.186 bouyer 986: if (flags & AT_WAIT)
987: (void) wdcreset(chp, RESET_SLEEP);
988: else
1.184 bouyer 989: (void) wdcreset(chp, RESET_POLL);
990:
991: /*
1.186 bouyer 992: * wait a bit after reset; in case the DMA engines needs some time
1.184 bouyer 993: * to recover.
994: */
1.284 jdolecek 995: ata_delay(chp, 1000, "atardl", flags);
996:
1.182 bouyer 997: /*
1.284 jdolecek 998: * Look for pending xfers. If we have a shared queue, we'll also reset
1.182 bouyer 999: * the other channel if the current xfer is running on it.
1.309 ! andvar 1000: * Then we'll kill the eventual active transfer explicitly, so that
1.284 jdolecek 1001: * it is queued for retry immediatelly without waiting for I/O timeout.
1.182 bouyer 1002: */
1.284 jdolecek 1003: if (xfer) {
1004: if (xfer->c_chp != chp) {
1.289 jdolecek 1005: ata_thread_run(xfer->c_chp, flags, ATACH_TH_RESET,
1006: ATACH_NODRIVE);
1.284 jdolecek 1007: } else {
1.238 itohy 1008: #if NATA_DMA || NATA_PIOBM
1.284 jdolecek 1009: /*
1010: * If we're waiting for DMA, stop the
1011: * DMA engine
1012: */
1013: if (chp->ch_flags & ATACH_DMA_WAIT) {
1014: (*wdc->dma_finish)(wdc->dma_arg,
1015: chp->ch_channel, xfer->c_drive,
1016: WDC_DMAEND_ABRT_QUIET);
1017: chp->ch_flags &= ~ATACH_DMA_WAIT;
1018: }
1.238 itohy 1019: #endif
1.184 bouyer 1020: }
1.284 jdolecek 1021: }
1.186 bouyer 1022:
1.284 jdolecek 1023: ata_kill_active(chp, KILL_RESET, flags);
1.31 bouyer 1024: }
1.12 cgd 1025:
1.213 thorpej 1026: static int
1.205 thorpej 1027: wdcreset(struct ata_channel *chp, int poll)
1.31 bouyer 1028: {
1.207 thorpej 1029: struct atac_softc *atac = chp->ch_atac;
1030: struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.205 thorpej 1031: struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
1.31 bouyer 1032: int drv_mask1, drv_mask2;
1.225 bouyer 1033:
1.284 jdolecek 1034: ata_channel_lock_owned(chp);
1035:
1.263 bouyer 1036: #ifdef WDC_NO_IDS
1037: poll = RESET_POLL;
1038: #endif
1.225 bouyer 1039: wdc->reset(chp, poll);
1040:
1.281 msaitoh 1041: drv_mask1 = (chp->ch_drive[0].drive_type != ATA_DRIVET_NONE)
1042: ? 0x01 : 0x00;
1.305 skrll 1043: if (chp->ch_ndrives > 1)
1.281 msaitoh 1044: drv_mask1 |= (chp->ch_drive[1].drive_type != ATA_DRIVET_NONE)
1045: ? 0x02 : 0x00;
1.225 bouyer 1046: drv_mask2 = __wdcwait_reset(chp, drv_mask1,
1047: (poll == RESET_SLEEP) ? 0 : 1);
1048: if (drv_mask2 != drv_mask1) {
1.253 cube 1049: aprint_error("%s channel %d: reset failed for",
1050: device_xname(atac->atac_dev), chp->ch_channel);
1.225 bouyer 1051: if ((drv_mask1 & 0x01) != 0 && (drv_mask2 & 0x01) == 0)
1.253 cube 1052: aprint_normal(" drive 0");
1.225 bouyer 1053: if ((drv_mask1 & 0x02) != 0 && (drv_mask2 & 0x02) == 0)
1.253 cube 1054: aprint_normal(" drive 1");
1055: aprint_normal("\n");
1.225 bouyer 1056: }
1.305 skrll 1057: if (! (wdc->cap & WDC_CAPABILITY_NO_AUXCTL))
1058: bus_space_write_1(wdr->ctl_iot, wdr->ctl_ioh, wd_aux_ctlr,
1.275 rkujawa 1059: WDCTL_4BIT);
1060:
1.225 bouyer 1061: return (drv_mask1 != drv_mask2) ? 1 : 0;
1062: }
1063:
1064: void
1065: wdc_do_reset(struct ata_channel *chp, int poll)
1066: {
1067: struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1068: struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
1.156 bouyer 1069: int s = 0;
1.2 bouyer 1070:
1.225 bouyer 1071: if (poll != RESET_SLEEP)
1072: s = splbio();
1.203 thorpej 1073: if (wdc->select)
1.169 thorpej 1074: wdc->select(chp,0);
1.157 fvdl 1075: /* master */
1.205 thorpej 1076: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], 0, WDSD_IBM);
1.131 mycroft 1077: delay(10); /* 400ns delay */
1.225 bouyer 1078: /* assert SRST, wait for reset to complete */
1.275 rkujawa 1079: if (! (wdc->cap & WDC_CAPABILITY_NO_AUXCTL)) {
1080: bus_space_write_1(wdr->ctl_iot, wdr->ctl_ioh, wd_aux_ctlr,
1081: WDCTL_RST | WDCTL_IDS | WDCTL_4BIT);
1082: delay(2000);
1083: }
1.205 thorpej 1084: (void) bus_space_read_1(wdr->cmd_iot, wdr->cmd_iohs[wd_error], 0);
1.305 skrll 1085: if (! (wdc->cap & WDC_CAPABILITY_NO_AUXCTL))
1.275 rkujawa 1086: bus_space_write_1(wdr->ctl_iot, wdr->ctl_ioh, wd_aux_ctlr,
1087: WDCTL_4BIT | WDCTL_IDS);
1.131 mycroft 1088: delay(10); /* 400ns delay */
1.156 bouyer 1089: if (poll != RESET_SLEEP) {
1.233 bouyer 1090: /* ACK interrupt in case there is one pending left */
1.203 thorpej 1091: if (wdc->irqack)
1.169 thorpej 1092: wdc->irqack(chp);
1.156 bouyer 1093: splx(s);
1094: }
1.31 bouyer 1095: }
1096:
1097: static int
1.205 thorpej 1098: __wdcwait_reset(struct ata_channel *chp, int drv_mask, int poll)
1.31 bouyer 1099: {
1.207 thorpej 1100: struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.205 thorpej 1101: struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
1.137 bouyer 1102: int timeout, nloop;
1.284 jdolecek 1103: int wflags = poll ? AT_POLL : AT_WAIT;
1.149 bouyer 1104: u_int8_t st0 = 0, st1 = 0;
1.204 thorpej 1105: #ifdef ATADEBUG
1.146 christos 1106: u_int8_t sc0 = 0, sn0 = 0, cl0 = 0, ch0 = 0;
1107: u_int8_t sc1 = 0, sn1 = 0, cl1 = 0, ch1 = 0;
1.70 bouyer 1108: #endif
1.137 bouyer 1109: if (poll)
1110: nloop = WDCNDELAY_RST;
1111: else
1112: nloop = WDC_RESET_WAIT * hz / 1000;
1.31 bouyer 1113: /* wait for BSY to deassert */
1.137 bouyer 1114: for (timeout = 0; timeout < nloop; timeout++) {
1.174 bouyer 1115: if ((drv_mask & 0x01) != 0) {
1.236 bouyer 1116: if (wdc->select)
1.174 bouyer 1117: wdc->select(chp,0);
1.205 thorpej 1118: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh],
1.174 bouyer 1119: 0, WDSD_IBM); /* master */
1120: delay(10);
1.205 thorpej 1121: st0 = bus_space_read_1(wdr->cmd_iot,
1122: wdr->cmd_iohs[wd_status], 0);
1.204 thorpej 1123: #ifdef ATADEBUG
1.205 thorpej 1124: sc0 = bus_space_read_1(wdr->cmd_iot,
1125: wdr->cmd_iohs[wd_seccnt], 0);
1126: sn0 = bus_space_read_1(wdr->cmd_iot,
1127: wdr->cmd_iohs[wd_sector], 0);
1128: cl0 = bus_space_read_1(wdr->cmd_iot,
1129: wdr->cmd_iohs[wd_cyl_lo], 0);
1130: ch0 = bus_space_read_1(wdr->cmd_iot,
1131: wdr->cmd_iohs[wd_cyl_hi], 0);
1.70 bouyer 1132: #endif
1.174 bouyer 1133: }
1134: if ((drv_mask & 0x02) != 0) {
1.236 bouyer 1135: if (wdc->select)
1.174 bouyer 1136: wdc->select(chp,1);
1.205 thorpej 1137: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh],
1.174 bouyer 1138: 0, WDSD_IBM | 0x10); /* slave */
1139: delay(10);
1.205 thorpej 1140: st1 = bus_space_read_1(wdr->cmd_iot,
1141: wdr->cmd_iohs[wd_status], 0);
1.204 thorpej 1142: #ifdef ATADEBUG
1.205 thorpej 1143: sc1 = bus_space_read_1(wdr->cmd_iot,
1144: wdr->cmd_iohs[wd_seccnt], 0);
1145: sn1 = bus_space_read_1(wdr->cmd_iot,
1146: wdr->cmd_iohs[wd_sector], 0);
1147: cl1 = bus_space_read_1(wdr->cmd_iot,
1148: wdr->cmd_iohs[wd_cyl_lo], 0);
1149: ch1 = bus_space_read_1(wdr->cmd_iot,
1150: wdr->cmd_iohs[wd_cyl_hi], 0);
1.70 bouyer 1151: #endif
1.174 bouyer 1152: }
1.31 bouyer 1153:
1154: if ((drv_mask & 0x01) == 0) {
1155: /* no master */
1156: if ((drv_mask & 0x02) != 0 && (st1 & WDCS_BSY) == 0) {
1157: /* No master, slave is ready, it's done */
1.65 bouyer 1158: goto end;
1.31 bouyer 1159: }
1.231 bouyer 1160: if ((drv_mask & 0x02) == 0) {
1161: /* No master, no slave: it's done */
1162: goto end;
1163: }
1.31 bouyer 1164: } else if ((drv_mask & 0x02) == 0) {
1165: /* no slave */
1166: if ((drv_mask & 0x01) != 0 && (st0 & WDCS_BSY) == 0) {
1167: /* No slave, master is ready, it's done */
1.65 bouyer 1168: goto end;
1.31 bouyer 1169: }
1.2 bouyer 1170: } else {
1.31 bouyer 1171: /* Wait for both master and slave to be ready */
1172: if ((st0 & WDCS_BSY) == 0 && (st1 & WDCS_BSY) == 0) {
1.65 bouyer 1173: goto end;
1.2 bouyer 1174: }
1175: }
1.284 jdolecek 1176: ata_delay(chp, WDCDELAY, "atarst", wflags);
1.2 bouyer 1177: }
1.116 wiz 1178: /* Reset timed out. Maybe it's because drv_mask was not right */
1.31 bouyer 1179: if (st0 & WDCS_BSY)
1180: drv_mask &= ~0x01;
1181: if (st1 & WDCS_BSY)
1182: drv_mask &= ~0x02;
1.65 bouyer 1183: end:
1.204 thorpej 1184: ATADEBUG_PRINT(("%s:%d:0: after reset, sc=0x%x sn=0x%x "
1.70 bouyer 1185: "cl=0x%x ch=0x%x\n",
1.253 cube 1186: device_xname(chp->ch_atac->atac_dev),
1.169 thorpej 1187: chp->ch_channel, sc0, sn0, cl0, ch0), DEBUG_PROBE);
1.204 thorpej 1188: ATADEBUG_PRINT(("%s:%d:1: after reset, sc=0x%x sn=0x%x "
1.70 bouyer 1189: "cl=0x%x ch=0x%x\n",
1.253 cube 1190: device_xname(chp->ch_atac->atac_dev),
1.169 thorpej 1191: chp->ch_channel, sc1, sn1, cl1, ch1), DEBUG_PROBE);
1.70 bouyer 1192:
1.204 thorpej 1193: ATADEBUG_PRINT(("%s:%d: wdcwait_reset() end, st0=0x%x st1=0x%x\n",
1.253 cube 1194: device_xname(chp->ch_atac->atac_dev), chp->ch_channel,
1.149 bouyer 1195: st0, st1), DEBUG_PROBE);
1.65 bouyer 1196:
1.31 bouyer 1197: return drv_mask;
1.2 bouyer 1198: }
1199:
1200: /*
1.31 bouyer 1201: * Wait for a drive to be !BSY, and have mask in its status register.
1202: * return -1 for a timeout after "timeout" ms.
1.2 bouyer 1203: */
1.167 thorpej 1204: static int
1.284 jdolecek 1205: __wdcwait(struct ata_channel *chp, int mask, int bits, int timeout, int *tfd)
1.2 bouyer 1206: {
1.207 thorpej 1207: struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.205 thorpej 1208: struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
1.284 jdolecek 1209: u_char status, error = 0;
1.222 christos 1210: int xtime = 0;
1.284 jdolecek 1211: int rv;
1.60 abs 1212:
1.207 thorpej 1213: ATADEBUG_PRINT(("__wdcwait %s:%d\n",
1.253 cube 1214: device_xname(chp->ch_atac->atac_dev),
1.169 thorpej 1215: chp->ch_channel), DEBUG_STATUS);
1.284 jdolecek 1216: *tfd = 0;
1.31 bouyer 1217:
1218: timeout = timeout * 1000 / WDCDELAY; /* delay uses microseconds */
1.2 bouyer 1219:
1.31 bouyer 1220: for (;;) {
1.284 jdolecek 1221: status =
1.205 thorpej 1222: bus_space_read_1(wdr->cmd_iot, wdr->cmd_iohs[wd_status], 0);
1.131 mycroft 1223: if ((status & (WDCS_BSY | mask)) == bits)
1.31 bouyer 1224: break;
1.222 christos 1225: if (++xtime > timeout) {
1.204 thorpej 1226: ATADEBUG_PRINT(("__wdcwait: timeout (time=%d), "
1.87 bouyer 1227: "status %x error %x (mask 0x%x bits 0x%x)\n",
1.222 christos 1228: xtime, status,
1.205 thorpej 1229: bus_space_read_1(wdr->cmd_iot,
1230: wdr->cmd_iohs[wd_error], 0), mask, bits),
1.87 bouyer 1231: DEBUG_STATUS | DEBUG_PROBE | DEBUG_DELAY);
1.284 jdolecek 1232: rv = WDCWAIT_TOUT;
1233: goto out;
1.31 bouyer 1234: }
1235: delay(WDCDELAY);
1.2 bouyer 1236: }
1.204 thorpej 1237: #ifdef ATADEBUG
1.222 christos 1238: if (xtime > 0 && (atadebug_mask & DEBUG_DELAY))
1239: printf("__wdcwait: did busy-wait, time=%d\n", xtime);
1.87 bouyer 1240: #endif
1.31 bouyer 1241: if (status & WDCS_ERR)
1.284 jdolecek 1242: error = bus_space_read_1(wdr->cmd_iot,
1.205 thorpej 1243: wdr->cmd_iohs[wd_error], 0);
1.31 bouyer 1244: #ifdef WDCNDELAY_DEBUG
1245: /* After autoconfig, there should be no long delays. */
1.222 christos 1246: if (!cold && xtime > WDCNDELAY_DEBUG) {
1.284 jdolecek 1247: struct ata_xfer *xfer;
1248:
1.295 prlw1 1249: xfer = ata_queue_get_active_xfer_locked(chp);
1.31 bouyer 1250: if (xfer == NULL)
1251: printf("%s channel %d: warning: busy-wait took %dus\n",
1.253 cube 1252: device_xname(chp->ch_atac->atac_dev),
1253: chp->ch_channel, WDCDELAY * xtime);
1.219 perry 1254: else
1.31 bouyer 1255: printf("%s:%d:%d: warning: busy-wait took %dus\n",
1.253 cube 1256: device_xname(chp->ch_atac->atac_dev),
1257: chp->ch_channel, xfer->c_drive,
1.222 christos 1258: WDCDELAY * xtime);
1.2 bouyer 1259: }
1260: #endif
1.284 jdolecek 1261: rv = WDCWAIT_OK;
1262:
1263: out:
1264: *tfd = ATACH_ERR_ST(error, status);
1265: return rv;
1.137 bouyer 1266: }
1267:
1268: /*
1.284 jdolecek 1269: * Call __wdcwait(), polling using kpause() or waking up the kernel
1.137 bouyer 1270: * thread if possible
1271: */
1272: int
1.284 jdolecek 1273: wdcwait(struct ata_channel *chp, int mask, int bits, int timeout, int flags,
1274: int *tfd)
1.137 bouyer 1275: {
1276: int error, i, timeout_hz = mstohz(timeout);
1277:
1.284 jdolecek 1278: ata_channel_lock_owned(chp);
1279:
1.137 bouyer 1280: if (timeout_hz == 0 ||
1281: (flags & (AT_WAIT | AT_POLL)) == AT_POLL)
1.284 jdolecek 1282: error = __wdcwait(chp, mask, bits, timeout, tfd);
1.137 bouyer 1283: else {
1.284 jdolecek 1284: error = __wdcwait(chp, mask, bits, WDCDELAY_POLL, tfd);
1.137 bouyer 1285: if (error != 0) {
1.298 jdolecek 1286: if (ata_is_thread_run(chp) || (flags & AT_WAIT)) {
1.137 bouyer 1287: /*
1.147 bouyer 1288: * we're running in the channel thread
1289: * or some userland thread context
1.137 bouyer 1290: */
1291: for (i = 0; i < timeout_hz; i++) {
1292: if (__wdcwait(chp, mask, bits,
1.284 jdolecek 1293: WDCDELAY_POLL, tfd) == 0) {
1.137 bouyer 1294: error = 0;
1295: break;
1296: }
1.284 jdolecek 1297: kpause("atapoll", true, 1,
1298: &chp->ch_lock);
1.137 bouyer 1299: }
1300: } else {
1301: /*
1.256 bouyer 1302: * we're probably in interrupt context,
1.284 jdolecek 1303: * caller must ask the thread to come back here
1.137 bouyer 1304: */
1305: return(WDCWAIT_THR);
1306: }
1307: }
1308: }
1.163 thorpej 1309: return (error);
1.2 bouyer 1310: }
1311:
1.137 bouyer 1312:
1.238 itohy 1313: #if NATA_DMA
1.84 bouyer 1314: /*
1315: * Busy-wait for DMA to complete
1316: */
1317: int
1.205 thorpej 1318: wdc_dmawait(struct ata_channel *chp, struct ata_xfer *xfer, int timeout)
1.84 bouyer 1319: {
1.207 thorpej 1320: struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.222 christos 1321: int xtime;
1.169 thorpej 1322:
1.222 christos 1323: for (xtime = 0; xtime < timeout * 1000 / WDCDELAY; xtime++) {
1.169 thorpej 1324: wdc->dma_status =
1325: (*wdc->dma_finish)(wdc->dma_arg,
1.185 bouyer 1326: chp->ch_channel, xfer->c_drive, WDC_DMAEND_END);
1.169 thorpej 1327: if ((wdc->dma_status & WDC_DMAST_NOIRQ) == 0)
1.84 bouyer 1328: return 0;
1329: delay(WDCDELAY);
1330: }
1331: /* timeout, force a DMA halt */
1.169 thorpej 1332: wdc->dma_status = (*wdc->dma_finish)(wdc->dma_arg,
1.185 bouyer 1333: chp->ch_channel, xfer->c_drive, WDC_DMAEND_ABRT);
1.84 bouyer 1334: return 1;
1335: }
1.238 itohy 1336: #endif
1.84 bouyer 1337:
1.31 bouyer 1338: void
1.163 thorpej 1339: wdctimeout(void *arg)
1.2 bouyer 1340: {
1.289 jdolecek 1341: struct ata_xfer *xfer;
1342: struct ata_channel *chp = arg;
1.238 itohy 1343: #if NATA_DMA || NATA_PIOBM
1.207 thorpej 1344: struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.238 itohy 1345: #endif
1.31 bouyer 1346: int s;
1.2 bouyer 1347:
1.204 thorpej 1348: ATADEBUG_PRINT(("wdctimeout\n"), DEBUG_FUNCS);
1.31 bouyer 1349:
1350: s = splbio();
1.289 jdolecek 1351:
1352: callout_ack(&chp->c_timo_callout);
1353:
1.300 jdolecek 1354: if ((chp->ch_flags & ATACH_IRQ_WAIT) == 0) {
1355: __wdcerror(chp, "timeout not expected without pending irq");
1356: goto out;
1357: }
1358:
1.289 jdolecek 1359: xfer = ata_queue_get_active_xfer(chp);
1.284 jdolecek 1360: KASSERT(xfer != NULL);
1361:
1362: if (ata_timo_xfer_check(xfer)) {
1363: /* Already logged */
1364: goto out;
1365: }
1366:
1367: __wdcerror(chp, "lost interrupt");
1368: printf("\ttype: %s tc_bcount: %d tc_skip: %d\n",
1369: (xfer->c_flags & C_ATAPI) ? "atapi" : "ata",
1370: xfer->c_bcount, xfer->c_skip);
1.238 itohy 1371: #if NATA_DMA || NATA_PIOBM
1.284 jdolecek 1372: if (chp->ch_flags & ATACH_DMA_WAIT) {
1373: wdc->dma_status =
1374: (*wdc->dma_finish)(wdc->dma_arg, chp->ch_channel,
1375: xfer->c_drive, WDC_DMAEND_ABRT);
1376: chp->ch_flags &= ~ATACH_DMA_WAIT;
1377: }
1.238 itohy 1378: #endif
1.284 jdolecek 1379: /*
1380: * Call the interrupt routine. If we just missed an interrupt,
1381: * it will do what's needed. Else, it will take the needed
1382: * action (reset the device).
1383: */
1384: xfer->c_flags |= C_TIMEOU;
1.301 jdolecek 1385: chp->ch_flags &= ~ATACH_IRQ_WAIT;
1.289 jdolecek 1386: KASSERT(xfer->ops != NULL && xfer->ops->c_intr != NULL);
1387: xfer->ops->c_intr(chp, xfer, 1);
1.284 jdolecek 1388:
1389: out:
1.31 bouyer 1390: splx(s);
1.2 bouyer 1391: }
1392:
1.289 jdolecek 1393: static const struct ata_xfer_ops wdc_cmd_xfer_ops = {
1394: .c_start = __wdccommand_start,
1395: .c_poll = __wdccommand_poll,
1396: .c_abort = __wdccommand_done,
1397: .c_intr = __wdccommand_intr,
1398: .c_kill_xfer = __wdccommand_kill_xfer,
1399: };
1400:
1.299 jdolecek 1401: void
1.284 jdolecek 1402: wdc_exec_command(struct ata_drive_datas *drvp, struct ata_xfer *xfer)
1.31 bouyer 1403: {
1.205 thorpej 1404: struct ata_channel *chp = drvp->chnl_softc;
1.284 jdolecek 1405: struct ata_command *ata_c = &xfer->c_ata_c;
1.2 bouyer 1406:
1.204 thorpej 1407: ATADEBUG_PRINT(("wdc_exec_command %s:%d:%d\n",
1.253 cube 1408: device_xname(chp->ch_atac->atac_dev), chp->ch_channel,
1409: drvp->drive), DEBUG_FUNCS);
1.2 bouyer 1410:
1.31 bouyer 1411: /* set up an xfer and queue. Wait for completion */
1.247 dyoung 1412: if (chp->ch_atac->atac_cap & ATAC_CAP_NOIRQ)
1.192 thorpej 1413: ata_c->flags |= AT_POLL;
1414: if (ata_c->flags & AT_POLL)
1.31 bouyer 1415: xfer->c_flags |= C_POLL;
1.217 bouyer 1416: if (ata_c->flags & AT_WAIT)
1417: xfer->c_flags |= C_WAIT;
1.165 thorpej 1418: xfer->c_drive = drvp->drive;
1.192 thorpej 1419: xfer->c_databuf = ata_c->data;
1420: xfer->c_bcount = ata_c->bcount;
1.289 jdolecek 1421: xfer->ops = &wdc_cmd_xfer_ops;
1.2 bouyer 1422:
1.201 thorpej 1423: ata_exec_xfer(chp, xfer);
1.2 bouyer 1424: }
1425:
1.284 jdolecek 1426: static int
1.205 thorpej 1427: __wdccommand_start(struct ata_channel *chp, struct ata_xfer *xfer)
1.219 perry 1428: {
1.207 thorpej 1429: struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.205 thorpej 1430: struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
1.165 thorpej 1431: int drive = xfer->c_drive;
1.230 bouyer 1432: int wait_flags = (xfer->c_flags & C_POLL) ? AT_POLL : 0;
1.284 jdolecek 1433: struct ata_command *ata_c = &xfer->c_ata_c;
1434: int tfd;
1.31 bouyer 1435:
1.204 thorpej 1436: ATADEBUG_PRINT(("__wdccommand_start %s:%d:%d\n",
1.253 cube 1437: device_xname(chp->ch_atac->atac_dev), chp->ch_channel,
1.281 msaitoh 1438: xfer->c_drive), DEBUG_FUNCS);
1.31 bouyer 1439:
1.203 thorpej 1440: if (wdc->select)
1.169 thorpej 1441: wdc->select(chp,drive);
1.205 thorpej 1442: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], 0,
1.31 bouyer 1443: WDSD_IBM | (drive << 4));
1.192 thorpej 1444: switch(wdcwait(chp, ata_c->r_st_bmask | WDCS_DRQ,
1.284 jdolecek 1445: ata_c->r_st_bmask, ata_c->timeout, wait_flags, &tfd)) {
1.137 bouyer 1446: case WDCWAIT_OK:
1447: break;
1448: case WDCWAIT_TOUT:
1.192 thorpej 1449: ata_c->flags |= AT_TIMEOU;
1.284 jdolecek 1450: return ATASTART_ABORT;
1.137 bouyer 1451: case WDCWAIT_THR:
1.284 jdolecek 1452: return ATASTART_TH;
1.31 bouyer 1453: }
1.192 thorpej 1454: if (ata_c->flags & AT_POLL) {
1.135 bouyer 1455: /* polled command, disable interrupts */
1.305 skrll 1456: if (! (wdc->cap & WDC_CAPABILITY_NO_AUXCTL))
1457: bus_space_write_1(wdr->ctl_iot, wdr->ctl_ioh,
1.275 rkujawa 1458: wd_aux_ctlr, WDCTL_4BIT | WDCTL_IDS);
1.135 bouyer 1459: }
1.268 jakllsch 1460: if ((ata_c->flags & AT_LBA48) != 0) {
1461: wdccommandext(chp, drive, ata_c->r_command,
1.277 jakllsch 1462: ata_c->r_lba, ata_c->r_count, ata_c->r_features,
1463: ata_c->r_device & ~0x10);
1.268 jakllsch 1464: } else {
1465: wdccommand(chp, drive, ata_c->r_command,
1466: (ata_c->r_lba >> 8) & 0xffff,
1467: WDSD_IBM | (drive << 4) |
1468: (((ata_c->flags & AT_LBA) != 0) ? WDSD_LBA : 0) |
1469: ((ata_c->r_lba >> 24) & 0x0f),
1470: ata_c->r_lba & 0xff,
1471: ata_c->r_count & 0xff,
1472: ata_c->r_features & 0xff);
1473: }
1.139 bouyer 1474:
1.192 thorpej 1475: if ((ata_c->flags & AT_POLL) == 0) {
1.287 jdolecek 1476: chp->ch_flags |= ATACH_IRQ_WAIT; /* wait for interrupt */
1.289 jdolecek 1477: callout_reset(&chp->c_timo_callout, ata_c->timeout / 1000 * hz,
1478: wdctimeout, chp);
1.284 jdolecek 1479: return ATASTART_STARTED;
1.2 bouyer 1480: }
1.284 jdolecek 1481:
1.2 bouyer 1482: /*
1.31 bouyer 1483: * Polled command. Wait for drive ready or drq. Done in intr().
1484: * Wait for at last 400ns for status bit to be valid.
1.2 bouyer 1485: */
1.134 mycroft 1486: delay(10); /* 400ns delay */
1.284 jdolecek 1487: return ATASTART_POLL;
1488: }
1489:
1.308 rin 1490: static int
1.284 jdolecek 1491: __wdccommand_poll(struct ata_channel *chp, struct ata_xfer *xfer)
1492: {
1.66 bouyer 1493: __wdccommand_intr(chp, xfer, 0);
1.308 rin 1494: return ATAPOLL_DONE;
1.2 bouyer 1495: }
1496:
1.167 thorpej 1497: static int
1.205 thorpej 1498: __wdccommand_intr(struct ata_channel *chp, struct ata_xfer *xfer, int irq)
1.2 bouyer 1499: {
1.207 thorpej 1500: struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.205 thorpej 1501: struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
1.284 jdolecek 1502: struct ata_command *ata_c = &xfer->c_ata_c;
1.192 thorpej 1503: int bcount = ata_c->bcount;
1504: char *data = ata_c->data;
1.284 jdolecek 1505: int wflags, tfd;
1.226 bouyer 1506: int drive_flags;
1507:
1508: if (ata_c->r_command == WDCC_IDENTIFY ||
1509: ata_c->r_command == ATAPI_IDENTIFY_DEVICE) {
1510: /*
1511: * The IDENTIFY data has been designed as an array of
1512: * u_int16_t, so we can byteswap it on the fly.
1513: * Historically it's what we have always done so keeping it
1514: * here ensure binary backward compatibility.
1515: */
1.274 bouyer 1516: drive_flags = ATA_DRIVE_NOSTREAM |
1.229 tacha 1517: chp->ch_drive[xfer->c_drive].drive_flags;
1.226 bouyer 1518: } else {
1519: /*
1.296 msaitoh 1520: * Other data structure are opaque and should be transferred
1.226 bouyer 1521: * as is.
1522: */
1523: drive_flags = chp->ch_drive[xfer->c_drive].drive_flags;
1524: }
1.137 bouyer 1525:
1.265 bouyer 1526: #ifdef WDC_NO_IDS
1527: wflags = AT_POLL;
1528: #else
1.192 thorpej 1529: if ((ata_c->flags & (AT_WAIT | AT_POLL)) == (AT_WAIT | AT_POLL)) {
1.284 jdolecek 1530: /* both wait and poll, we can kpause here */
1.147 bouyer 1531: wflags = AT_WAIT | AT_POLL;
1.265 bouyer 1532: } else {
1533: wflags = AT_POLL;
1534: }
1.264 christos 1535: #endif
1.31 bouyer 1536:
1.284 jdolecek 1537: ata_channel_lock(chp);
1538:
1539: again:
1.204 thorpej 1540: ATADEBUG_PRINT(("__wdccommand_intr %s:%d:%d\n",
1.253 cube 1541: device_xname(chp->ch_atac->atac_dev), chp->ch_channel,
1542: xfer->c_drive), DEBUG_INTR);
1.137 bouyer 1543: /*
1544: * after a ATAPI_SOFT_RESET, the device will have released the bus.
1545: * Reselect again, it doesn't hurt for others commands, and the time
1.266 jakllsch 1546: * penalty for the extra register write is acceptable,
1547: * wdc_exec_command() isn't called often (mostly for autoconfig)
1.137 bouyer 1548: */
1.268 jakllsch 1549: if ((xfer->c_flags & C_ATAPI) != 0) {
1550: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], 0,
1551: WDSD_IBM | (xfer->c_drive << 4));
1552: }
1.192 thorpej 1553: if ((ata_c->flags & AT_XFDONE) != 0) {
1.114 bouyer 1554: /*
1555: * We have completed a data xfer. The drive should now be
1556: * in its initial state
1557: */
1.192 thorpej 1558: if (wdcwait(chp, ata_c->r_st_bmask | WDCS_DRQ,
1559: ata_c->r_st_bmask, (irq == 0) ? ata_c->timeout : 0,
1.284 jdolecek 1560: wflags, &tfd) == WDCWAIT_TOUT) {
1561: if (irq && (xfer->c_flags & C_TIMEOU) == 0) {
1562: ata_channel_unlock(chp);
1.114 bouyer 1563: return 0; /* IRQ was not for us */
1.284 jdolecek 1564: }
1.192 thorpej 1565: ata_c->flags |= AT_TIMEOU;
1.114 bouyer 1566: }
1.131 mycroft 1567: goto out;
1.114 bouyer 1568: }
1.192 thorpej 1569: if (wdcwait(chp, ata_c->r_st_pmask, ata_c->r_st_pmask,
1.284 jdolecek 1570: (irq == 0) ? ata_c->timeout : 0, wflags, &tfd) == WDCWAIT_TOUT) {
1571: if (irq && (xfer->c_flags & C_TIMEOU) == 0) {
1572: ata_channel_unlock(chp);
1.63 bouyer 1573: return 0; /* IRQ was not for us */
1.284 jdolecek 1574: }
1.192 thorpej 1575: ata_c->flags |= AT_TIMEOU;
1.131 mycroft 1576: goto out;
1.2 bouyer 1577: }
1.203 thorpej 1578: if (wdc->irqack)
1.169 thorpej 1579: wdc->irqack(chp);
1.192 thorpej 1580: if (ata_c->flags & AT_READ) {
1.284 jdolecek 1581: if ((ATACH_ST(tfd) & WDCS_DRQ) == 0) {
1.192 thorpej 1582: ata_c->flags |= AT_TIMEOU;
1.131 mycroft 1583: goto out;
1584: }
1.226 bouyer 1585: wdc->datain_pio(chp, drive_flags, data, bcount);
1.114 bouyer 1586: /* at this point the drive should be in its initial state */
1.192 thorpej 1587: ata_c->flags |= AT_XFDONE;
1.234 bouyer 1588: /*
1589: * XXX checking the status register again here cause some
1590: * hardware to timeout.
1591: */
1.192 thorpej 1592: } else if (ata_c->flags & AT_WRITE) {
1.284 jdolecek 1593: if ((ATACH_ST(tfd) & WDCS_DRQ) == 0) {
1.192 thorpej 1594: ata_c->flags |= AT_TIMEOU;
1.131 mycroft 1595: goto out;
1596: }
1.226 bouyer 1597: wdc->dataout_pio(chp, drive_flags, data, bcount);
1.192 thorpej 1598: ata_c->flags |= AT_XFDONE;
1599: if ((ata_c->flags & AT_POLL) == 0) {
1.287 jdolecek 1600: chp->ch_flags |= ATACH_IRQ_WAIT; /* wait for interrupt */
1.289 jdolecek 1601: callout_reset(&chp->c_timo_callout,
1602: mstohz(ata_c->timeout), wdctimeout, chp);
1.284 jdolecek 1603: ata_channel_unlock(chp);
1.114 bouyer 1604: return 1;
1605: } else {
1606: goto again;
1607: }
1.2 bouyer 1608: }
1.284 jdolecek 1609: out:
1610: if (ATACH_ST(tfd) & WDCS_DWF)
1611: ata_c->flags |= AT_DF;
1612: if (ATACH_ST(tfd) & WDCS_ERR) {
1613: ata_c->flags |= AT_ERROR;
1614: ata_c->r_error = ATACH_ST(tfd);
1615: }
1616:
1617: ata_channel_unlock(chp);
1618:
1.31 bouyer 1619: __wdccommand_done(chp, xfer);
1620: return 1;
1.2 bouyer 1621: }
1622:
1.167 thorpej 1623: static void
1.205 thorpej 1624: __wdccommand_done(struct ata_channel *chp, struct ata_xfer *xfer)
1.2 bouyer 1625: {
1.207 thorpej 1626: struct atac_softc *atac = chp->ch_atac;
1627: struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.205 thorpej 1628: struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
1.284 jdolecek 1629: struct ata_command *ata_c = &xfer->c_ata_c;
1630: bool start = true;
1.2 bouyer 1631:
1.233 bouyer 1632: ATADEBUG_PRINT(("__wdccommand_done %s:%d:%d flags 0x%x\n",
1.253 cube 1633: device_xname(atac->atac_dev), chp->ch_channel, xfer->c_drive,
1.233 bouyer 1634: ata_c->flags), DEBUG_FUNCS);
1.70 bouyer 1635:
1.284 jdolecek 1636: if (ata_waitdrain_xfer_check(chp, xfer)) {
1637: start = false;
1638: goto out;
1639: }
1.70 bouyer 1640:
1.192 thorpej 1641: if ((ata_c->flags & AT_READREG) != 0 &&
1.253 cube 1642: device_is_active(atac->atac_dev) &&
1.192 thorpej 1643: (ata_c->flags & (AT_ERROR | AT_DF)) == 0) {
1.268 jakllsch 1644: ata_c->r_status = bus_space_read_1(wdr->cmd_iot,
1645: wdr->cmd_iohs[wd_status], 0);
1646: ata_c->r_error = bus_space_read_1(wdr->cmd_iot,
1647: wdr->cmd_iohs[wd_error], 0);
1.205 thorpej 1648: ata_c->r_count = bus_space_read_1(wdr->cmd_iot,
1649: wdr->cmd_iohs[wd_seccnt], 0);
1.268 jakllsch 1650: ata_c->r_lba = (uint64_t)bus_space_read_1(wdr->cmd_iot,
1651: wdr->cmd_iohs[wd_sector], 0) << 0;
1652: ata_c->r_lba |= (uint64_t)bus_space_read_1(wdr->cmd_iot,
1653: wdr->cmd_iohs[wd_cyl_lo], 0) << 8;
1654: ata_c->r_lba |= (uint64_t)bus_space_read_1(wdr->cmd_iot,
1655: wdr->cmd_iohs[wd_cyl_hi], 0) << 16;
1656: ata_c->r_device = bus_space_read_1(wdr->cmd_iot,
1657: wdr->cmd_iohs[wd_sdh], 0);
1658:
1659: if ((ata_c->flags & AT_LBA48) != 0) {
1.275 rkujawa 1660: if (! (wdc->cap & WDC_CAPABILITY_NO_AUXCTL)) {
1661: if ((ata_c->flags & AT_POLL) != 0)
1.305 skrll 1662: bus_space_write_1(wdr->ctl_iot,
1.275 rkujawa 1663: wdr->ctl_ioh, wd_aux_ctlr,
1664: WDCTL_HOB|WDCTL_4BIT|WDCTL_IDS);
1665: else
1.305 skrll 1666: bus_space_write_1(wdr->ctl_iot,
1667: wdr->ctl_ioh, wd_aux_ctlr,
1.275 rkujawa 1668: WDCTL_HOB|WDCTL_4BIT);
1669: }
1.268 jakllsch 1670: ata_c->r_count |= bus_space_read_1(wdr->cmd_iot,
1671: wdr->cmd_iohs[wd_seccnt], 0) << 8;
1672: ata_c->r_lba |= (uint64_t)bus_space_read_1(wdr->cmd_iot,
1673: wdr->cmd_iohs[wd_sector], 0) << 24;
1674: ata_c->r_lba |= (uint64_t)bus_space_read_1(wdr->cmd_iot,
1675: wdr->cmd_iohs[wd_cyl_lo], 0) << 32;
1676: ata_c->r_lba |= (uint64_t)bus_space_read_1(wdr->cmd_iot,
1677: wdr->cmd_iohs[wd_cyl_hi], 0) << 40;
1.275 rkujawa 1678: if (! (wdc->cap & WDC_CAPABILITY_NO_AUXCTL)) {
1679: if ((ata_c->flags & AT_POLL) != 0)
1.305 skrll 1680: bus_space_write_1(wdr->ctl_iot,
1681: wdr->ctl_ioh, wd_aux_ctlr,
1.275 rkujawa 1682: WDCTL_4BIT|WDCTL_IDS);
1683: else
1.305 skrll 1684: bus_space_write_1(wdr->ctl_iot,
1685: wdr->ctl_ioh, wd_aux_ctlr,
1.275 rkujawa 1686: WDCTL_4BIT);
1687: }
1.268 jakllsch 1688: } else {
1689: ata_c->r_lba |=
1690: (uint64_t)(ata_c->r_device & 0x0f) << 24;
1691: }
1692: ata_c->r_device &= 0xf0;
1.135 bouyer 1693: }
1.284 jdolecek 1694:
1.289 jdolecek 1695: __wdccommand_done_end(chp, xfer);
1696:
1.284 jdolecek 1697: ata_deactivate_xfer(chp, xfer);
1698:
1699: out:
1.192 thorpej 1700: if (ata_c->flags & AT_POLL) {
1.187 bouyer 1701: /* enable interrupts */
1.305 skrll 1702: if (! (wdc->cap & WDC_CAPABILITY_NO_AUXCTL))
1703: bus_space_write_1(wdr->ctl_iot, wdr->ctl_ioh,
1.275 rkujawa 1704: wd_aux_ctlr, WDCTL_4BIT);
1.187 bouyer 1705: delay(10); /* some drives need a little delay here */
1706: }
1.284 jdolecek 1707:
1708: if (start)
1709: atastart(chp);
1.182 bouyer 1710: }
1.219 perry 1711:
1.182 bouyer 1712: static void
1.205 thorpej 1713: __wdccommand_done_end(struct ata_channel *chp, struct ata_xfer *xfer)
1.182 bouyer 1714: {
1.284 jdolecek 1715: struct ata_command *ata_c = &xfer->c_ata_c;
1.182 bouyer 1716:
1.192 thorpej 1717: ata_c->flags |= AT_DONE;
1.2 bouyer 1718: }
1719:
1.182 bouyer 1720: static void
1.205 thorpej 1721: __wdccommand_kill_xfer(struct ata_channel *chp, struct ata_xfer *xfer,
1.182 bouyer 1722: int reason)
1723: {
1.284 jdolecek 1724: struct ata_command *ata_c = &xfer->c_ata_c;
1725: bool deactivate = true;
1.182 bouyer 1726:
1727: switch (reason) {
1.284 jdolecek 1728: case KILL_GONE_INACTIVE:
1729: deactivate = false;
1730: /* FALLTHROUGH */
1.182 bouyer 1731: case KILL_GONE:
1.192 thorpej 1732: ata_c->flags |= AT_GONE;
1.219 perry 1733: break;
1.182 bouyer 1734: case KILL_RESET:
1.192 thorpej 1735: ata_c->flags |= AT_RESET;
1.182 bouyer 1736: break;
1737: default:
1738: printf("__wdccommand_kill_xfer: unknown reason %d\n",
1739: reason);
1740: panic("__wdccommand_kill_xfer");
1741: }
1.284 jdolecek 1742:
1.289 jdolecek 1743: __wdccommand_done_end(chp, xfer);
1744:
1.284 jdolecek 1745: if (deactivate)
1746: ata_deactivate_xfer(chp, xfer);
1.182 bouyer 1747: }
1748:
1.2 bouyer 1749: /*
1.31 bouyer 1750: * Send a command. The drive should be ready.
1.2 bouyer 1751: * Assumes interrupts are blocked.
1752: */
1.31 bouyer 1753: void
1.205 thorpej 1754: wdccommand(struct ata_channel *chp, u_int8_t drive, u_int8_t command,
1.163 thorpej 1755: u_int16_t cylin, u_int8_t head, u_int8_t sector, u_int8_t count,
1.178 thorpej 1756: u_int8_t features)
1.31 bouyer 1757: {
1.207 thorpej 1758: struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.205 thorpej 1759: struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
1.163 thorpej 1760:
1.204 thorpej 1761: ATADEBUG_PRINT(("wdccommand %s:%d:%d: command=0x%x cylin=%d head=%d "
1.253 cube 1762: "sector=%d count=%d features=%d\n",
1763: device_xname(chp->ch_atac->atac_dev), chp->ch_channel, drive,
1764: command, cylin, head, sector, count, features), DEBUG_FUNCS);
1.31 bouyer 1765:
1.203 thorpej 1766: if (wdc->select)
1.169 thorpej 1767: wdc->select(chp,drive);
1.107 dbj 1768:
1.31 bouyer 1769: /* Select drive, head, and addressing mode. */
1.205 thorpej 1770: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], 0,
1.31 bouyer 1771: WDSD_IBM | (drive << 4) | head);
1.177 thorpej 1772: /* Load parameters into the wd_features register. */
1.205 thorpej 1773: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_features], 0,
1.178 thorpej 1774: features);
1.205 thorpej 1775: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_seccnt], 0, count);
1776: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sector], 0, sector);
1777: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_cyl_lo], 0, cylin);
1778: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_cyl_hi],
1.157 fvdl 1779: 0, cylin >> 8);
1.108 christos 1780:
1781: /* Send command. */
1.205 thorpej 1782: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_command], 0, command);
1.108 christos 1783: return;
1784: }
1785:
1786: /*
1787: * Send a 48-bit addressing command. The drive should be ready.
1788: * Assumes interrupts are blocked.
1789: */
1790: void
1.205 thorpej 1791: wdccommandext(struct ata_channel *chp, u_int8_t drive, u_int8_t command,
1.277 jakllsch 1792: u_int64_t blkno, u_int16_t count, u_int16_t features, u_int8_t device)
1.108 christos 1793: {
1.207 thorpej 1794: struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.205 thorpej 1795: struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
1.163 thorpej 1796:
1.277 jakllsch 1797: ATADEBUG_PRINT(("wdccommandext %s:%d:%d: command=0x%02x "
1798: "blkno=0x%012"PRIx64" count=0x%04x features=0x%04x "
1799: "device=0x%02x\n", device_xname(chp->ch_atac->atac_dev),
1800: chp->ch_channel, drive, command, blkno, count, features, device),
1.108 christos 1801: DEBUG_FUNCS);
1802:
1.277 jakllsch 1803: KASSERT(drive < wdc->wdc_maxdrives);
1804:
1.203 thorpej 1805: if (wdc->select)
1.169 thorpej 1806: wdc->select(chp,drive);
1.108 christos 1807:
1808: /* Select drive, head, and addressing mode. */
1.205 thorpej 1809: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], 0,
1.277 jakllsch 1810: (drive << 4) | device);
1.108 christos 1811:
1.218 rearnsha 1812: if (wdc->cap & WDC_CAPABILITY_WIDEREGS) {
1.267 jakllsch 1813: bus_space_write_2(wdr->cmd_iot, wdr->cmd_iohs[wd_features],
1814: 0, features);
1.218 rearnsha 1815: bus_space_write_2(wdr->cmd_iot, wdr->cmd_iohs[wd_seccnt],
1816: 0, count);
1817: bus_space_write_2(wdr->cmd_iot, wdr->cmd_iohs[wd_lba_lo],
1818: 0, (((blkno >> 16) & 0xff00) | (blkno & 0x00ff)));
1819: bus_space_write_2(wdr->cmd_iot, wdr->cmd_iohs[wd_lba_mi],
1820: 0, (((blkno >> 24) & 0xff00) | ((blkno >> 8) & 0x00ff)));
1821: bus_space_write_2(wdr->cmd_iot, wdr->cmd_iohs[wd_lba_hi],
1822: 0, (((blkno >> 32) & 0xff00) | ((blkno >> 16) & 0x00ff)));
1823: } else {
1824: /* previous */
1.267 jakllsch 1825: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_features],
1826: 0, features >> 8);
1.218 rearnsha 1827: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_seccnt],
1828: 0, count >> 8);
1829: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_lba_lo],
1830: 0, blkno >> 24);
1831: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_lba_mi],
1832: 0, blkno >> 32);
1833: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_lba_hi],
1834: 0, blkno >> 40);
1835:
1836: /* current */
1.267 jakllsch 1837: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_features],
1838: 0, features);
1839: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_seccnt],
1840: 0, count);
1841: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_lba_lo],
1842: 0, blkno);
1.218 rearnsha 1843: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_lba_mi],
1844: 0, blkno >> 8);
1845: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_lba_hi],
1846: 0, blkno >> 16);
1847: }
1.2 bouyer 1848:
1.31 bouyer 1849: /* Send command. */
1.205 thorpej 1850: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_command], 0, command);
1.31 bouyer 1851: return;
1.2 bouyer 1852: }
1853:
1854: /*
1.31 bouyer 1855: * Simplified version of wdccommand(). Unbusy/ready/drq must be
1856: * tested by the caller.
1.2 bouyer 1857: */
1.31 bouyer 1858: void
1.205 thorpej 1859: wdccommandshort(struct ata_channel *chp, int drive, int command)
1.2 bouyer 1860: {
1.207 thorpej 1861: struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.205 thorpej 1862: struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
1.2 bouyer 1863:
1.204 thorpej 1864: ATADEBUG_PRINT(("wdccommandshort %s:%d:%d command 0x%x\n",
1.253 cube 1865: device_xname(chp->ch_atac->atac_dev), chp->ch_channel, drive,
1866: command), DEBUG_FUNCS);
1.107 dbj 1867:
1.203 thorpej 1868: if (wdc->select)
1.169 thorpej 1869: wdc->select(chp,drive);
1.2 bouyer 1870:
1.31 bouyer 1871: /* Select drive. */
1.205 thorpej 1872: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], 0,
1.31 bouyer 1873: WDSD_IBM | (drive << 4));
1.2 bouyer 1874:
1.205 thorpej 1875: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_command], 0, command);
1.31 bouyer 1876: }
1.2 bouyer 1877:
1.31 bouyer 1878: static void
1.222 christos 1879: __wdcerror(struct ata_channel *chp, const char *msg)
1.2 bouyer 1880: {
1.207 thorpej 1881: struct atac_softc *atac = chp->ch_atac;
1.284 jdolecek 1882: struct ata_xfer *xfer = ata_queue_get_active_xfer(chp);
1.88 mrg 1883:
1.2 bouyer 1884: if (xfer == NULL)
1.253 cube 1885: aprint_error("%s:%d: %s\n", device_xname(atac->atac_dev),
1886: chp->ch_channel, msg);
1.2 bouyer 1887: else
1.253 cube 1888: aprint_error("%s:%d:%d: %s\n", device_xname(atac->atac_dev),
1.169 thorpej 1889: chp->ch_channel, xfer->c_drive, msg);
1.2 bouyer 1890: }
1891:
1.219 perry 1892: /*
1.2 bouyer 1893: * the bit bucket
1894: */
1895: void
1.205 thorpej 1896: wdcbit_bucket(struct ata_channel *chp, int size)
1.2 bouyer 1897: {
1.207 thorpej 1898: struct wdc_regs *wdr = CHAN_TO_WDC_REGS(chp);
1.2 bouyer 1899:
1.12 cgd 1900: for (; size >= 2; size -= 2)
1.205 thorpej 1901: (void)bus_space_read_2(wdr->cmd_iot, wdr->cmd_iohs[wd_data], 0);
1.12 cgd 1902: if (size)
1.205 thorpej 1903: (void)bus_space_read_1(wdr->cmd_iot, wdr->cmd_iohs[wd_data], 0);
1.44 thorpej 1904: }
1905:
1.213 thorpej 1906: static void
1.222 christos 1907: wdc_datain_pio(struct ata_channel *chp, int flags, void *bf, size_t len)
1.190 mycroft 1908: {
1.207 thorpej 1909: struct wdc_regs *wdr = CHAN_TO_WDC_REGS(chp);
1.190 mycroft 1910:
1.244 martin 1911: #ifndef __NO_STRICT_ALIGNMENT
1912: if ((uintptr_t)bf & 1)
1913: goto unaligned;
1.274 bouyer 1914: if ((flags & ATA_DRIVE_CAP32) && ((uintptr_t)bf & 3))
1.244 martin 1915: goto unaligned;
1916: #endif
1917:
1.274 bouyer 1918: if (flags & ATA_DRIVE_NOSTREAM) {
1919: if ((flags & ATA_DRIVE_CAP32) && len > 3) {
1.205 thorpej 1920: bus_space_read_multi_4(wdr->data32iot,
1.222 christos 1921: wdr->data32ioh, 0, bf, len >> 2);
1922: bf = (char *)bf + (len & ~3);
1.190 mycroft 1923: len &= 3;
1924: }
1.273 christos 1925: if (len > 1) {
1.205 thorpej 1926: bus_space_read_multi_2(wdr->cmd_iot,
1.222 christos 1927: wdr->cmd_iohs[wd_data], 0, bf, len >> 1);
1.273 christos 1928: bf = (char *)bf + (len & ~1);
1929: len &= 1;
1.190 mycroft 1930: }
1931: } else {
1.274 bouyer 1932: if ((flags & ATA_DRIVE_CAP32) && len > 3) {
1.205 thorpej 1933: bus_space_read_multi_stream_4(wdr->data32iot,
1.222 christos 1934: wdr->data32ioh, 0, bf, len >> 2);
1935: bf = (char *)bf + (len & ~3);
1.190 mycroft 1936: len &= 3;
1937: }
1.273 christos 1938: if (len > 1) {
1.205 thorpej 1939: bus_space_read_multi_stream_2(wdr->cmd_iot,
1.222 christos 1940: wdr->cmd_iohs[wd_data], 0, bf, len >> 1);
1.273 christos 1941: bf = (char *)bf + (len & ~1);
1942: len &= 1;
1.190 mycroft 1943: }
1944: }
1.273 christos 1945: if (len)
1946: *((uint8_t *)bf) = bus_space_read_1(wdr->cmd_iot,
1947: wdr->cmd_iohs[wd_data], 0);
1.244 martin 1948: return;
1949:
1950: #ifndef __NO_STRICT_ALIGNMENT
1951: unaligned:
1.274 bouyer 1952: if (flags & ATA_DRIVE_NOSTREAM) {
1953: if (flags & ATA_DRIVE_CAP32) {
1.245 bouyer 1954: while (len > 3) {
1955: uint32_t val;
1956:
1957: val = bus_space_read_4(wdr->data32iot,
1958: wdr->data32ioh, 0);
1959: memcpy(bf, &val, 4);
1960: bf = (char *)bf + 4;
1961: len -= 4;
1962: }
1963: }
1964: while (len > 1) {
1965: uint16_t val;
1966:
1967: val = bus_space_read_2(wdr->cmd_iot,
1968: wdr->cmd_iohs[wd_data], 0);
1969: memcpy(bf, &val, 2);
1970: bf = (char *)bf + 2;
1971: len -= 2;
1972: }
1973: } else {
1.274 bouyer 1974: if (flags & ATA_DRIVE_CAP32) {
1.245 bouyer 1975: while (len > 3) {
1976: uint32_t val;
1.244 martin 1977:
1.245 bouyer 1978: val = bus_space_read_stream_4(wdr->data32iot,
1979: wdr->data32ioh, 0);
1980: memcpy(bf, &val, 4);
1981: bf = (char *)bf + 4;
1982: len -= 4;
1983: }
1984: }
1985: while (len > 1) {
1986: uint16_t val;
1987:
1988: val = bus_space_read_stream_2(wdr->cmd_iot,
1.244 martin 1989: wdr->cmd_iohs[wd_data], 0);
1.245 bouyer 1990: memcpy(bf, &val, 2);
1991: bf = (char *)bf + 2;
1992: len -= 2;
1.244 martin 1993: }
1994: }
1995: #endif
1.190 mycroft 1996: }
1997:
1.213 thorpej 1998: static void
1.222 christos 1999: wdc_dataout_pio(struct ata_channel *chp, int flags, void *bf, size_t len)
1.190 mycroft 2000: {
1.207 thorpej 2001: struct wdc_regs *wdr = CHAN_TO_WDC_REGS(chp);
1.190 mycroft 2002:
1.244 martin 2003: #ifndef __NO_STRICT_ALIGNMENT
2004: if ((uintptr_t)bf & 1)
2005: goto unaligned;
1.274 bouyer 2006: if ((flags & ATA_DRIVE_CAP32) && ((uintptr_t)bf & 3))
1.244 martin 2007: goto unaligned;
2008: #endif
2009:
1.274 bouyer 2010: if (flags & ATA_DRIVE_NOSTREAM) {
2011: if (flags & ATA_DRIVE_CAP32) {
1.205 thorpej 2012: bus_space_write_multi_4(wdr->data32iot,
1.222 christos 2013: wdr->data32ioh, 0, bf, len >> 2);
2014: bf = (char *)bf + (len & ~3);
1.190 mycroft 2015: len &= 3;
2016: }
2017: if (len) {
1.205 thorpej 2018: bus_space_write_multi_2(wdr->cmd_iot,
1.222 christos 2019: wdr->cmd_iohs[wd_data], 0, bf, len >> 1);
1.190 mycroft 2020: }
2021: } else {
1.274 bouyer 2022: if (flags & ATA_DRIVE_CAP32) {
1.205 thorpej 2023: bus_space_write_multi_stream_4(wdr->data32iot,
1.222 christos 2024: wdr->data32ioh, 0, bf, len >> 2);
2025: bf = (char *)bf + (len & ~3);
1.190 mycroft 2026: len &= 3;
2027: }
2028: if (len) {
1.205 thorpej 2029: bus_space_write_multi_stream_2(wdr->cmd_iot,
1.222 christos 2030: wdr->cmd_iohs[wd_data], 0, bf, len >> 1);
1.190 mycroft 2031: }
2032: }
1.244 martin 2033: return;
2034:
2035: #ifndef __NO_STRICT_ALIGNMENT
2036: unaligned:
1.274 bouyer 2037: if (flags & ATA_DRIVE_NOSTREAM) {
2038: if (flags & ATA_DRIVE_CAP32) {
1.245 bouyer 2039: while (len > 3) {
2040: uint32_t val;
1.244 martin 2041:
1.245 bouyer 2042: memcpy(&val, bf, 4);
2043: bus_space_write_4(wdr->data32iot,
2044: wdr->data32ioh, 0, val);
2045: bf = (char *)bf + 4;
2046: len -= 4;
2047: }
2048: }
2049: while (len > 1) {
2050: uint16_t val;
2051:
2052: memcpy(&val, bf, 2);
2053: bus_space_write_2(wdr->cmd_iot,
1.244 martin 2054: wdr->cmd_iohs[wd_data], 0, val);
1.245 bouyer 2055: bf = (char *)bf + 2;
2056: len -= 2;
1.244 martin 2057: }
1.245 bouyer 2058: } else {
1.274 bouyer 2059: if (flags & ATA_DRIVE_CAP32) {
1.245 bouyer 2060: while (len > 3) {
2061: uint32_t val;
2062:
2063: memcpy(&val, bf, 4);
2064: bus_space_write_stream_4(wdr->data32iot,
2065: wdr->data32ioh, 0, val);
2066: bf = (char *)bf + 4;
2067: len -= 4;
2068: }
2069: }
2070: while (len > 1) {
2071: uint16_t val;
1.244 martin 2072:
1.245 bouyer 2073: memcpy(&val, bf, 2);
2074: bus_space_write_stream_2(wdr->cmd_iot,
2075: wdr->cmd_iohs[wd_data], 0, val);
2076: bf = (char *)bf + 2;
2077: len -= 2;
2078: }
1.244 martin 2079: }
2080: #endif
1.190 mycroft 2081: }
CVSweb <webmaster@jp.NetBSD.org>