1/* $OpenBSD: wdc_obio.c,v 1.31 2022/03/13 12:33:01 mpi Exp $ */ 2/* $NetBSD: wdc_obio.c,v 1.15 2001/07/25 20:26:33 bouyer Exp $ */ 3 4/*- 5 * Copyright (c) 1998 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Charles M. Hannum and by Onno van der Linden. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#include <sys/param.h> 34#include <sys/systm.h> 35#include <sys/device.h> 36#include <sys/malloc.h> 37 38#include <uvm/uvm_extern.h> 39 40#include <machine/bus.h> 41#include <machine/autoconf.h> 42 43#include <dev/ofw/openfirm.h> 44#include <dev/ata/atavar.h> 45#include <dev/ata/atareg.h> 46#include <dev/ic/wdcvar.h> 47 48#include <macppc/dev/dbdma.h> 49 50#define WDC_REG_NPORTS 8 51#define WDC_AUXREG_OFFSET 0x16 52#define WDC_DEFAULT_PIO_IRQ 13 /* XXX */ 53#define WDC_DEFAULT_DMA_IRQ 2 /* XXX */ 54 55#define WDC_OPTIONS_DMA 0x01 56 57#define WDC_DMALIST_MAX 32 58 59struct wdc_obio_softc { 60 struct wdc_softc sc_wdcdev; 61 struct channel_softc *wdc_chanptr; 62 struct channel_softc wdc_channel; 63 64 bus_dma_tag_t sc_dmat; 65 bus_dmamap_t sc_dmamap; 66 dbdma_regmap_t *sc_dmareg; 67 dbdma_command_t *sc_dmacmd; 68 dbdma_t sc_dbdma; 69 70 void *sc_ih; 71 int sc_use_dma; 72 bus_size_t sc_cmdsize; 73 size_t sc_dmasize; 74}; 75 76u_int8_t wdc_obio_read_reg(struct channel_softc *, enum wdc_regs); 77void wdc_obio_write_reg(struct channel_softc *, enum wdc_regs, u_int8_t); 78 79struct channel_softc_vtbl wdc_obio_vtbl = { 80 wdc_obio_read_reg, 81 wdc_obio_write_reg, 82 wdc_default_lba48_write_reg, 83 wdc_default_read_raw_multi_2, 84 wdc_default_write_raw_multi_2, 85 wdc_default_read_raw_multi_4, 86 wdc_default_write_raw_multi_4 87}; 88 89int wdc_obio_probe(struct device *, void *, void *); 90void wdc_obio_attach(struct device *, struct device *, void *); 91int wdc_obio_detach(struct device *, int); 92 93const struct cfattach wdc_obio_ca = { 94 sizeof(struct wdc_obio_softc), wdc_obio_probe, wdc_obio_attach, 95 wdc_obio_detach 96}; 97 98int wdc_obio_dma_init(void *, int, int, void *, size_t, int); 99void wdc_obio_dma_start(void *, int, int); 100int wdc_obio_dma_finish(void *, int, int, int); 101void wdc_obio_adjust_timing(struct channel_softc *); 102void wdc_obio_ata4_adjust_timing(struct channel_softc *); 103void wdc_obio_ata6_adjust_timing(struct channel_softc *); 104 105int 106wdc_obio_probe(struct device *parent, void *match, void *aux) 107{ 108 struct confargs *ca = aux; 109 char compat[32]; 110 111 if (ca->ca_nreg < 8) 112 return 0; 113 114 /* XXX should not use name */ 115 if (strcmp(ca->ca_name, "ATA") == 0 || 116 strncmp(ca->ca_name, "ata", 3) == 0 || 117 strcmp(ca->ca_name, "ide") == 0) 118 return 1; 119 120 bzero(compat, sizeof(compat)); 121 OF_getprop(ca->ca_node, "compatible", compat, sizeof(compat)); 122 if (strcmp(compat, "heathrow-ata") == 0 || 123 strcmp(compat, "keylargo-ata") == 0) 124 return 1; 125 126 return 0; 127} 128 129void 130wdc_obio_attach(struct device *parent, struct device *self, void *aux) 131{ 132 struct wdc_obio_softc *sc = (void *)self; 133 struct confargs *ca = aux; 134 struct channel_softc *chp = &sc->wdc_channel; 135 int intr, error; 136 bus_addr_t cmdbase; 137 138 sc->sc_use_dma = 0; 139 if (ca->ca_nreg >= 16) 140 sc->sc_use_dma = 1; /* Enable dma */ 141 142 sc->sc_dmat = ca->ca_dmat; 143 if ((error = bus_dmamap_create(sc->sc_dmat, 144 WDC_DMALIST_MAX * DBDMA_COUNT_MAX, WDC_DMALIST_MAX, 145 DBDMA_COUNT_MAX, NBPG, BUS_DMA_NOWAIT, &sc->sc_dmamap)) != 0) { 146 printf(": cannot create dma map, error = %d\n", error); 147 return; 148 } 149 150 if (ca->ca_nintr >= 4 && ca->ca_nreg >= 8) { 151 intr = ca->ca_intr[0]; 152 printf(" irq %d", intr); 153 } else if (ca->ca_nintr == -1) { 154 intr = WDC_DEFAULT_PIO_IRQ; 155 printf(" irq property not found; using %d", intr); 156 } else { 157 printf(": couldn't get irq property\n"); 158 return; 159 } 160 161 if (sc->sc_use_dma) 162 printf(": DMA"); 163 164 printf("\n"); 165 166 chp->cmd_iot = chp->ctl_iot = ca->ca_iot; 167 chp->_vtbl = &wdc_obio_vtbl; 168 169 cmdbase = ca->ca_reg[0]; 170 sc->sc_cmdsize = ca->ca_reg[1]; 171 172 if (bus_space_map(chp->cmd_iot, cmdbase, sc->sc_cmdsize, 0, 173 &chp->cmd_ioh) || bus_space_subregion(chp->cmd_iot, chp->cmd_ioh, 174 /* WDC_AUXREG_OFFSET<<4 */ 0x160, 1, &chp->ctl_ioh)) { 175 printf("%s: couldn't map registers\n", 176 sc->sc_wdcdev.sc_dev.dv_xname); 177 return; 178 } 179 chp->data32iot = chp->cmd_iot; 180 chp->data32ioh = chp->cmd_ioh; 181 182 sc->sc_ih = mac_intr_establish(parent, intr, IST_LEVEL, IPL_BIO, 183 wdcintr, chp, sc->sc_wdcdev.sc_dev.dv_xname); 184 185 sc->sc_wdcdev.set_modes = wdc_obio_adjust_timing; 186 if (sc->sc_use_dma) { 187 sc->sc_dbdma = dbdma_alloc(sc->sc_dmat, WDC_DMALIST_MAX + 1); 188 sc->sc_dmacmd = sc->sc_dbdma->d_addr; 189 190 sc->sc_dmareg = mapiodev(ca->ca_baseaddr + ca->ca_reg[2], 191 sc->sc_dmasize = ca->ca_reg[3]); 192 193 sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA; 194 sc->sc_wdcdev.DMA_cap = 2; 195 if (strcmp(ca->ca_name, "ata-4") == 0) { 196 sc->sc_wdcdev.cap |= WDC_CAPABILITY_UDMA | 197 WDC_CAPABILITY_MODE; 198 sc->sc_wdcdev.UDMA_cap = 4; 199 sc->sc_wdcdev.set_modes = wdc_obio_ata4_adjust_timing; 200 } 201 if (strcmp(ca->ca_name, "ata-6") == 0) { 202 sc->sc_wdcdev.cap |= WDC_CAPABILITY_UDMA | 203 WDC_CAPABILITY_MODE; 204 sc->sc_wdcdev.UDMA_cap = 5; 205 sc->sc_wdcdev.set_modes = wdc_obio_ata6_adjust_timing; 206 } 207 } 208 sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA16; 209 sc->sc_wdcdev.PIO_cap = 4; 210 sc->wdc_chanptr = chp; 211 sc->sc_wdcdev.channels = &sc->wdc_chanptr; 212 sc->sc_wdcdev.nchannels = 1; 213 sc->sc_wdcdev.dma_arg = sc; 214 sc->sc_wdcdev.dma_init = wdc_obio_dma_init; 215 sc->sc_wdcdev.dma_start = wdc_obio_dma_start; 216 sc->sc_wdcdev.dma_finish = wdc_obio_dma_finish; 217 chp->channel = 0; 218 chp->wdc = &sc->sc_wdcdev; 219 220 chp->ch_queue = wdc_alloc_queue(); 221 if (chp->ch_queue == NULL) { 222 printf("%s: cannot allocate channel queue", 223 sc->sc_wdcdev.sc_dev.dv_xname); 224 return; 225 } 226 227 wdcattach(chp); 228 sc->sc_wdcdev.set_modes(chp); 229 wdc_print_current_modes(chp); 230} 231 232int 233wdc_obio_detach(struct device *self, int flags) 234{ 235 struct wdc_obio_softc *sc = (struct wdc_obio_softc *)self; 236 struct channel_softc *chp = &sc->wdc_channel; 237 int error; 238 239 if ((error = wdcdetach(chp, flags)) != 0) 240 return (error); 241 242 wdc_free_queue(chp->ch_queue); 243 244 if (sc->sc_use_dma) { 245 unmapiodev((void *)sc->sc_dmareg, sc->sc_dmasize); 246 dbdma_free(sc->sc_dbdma); 247 } 248 mac_intr_disestablish(NULL, sc->sc_ih); 249 250 bus_space_unmap(chp->cmd_iot, chp->cmd_ioh, sc->sc_cmdsize); 251 bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmamap); 252 253 return (0); 254} 255 256/* Multiword DMA transfer timings */ 257struct ide_timings { 258 int cycle; /* minimum cycle time [ns] */ 259 int active; /* minimum command active time [ns] */ 260}; 261 262static const struct ide_timings pio_timing[] = { 263 { 600, 165 }, /* Mode 0 */ 264 { 383, 125 }, /* 1 */ 265 { 240, 100 }, /* 2 */ 266 { 180, 80 }, /* 3 */ 267 { 120, 70 } /* 4 */ 268}; 269 270static const struct ide_timings dma_timing[] = { 271 { 480, 215 }, /* Mode 0 */ 272 { 150, 80 }, /* Mode 1 */ 273 { 120, 70 }, /* Mode 2 */ 274}; 275 276static const struct ide_timings udma_timing[] = { 277 {114, 0}, /* Mode 0 */ 278 { 75, 0}, /* Mode 1 */ 279 { 55, 0}, /* Mode 2 */ 280 { 45, 100}, /* Mode 3 */ 281 { 25, 100} /* Mode 4 */ 282}; 283 284/* these number _guessed_ from linux driver. */ 285static u_int32_t kauai_pio_timing[] = { 286 /*600*/ 0x08000a92, /* Mode 0 */ 287 /*360*/ 0x08000492, /* Mode 1 */ 288 /*240*/ 0x0800038b, /* Mode 2 */ 289 /*180*/ 0x05000249, /* Mode 3 */ 290 /*120*/ 0x04000148 /* Mode 4 */ 291 292}; 293static u_int32_t kauai_dma_timing[] = { 294 /*480*/ 0x00618000, /* Mode 0 */ 295 /*360*/ 0x00492000, /* Mode 1 */ 296 /*240*/ 0x00149000 /* Mode 2 */ /* fw value */ 297}; 298static u_int32_t kauai_udma_timing[] = { 299 /*120*/ 0x000070c0, /* Mode 0 */ 300 /* 90*/ 0x00005d80, /* Mode 1 */ 301 /* 60*/ 0x00004a60, /* Mode 2 */ 302 /* 45*/ 0x00003a50, /* Mode 3 */ 303 /* 30*/ 0x00002a30, /* Mode 4 */ 304 /* 20*/ 0x00002921 /* Mode 5 */ 305}; 306 307#define TIME_TO_TICK(time) howmany((time), 30) 308#define PIO_REC_OFFSET 4 309#define PIO_REC_MIN 1 310#define PIO_ACT_MIN 1 311#define DMA_REC_OFFSET 1 312#define DMA_REC_MIN 1 313#define DMA_ACT_MIN 1 314 315#define ATA4_TIME_TO_TICK(time) howmany((time) * 1000, 7500) 316 317#define CONFIG_REG (0x200) /* IDE access timing register */ 318#define KAUAI_ULTRA_CONFIG (0x210) /* secondary config register (kauai)*/ 319 320#define KAUAI_PIO_MASK 0xff000fff 321#define KAUAI_DMA_MASK 0x00fff000 322#define KAUAI_UDMA_MASK 0x0000ffff 323#define KAUAI_UDMA_EN 0x00000001 324 325void 326wdc_obio_adjust_timing(struct channel_softc *chp) 327{ 328 struct ata_drive_datas *drvp; 329 u_int conf; 330 int drive; 331 int piomode = -1, dmamode = -1; 332 int min_cycle, min_active; 333 int cycle_tick, act_tick, inact_tick, half_tick; 334 335 for (drive = 0; drive < 2; drive++) { 336 drvp = &chp->ch_drive[drive]; 337 if ((drvp->drive_flags & DRIVE) == 0) 338 continue; 339 if (piomode == -1 || piomode > drvp->PIO_mode) 340 piomode = drvp->PIO_mode; 341 if (drvp->drive_flags & DRIVE_DMA) 342 if (dmamode == -1 || dmamode > drvp->DMA_mode) 343 dmamode = drvp->DMA_mode; 344 } 345 if (piomode == -1) 346 return; /* No drive */ 347 for (drive = 0; drive < 2; drive++) { 348 drvp = &chp->ch_drive[drive]; 349 if (drvp->drive_flags & DRIVE) { 350 drvp->PIO_mode = piomode; 351 if (drvp->drive_flags & DRIVE_DMA) 352 drvp->DMA_mode = dmamode; 353 } 354 } 355 min_cycle = pio_timing[piomode].cycle; 356 min_active = pio_timing[piomode].active; 357 358 cycle_tick = TIME_TO_TICK(min_cycle); 359 act_tick = TIME_TO_TICK(min_active); 360 if (act_tick < PIO_ACT_MIN) 361 act_tick = PIO_ACT_MIN; 362 inact_tick = cycle_tick - act_tick - PIO_REC_OFFSET; 363 if (inact_tick < PIO_REC_MIN) 364 inact_tick = PIO_REC_MIN; 365 /* mask: 0x000007ff */ 366 conf = (inact_tick << 5) | act_tick; 367 if (dmamode != -1) { 368 /* there are active DMA mode */ 369 370 min_cycle = dma_timing[dmamode].cycle; 371 min_active = dma_timing[dmamode].active; 372 cycle_tick = TIME_TO_TICK(min_cycle); 373 act_tick = TIME_TO_TICK(min_active); 374 inact_tick = cycle_tick - act_tick - DMA_REC_OFFSET; 375 if (inact_tick < DMA_REC_MIN) 376 inact_tick = DMA_REC_MIN; 377 half_tick = 0; /* XXX */ 378 /* mask: 0xfffff800 */ 379 conf |= 380 (half_tick << 21) | 381 (inact_tick << 16) | (act_tick << 11); 382 } 383 bus_space_write_4(chp->cmd_iot, chp->cmd_ioh, CONFIG_REG, conf); 384#if 0 385 printf("conf = 0x%x, cyc = %d (%d ns), act = %d (%d ns), inact = %d\n", 386 conf, cycle_tick, min_cycle, act_tick, min_active, inact_tick); 387#endif 388} 389 390void 391wdc_obio_ata4_adjust_timing(struct channel_softc *chp) 392{ 393 struct ata_drive_datas *drvp; 394 u_int conf; 395 int drive; 396 int piomode = -1, dmamode = -1; 397 int min_cycle, min_active; 398 int cycle_tick, act_tick, inact_tick; 399 int udmamode = -1; 400 401 for (drive = 0; drive < 2; drive++) { 402 drvp = &chp->ch_drive[drive]; 403 if ((drvp->drive_flags & DRIVE) == 0) 404 continue; 405 if (piomode == -1 || piomode > drvp->PIO_mode) 406 piomode = drvp->PIO_mode; 407 if (drvp->drive_flags & DRIVE_DMA) 408 if (dmamode == -1 || dmamode > drvp->DMA_mode) 409 dmamode = drvp->DMA_mode; 410 if (drvp->drive_flags & DRIVE_UDMA) { 411 if (udmamode == -1 || udmamode > drvp->UDMA_mode) 412 udmamode = drvp->UDMA_mode; 413 } else 414 udmamode = -2; 415 } 416 if (piomode == -1) 417 return; /* No drive */ 418 for (drive = 0; drive < 2; drive++) { 419 drvp = &chp->ch_drive[drive]; 420 if (drvp->drive_flags & DRIVE) { 421 drvp->PIO_mode = piomode; 422 if (drvp->drive_flags & DRIVE_DMA) 423 drvp->DMA_mode = dmamode; 424 if (drvp->drive_flags & DRIVE_UDMA) { 425 if (udmamode == -2) 426 drvp->drive_flags &= ~DRIVE_UDMA; 427 else 428 drvp->UDMA_mode = udmamode; 429 } 430 } 431 } 432 433 if (udmamode == -2) 434 udmamode = -1; 435 436 min_cycle = pio_timing[piomode].cycle; 437 min_active = pio_timing[piomode].active; 438 439 cycle_tick = ATA4_TIME_TO_TICK(min_cycle); 440 act_tick = ATA4_TIME_TO_TICK(min_active); 441 inact_tick = cycle_tick - act_tick; 442 /* mask: 0x000003ff */ 443 conf = (inact_tick << 5) | act_tick; 444 if (dmamode != -1) { 445 /* there are active DMA mode */ 446 447 min_cycle = dma_timing[dmamode].cycle; 448 min_active = dma_timing[dmamode].active; 449 cycle_tick = ATA4_TIME_TO_TICK(min_cycle); 450 act_tick = ATA4_TIME_TO_TICK(min_active); 451 inact_tick = cycle_tick - act_tick; 452 /* mask: 0x001ffc00 */ 453 conf |= (act_tick << 10) | (inact_tick << 15); 454 } 455 if (udmamode != -1) { 456 min_cycle = udma_timing[udmamode].cycle; 457 min_active = udma_timing[udmamode].active; 458 act_tick = ATA4_TIME_TO_TICK(min_active); 459 cycle_tick = ATA4_TIME_TO_TICK(min_cycle); 460 /* mask: 0x1ff00000 */ 461 conf |= (cycle_tick << 21) | (act_tick << 25) | 0x100000; 462 } 463 464 bus_space_write_4(chp->cmd_iot, chp->cmd_ioh, CONFIG_REG, conf); 465#if 0 466 printf("ata4 conf = 0x%x, cyc = %d (%d ns), act = %d (%d ns), inact = %d\n", 467 conf, cycle_tick, min_cycle, act_tick, min_active, inact_tick); 468#endif 469} 470 471void 472wdc_obio_ata6_adjust_timing(struct channel_softc *chp) 473{ 474 struct ata_drive_datas *drvp; 475 u_int conf, conf1; 476 int drive; 477 int piomode = -1, dmamode = -1; 478 int udmamode = -1; 479 480 for (drive = 0; drive < 2; drive++) { 481 drvp = &chp->ch_drive[drive]; 482 if ((drvp->drive_flags & DRIVE) == 0) 483 continue; 484 if (piomode == -1 || piomode > drvp->PIO_mode) 485 piomode = drvp->PIO_mode; 486 if (drvp->drive_flags & DRIVE_DMA) { 487 if (dmamode == -1 || dmamode > drvp->DMA_mode) 488 dmamode = drvp->DMA_mode; 489 } 490 if (drvp->drive_flags & DRIVE_UDMA) { 491 if (udmamode == -1 || udmamode > drvp->UDMA_mode) 492 udmamode = drvp->UDMA_mode; 493 } else 494 udmamode = -2; 495 } 496 if (piomode == -1) 497 return; /* No drive */ 498 for (drive = 0; drive < 2; drive++) { 499 drvp = &chp->ch_drive[drive]; 500 if (drvp->drive_flags & DRIVE) { 501 drvp->PIO_mode = piomode; 502 if (drvp->drive_flags & DRIVE_DMA) 503 drvp->DMA_mode = dmamode; 504 if (drvp->drive_flags & DRIVE_UDMA) { 505 if (udmamode == -2) 506 drvp->drive_flags &= ~DRIVE_UDMA; 507 else 508 drvp->UDMA_mode = udmamode; 509 } 510 } 511 } 512 513 if (udmamode == -2) 514 udmamode = -1; 515 516 conf = bus_space_read_4(chp->cmd_iot, chp->cmd_ioh, CONFIG_REG); 517 conf1 = bus_space_read_4(chp->cmd_iot, chp->cmd_ioh, 518 KAUAI_ULTRA_CONFIG); 519 520 conf = (conf & ~KAUAI_PIO_MASK) | kauai_pio_timing[piomode]; 521 522 if (dmamode != -1) 523 conf = (conf & ~KAUAI_DMA_MASK) | kauai_dma_timing[dmamode]; 524 if (udmamode != -1) 525 conf1 = (conf1 & ~KAUAI_UDMA_MASK) | 526 kauai_udma_timing[udmamode] | KAUAI_UDMA_EN; 527 else 528 conf1 = conf1 & ~KAUAI_UDMA_EN; 529 530 bus_space_write_4(chp->cmd_iot, chp->cmd_ioh, CONFIG_REG, conf); 531 bus_space_write_4(chp->cmd_iot, chp->cmd_ioh, KAUAI_ULTRA_CONFIG, 532 conf1); 533} 534 535int 536wdc_obio_dma_init(void *v, int channel, int drive, void *databuf, 537 size_t datalen, int flags) 538{ 539 struct wdc_obio_softc *sc = v; 540 dbdma_command_t *cmdp; 541 u_int cmd; 542 int i, error; 543 544 if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, databuf, 545 datalen, NULL, BUS_DMA_NOWAIT)) != 0) 546 return (error); 547 548 cmdp = sc->sc_dmacmd; 549 cmd = (flags & WDC_DMA_READ) ? DBDMA_CMD_IN_MORE : DBDMA_CMD_OUT_MORE; 550 551 for (i = 0; i < sc->sc_dmamap->dm_nsegs; i++, cmdp++) { 552 if (i + 1 == sc->sc_dmamap->dm_nsegs) 553 cmd = (flags & WDC_DMA_READ) ? DBDMA_CMD_IN_LAST : 554 DBDMA_CMD_OUT_LAST; 555 556 DBDMA_BUILD(cmdp, cmd, 0, sc->sc_dmamap->dm_segs[i].ds_len, 557 sc->sc_dmamap->dm_segs[i].ds_addr, 558 DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); 559 } 560 561 DBDMA_BUILD(cmdp, DBDMA_CMD_STOP, 0, 0, 0, 562 DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); 563 564 return 0; 565} 566 567void 568wdc_obio_dma_start(void *v, int channel, int drive) 569{ 570 struct wdc_obio_softc *sc = v; 571 572 dbdma_start(sc->sc_dmareg, sc->sc_dbdma); 573} 574 575int 576wdc_obio_dma_finish(void *v, int channel, int drive, int force) 577{ 578 struct wdc_obio_softc *sc = v; 579 580 dbdma_stop(sc->sc_dmareg); 581 bus_dmamap_unload(sc->sc_dmat, sc->sc_dmamap); 582 return 0; 583} 584 585/* read register code 586 * this allows the registers to be spaced by 0x10, instead of 0x1. 587 * mac hardware (obio) requires this. 588 */ 589 590u_int8_t 591wdc_obio_read_reg(struct channel_softc *chp, enum wdc_regs reg) 592{ 593#ifdef DIAGNOSTIC 594 if (reg & _WDC_WRONLY) { 595 printf ("wdc_obio_read_reg: reading from a write-only register %d\n", reg); 596 } 597#endif 598 599 if (reg & _WDC_AUX) 600 return (bus_space_read_1(chp->ctl_iot, chp->ctl_ioh, 601 (reg & _WDC_REGMASK) << 4)); 602 else 603 return (bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, 604 (reg & _WDC_REGMASK) << 4)); 605} 606 607 608void 609wdc_obio_write_reg(struct channel_softc *chp, enum wdc_regs reg, u_int8_t val) 610{ 611#ifdef DIAGNOSTIC 612 if (reg & _WDC_RDONLY) { 613 printf ("wdc_obio_write_reg: writing to a read-only register %d\n", reg); 614 } 615#endif 616 617 if (reg & _WDC_AUX) 618 bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, 619 (reg & _WDC_REGMASK) << 4, val); 620 else 621 bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, 622 (reg & _WDC_REGMASK) << 4, val); 623} 624