1 /* $NetBSD: mvsata_pci.c,v 1.1 2009/07/27 12:34:14 kiyohara Exp $ */ 2 /* 3 * Copyright (c) 2008 KIYOHARA Takashi 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 24 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __KERNEL_RCSID(0, "$NetBSD: mvsata_pci.c,v 1.1 2009/07/27 12:34:14 kiyohara Exp $"); 30 31 #include <sys/param.h> 32 #include <sys/bus.h> 33 #include <sys/device.h> 34 #include <sys/errno.h> 35 #include <sys/pmf.h> 36 37 #include <dev/pci/pcivar.h> 38 #include <dev/pci/pcidevs.h> 39 #include <dev/pci/pciidereg.h> 40 #include <dev/pci/pciidevar.h> 41 42 #include <dev/ic/mvsatareg.h> 43 #include <dev/ic/mvsatavar.h> 44 45 #define MVSATA_PCI_HCARBITER_SPACE_OFFSET 0x20000 46 47 #define MVSATA_PCI_COMMAND 0x00c00 48 #define MVSATA_PCI_COMMAND_MWRITECOMBINE (1 << 4) 49 #define MVSATA_PCI_COMMAND_MREADCOMBINE (1 << 5) 50 #define MVSATA_PCI_SERRMASK 0x00c28 51 #define MVSATA_PCI_MSITRIGGER 0x00c38 52 #define MVSATA_PCI_MODE 0x00d00 53 #define MVSATA_PCI_DISCTIMER 0x00d04 54 #define MVSATA_PCI_EROMBAR 0x00d2c 55 #define MVSATA_PCI_MAINCS 0x00d30 56 #define MVSATA_PCI_MAINCS_SPM (1 << 2) /* stop pci master */ 57 #define MVSATA_PCI_MAINCS_PME (1 << 3) /* pci master empty */ 58 #define MVSATA_PCI_MAINCS_GSR (1 << 4) /* glab soft reset */ 59 #define MVSATA_PCI_E_IRQCAUSE 0x01900 60 #define MVSATA_PCI_E_IRQMASK 0x01910 61 #define MVSATA_PCI_XBARTIMEOUT 0x01d04 62 #define MVSATA_PCI_ERRLOWADDR 0x01d40 63 #define MVSATA_PCI_ERRHIGHADDR 0x01d44 64 #define MVSATA_PCI_ERRATTRIBUTE 0x01d48 65 #define MVSATA_PCI_ERRCOMMAND 0x01d50 66 #define MVSATA_PCI_IRQCAUSE 0x01d58 67 #define MVSATA_PCI_IRQMASK 0x01d5c 68 #define MVSATA_PCI_MAINIRQCAUSE 0x01d60 69 #define MVSATA_PCI_MAINIRQMASK 0x01d64 70 #define MVSATA_PCI_MAINIRQ_SATAERR(hc, port) \ 71 (1 << (((port) << 1) + (hc) * 9)) 72 #define MVSATA_PCI_MAINIRQ_SATADONE(hc, port) \ 73 (1 << (((port) << 1) + (hc) * 9 + 1)) 74 #define MVSATA_PCI_MAINIRQ_SATACOALDONE(hc) (1 << ((hc) * 9 + 8)) 75 #define MVSATA_PCI_MAINIRQ_PCI (1 << 18) 76 #define MVSATA_PCI_FLASHCTL 0x1046c 77 #define MVSATA_PCI_GPIOPORTCTL 0x104f0 78 #define MVSATA_PCI_RESETCFG 0x180d8 79 80 #define MVSATA_PCI_DEV(psc) (psc->psc_sc.sc_wdcdev.sc_atac.atac_dev) 81 82 83 struct mvsata_pci_softc { 84 struct mvsata_softc psc_sc; 85 86 pci_chipset_tag_t psc_pc; 87 pcitag_t psc_tag; 88 89 bus_space_tag_t psc_iot; 90 bus_space_handle_t psc_ioh; 91 92 void *psc_ih; 93 }; 94 95 96 static int mvsata_pci_match(device_t, struct cfdata *, void *); 97 static void mvsata_pci_attach(device_t, device_t, void *); 98 static int mvsata_pci_detach(device_t, int); 99 100 static int mvsata_pci_intr(void *); 101 static bool mvsata_pci_resume(device_t PMF_FN_ARGS); 102 103 static int mvsata_pci_sreset(struct mvsata_softc *); 104 static int mvsata_pci_misc_reset(struct mvsata_softc *); 105 static void mvsata_pci_enable_intr(struct mvsata_port *, int); 106 107 108 CFATTACH_DECL_NEW(mvsata_pci, sizeof(struct mvsata_pci_softc), 109 mvsata_pci_match, mvsata_pci_attach, mvsata_pci_detach, NULL); 110 111 112 /* 113 * mvsata_pci_match() 114 * This function returns 2, because mvsata is high priority more than pciide. 115 */ 116 static int 117 mvsata_pci_match(device_t parent, struct cfdata *match, void *aux) 118 { 119 struct pci_attach_args *pa = aux; 120 121 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_MARVELL) 122 switch (PCI_PRODUCT(pa->pa_id)) { 123 case PCI_PRODUCT_MARVELL_88SX5040: 124 case PCI_PRODUCT_MARVELL_88SX5041: 125 case PCI_PRODUCT_MARVELL_88SX5080: 126 case PCI_PRODUCT_MARVELL_88SX5081: 127 case PCI_PRODUCT_MARVELL_88SX6040: 128 case PCI_PRODUCT_MARVELL_88SX6041: 129 case PCI_PRODUCT_MARVELL_88SX6042: 130 case PCI_PRODUCT_MARVELL_88SX6080: 131 case PCI_PRODUCT_MARVELL_88SX6081: 132 case PCI_PRODUCT_MARVELL_88SX7042: 133 return 2; 134 } 135 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ADP2) 136 switch (PCI_PRODUCT(pa->pa_id)) { 137 case PCI_PRODUCT_ADP2_1420SA: 138 case PCI_PRODUCT_ADP2_1430SA: 139 return 2; 140 } 141 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_TRIONES && 142 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_TRIONES_ROCKETRAID_2310) 143 return 2; 144 return 0; 145 } 146 147 static void 148 mvsata_pci_attach(device_t parent, device_t self, void *aux) 149 { 150 struct pci_attach_args *pa = aux; 151 struct mvsata_pci_softc *psc = device_private(self); 152 struct mvsata_softc *sc = &psc->psc_sc; 153 pci_intr_handle_t intrhandle; 154 pcireg_t csr; 155 bus_size_t size; 156 uint32_t reg, mask; 157 int read_pre_amps, hc, port, rv; 158 char devinfo[256]; 159 const char *intrstr; 160 161 sc->sc_wdcdev.sc_atac.atac_dev = self; 162 sc->sc_model = PCI_PRODUCT(pa->pa_id); 163 sc->sc_rev = PCI_REVISION(pa->pa_class); 164 sc->sc_dmat = pa->pa_dmat; 165 sc->sc_enable_intr = mvsata_pci_enable_intr; 166 167 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo)); 168 aprint_naive(": Marvell Serial-ATA Host Controller\n"); 169 aprint_normal(": %s\n", devinfo); 170 171 /* Map I/O register */ 172 if (pci_mapreg_map(pa, PCI_MAPREG_START, 173 PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, 174 &psc->psc_iot, &psc->psc_ioh, NULL, &size) != 0) { 175 aprint_error_dev(self, "can't map registers\n"); 176 return; 177 } 178 psc->psc_pc = pa->pa_pc; 179 psc->psc_tag = pa->pa_tag; 180 181 if (bus_space_subregion(psc->psc_iot, psc->psc_ioh, 182 MVSATA_PCI_HCARBITER_SPACE_OFFSET, 183 size - MVSATA_PCI_HCARBITER_SPACE_OFFSET, &sc->sc_ioh)) { 184 aprint_error_dev(self, "can't subregion registers\n"); 185 return; 186 } 187 sc->sc_iot = psc->psc_iot; 188 189 /* Enable device */ 190 csr = pci_conf_read(psc->psc_pc, psc->psc_tag, PCI_COMMAND_STATUS_REG); 191 csr |= PCI_COMMAND_MASTER_ENABLE; 192 pci_conf_write(psc->psc_pc, psc->psc_tag, PCI_COMMAND_STATUS_REG, csr); 193 194 if (pci_intr_map(pa, &intrhandle) != 0) { 195 aprint_error_dev(self, "couldn't map interrupt\n"); 196 return; 197 } 198 intrstr = pci_intr_string(psc->psc_pc, intrhandle); 199 psc->psc_ih = pci_intr_establish(psc->psc_pc, intrhandle, IPL_BIO, 200 mvsata_pci_intr, sc); 201 if (psc->psc_ih == NULL) { 202 aprint_error_dev(self, "couldn't establish interrupt\n"); 203 return; 204 } 205 aprint_normal_dev(self, "interrupting at %s\n", 206 intrstr ? intrstr : "unknown interrupt"); 207 208 /* 209 * Check if TWSI serial ROM initialization was triggered. 210 * If so, then PRE/AMP configuration probably are set after 211 * reset by serial ROM. If not then override the PRE/AMP 212 * values. 213 */ 214 reg = bus_space_read_4(psc->psc_iot, psc->psc_ioh, MVSATA_PCI_RESETCFG); 215 read_pre_amps = (reg & 0x00000001) ? 1 : 0; 216 217 rv = mvsata_attach(sc, mvsata_pci_sreset, mvsata_pci_misc_reset, 218 read_pre_amps); 219 if (rv != 0) { 220 pci_intr_disestablish(psc->psc_pc, psc->psc_ih); 221 return; 222 } 223 224 mask = MVSATA_PCI_MAINIRQ_PCI; 225 for (hc = 0; hc < sc->sc_hc; hc++) 226 for (port = 0; port < sc->sc_port; port++) 227 mask |= 228 MVSATA_PCI_MAINIRQ_SATAERR(hc, port) | 229 MVSATA_PCI_MAINIRQ_SATADONE(hc, port); 230 bus_space_write_4(psc->psc_iot, psc->psc_ioh, MVSATA_PCI_MAINIRQMASK, 231 mask); 232 233 if (!pmf_device_register(self, NULL, mvsata_pci_resume)) 234 aprint_error_dev(self, "couldn't establish power handler\n"); 235 } 236 237 static int 238 mvsata_pci_detach(device_t self, int flags) 239 { 240 struct mvsata_pci_softc *psc = device_private(self); 241 242 /* XXXX: needs reset ? */ 243 244 pci_intr_disestablish(psc->psc_pc, psc->psc_ih); 245 pmf_device_deregister(self); 246 return 0; 247 } 248 249 static int 250 mvsata_pci_intr(void *arg) 251 { 252 struct mvsata_pci_softc *psc = (struct mvsata_pci_softc *)arg; 253 struct mvsata_softc *sc = &psc->psc_sc; 254 uint32_t cause; 255 int hc, port, handled = 0; 256 257 cause = bus_space_read_4(psc->psc_iot, psc->psc_ioh, 258 MVSATA_PCI_MAINIRQCAUSE); 259 for (hc = 0; hc < sc->sc_hc; hc++) 260 for (port = 0; port < sc->sc_port; port++) 261 if (cause & MVSATA_PCI_MAINIRQ_SATAERR(hc, port)) { 262 struct mvsata_port *mvport; 263 264 mvport = sc->sc_hcs[hc].hc_ports[port]; 265 handled |= mvsata_error(mvport); 266 } 267 for (hc = 0; hc < sc->sc_hc; hc++) 268 if (cause & 269 (MVSATA_PCI_MAINIRQ_SATADONE(hc, 0) | 270 MVSATA_PCI_MAINIRQ_SATADONE(hc, 1) | 271 MVSATA_PCI_MAINIRQ_SATADONE(hc, 2) | 272 MVSATA_PCI_MAINIRQ_SATADONE(hc, 3))) 273 handled |= mvsata_intr(&sc->sc_hcs[hc]); 274 275 if (cause & MVSATA_PCI_MAINIRQ_PCI) { 276 uint32_t pe_cause; 277 278 if (sc->sc_flags & MVSATA_FLAGS_PCIE) { 279 pe_cause = bus_space_read_4(psc->psc_iot, psc->psc_ioh, 280 MVSATA_PCI_E_IRQCAUSE); 281 aprint_error_dev(MVSATA_PCI_DEV(psc), 282 "PCIe error: 0x%x\n", pe_cause); 283 bus_space_write_4(psc->psc_iot, psc->psc_ioh, 284 MVSATA_PCI_E_IRQCAUSE, ~pe_cause); 285 } else { 286 pe_cause = bus_space_read_4(psc->psc_iot, psc->psc_ioh, 287 MVSATA_PCI_IRQCAUSE); 288 aprint_error_dev(MVSATA_PCI_DEV(psc), 289 "PCI error: 0x%x\n", pe_cause); 290 bus_space_write_4(psc->psc_iot, psc->psc_ioh, 291 MVSATA_PCI_IRQCAUSE, ~pe_cause); 292 } 293 294 handled = 1; /* XXXXX */ 295 } 296 297 return handled; 298 } 299 300 static bool 301 mvsata_pci_resume(device_t dev PMF_FN_ARGS) 302 { 303 304 /* not yet... */ 305 306 return true; 307 } 308 309 310 static int 311 mvsata_pci_sreset(struct mvsata_softc *sc) 312 { 313 struct mvsata_pci_softc *psc = (struct mvsata_pci_softc *)sc; 314 uint32_t val; 315 int i; 316 317 val = bus_space_read_4(psc->psc_iot, psc->psc_ioh, MVSATA_PCI_MAINCS); 318 val |= MVSATA_PCI_MAINCS_SPM; 319 bus_space_write_4(psc->psc_iot, psc->psc_ioh, MVSATA_PCI_MAINCS, val); 320 321 for (i = 0; i < 1000; i++) { 322 delay(1); 323 val = bus_space_read_4(psc->psc_iot, psc->psc_ioh, 324 MVSATA_PCI_MAINCS); 325 if (val & MVSATA_PCI_MAINCS_PME) 326 break; 327 } 328 if (!(val & MVSATA_PCI_MAINCS_PME)) { 329 aprint_error_dev(MVSATA_PCI_DEV(psc), 330 "PCI master won't flush\n"); 331 return -1; 332 } 333 334 /* reset */ 335 bus_space_write_4(psc->psc_iot, psc->psc_ioh, MVSATA_PCI_MAINCS, 336 val | MVSATA_PCI_MAINCS_GSR); 337 val = bus_space_read_4(psc->psc_iot, psc->psc_ioh, MVSATA_PCI_MAINCS); 338 delay(5); 339 if (!(val & MVSATA_PCI_MAINCS_GSR)) { 340 aprint_error_dev(MVSATA_PCI_DEV(psc), 341 "can't set global reset\n"); 342 return -1; 343 } 344 345 /* clear reset and *reenable the PCI master* (not mentioned in spec) */ 346 val &= ~(MVSATA_PCI_MAINCS_GSR | MVSATA_PCI_MAINCS_SPM); 347 bus_space_write_4(psc->psc_iot, psc->psc_ioh, MVSATA_PCI_MAINCS, val); 348 val = bus_space_read_4(psc->psc_iot, psc->psc_ioh, MVSATA_PCI_MAINCS); 349 delay(5); 350 if (val & MVSATA_PCI_MAINCS_GSR) { 351 aprint_error_dev(MVSATA_PCI_DEV(psc), 352 "can't set global reset\n"); 353 return -1; 354 } 355 356 return 0; 357 } 358 359 static int 360 mvsata_pci_misc_reset(struct mvsata_softc *sc) 361 { 362 struct mvsata_pci_softc *psc = (struct mvsata_pci_softc *)sc; 363 #define MVSATA_PCI_COMMAND_DEFAULT 0x0107e371 364 #define MVSATA_PCI_COMMAND_PCI_CONVENTIONAL_ONLY 0x800003e0 365 uint32_t val, pci_command = MVSATA_PCI_COMMAND_DEFAULT; 366 367 bus_space_write_4(psc->psc_iot, psc->psc_ioh, MVSATA_PCI_FLASHCTL, 368 0x0fcfffff); 369 370 if (sc->sc_gen == gen2 || sc->sc_gen == gen2e) { 371 val = bus_space_read_4(psc->psc_iot, psc->psc_ioh, 372 MVSATA_PCI_GPIOPORTCTL); 373 val &= 0x3; 374 #if 0 375 val |= 0x00000060; 376 #else /* XXXX */ 377 val |= 0x00000070; 378 #endif 379 bus_space_write_4(psc->psc_iot, psc->psc_ioh, 380 MVSATA_PCI_GPIOPORTCTL, val); 381 } 382 383 if (sc->sc_gen == gen1) { 384 /* Expansion ROM BAR Enable */ 385 val = bus_space_read_4(psc->psc_iot, psc->psc_ioh, 386 MVSATA_PCI_EROMBAR); 387 bus_space_write_4(psc->psc_iot, psc->psc_ioh, 388 MVSATA_PCI_EROMBAR, val | 0x00000001); 389 } 390 391 if (sc->sc_flags & MVSATA_FLAGS_PCIE) { 392 bus_space_write_4(psc->psc_iot, psc->psc_ioh, 393 MVSATA_PCI_MAINIRQMASK, 0); 394 bus_space_write_4(psc->psc_iot, psc->psc_ioh, 395 MVSATA_PCI_E_IRQCAUSE, 0); 396 bus_space_write_4(psc->psc_iot, psc->psc_ioh, 397 MVSATA_PCI_E_IRQMASK, 0); 398 } else { 399 val = bus_space_read_4(psc->psc_iot, psc->psc_ioh, 400 MVSATA_PCI_MODE); 401 bus_space_write_4(psc->psc_iot, psc->psc_ioh, 402 MVSATA_PCI_MODE, val & 0xff00ffff); 403 bus_space_write_4(psc->psc_iot, psc->psc_ioh, 404 MVSATA_PCI_DISCTIMER, 0); 405 bus_space_write_4(psc->psc_iot, psc->psc_ioh, 406 MVSATA_PCI_MSITRIGGER, 0); 407 bus_space_write_4(psc->psc_iot, psc->psc_ioh, 408 MVSATA_PCI_XBARTIMEOUT, 0x000100ff); 409 bus_space_write_4(psc->psc_iot, psc->psc_ioh, 410 MVSATA_PCI_MAINIRQMASK, 0); 411 bus_space_write_4(psc->psc_iot, psc->psc_ioh, 412 MVSATA_PCI_SERRMASK, 0); 413 bus_space_write_4(psc->psc_iot, psc->psc_ioh, 414 MVSATA_PCI_IRQCAUSE, 0); 415 bus_space_write_4(psc->psc_iot, psc->psc_ioh, 416 MVSATA_PCI_IRQMASK, 0); 417 bus_space_write_4(psc->psc_iot, psc->psc_ioh, 418 MVSATA_PCI_ERRLOWADDR, 0); 419 bus_space_write_4(psc->psc_iot, psc->psc_ioh, 420 MVSATA_PCI_ERRHIGHADDR, 0); 421 bus_space_write_4(psc->psc_iot, psc->psc_ioh, 422 MVSATA_PCI_ERRATTRIBUTE, 0); 423 bus_space_write_4(psc->psc_iot, psc->psc_ioh, 424 MVSATA_PCI_ERRCOMMAND, 0); 425 } 426 427 /* Enable LED */ 428 if (sc->sc_gen == gen1) { 429 bus_space_write_4(psc->psc_iot, psc->psc_ioh, 430 MVSATA_PCI_GPIOPORTCTL, 0); 431 432 /* XXXX: 50xxB2 errata ? */ 433 #if 0 434 if (sc->sc_rev == 3) { 435 int port; 436 437 val = bus_space_read_4(psc->psc_iot, psc->psc_ioh, 438 MVSATA_PCI_GPIOPORTCTL); 439 440 /* XXXX: check HDD connected */ 441 442 bus_space_write_4(psc->psc_iot, psc->psc_ioh, 443 MVSATA_PCI_GPIOPORTCTL, val); 444 } 445 #endif 446 447 /* Disable Flash controller clock */ 448 val = bus_space_read_4(psc->psc_iot, psc->psc_ioh, 449 MVSATA_PCI_EROMBAR); 450 bus_space_write_4(psc->psc_iot, psc->psc_ioh, 451 MVSATA_PCI_EROMBAR, val & ~0x00000001); 452 } else 453 #if 0 454 bus_space_write_4(psc->psc_iot, psc->psc_ioh, 455 MVSATA_PCI_GPIOPORTCTL, 0x00000060); 456 #else /* XXXX */ 457 bus_space_write_4(psc->psc_iot, psc->psc_ioh, 458 MVSATA_PCI_GPIOPORTCTL, 0x00000070); 459 #endif 460 461 if (sc->sc_flags & MVSATA_FLAGS_PCIE) 462 bus_space_write_4(psc->psc_iot, psc->psc_ioh, 463 MVSATA_PCI_E_IRQMASK, 0x0000070a); 464 else { 465 val = bus_space_read_4(psc->psc_iot, psc->psc_ioh, 466 MVSATA_PCI_MODE); 467 if ((val & 0x30) >> 4) { /* PCI-X */ 468 int mv60x1b2 = 469 ((sc->sc_model == PCI_PRODUCT_MARVELL_88SX6041 || 470 sc->sc_model == PCI_PRODUCT_MARVELL_88SX6081) && 471 sc->sc_rev == 7); 472 473 pci_command &= 474 ~MVSATA_PCI_COMMAND_PCI_CONVENTIONAL_ONLY; 475 if (sc->sc_gen == gen1 || mv60x1b2) 476 pci_command &= 477 ~MVSATA_PCI_COMMAND_MWRITECOMBINE; 478 } else 479 if (sc->sc_gen == gen1) 480 pci_command &= 481 ~(MVSATA_PCI_COMMAND_MWRITECOMBINE | 482 MVSATA_PCI_COMMAND_MREADCOMBINE); 483 bus_space_write_4(psc->psc_iot, psc->psc_ioh, 484 MVSATA_PCI_COMMAND, pci_command); 485 486 #define MVSATA_PCI_INTERRUPT_MASK 0x00d77fe6 487 bus_space_write_4(psc->psc_iot, psc->psc_ioh, 488 MVSATA_PCI_SERRMASK, MVSATA_PCI_INTERRUPT_MASK); 489 bus_space_write_4(psc->psc_iot, psc->psc_ioh, 490 MVSATA_PCI_IRQMASK, MVSATA_PCI_INTERRUPT_MASK); 491 } 492 493 return 0; 494 } 495 496 static void 497 mvsata_pci_enable_intr(struct mvsata_port *mvport, int on) 498 { 499 struct mvsata_pci_softc *psc = 500 device_private(mvport->port_ata_channel.ch_atac->atac_dev); 501 uint32_t mask; 502 int hc = mvport->port_hc->hc, port = mvport->port; 503 504 mask = bus_space_read_4(psc->psc_iot, psc->psc_ioh, 505 MVSATA_PCI_MAINIRQMASK); 506 if (on) 507 mask |= MVSATA_PCI_MAINIRQ_SATADONE(hc, port); 508 else 509 mask &= ~MVSATA_PCI_MAINIRQ_SATADONE(hc, port); 510 bus_space_write_4(psc->psc_iot, psc->psc_ioh, MVSATA_PCI_MAINIRQMASK, 511 mask); 512 } 513