1 /* $OpenBSD: wdc_obio.c,v 1.4 2011/05/09 22:33:53 matthew Exp $ */ 2 /* $NetBSD: wdc_obio.c,v 1.1 2006/09/01 21:26:18 uwe Exp $ */ 3 4 /*- 5 * Copyright (c) 1998, 2003 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 <machine/bus.h> 39 #include <machine/intr.h> 40 41 #include <dev/ata/atavar.h> 42 #include <dev/ic/wdcvar.h> 43 44 #include <landisk/dev/obiovar.h> 45 46 struct wdc_obio_softc { 47 struct wdc_softc sc_wdcdev; 48 struct channel_softc *sc_chanptr; 49 struct channel_softc sc_channel; 50 51 void *sc_ih; 52 }; 53 54 int wdc_obio_match(struct device *, void *, void *); 55 void wdc_obio_attach(struct device *, struct device *, void *); 56 57 struct cfattach wdc_obio_ca = { 58 sizeof(struct wdc_obio_softc), wdc_obio_match, wdc_obio_attach 59 }; 60 61 #define WDC_OBIO_REG_NPORTS WDC_NREG 62 #define WDC_OBIO_REG_SIZE (WDC_OBIO_REG_NPORTS * 2) 63 #define WDC_OBIO_AUXREG_NPORTS 1 64 #define WDC_OBIO_AUXREG_SIZE (WDC_OBIO_AUXREG_NPORTS * 2) 65 #define WDC_OBIO_AUXREG_OFFSET 0x2c 66 67 u_int8_t wdc_obio_read_reg(struct channel_softc *chp, enum wdc_regs reg); 68 void wdc_obio_write_reg(struct channel_softc *chp, enum wdc_regs reg, 69 u_int8_t val); 70 71 struct channel_softc_vtbl wdc_obio_vtbl = { 72 wdc_obio_read_reg, 73 wdc_obio_write_reg, 74 wdc_default_lba48_write_reg, 75 wdc_default_read_raw_multi_2, 76 wdc_default_write_raw_multi_2, 77 wdc_default_read_raw_multi_4, 78 wdc_default_write_raw_multi_4 79 }; 80 81 int 82 wdc_obio_match(struct device *parent, void *vcf, void *aux) 83 { 84 struct obio_attach_args *oa = aux; 85 86 if (oa->oa_nio != 1) 87 return (0); 88 if (oa->oa_nirq != 1) 89 return (0); 90 if (oa->oa_niomem != 0) 91 return (0); 92 93 if (oa->oa_io[0].or_addr == IOBASEUNK) 94 return (0); 95 if (oa->oa_irq[0].or_irq == IRQUNK) 96 return (0); 97 98 /* XXX should probe for hardware */ 99 100 oa->oa_io[0].or_size = WDC_OBIO_REG_SIZE; 101 102 return (1); 103 } 104 105 void 106 wdc_obio_attach(struct device *parent, struct device *self, void *aux) 107 { 108 struct wdc_obio_softc *sc = (void *)self; 109 struct obio_attach_args *oa = aux; 110 struct channel_softc *chp = &sc->sc_channel; 111 112 printf("\n"); 113 114 chp->cmd_iot = chp->ctl_iot = oa->oa_iot; 115 chp->_vtbl = &wdc_obio_vtbl; 116 117 if (bus_space_map(chp->cmd_iot, oa->oa_io[0].or_addr, 118 WDC_OBIO_REG_SIZE, 0, &chp->cmd_ioh) 119 || bus_space_map(chp->ctl_iot, 120 oa->oa_io[0].or_addr + WDC_OBIO_AUXREG_OFFSET, 121 WDC_OBIO_AUXREG_SIZE, 0, &chp->ctl_ioh)) { 122 printf(": couldn't map registers\n"); 123 return; 124 } 125 126 sc->sc_ih = obio_intr_establish(oa->oa_irq[0].or_irq, IPL_BIO, wdcintr, 127 chp, self->dv_xname); 128 129 sc->sc_wdcdev.cap |= WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_PREATA; 130 sc->sc_wdcdev.PIO_cap = 0; 131 sc->sc_chanptr = chp; 132 sc->sc_wdcdev.channels = &sc->sc_chanptr; 133 sc->sc_wdcdev.nchannels = 1; 134 chp->channel = 0; 135 chp->wdc = &sc->sc_wdcdev; 136 137 chp->ch_queue = wdc_alloc_queue(); 138 if (chp->ch_queue == NULL) { 139 printf("%s: cannot allocate channel queue\n", 140 self->dv_xname); 141 obio_intr_disestablish(sc->sc_ih); 142 return; 143 } 144 145 wdcattach(chp); 146 wdc_print_current_modes(chp); 147 } 148 149 u_int8_t 150 wdc_obio_read_reg(struct channel_softc *chp, enum wdc_regs reg) 151 { 152 if (reg & _WDC_AUX) 153 return (bus_space_read_1(chp->ctl_iot, chp->ctl_ioh, 154 (reg & _WDC_REGMASK) << 1)); 155 else 156 return (bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, 157 (reg & _WDC_REGMASK) << 1)); 158 } 159 160 void 161 wdc_obio_write_reg(struct channel_softc *chp, enum wdc_regs reg, u_int8_t val) 162 { 163 if (reg & _WDC_AUX) 164 bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, 165 (reg & _WDC_REGMASK) << 1, val); 166 else 167 bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, 168 (reg & _WDC_REGMASK) << 1, val); 169 } 170