1 /* $OpenBSD: wdc_obio.c,v 1.30 2013/05/30 16:15:01 deraadt 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 59 struct 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 76 u_int8_t wdc_obio_read_reg(struct channel_softc *, enum wdc_regs); 77 void wdc_obio_write_reg(struct channel_softc *, enum wdc_regs, u_int8_t); 78 79 struct 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 89 int wdc_obio_probe(struct device *, void *, void *); 90 void wdc_obio_attach(struct device *, struct device *, void *); 91 int wdc_obio_detach(struct device *, int); 92 93 struct cfattach wdc_obio_ca = { 94 sizeof(struct wdc_obio_softc), wdc_obio_probe, wdc_obio_attach, 95 wdc_obio_detach 96 }; 97 98 int wdc_obio_dma_init(void *, int, int, void *, size_t, int); 99 void wdc_obio_dma_start(void *, int, int); 100 int wdc_obio_dma_finish(void *, int, int, int); 101 void wdc_obio_adjust_timing(struct channel_softc *); 102 void wdc_obio_ata4_adjust_timing(struct channel_softc *); 103 void wdc_obio_ata6_adjust_timing(struct channel_softc *); 104 105 int 106 wdc_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 129 void 130 wdc_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 232 int 233 wdc_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 */ 257 struct ide_timings { 258 int cycle; /* minimum cycle time [ns] */ 259 int active; /* minimum command active time [ns] */ 260 }; 261 262 static 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 270 static const struct ide_timings dma_timing[] = { 271 { 480, 215 }, /* Mode 0 */ 272 { 150, 80 }, /* Mode 1 */ 273 { 120, 70 }, /* Mode 2 */ 274 }; 275 276 static 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. */ 285 static 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 }; 293 static u_int32_t kauai_dma_timing[] = { 294 /*480*/ 0x00618000, /* Mode 0 */ 295 /*360*/ 0x00492000, /* Mode 1 */ 296 /*240*/ 0x00149000 /* Mode 2 */ /* fw value */ 297 }; 298 static 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 325 void 326 wdc_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 390 void 391 wdc_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 471 void 472 wdc_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 535 int 536 wdc_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 567 void 568 wdc_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 575 int 576 wdc_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 590 u_int8_t 591 wdc_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 608 void 609 wdc_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