* BHND MIPS device attach. * * This must be called from subclass drivers' DEVICE_ATTACH(). * * @param dev BHND MIPS device. * @param num_cpuirqs The number of usable MIPS HW IRQs. * @param timer_irq The MIPS HW IRQ assigned to the MIPS CPU timer. * @param filter The subclass's core-specific IRQ dispatch filter. Will be * passed the associated bcm_mips_cpuirq instance as its argument. */
| 297 | * passed the associated bcm_mips_cpuirq instance as its argument. |
| 298 | */ |
| 299 | int |
| 300 | bcm_mips_attach(device_t dev, u_int num_cpuirqs, u_int timer_irq, |
| 301 | driver_filter_t filter) |
| 302 | { |
| 303 | struct bcm_mips_softc *sc; |
| 304 | struct intr_pic *pic; |
| 305 | uintptr_t xref; |
| 306 | u_int irq_rid; |
| 307 | rman_res_t irq; |
| 308 | int error; |
| 309 | |
| 310 | sc = device_get_softc(dev); |
| 311 | sc->dev = dev; |
| 312 | sc->num_cpuirqs = num_cpuirqs; |
| 313 | sc->timer_irq = timer_irq; |
| 314 | |
| 315 | /* Must not exceed the actual size of our fixed IRQ array */ |
| 316 | if (sc->num_cpuirqs > nitems(sc->cpuirqs)) { |
| 317 | device_printf(dev, "%u nirqs exceeds maximum supported %zu", |
| 318 | sc->num_cpuirqs, nitems(sc->cpuirqs)); |
| 319 | return (ENXIO); |
| 320 | } |
| 321 | |
| 322 | pic = NULL; |
| 323 | xref = bcm_mips_pic_xref(sc); |
| 324 | |
| 325 | BCM_MIPS_LOCK_INIT(sc); |
| 326 | |
| 327 | /* Register our interrupt sources */ |
| 328 | if ((error = bcm_mips_register_isrcs(sc))) { |
| 329 | BCM_MIPS_LOCK_DESTROY(sc); |
| 330 | return (error); |
| 331 | } |
| 332 | |
| 333 | /* Initialize our CPU interrupt state */ |
| 334 | irq_rid = bhnd_get_intr_count(dev); /* last bhnd-assigned RID + 1 */ |
| 335 | irq = 0; |
| 336 | for (u_int i = 0; i < sc->num_cpuirqs; i++) { |
| 337 | /* Must not overflow signed resource ID representation */ |
| 338 | if (irq_rid >= INT_MAX) { |
| 339 | device_printf(dev, "exhausted IRQ resource IDs\n"); |
| 340 | error = ENOMEM; |
| 341 | goto failed; |
| 342 | } |
| 343 | |
| 344 | if (irq == sc->timer_irq) { |
| 345 | /* Mark the CPU timer's IRQ as unavailable */ |
| 346 | error = bcm_mips_init_cpuirq_unavail(sc, |
| 347 | &sc->cpuirqs[i]); |
| 348 | } else { |
| 349 | /* Initialize state */ |
| 350 | error = bcm_mips_init_cpuirq(sc, &sc->cpuirqs[i], |
| 351 | irq_rid, irq, filter); |
| 352 | } |
| 353 | |
| 354 | if (error) |
| 355 | goto failed; |
| 356 |
no test coverage detected