1 1.130 thorpej /* $NetBSD: wdc_pcmcia.c,v 1.130 2022/09/25 21:53:54 thorpej Exp $ */ 2 1.1 matt 3 1.8 mycroft /*- 4 1.78 mycroft * Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc. 5 1.8 mycroft * All rights reserved. 6 1.1 matt * 7 1.8 mycroft * This code is derived from software contributed to The NetBSD Foundation 8 1.8 mycroft * by Charles M. Hannum, by Onno van der Linden and by Manuel Bouyer. 9 1.1 matt * 10 1.1 matt * Redistribution and use in source and binary forms, with or without 11 1.1 matt * modification, are permitted provided that the following conditions 12 1.1 matt * are met: 13 1.1 matt * 1. Redistributions of source code must retain the above copyright 14 1.1 matt * notice, this list of conditions and the following disclaimer. 15 1.1 matt * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 matt * notice, this list of conditions and the following disclaimer in the 17 1.1 matt * documentation and/or other materials provided with the distribution. 18 1.1 matt * 19 1.8 mycroft * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.8 mycroft * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.8 mycroft * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.8 mycroft * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.8 mycroft * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.8 mycroft * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.8 mycroft * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.8 mycroft * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.8 mycroft * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.8 mycroft * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.8 mycroft * POSSIBILITY OF SUCH DAMAGE. 30 1.1 matt */ 31 1.44 lukem 32 1.44 lukem #include <sys/cdefs.h> 33 1.130 thorpej __KERNEL_RCSID(0, "$NetBSD: wdc_pcmcia.c,v 1.130 2022/09/25 21:53:54 thorpej Exp $"); 34 1.1 matt 35 1.1 matt #include <sys/param.h> 36 1.30 enami #include <sys/device.h> 37 1.100 bouyer #include <sys/kernel.h> 38 1.1 matt #include <sys/systm.h> 39 1.100 bouyer #include <sys/proc.h> 40 1.1 matt 41 1.109 ad #include <sys/bus.h> 42 1.109 ad #include <sys/intr.h> 43 1.1 matt 44 1.14 enami #include <dev/pcmcia/pcmciareg.h> 45 1.1 matt #include <dev/pcmcia/pcmciavar.h> 46 1.9 kenh #include <dev/pcmcia/pcmciadevs.h> 47 1.9 kenh 48 1.64 fvdl #include <dev/ic/wdcreg.h> 49 1.12 bouyer #include <dev/ata/atavar.h> 50 1.1 matt #include <dev/ic/wdcvar.h> 51 1.1 matt 52 1.99 matt #ifndef __BUS_SPACE_HAS_STREAM_METHODS 53 1.99 matt #define bus_space_write_multi_stream_2 bus_space_write_multi_2 54 1.99 matt #define bus_space_write_multi_stream_4 bus_space_write_multi_4 55 1.99 matt #define bus_space_read_multi_stream_2 bus_space_read_multi_2 56 1.99 matt #define bus_space_read_multi_stream_4 bus_space_read_multi_4 57 1.99 matt #endif /* __BUS_SPACE_HAS_STREAM_METHODS */ 58 1.99 matt 59 1.1 matt #define WDC_PCMCIA_REG_NPORTS 8 60 1.9 kenh #define WDC_PCMCIA_AUXREG_OFFSET (WDC_PCMCIA_REG_NPORTS + 6) 61 1.2 mycroft #define WDC_PCMCIA_AUXREG_NPORTS 2 62 1.1 matt 63 1.1 matt struct wdc_pcmcia_softc { 64 1.1 matt struct wdc_softc sc_wdcdev; 65 1.91 thorpej struct ata_channel *wdc_chanlist[1]; 66 1.91 thorpej struct ata_channel ata_channel; 67 1.91 thorpej struct wdc_regs wdc_regs; 68 1.84 mycroft 69 1.84 mycroft struct pcmcia_function *sc_pf; 70 1.1 matt void *sc_ih; 71 1.75 mycroft 72 1.75 mycroft int sc_state; 73 1.75 mycroft #define WDC_PCMCIA_ATTACHED 3 74 1.1 matt }; 75 1.1 matt 76 1.97 toshii #ifndef __BUS_SPACE_HAS_STREAM_METHODS 77 1.97 toshii #define bus_space_read_region_stream_2 bus_space_read_region_2 78 1.97 toshii #define bus_space_read_region_stream_4 bus_space_read_region_4 79 1.97 toshii #define bus_space_write_region_stream_2 bus_space_write_region_2 80 1.97 toshii #define bus_space_write_region_stream_4 bus_space_write_region_4 81 1.97 toshii #endif /* __BUS_SPACE_HAS_STREAM_METHODS */ 82 1.97 toshii 83 1.110 cube static int wdc_pcmcia_match(device_t, cfdata_t, void *); 84 1.94 thorpej static int wdc_pcmcia_validate_config_io(struct pcmcia_config_entry *); 85 1.94 thorpej static int wdc_pcmcia_validate_config_memory(struct pcmcia_config_entry *); 86 1.110 cube static void wdc_pcmcia_attach(device_t, device_t, void *); 87 1.110 cube static int wdc_pcmcia_detach(device_t, int); 88 1.1 matt 89 1.110 cube CFATTACH_DECL_NEW(wdc_pcmcia, sizeof(struct wdc_pcmcia_softc), 90 1.117 dyoung wdc_pcmcia_match, wdc_pcmcia_attach, wdc_pcmcia_detach, NULL); 91 1.1 matt 92 1.103 bouyer static const struct wdc_pcmcia_product { 93 1.103 bouyer struct pcmcia_product wdc_product; 94 1.103 bouyer int wdc_ndrive; 95 1.103 bouyer } wdc_pcmcia_products[] = { 96 1.103 bouyer { { PCMCIA_VENDOR_DIGITAL, 97 1.9 kenh PCMCIA_PRODUCT_DIGITAL_MOBILE_MEDIA_CDROM, 98 1.103 bouyer {NULL, "Digital Mobile Media CD-ROM", NULL, NULL} }, 2 }, 99 1.19 abs 100 1.103 bouyer { { PCMCIA_VENDOR_IBM, 101 1.24 soren PCMCIA_PRODUCT_IBM_PORTABLE_CDROM, 102 1.103 bouyer {NULL, "PCMCIA Portable CD-ROM Drive", NULL, NULL} }, 2 }, 103 1.9 kenh 104 1.9 kenh /* The TEAC IDE/Card II is used on the Sony Vaio */ 105 1.103 bouyer { { PCMCIA_VENDOR_TEAC, 106 1.9 kenh PCMCIA_PRODUCT_TEAC_IDECARDII, 107 1.103 bouyer PCMCIA_CIS_TEAC_IDECARDII }, 2 }, 108 1.43 christos 109 1.43 christos /* 110 1.98 perry * A fujitsu rebranded panasonic drive that reports 111 1.43 christos * itself as function "scsi", disk interface 0 112 1.43 christos */ 113 1.103 bouyer { { PCMCIA_VENDOR_PANASONIC, 114 1.43 christos PCMCIA_PRODUCT_PANASONIC_KXLC005, 115 1.103 bouyer PCMCIA_CIS_PANASONIC_KXLC005 }, 2 }, 116 1.26 augustss 117 1.103 bouyer { { PCMCIA_VENDOR_SANDISK, 118 1.102 christos PCMCIA_PRODUCT_SANDISK_SDCFB, 119 1.103 bouyer PCMCIA_CIS_SANDISK_SDCFB }, 1 }, 120 1.102 christos 121 1.27 enami /* 122 1.27 enami * EXP IDE/ATAPI DVD Card use with some DVD players. 123 1.27 enami * Does not have a vendor ID or product ID. 124 1.27 enami */ 125 1.103 bouyer { { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, 126 1.103 bouyer PCMCIA_CIS_EXP_EXPMULTIMEDIA }, 2 }, 127 1.23 takemura 128 1.36 abs /* Mobile Dock 2, neither vendor ID nor product ID */ 129 1.103 bouyer { { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, 130 1.103 bouyer {"SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", NULL, NULL} }, 2 }, 131 1.34 abs 132 1.36 abs /* Toshiba Portege 3110 CD, neither vendor ID nor product ID */ 133 1.103 bouyer { { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, 134 1.103 bouyer {"FREECOM", "PCCARD-IDE", NULL, NULL} }, 2 }, 135 1.36 abs 136 1.98 perry /* Random CD-ROM, (badged AMACOM), neither vendor ID nor product ID */ 137 1.103 bouyer { { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, 138 1.103 bouyer {"PCMCIA", "CD-ROM", NULL, NULL} }, 2 }, 139 1.37 haya 140 1.37 haya /* IO DATA CBIDE2, with neither vendor ID nor product ID */ 141 1.103 bouyer { { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, 142 1.103 bouyer PCMCIA_CIS_IODATA_CBIDE2 }, 2 }, 143 1.54 ichiro 144 1.54 ichiro /* TOSHIBA PA2673U(IODATA_CBIDE2 OEM), */ 145 1.54 ichiro /* with neither vendor ID nor product ID */ 146 1.103 bouyer { { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, 147 1.103 bouyer PCMCIA_CIS_TOSHIBA_CBIDE2 }, 2 }, 148 1.38 sato 149 1.98 perry /* 150 1.98 perry * Novac PCMCIA-IDE Card for HD530P IDE Box, 151 1.38 sato * with neither vendor ID nor product ID 152 1.38 sato */ 153 1.103 bouyer { { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, 154 1.103 bouyer {"PCMCIA", "PnPIDE", NULL, NULL} }, 2 }, 155 1.106 christos 156 1.106 christos { { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, 157 1.106 christos {"PCMCIA", "IDE CARD", NULL, NULL} }, 2 }, 158 1.106 christos 159 1.9 kenh }; 160 1.94 thorpej static const size_t wdc_pcmcia_nproducts = 161 1.81 mycroft sizeof(wdc_pcmcia_products) / sizeof(wdc_pcmcia_products[0]); 162 1.9 kenh 163 1.110 cube static int wdc_pcmcia_enable(device_t, int); 164 1.94 thorpej static void wdc_pcmcia_datain_memory(struct ata_channel *, int, void *, 165 1.94 thorpej size_t); 166 1.94 thorpej static void wdc_pcmcia_dataout_memory(struct ata_channel *, int, void *, 167 1.94 thorpej size_t); 168 1.14 enami 169 1.1 matt static int 170 1.110 cube wdc_pcmcia_match(device_t parent, cfdata_t match, void *aux) 171 1.1 matt { 172 1.1 matt struct pcmcia_attach_args *pa = aux; 173 1.35 haya 174 1.98 perry if (pa->pf->function == PCMCIA_FUNCTION_DISK && 175 1.81 mycroft pa->pf->pf_funce_disk_interface == PCMCIA_TPLFE_DDI_PCCARD_ATA) 176 1.9 kenh return (1); 177 1.81 mycroft if (pcmcia_product_lookup(pa, wdc_pcmcia_products, wdc_pcmcia_nproducts, 178 1.81 mycroft sizeof(wdc_pcmcia_products[0]), NULL)) 179 1.81 mycroft return (2); 180 1.9 kenh return (0); 181 1.1 matt } 182 1.1 matt 183 1.72 mycroft static int 184 1.94 thorpej wdc_pcmcia_validate_config_io(struct pcmcia_config_entry *cfe) 185 1.72 mycroft { 186 1.87 mycroft if (cfe->iftype != PCMCIA_IFTYPE_IO || 187 1.87 mycroft cfe->num_iospace < 1 || cfe->num_iospace > 2) 188 1.87 mycroft return (EINVAL); 189 1.87 mycroft cfe->num_memspace = 0; 190 1.87 mycroft return (0); 191 1.87 mycroft } 192 1.87 mycroft 193 1.87 mycroft static int 194 1.94 thorpej wdc_pcmcia_validate_config_memory(struct pcmcia_config_entry *cfe) 195 1.87 mycroft { 196 1.87 mycroft if (cfe->iftype != PCMCIA_IFTYPE_MEMORY || 197 1.87 mycroft cfe->num_memspace > 1 || 198 1.87 mycroft cfe->memspace[0].length < 2048) 199 1.72 mycroft return (EINVAL); 200 1.87 mycroft cfe->num_iospace = 0; 201 1.72 mycroft return (0); 202 1.72 mycroft } 203 1.72 mycroft 204 1.1 matt static void 205 1.110 cube wdc_pcmcia_attach(device_t parent, device_t self, void *aux) 206 1.1 matt { 207 1.110 cube struct wdc_pcmcia_softc *sc = device_private(self); 208 1.1 matt struct pcmcia_attach_args *pa = aux; 209 1.5 enami struct pcmcia_config_entry *cfe; 210 1.91 thorpej struct wdc_regs *wdr; 211 1.103 bouyer const struct wdc_pcmcia_product *wdcp; 212 1.72 mycroft bus_size_t offset; 213 1.73 mycroft int i; 214 1.72 mycroft int error; 215 1.1 matt 216 1.112 uwe aprint_naive("\n"); 217 1.112 uwe 218 1.110 cube sc->sc_wdcdev.sc_atac.atac_dev = self; 219 1.15 thorpej sc->sc_pf = pa->pf; 220 1.15 thorpej 221 1.87 mycroft error = pcmcia_function_configure(pa->pf, 222 1.87 mycroft wdc_pcmcia_validate_config_io); 223 1.87 mycroft if (error) 224 1.87 mycroft /*XXXmem16|common*/ 225 1.87 mycroft error = pcmcia_function_configure(pa->pf, 226 1.87 mycroft wdc_pcmcia_validate_config_memory); 227 1.72 mycroft if (error) { 228 1.110 cube aprint_error_dev(self, "configure failed, error=%d\n", error); 229 1.72 mycroft return; 230 1.1 matt } 231 1.1 matt 232 1.72 mycroft cfe = pa->pf->cfe; 233 1.129 rin sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DATA16 | ATAC_CAP_DATA32; 234 1.41 uch 235 1.91 thorpej sc->sc_wdcdev.regs = wdr = &sc->wdc_regs; 236 1.91 thorpej 237 1.87 mycroft if (cfe->iftype == PCMCIA_IFTYPE_MEMORY) { 238 1.91 thorpej wdr->cmd_iot = cfe->memspace[0].handle.memt; 239 1.91 thorpej wdr->cmd_baseioh = cfe->memspace[0].handle.memh; 240 1.87 mycroft offset = cfe->memspace[0].offset; 241 1.91 thorpej wdr->ctl_iot = cfe->memspace[0].handle.memt; 242 1.87 mycroft if (bus_space_subregion(cfe->memspace[0].handle.memt, 243 1.87 mycroft cfe->memspace[0].handle.memh, 244 1.87 mycroft offset + WDC_PCMCIA_AUXREG_OFFSET, WDC_PCMCIA_AUXREG_NPORTS, 245 1.91 thorpej &wdr->ctl_ioh)) 246 1.72 mycroft goto fail; 247 1.41 uch } else { 248 1.91 thorpej wdr->cmd_iot = cfe->iospace[0].handle.iot; 249 1.91 thorpej wdr->cmd_baseioh = cfe->iospace[0].handle.ioh; 250 1.87 mycroft offset = 0; 251 1.87 mycroft if (cfe->num_iospace == 1) { 252 1.91 thorpej wdr->ctl_iot = cfe->iospace[0].handle.iot; 253 1.87 mycroft if (bus_space_subregion(cfe->iospace[0].handle.iot, 254 1.87 mycroft cfe->iospace[0].handle.ioh, 255 1.87 mycroft WDC_PCMCIA_AUXREG_OFFSET, WDC_PCMCIA_AUXREG_NPORTS, 256 1.91 thorpej &wdr->ctl_ioh)) 257 1.87 mycroft goto fail; 258 1.87 mycroft } else { 259 1.91 thorpej wdr->ctl_iot = cfe->iospace[1].handle.iot; 260 1.91 thorpej wdr->ctl_ioh = cfe->iospace[1].handle.ioh; 261 1.87 mycroft } 262 1.25 sommerfe } 263 1.5 enami 264 1.64 fvdl for (i = 0; i < WDC_PCMCIA_REG_NPORTS; i++) { 265 1.91 thorpej if (bus_space_subregion(wdr->cmd_iot, 266 1.91 thorpej wdr->cmd_baseioh, 267 1.64 fvdl offset + i, i == 0 ? 4 : 1, 268 1.91 thorpej &wdr->cmd_iohs[i]) != 0) { 269 1.110 cube aprint_error_dev(self, "can't subregion I/O space\n"); 270 1.96 enami goto fail; 271 1.64 fvdl } 272 1.64 fvdl } 273 1.85 mycroft 274 1.87 mycroft if (cfe->iftype == PCMCIA_IFTYPE_MEMORY) { 275 1.110 cube aprint_normal_dev(self, "memory mapped mode\n"); 276 1.91 thorpej wdr->data32iot = cfe->memspace[0].handle.memt; 277 1.85 mycroft if (bus_space_subregion(cfe->memspace[0].handle.memt, 278 1.87 mycroft cfe->memspace[0].handle.memh, offset + 1024, 1024, 279 1.91 thorpej &wdr->data32ioh)) 280 1.85 mycroft goto fail; 281 1.87 mycroft sc->sc_wdcdev.datain_pio = wdc_pcmcia_datain_memory; 282 1.87 mycroft sc->sc_wdcdev.dataout_pio = wdc_pcmcia_dataout_memory; 283 1.95 thorpej sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_NOIRQ; 284 1.85 mycroft } else { 285 1.110 cube aprint_normal_dev(self, "i/o mapped mode\n"); 286 1.91 thorpej wdr->data32iot = wdr->cmd_iot; 287 1.91 thorpej wdr->data32ioh = wdr->cmd_iohs[wd_data]; 288 1.85 mycroft } 289 1.85 mycroft 290 1.95 thorpej sc->sc_wdcdev.sc_atac.atac_pio_cap = 0; 291 1.91 thorpej sc->wdc_chanlist[0] = &sc->ata_channel; 292 1.95 thorpej sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanlist; 293 1.95 thorpej sc->sc_wdcdev.sc_atac.atac_nchannels = 1; 294 1.91 thorpej sc->ata_channel.ch_channel = 0; 295 1.95 thorpej sc->ata_channel.ch_atac = &sc->sc_wdcdev.sc_atac; 296 1.126 jdolecek 297 1.103 bouyer wdcp = pcmcia_product_lookup(pa, wdc_pcmcia_products, 298 1.103 bouyer wdc_pcmcia_nproducts, sizeof(wdc_pcmcia_products[0]), NULL); 299 1.123 bouyer sc->sc_wdcdev.wdc_maxdrives = wdcp ? wdcp->wdc_ndrive : 2; 300 1.125 jdolecek wdc_init_shadow_regs(wdr); 301 1.15 thorpej 302 1.90 mycroft error = wdc_pcmcia_enable(self, 1); 303 1.90 mycroft if (error) 304 1.90 mycroft goto fail; 305 1.90 mycroft 306 1.15 thorpej /* We can enable and disable the controller. */ 307 1.95 thorpej sc->sc_wdcdev.sc_atac.atac_atapi_adapter._generic.adapt_enable = 308 1.32 bouyer wdc_pcmcia_enable; 309 1.95 thorpej sc->sc_wdcdev.sc_atac.atac_atapi_adapter._generic.adapt_refcnt = 1; 310 1.15 thorpej 311 1.100 bouyer /* 312 1.100 bouyer * Some devices needs some more delay after power up to stabilize 313 1.100 bouyer * and probe properly, so give them half a second. 314 1.100 bouyer * See PR 25659 for details. 315 1.100 bouyer */ 316 1.124 christos config_pending_incr(self); 317 1.100 bouyer tsleep(wdc_pcmcia_attach, PWAIT, "wdcattach", hz / 2); 318 1.100 bouyer 319 1.91 thorpej wdcattach(&sc->ata_channel); 320 1.115 uwe 321 1.115 uwe if (!pmf_device_register(self, NULL, NULL)) 322 1.115 uwe aprint_error_dev(self, "unable to establish power handler\n"); 323 1.115 uwe 324 1.124 christos config_pending_decr(self); 325 1.91 thorpej ata_delref(&sc->ata_channel); 326 1.75 mycroft sc->sc_state = WDC_PCMCIA_ATTACHED; 327 1.29 enami return; 328 1.29 enami 329 1.72 mycroft fail: 330 1.72 mycroft pcmcia_function_unconfigure(pa->pf); 331 1.21 enami } 332 1.21 enami 333 1.94 thorpej static int 334 1.110 cube wdc_pcmcia_detach(device_t self, int flags) 335 1.21 enami { 336 1.110 cube struct wdc_pcmcia_softc *sc = device_private(self); 337 1.21 enami int error; 338 1.29 enami 339 1.75 mycroft if (sc->sc_state != WDC_PCMCIA_ATTACHED) 340 1.29 enami return (0); 341 1.21 enami 342 1.115 uwe pmf_device_deregister(self); 343 1.115 uwe 344 1.21 enami if ((error = wdcdetach(self, flags)) != 0) 345 1.21 enami return (error); 346 1.21 enami 347 1.72 mycroft pcmcia_function_unconfigure(sc->sc_pf); 348 1.61 briggs 349 1.21 enami return (0); 350 1.15 thorpej } 351 1.15 thorpej 352 1.94 thorpej static int 353 1.116 cegger wdc_pcmcia_enable(device_t self, int onoff) 354 1.15 thorpej { 355 1.110 cube struct wdc_pcmcia_softc *sc = device_private(self); 356 1.79 mycroft int error; 357 1.15 thorpej 358 1.114 drochner #if 1 359 1.114 drochner /* 360 1.114 drochner * XXX temporary kludge: we need to allow enabling while (cold) 361 1.114 drochner * for some hpc* ports which attach pcmcia devices too early. 362 1.114 drochner * This is problematic because pcmcia code uses tsleep() in 363 1.114 drochner * the attach code path, but it seems to work somehow. 364 1.114 drochner */ 365 1.114 drochner if (doing_shutdown) 366 1.114 drochner return (EIO); 367 1.114 drochner #else 368 1.113 drochner if (cold || doing_shutdown) 369 1.113 drochner return (EIO); 370 1.114 drochner #endif 371 1.113 drochner 372 1.15 thorpej if (onoff) { 373 1.128 rin if (!(sc->sc_wdcdev.sc_atac.atac_cap & ATAC_CAP_NOIRQ)) { 374 1.128 rin /* Establish the interrupt handler. */ 375 1.128 rin sc->sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_BIO, 376 1.128 rin wdcintr, &sc->ata_channel); 377 1.128 rin if (!sc->sc_ih) 378 1.128 rin return (EIO); 379 1.128 rin } 380 1.83 mycroft 381 1.83 mycroft error = pcmcia_function_enable(sc->sc_pf); 382 1.83 mycroft if (error) { 383 1.128 rin if (sc->sc_ih) { 384 1.128 rin pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih); 385 1.128 rin sc->sc_ih = 0; 386 1.128 rin } 387 1.83 mycroft return (error); 388 1.15 thorpej } 389 1.15 thorpej } else { 390 1.15 thorpej pcmcia_function_disable(sc->sc_pf); 391 1.128 rin if (sc->sc_ih) { 392 1.128 rin pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih); 393 1.128 rin sc->sc_ih = 0; 394 1.128 rin } 395 1.15 thorpej } 396 1.15 thorpej 397 1.15 thorpej return (0); 398 1.1 matt } 399 1.86 mycroft 400 1.94 thorpej static void 401 1.94 thorpej wdc_pcmcia_datain_memory(struct ata_channel *chp, int flags, void *buf, 402 1.94 thorpej size_t len) 403 1.86 mycroft { 404 1.93 thorpej struct wdc_regs *wdr = CHAN_TO_WDC_REGS(chp); 405 1.86 mycroft 406 1.86 mycroft while (len > 0) { 407 1.86 mycroft size_t n; 408 1.86 mycroft 409 1.127 riastrad n = uimin(len, 1024); 410 1.123 bouyer if ((flags & ATA_DRIVE_CAP32) && (n & 3) == 0) 411 1.91 thorpej bus_space_read_region_stream_4(wdr->data32iot, 412 1.91 thorpej wdr->data32ioh, 0, buf, n >> 2); 413 1.88 mycroft else 414 1.91 thorpej bus_space_read_region_stream_2(wdr->data32iot, 415 1.91 thorpej wdr->data32ioh, 0, buf, n >> 1); 416 1.86 mycroft buf = (char *)buf + n; 417 1.86 mycroft len -= n; 418 1.86 mycroft } 419 1.86 mycroft } 420 1.86 mycroft 421 1.94 thorpej static void 422 1.94 thorpej wdc_pcmcia_dataout_memory(struct ata_channel *chp, int flags, void *buf, 423 1.94 thorpej size_t len) 424 1.86 mycroft { 425 1.93 thorpej struct wdc_regs *wdr = CHAN_TO_WDC_REGS(chp); 426 1.86 mycroft 427 1.86 mycroft while (len > 0) { 428 1.86 mycroft size_t n; 429 1.86 mycroft 430 1.127 riastrad n = uimin(len, 1024); 431 1.123 bouyer if ((flags & ATA_DRIVE_CAP32) && (n & 3) == 0) 432 1.91 thorpej bus_space_write_region_stream_4(wdr->data32iot, 433 1.91 thorpej wdr->data32ioh, 0, buf, n >> 2); 434 1.88 mycroft else 435 1.91 thorpej bus_space_write_region_stream_2(wdr->data32iot, 436 1.91 thorpej wdr->data32ioh, 0, buf, n >> 1); 437 1.86 mycroft buf = (char *)buf + n; 438 1.86 mycroft len -= n; 439 1.86 mycroft } 440 1.86 mycroft } 441