Annotation of src/sys/dev/ata/ata.c, Revision 1.18.2.1
1.18.2.1! skrll 1: /* $NetBSD$ */
! 2:
1.2 bouyer 3: /*
1.16 bouyer 4: * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved.
1.2 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: * 3. All advertising materials mentioning features or use of this software
15: * must display the following acknowledgement:
16: * This product includes software developed by Manuel Bouyer.
17: * 4. The name of the author may not be used to endorse or promote products
18: * derived from this software without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1.13 bouyer 23: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1.2 bouyer 24: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30: */
1.14 lukem 31:
32: #include <sys/cdefs.h>
1.18.2.1! skrll 33: __KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.29 2004/05/27 02:23:12 thorpej Exp $");
1.2 bouyer 34:
1.6 hubertf 35: #ifndef WDCDEBUG
1.2 bouyer 36: #define WDCDEBUG
1.6 hubertf 37: #endif /* WDCDEBUG */
1.2 bouyer 38:
39: #include <sys/param.h>
40: #include <sys/systm.h>
41: #include <sys/kernel.h>
42: #include <sys/malloc.h>
43: #include <sys/device.h>
1.18.2.1! skrll 44: #include <sys/conf.h>
! 45: #include <sys/fcntl.h>
! 46: #include <sys/proc.h>
! 47: #include <sys/kthread.h>
! 48: #include <sys/errno.h>
! 49: #include <sys/ataio.h>
1.2 bouyer 50:
1.15 bouyer 51: #include <machine/intr.h>
52: #include <machine/bus.h>
53:
1.2 bouyer 54: #include <dev/ata/atareg.h>
55: #include <dev/ata/atavar.h>
1.15 bouyer 56: #include <dev/ic/wdcreg.h>
57: #include <dev/ic/wdcvar.h>
1.2 bouyer 58:
1.18.2.1! skrll 59: #include "locators.h"
! 60:
1.2 bouyer 61: #define DEBUG_FUNCS 0x08
62: #define DEBUG_PROBE 0x10
1.18.2.1! skrll 63: #define DEBUG_DETACH 0x20
1.2 bouyer 64: #ifdef WDCDEBUG
65: extern int wdcdebug_mask; /* init'ed in wdc.c */
66: #define WDCDEBUG_PRINT(args, level) \
67: if (wdcdebug_mask & (level)) \
68: printf args
69: #else
70: #define WDCDEBUG_PRINT(args, level)
71: #endif
72:
1.18.2.1! skrll 73: /*****************************************************************************
! 74: * ATA bus layer.
! 75: *
! 76: * ATA controllers attach an atabus instance, which handles probing the bus
! 77: * for drives, etc.
! 78: *****************************************************************************/
! 79:
! 80: dev_type_open(atabusopen);
! 81: dev_type_close(atabusclose);
! 82: dev_type_ioctl(atabusioctl);
! 83:
! 84: const struct cdevsw atabus_cdevsw = {
! 85: atabusopen, atabusclose, noread, nowrite, atabusioctl,
! 86: nostop, notty, nopoll, nommap, nokqfilter,
! 87: };
! 88:
! 89: extern struct cfdriver atabus_cd;
! 90:
! 91:
! 92: /*
! 93: * atabusprint:
! 94: *
! 95: * Autoconfiguration print routine used by ATA controllers when
! 96: * attaching an atabus instance.
! 97: */
! 98: int
! 99: atabusprint(void *aux, const char *pnp)
! 100: {
! 101: struct wdc_channel *chan = aux;
! 102:
! 103: if (pnp)
! 104: aprint_normal("atabus at %s", pnp);
! 105: aprint_normal(" channel %d", chan->ch_channel);
! 106:
! 107: return (UNCONF);
! 108: }
! 109:
! 110: /*
! 111: * ataprint:
! 112: *
! 113: * Autoconfiguration print routine.
! 114: */
! 115: int
! 116: ataprint(void *aux, const char *pnp)
! 117: {
! 118: struct ata_device *adev = aux;
! 119:
! 120: if (pnp)
! 121: aprint_normal("wd at %s", pnp);
! 122: aprint_normal(" drive %d", adev->adev_drv_data->drive);
! 123:
! 124: return (UNCONF);
! 125: }
! 126:
! 127: /*
! 128: * atabus_thread:
! 129: *
! 130: * Worker thread for the ATA bus.
! 131: */
! 132: static void
! 133: atabus_thread(void *arg)
! 134: {
! 135: struct atabus_softc *sc = arg;
! 136: struct wdc_channel *chp = sc->sc_chan;
! 137: struct ata_xfer *xfer;
! 138: int s;
! 139:
! 140: s = splbio();
! 141: chp->ch_flags |= WDCF_TH_RUN;
! 142: splx(s);
! 143:
! 144: /* Configure the devices on the bus. */
! 145: atabusconfig(sc);
! 146:
! 147: for (;;) {
! 148: s = splbio();
! 149: if ((chp->ch_flags & (WDCF_TH_RESET | WDCF_SHUTDOWN)) == 0 &&
! 150: ((chp->ch_flags & WDCF_ACTIVE) == 0 ||
! 151: chp->ch_queue->queue_freeze == 0)) {
! 152: chp->ch_flags &= ~WDCF_TH_RUN;
! 153: (void) tsleep(&chp->ch_thread, PRIBIO, "atath", 0);
! 154: chp->ch_flags |= WDCF_TH_RUN;
! 155: }
! 156: splx(s);
! 157: if (chp->ch_flags & WDCF_SHUTDOWN)
! 158: break;
! 159: s = splbio();
! 160: if (chp->ch_flags & WDCF_TH_RESET) {
! 161: /*
! 162: * wdc_reset_channel() will freeze 2 times, so
! 163: * unfreeze one time. Not a problem as we're at splbio
! 164: */
! 165: chp->ch_queue->queue_freeze--;
! 166: wdc_reset_channel(chp, AT_WAIT | chp->ch_reset_flags);
! 167: } else if ((chp->ch_flags & WDCF_ACTIVE) != 0 &&
! 168: chp->ch_queue->queue_freeze == 1) {
! 169: /*
! 170: * Caller has bumped queue_freeze, decrease it.
! 171: */
! 172: chp->ch_queue->queue_freeze--;
! 173: xfer = TAILQ_FIRST(&chp->ch_queue->queue_xfer);
! 174: KASSERT(xfer != NULL);
! 175: (*xfer->c_start)(chp, xfer);
! 176: } else if (chp->ch_queue->queue_freeze > 1)
! 177: panic("ata_thread: queue_freeze");
! 178: splx(s);
! 179: }
! 180: chp->ch_thread = NULL;
! 181: wakeup((void *)&chp->ch_flags);
! 182: kthread_exit(0);
! 183: }
! 184:
! 185: /*
! 186: * atabus_create_thread:
! 187: *
! 188: * Helper routine to create the ATA bus worker thread.
! 189: */
! 190: static void
! 191: atabus_create_thread(void *arg)
! 192: {
! 193: struct atabus_softc *sc = arg;
! 194: struct wdc_channel *chp = sc->sc_chan;
! 195: int error;
! 196:
! 197: if ((error = kthread_create1(atabus_thread, sc, &chp->ch_thread,
! 198: "%s", sc->sc_dev.dv_xname)) != 0)
! 199: aprint_error("%s: unable to create kernel thread: error %d\n",
! 200: sc->sc_dev.dv_xname, error);
! 201: }
! 202:
! 203: /*
! 204: * atabus_match:
! 205: *
! 206: * Autoconfiguration match routine.
! 207: */
! 208: static int
! 209: atabus_match(struct device *parent, struct cfdata *cf, void *aux)
! 210: {
! 211: struct wdc_channel *chp = aux;
! 212:
! 213: if (chp == NULL)
! 214: return (0);
! 215:
! 216: if (cf->cf_loc[ATACF_CHANNEL] != chp->ch_channel &&
! 217: cf->cf_loc[ATACF_CHANNEL] != ATACF_CHANNEL_DEFAULT)
! 218: return (0);
! 219:
! 220: return (1);
! 221: }
! 222:
! 223: /*
! 224: * atabus_attach:
! 225: *
! 226: * Autoconfiguration attach routine.
! 227: */
! 228: static void
! 229: atabus_attach(struct device *parent, struct device *self, void *aux)
! 230: {
! 231: struct atabus_softc *sc = (void *) self;
! 232: struct wdc_channel *chp = aux;
! 233: struct atabus_initq *initq;
! 234:
! 235: sc->sc_chan = chp;
! 236:
! 237: aprint_normal("\n");
! 238: aprint_naive("\n");
! 239:
! 240: initq = malloc(sizeof(*initq), M_DEVBUF, M_WAITOK);
! 241: initq->atabus_sc = sc;
! 242: TAILQ_INSERT_TAIL(&atabus_initq_head, initq, atabus_initq);
! 243: config_pending_incr();
! 244: kthread_create(atabus_create_thread, sc);
! 245: }
! 246:
! 247: /*
! 248: * atabus_activate:
! 249: *
! 250: * Autoconfiguration activation routine.
! 251: */
! 252: static int
! 253: atabus_activate(struct device *self, enum devact act)
! 254: {
! 255: struct atabus_softc *sc = (void *) self;
! 256: struct wdc_channel *chp = sc->sc_chan;
! 257: struct device *dev = NULL;
! 258: int s, i, error = 0;
! 259:
! 260: s = splbio();
! 261: switch (act) {
! 262: case DVACT_ACTIVATE:
! 263: error = EOPNOTSUPP;
! 264: break;
! 265:
! 266: case DVACT_DEACTIVATE:
! 267: /*
! 268: * We might deactivate the children of atapibus twice
! 269: * (once bia atapibus, once directly), but since the
! 270: * generic autoconfiguration code maintains the DVF_ACTIVE
! 271: * flag, it's safe.
! 272: */
! 273: if ((dev = chp->atapibus) != NULL) {
! 274: error = config_deactivate(dev);
! 275: if (error)
! 276: goto out;
! 277: }
! 278:
! 279: for (i = 0; i < 2; i++) {
! 280: if ((dev = chp->ch_drive[i].drv_softc) != NULL) {
! 281: WDCDEBUG_PRINT(("atabus_activate: %s: "
! 282: "deactivating %s\n", sc->sc_dev.dv_xname,
! 283: dev->dv_xname),
! 284: DEBUG_DETACH);
! 285: error = config_deactivate(dev);
! 286: if (error)
! 287: goto out;
! 288: }
! 289: }
! 290: break;
! 291: }
! 292: out:
! 293: splx(s);
! 294:
! 295: #ifdef WDCDEBUG
! 296: if (dev != NULL && error != 0)
! 297: WDCDEBUG_PRINT(("atabus_activate: %s: "
! 298: "error %d deactivating %s\n", sc->sc_dev.dv_xname,
! 299: error, dev->dv_xname), DEBUG_DETACH);
! 300: #endif /* WDCDEBUG */
! 301:
! 302: return (error);
! 303: }
! 304:
! 305: /*
! 306: * atabus_detach:
! 307: *
! 308: * Autoconfiguration detach routine.
! 309: */
! 310: static int
! 311: atabus_detach(struct device *self, int flags)
! 312: {
! 313: struct atabus_softc *sc = (void *) self;
! 314: struct wdc_channel *chp = sc->sc_chan;
! 315: struct device *dev = NULL;
! 316: int i, error = 0;
! 317:
! 318: /* Shutdown the channel. */
! 319: /* XXX NEED AN INTERLOCK HERE. */
! 320: chp->ch_flags |= WDCF_SHUTDOWN;
! 321: wakeup(&chp->ch_thread);
! 322: while (chp->ch_thread != NULL)
! 323: (void) tsleep((void *)&chp->ch_flags, PRIBIO, "atadown", 0);
! 324:
! 325: /*
! 326: * Detach atapibus and its children.
! 327: */
! 328: if ((dev = chp->atapibus) != NULL) {
! 329: WDCDEBUG_PRINT(("atabus_detach: %s: detaching %s\n",
! 330: sc->sc_dev.dv_xname, dev->dv_xname), DEBUG_DETACH);
! 331: error = config_detach(dev, flags);
! 332: if (error)
! 333: goto out;
! 334: }
! 335:
! 336: /*
! 337: * Detach our other children.
! 338: */
! 339: for (i = 0; i < 2; i++) {
! 340: if (chp->ch_drive[i].drive_flags & DRIVE_ATAPI)
! 341: continue;
! 342: if ((dev = chp->ch_drive[i].drv_softc) != NULL) {
! 343: WDCDEBUG_PRINT(("atabus_detach: %s: detaching %s\n",
! 344: sc->sc_dev.dv_xname, dev->dv_xname),
! 345: DEBUG_DETACH);
! 346: error = config_detach(dev, flags);
! 347: if (error)
! 348: goto out;
! 349: }
! 350: }
! 351:
! 352: wdc_kill_pending(chp);
! 353: out:
! 354: #ifdef WDCDEBUG
! 355: if (dev != NULL && error != 0)
! 356: WDCDEBUG_PRINT(("atabus_detach: %s: error %d detaching %s\n",
! 357: sc->sc_dev.dv_xname, error, dev->dv_xname),
! 358: DEBUG_DETACH);
! 359: #endif /* WDCDEBUG */
! 360:
! 361: return (error);
! 362: }
! 363:
! 364: CFATTACH_DECL(atabus, sizeof(struct atabus_softc),
! 365: atabus_match, atabus_attach, atabus_detach, atabus_activate);
! 366:
! 367: /*****************************************************************************
! 368: * Common ATA bus operations.
! 369: *****************************************************************************/
! 370:
1.2 bouyer 371: /* Get the disk's parameters */
372: int
1.18.2.1! skrll 373: ata_get_params(struct ata_drive_datas *drvp, u_int8_t flags,
! 374: struct ataparams *prms)
1.2 bouyer 375: {
376: char tb[DEV_BSIZE];
377: struct wdc_command wdc_c;
378:
379: #if BYTE_ORDER == LITTLE_ENDIAN
380: int i;
381: u_int16_t *p;
382: #endif
383:
1.18.2.1! skrll 384: WDCDEBUG_PRINT(("ata_get_parms\n"), DEBUG_FUNCS);
1.2 bouyer 385:
386: memset(tb, 0, DEV_BSIZE);
387: memset(prms, 0, sizeof(struct ataparams));
388: memset(&wdc_c, 0, sizeof(struct wdc_command));
389:
390: if (drvp->drive_flags & DRIVE_ATA) {
391: wdc_c.r_command = WDCC_IDENTIFY;
1.5 bouyer 392: wdc_c.r_st_bmask = WDCS_DRDY;
1.18.2.1! skrll 393: wdc_c.r_st_pmask = 0;
1.18 bouyer 394: wdc_c.timeout = 3000; /* 3s */
1.7 bouyer 395: } else if (drvp->drive_flags & DRIVE_ATAPI) {
1.2 bouyer 396: wdc_c.r_command = ATAPI_IDENTIFY_DEVICE;
397: wdc_c.r_st_bmask = 0;
1.18.2.1! skrll 398: wdc_c.r_st_pmask = 0;
1.9 bouyer 399: wdc_c.timeout = 10000; /* 10s */
1.7 bouyer 400: } else {
1.18.2.1! skrll 401: WDCDEBUG_PRINT(("ata_get_parms: no disks\n"),
1.10 bouyer 402: DEBUG_FUNCS|DEBUG_PROBE);
1.7 bouyer 403: return CMD_ERR;
1.2 bouyer 404: }
405: wdc_c.flags = AT_READ | flags;
406: wdc_c.data = tb;
407: wdc_c.bcount = DEV_BSIZE;
1.10 bouyer 408: if (wdc_exec_command(drvp, &wdc_c) != WDC_COMPLETE) {
1.18.2.1! skrll 409: WDCDEBUG_PRINT(("ata_get_parms: wdc_exec_command failed\n"),
1.10 bouyer 410: DEBUG_FUNCS|DEBUG_PROBE);
1.2 bouyer 411: return CMD_AGAIN;
1.10 bouyer 412: }
1.2 bouyer 413: if (wdc_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
1.18.2.1! skrll 414: WDCDEBUG_PRINT(("ata_get_parms: wdc_c.flags=0x%x\n",
1.10 bouyer 415: wdc_c.flags), DEBUG_FUNCS|DEBUG_PROBE);
1.2 bouyer 416: return CMD_ERR;
417: } else {
1.17 bouyer 418: /* if we didn't read any data something is wrong */
419: if ((wdc_c.flags & AT_XFDONE) == 0)
420: return CMD_ERR;
1.2 bouyer 421: /* Read in parameter block. */
422: memcpy(prms, tb, sizeof(struct ataparams));
423: #if BYTE_ORDER == LITTLE_ENDIAN
424: /*
425: * Shuffle string byte order.
426: * ATAPI Mitsumi and NEC drives don't need this.
427: */
428: if ((prms->atap_config & WDC_CFG_ATAPI_MASK) ==
429: WDC_CFG_ATAPI &&
430: ((prms->atap_model[0] == 'N' &&
431: prms->atap_model[1] == 'E') ||
432: (prms->atap_model[0] == 'F' &&
433: prms->atap_model[1] == 'X')))
434: return 0;
435: for (i = 0; i < sizeof(prms->atap_model); i += 2) {
436: p = (u_short *)(prms->atap_model + i);
437: *p = ntohs(*p);
438: }
439: for (i = 0; i < sizeof(prms->atap_serial); i += 2) {
440: p = (u_short *)(prms->atap_serial + i);
441: *p = ntohs(*p);
442: }
443: for (i = 0; i < sizeof(prms->atap_revision); i += 2) {
444: p = (u_short *)(prms->atap_revision + i);
445: *p = ntohs(*p);
446: }
447: #endif
448: return CMD_OK;
449: }
450: }
451:
452: int
1.18.2.1! skrll 453: ata_set_mode(struct ata_drive_datas *drvp, u_int8_t mode, u_int8_t flags)
1.2 bouyer 454: {
455: struct wdc_command wdc_c;
456:
1.18.2.1! skrll 457: WDCDEBUG_PRINT(("ata_set_mode=0x%x\n", mode), DEBUG_FUNCS);
1.2 bouyer 458: memset(&wdc_c, 0, sizeof(struct wdc_command));
459:
460: wdc_c.r_command = SET_FEATURES;
461: wdc_c.r_st_bmask = 0;
462: wdc_c.r_st_pmask = 0;
1.18.2.1! skrll 463: wdc_c.r_features = WDSF_SET_MODE;
1.2 bouyer 464: wdc_c.r_count = mode;
1.18.2.1! skrll 465: wdc_c.flags = flags;
1.2 bouyer 466: wdc_c.timeout = 1000; /* 1s */
467: if (wdc_exec_command(drvp, &wdc_c) != WDC_COMPLETE)
468: return CMD_AGAIN;
469: if (wdc_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
470: return CMD_ERR;
471: }
472: return CMD_OK;
1.11 bouyer 473: }
474:
475: void
1.18.2.1! skrll 476: ata_dmaerr(struct ata_drive_datas *drvp, int flags)
1.11 bouyer 477: {
478: /*
479: * Downgrade decision: if we get NERRS_MAX in NXFER.
480: * We start with n_dmaerrs set to NERRS_MAX-1 so that the
481: * first error within the first NXFER ops will immediatly trigger
482: * a downgrade.
483: * If we got an error and n_xfers is bigger than NXFER reset counters.
484: */
485: drvp->n_dmaerrs++;
486: if (drvp->n_dmaerrs >= NERRS_MAX && drvp->n_xfers <= NXFER) {
1.18.2.1! skrll 487: wdc_downgrade_mode(drvp, flags);
1.11 bouyer 488: drvp->n_dmaerrs = NERRS_MAX-1;
489: drvp->n_xfers = 0;
490: return;
491: }
492: if (drvp->n_xfers > NXFER) {
493: drvp->n_dmaerrs = 1; /* just got an error */
494: drvp->n_xfers = 1; /* restart counting from this error */
1.4 bouyer 495: }
1.2 bouyer 496: }
1.18.2.1! skrll 497:
! 498: /* management of the /dev/atabus* devices */
! 499: int atabusopen(dev, flag, fmt, l)
! 500: dev_t dev;
! 501: int flag, fmt;
! 502: struct lwp *l;
! 503: {
! 504: struct atabus_softc *sc;
! 505: int error, unit = minor(dev);
! 506:
! 507: if (unit >= atabus_cd.cd_ndevs ||
! 508: (sc = atabus_cd.cd_devs[unit]) == NULL)
! 509: return (ENXIO);
! 510:
! 511: if (sc->sc_flags & ATABUSCF_OPEN)
! 512: return (EBUSY);
! 513:
! 514: if ((error = wdc_addref(sc->sc_chan)) != 0)
! 515: return (error);
! 516:
! 517: sc->sc_flags |= ATABUSCF_OPEN;
! 518:
! 519: return (0);
! 520: }
! 521:
! 522:
! 523: int
! 524: atabusclose(dev, flag, fmt, l)
! 525: dev_t dev;
! 526: int flag, fmt;
! 527: struct lwp *l;
! 528: {
! 529: struct atabus_softc *sc = atabus_cd.cd_devs[minor(dev)];
! 530:
! 531: wdc_delref(sc->sc_chan);
! 532:
! 533: sc->sc_flags &= ~ATABUSCF_OPEN;
! 534:
! 535: return (0);
! 536: }
! 537:
! 538: int
! 539: atabusioctl(dev, cmd, addr, flag, l)
! 540: dev_t dev;
! 541: u_long cmd;
! 542: caddr_t addr;
! 543: int flag;
! 544: struct lwp *l;
! 545: {
! 546: struct atabus_softc *sc = atabus_cd.cd_devs[minor(dev)];
! 547: int error;
! 548: int s;
! 549:
! 550: /*
! 551: * Enforce write permission for ioctls that change the
! 552: * state of the bus. Host adapter specific ioctls must
! 553: * be checked by the adapter driver.
! 554: */
! 555: switch (cmd) {
! 556: case ATABUSIOSCAN:
! 557: case ATABUSIODETACH:
! 558: case ATABUSIORESET:
! 559: if ((flag & FWRITE) == 0)
! 560: return (EBADF);
! 561: }
! 562:
! 563: switch (cmd) {
! 564: case ATABUSIORESET:
! 565: s = splbio();
! 566: wdc_reset_channel(sc->sc_chan, AT_WAIT | AT_POLL);
! 567: splx(s);
! 568: error = 0;
! 569: break;
! 570: default:
! 571: error = ENOTTY;
! 572: }
! 573: return (error);
! 574: };
CVSweb <webmaster@jp.NetBSD.org>