[BACK]Return to wdc_obio.c CVS log [TXT][DIR] Up to [local] / sys / arch / macppc / dev

Annotation of sys/arch/macppc/dev/wdc_obio.c, Revision 1.1.1.1

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

CVSweb