static int awin_hdmi_i2c_exec(void *priv, i2c_op_t op, i2c_addr_t addr, const void *cmdbuf, size_t cmdlen, void *buf, size_t len, int flags) { struct awin_hdmi_softc *sc = priv; uint8_t *pbuf; uint8_t block; int resid; off_t off; int err; KASSERT(mutex_owned(&sc->sc_ic_lock)); KASSERT(op == I2C_OP_READ_WITH_STOP); KASSERT(addr == DDC_ADDR); KASSERT(cmdlen > 0); KASSERT(buf != NULL); err = awin_hdmi_i2c_reset(sc, flags); if (err) goto done; block = *(const uint8_t *)cmdbuf; off = (block & 1) ? 128 : 0; pbuf = buf; resid = len; while (resid > 0) { size_t blklen = min(resid, sc->sc_i2c_blklen); err = awin_hdmi_i2c_xfer(sc, addr, block >> 1, off, blklen, AWIN_HDMI_DDC_COMMAND_ACCESS_CMD_EOREAD, flags); if (err) goto done; if (HDMI_1_3_P(sc)) { bus_space_read_multi_1(sc->sc_bst, sc->sc_bsh, AWIN_HDMI_DDC_FIFO_ACCESS_REG, pbuf, blklen); } else { bus_space_read_multi_1(sc->sc_bst, sc->sc_bsh, AWIN_A31_HDMI_DDC_FIFO_ACCESS_REG, pbuf, blklen); } #ifdef AWIN_HDMI_DEBUG printf("off=%d:", (int)off); for (int i = 0; i < blklen; i++) printf(" %02x", pbuf[i]); printf("\n"); #endif pbuf += blklen; off += blklen; resid -= blklen; } done: return err; }
/*---------------------------------------------------------------------------* * AVM read fifo routine *---------------------------------------------------------------------------*/ static void avma1_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size) { bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[what+4]); bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[what+4]); bus_space_read_multi_1(t, h, 0, buf, size); }
static int hcsc_pdma_in(struct ncr5380_softc *ncr_sc, int phase, int datalen, uint8_t *data) { struct hcsc_softc *sc = (struct hcsc_softc *)ncr_sc; bus_space_tag_t pdmat = sc->sc_pdmat; bus_space_handle_t pdmah = sc->sc_pdmah; int s, resid, len; s = splbio(); NCR5380_WRITE(ncr_sc, sci_mode, NCR5380_READ(ncr_sc, sci_mode) | SCI_MODE_DMA); NCR5380_WRITE(ncr_sc, sci_irecv, 0); resid = datalen; while (resid > 0) { len = min(resid, HCSC_TSIZE_IN); if (hcsc_ready(ncr_sc) == 0) goto interrupt; bus_space_read_multi_1(pdmat, pdmah, 0, data, len); data += len; resid -= len; } hcsc_wait_not_req(ncr_sc); interrupt: SCI_CLR_INTR(ncr_sc); NCR5380_WRITE(ncr_sc, sci_mode, NCR5380_READ(ncr_sc, sci_mode) & ~SCI_MODE_DMA); splx(s); return datalen - resid; }
static void avma1_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size) { bus_space_tag_t t = sc->sc_maps[what+4].t; bus_space_handle_t h = sc->sc_maps[what+4].h; bus_space_read_multi_1(t, h, 0, buf, size); }
__stdcall static void hal_readport_buf_uchar(uint8_t *port, uint8_t *val, uint32_t cnt) { bus_space_read_multi_1(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port, val, cnt); return; }
static void avma1_pcmcia_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size) { bus_space_tag_t t = sc->sc_maps[0].t; bus_space_handle_t h = sc->sc_maps[0].h; bus_space_write_1(t, h, ADDR_REG_OFFSET, what_map[what]); bus_space_read_multi_1(t, h, DATA_REG_OFFSET, buf, size); }
static void ctxs0P_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size) { bus_space_tag_t t = sc->sc_maps[what+1].t; bus_space_handle_t h = sc->sc_maps[what+1].h; bus_size_t o = sc->sc_maps[what+1].offset; bus_space_read_multi_1(t, h, o + 0x3e, buf, size); }
static void dynalink_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size) { bus_space_tag_t t = sc->sc_maps[0].t; bus_space_handle_t h = sc->sc_maps[0].h; switch (what) { case ISIC_WHAT_ISAC: bus_space_write_1(t, h, ADDR, 0); bus_space_read_multi_1(t, h, ISAC, buf, size); break; case ISIC_WHAT_HSCXA: bus_space_write_1(t, h, ADDR, HSCXA); bus_space_read_multi_1(t, h, HSCX, buf, size); break; case ISIC_WHAT_HSCXB: bus_space_write_1(t, h, ADDR, HSCXB); bus_space_read_multi_1(t, h, HSCX, buf, size); break; } }
static void itkix1_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size) { bus_space_tag_t t = sc->sc_maps[0].t; bus_space_handle_t h = sc->sc_maps[0].h; switch (what) { case ISIC_WHAT_ISAC: bus_space_write_1(t, h, ITK_ALE, 0); bus_space_read_multi_1(t, h, ITK_ISAC_DATA, buf, size); break; case ISIC_WHAT_HSCXA: bus_space_write_1(t, h, ITK_ALE, HSCXA); bus_space_read_multi_1(t, h, ITK_HSCX_DATA, buf, size); break; case ISIC_WHAT_HSCXB: bus_space_write_1(t, h, ITK_ALE, HSCXB); bus_space_read_multi_1(t, h, ITK_HSCX_DATA, buf, size); break; } }
static void sws_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size) { bus_space_tag_t t = sc->sc_maps[0].t; bus_space_handle_t h = sc->sc_maps[0].h; switch (what) { case ISIC_WHAT_ISAC: bus_space_write_1(t, h, SWS_RW, 0); bus_space_read_multi_1(t, h, SWS_ISAC, buf, size); break; case ISIC_WHAT_HSCXA: bus_space_write_1(t, h, SWS_RW, 0); bus_space_read_multi_1(t, h, SWS_HSCX0, buf, size); break; case ISIC_WHAT_HSCXB: bus_space_write_1(t, h, SWS_RW, 0x40); bus_space_read_multi_1(t, h, SWS_HSCX0, buf, size); break; } }
static void siemens_isurf_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size) { bus_space_tag_t t = sc->sc_maps[0].t; bus_space_handle_t h = sc->sc_maps[0].h; switch (what) { case ISIC_WHAT_ISAC: bus_space_write_1(t, h, SIE_ISURF_OFF_ALE, IPAC_ISAC_OFF); bus_space_read_multi_1(t, h, SIE_ISURF_OFF_RW, buf, size); break; case ISIC_WHAT_HSCXA: bus_space_write_1(t, h, SIE_ISURF_OFF_ALE, IPAC_HSCXA_OFF); bus_space_read_multi_1(t, h, SIE_ISURF_OFF_RW, buf, size); break; case ISIC_WHAT_HSCXB: bus_space_write_1(t, h, SIE_ISURF_OFF_ALE, IPAC_HSCXB_OFF); bus_space_read_multi_1(t, h, SIE_ISURF_OFF_RW, buf, size); break; } }
/*---------------------------------------------------------------------------* * ELSA QuickStep 1000pro/ISA ISAC get fifo routine *---------------------------------------------------------------------------*/ static void eqs1pi_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size) { bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); switch (what) { case ISIC_WHAT_ISAC: bus_space_write_1(t, h, ELSA_OFF_OFF, 0); bus_space_read_multi_1(t, h, ELSA_OFF_ISAC, buf, size); break; case ISIC_WHAT_HSCXA: bus_space_write_1(t, h, ELSA_OFF_OFF, 0); bus_space_read_multi_1(t, h, ELSA_OFF_HSCX, buf, size); break; case ISIC_WHAT_HSCXB: bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40); bus_space_read_multi_1(t, h, ELSA_OFF_HSCX, buf, size); break; } }
/*---------------------------------------------------------------------------* * Eicon Diehl DIVA 2.02 *---------------------------------------------------------------------------*/ static void diva_ipac_read_fifo(struct l1_softc *sc,int what,void *buf,size_t size) { bus_space_tag_t t = rman_get_bustag(sc->sc_resources.io_base[0]); bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]); switch ( what ) { case ISIC_WHAT_ISAC: bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,IPAC_ISAC_OFF); bus_space_read_multi_1(t,h,DIVA_IPAC_OFF_RW,buf,size); break; case ISIC_WHAT_HSCXA: bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,IPAC_HSCXA_OFF); bus_space_read_multi_1(t,h,DIVA_IPAC_OFF_RW,buf,size); break; case ISIC_WHAT_HSCXB: bus_space_write_1(t,h,DIVA_IPAC_OFF_ALE,IPAC_HSCXB_OFF); bus_space_read_multi_1(t,h,DIVA_IPAC_OFF_RW,buf,size); break; } }
static void avm_pnp_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size) { bus_space_handle_t bhandle = rman_get_bushandle(sc->sc_resources.io_base[0]); bus_space_tag_t btag = rman_get_bustag(sc->sc_resources.io_base[0]); switch (what) { case ISIC_WHAT_ISAC: bus_space_write_1(btag, bhandle, ADDR_REG_OFFSET, ISAC_FIFO); bus_space_read_multi_1(btag, bhandle, ISAC_REG_OFFSET, buf, size); break; case ISIC_WHAT_HSCXA: hscx_read_fifo(0, buf, size, sc); break; case ISIC_WHAT_HSCXB: hscx_read_fifo(1, buf, size, sc); break; } }
static int ath_ahb_attach(device_t dev) { struct ath_ahb_softc *psc = device_get_softc(dev); struct ath_softc *sc = &psc->sc_sc; int error = ENXIO; int rid; long eepromaddr; int eepromsize; uint8_t *p; int device_id, vendor_id; sc->sc_dev = dev; rid = 0; psc->sc_sr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (psc->sc_sr == NULL) { device_printf(dev, "cannot map register space\n"); goto bad; } if (resource_long_value(device_get_name(dev), device_get_unit(dev), "eepromaddr", &eepromaddr) != 0) { device_printf(dev, "cannot fetch 'eepromaddr' from hints\n"); goto bad0; } /* * The default EEPROM size is 2048 * 16 bit words. * Later EEPROM/OTP/flash regions may be quite a bit bigger. */ if (resource_int_value(device_get_name(dev), device_get_unit(dev), "eepromsize", &eepromsize) != 0) { eepromsize = ATH_EEPROM_DATA_SIZE * 2; } rid = 0; device_printf(sc->sc_dev, "eeprom @ %p (%d bytes)\n", (void *) eepromaddr, eepromsize); /* * XXX this assumes that the parent device is the nexus * and will just pass through requests for all of memory. * * Later on, when this has to attach off of the actual * AHB, this won't work. * * Ideally this would be done in machdep code in mips/atheros/ * and it'd expose the EEPROM via the firmware interface, * so the ath/ath_ahb drivers can be loaded as modules * after boot-time. */ psc->sc_eeprom = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, (uintptr_t) eepromaddr, (uintptr_t) eepromaddr + (uintptr_t) (eepromsize - 1), 0, RF_ACTIVE); if (psc->sc_eeprom == NULL) { device_printf(dev, "cannot map eeprom space\n"); goto bad0; } sc->sc_st = (HAL_BUS_TAG) rman_get_bustag(psc->sc_sr); sc->sc_sh = (HAL_BUS_HANDLE) rman_get_bushandle(psc->sc_sr); /* * Mark device invalid so any interrupts (shared or otherwise) * that arrive before the HAL is setup are discarded. */ sc->sc_invalid = 1; /* Copy the EEPROM data out */ sc->sc_eepromdata = malloc(eepromsize, M_TEMP, M_NOWAIT | M_ZERO); if (sc->sc_eepromdata == NULL) { device_printf(dev, "cannot allocate memory for eeprom data\n"); goto bad1; } device_printf(sc->sc_dev, "eeprom data @ %p\n", (void *) rman_get_bushandle(psc->sc_eeprom)); /* XXX why doesn't this work? -adrian */ #if 0 bus_space_read_multi_1( rman_get_bustag(psc->sc_eeprom), rman_get_bushandle(psc->sc_eeprom), 0, (u_int8_t *) sc->sc_eepromdata, eepromsize); #endif p = (void *) rman_get_bushandle(psc->sc_eeprom); memcpy(sc->sc_eepromdata, p, eepromsize); /* * Arrange interrupt line. */ rid = 0; psc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE|RF_ACTIVE); if (psc->sc_irq == NULL) { device_printf(dev, "could not map interrupt\n"); goto bad1; } if (bus_setup_intr(dev, psc->sc_irq, INTR_TYPE_NET | INTR_MPSAFE, NULL, ath_ahb_intr, sc, &psc->sc_ih)) { device_printf(dev, "could not establish interrupt\n"); goto bad2; } /* * Setup DMA descriptor area. */ if (bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */ 1, 0, /* alignment, bounds */ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ 0x3ffff, /* maxsize XXX */ ATH_MAX_SCATTER, /* nsegments */ 0x3ffff, /* maxsegsize XXX */ BUS_DMA_ALLOCNOW, /* flags */ NULL, /* lockfunc */ NULL, /* lockarg */ &sc->sc_dmat)) { device_printf(dev, "cannot allocate DMA tag\n"); goto bad3; } /* * Check if a device/vendor ID is provided in hints. */ if (resource_int_value(device_get_name(dev), device_get_unit(dev), "vendor_id", &vendor_id) != 0) { vendor_id = VENDOR_ATHEROS; } if (resource_int_value(device_get_name(dev), device_get_unit(dev), "device_id", &device_id) != 0) { device_id = AR9130_DEVID; } ATH_LOCK_INIT(sc); ATH_PCU_LOCK_INIT(sc); ATH_RX_LOCK_INIT(sc); ATH_TX_LOCK_INIT(sc); ATH_TX_IC_LOCK_INIT(sc); ATH_TXSTATUS_LOCK_INIT(sc); error = ath_attach(device_id, sc); if (error == 0) /* success */ return 0; ATH_TXSTATUS_LOCK_DESTROY(sc); ATH_RX_LOCK_DESTROY(sc); ATH_TX_LOCK_DESTROY(sc); ATH_TX_IC_LOCK_DESTROY(sc); ATH_PCU_LOCK_DESTROY(sc); ATH_LOCK_DESTROY(sc); bus_dma_tag_destroy(sc->sc_dmat); bad3: bus_teardown_intr(dev, psc->sc_irq, psc->sc_ih); bad2: bus_release_resource(dev, SYS_RES_IRQ, 0, psc->sc_irq); bad1: bus_release_resource(dev, SYS_RES_MEMORY, 0, psc->sc_eeprom); bad0: bus_release_resource(dev, SYS_RES_MEMORY, 0, psc->sc_sr); bad: /* XXX?! */ if (sc->sc_eepromdata) free(sc->sc_eepromdata, M_TEMP); return (error); }
static int ath_ahb_attach(device_t dev) { struct ath_ahb_softc *psc = device_get_softc(dev); struct ath_softc *sc = &psc->sc_sc; int error = ENXIO; int rid; long eepromaddr; uint8_t *p; sc->sc_dev = dev; rid = 0; psc->sc_sr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (psc->sc_sr == NULL) { device_printf(dev, "cannot map register space\n"); goto bad; } if (resource_long_value(device_get_name(dev), device_get_unit(dev), "eepromaddr", &eepromaddr) != 0) { device_printf(dev, "cannot fetch 'eepromaddr' from hints\n"); goto bad0; } rid = 0; device_printf(sc->sc_dev, "eeprom @ %p\n", (void *) eepromaddr); psc->sc_eeprom = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, (uintptr_t) eepromaddr, (uintptr_t) eepromaddr + (uintptr_t) ((ATH_EEPROM_DATA_SIZE * 2) - 1), 0, RF_ACTIVE); if (psc->sc_eeprom == NULL) { device_printf(dev, "cannot map eeprom space\n"); goto bad0; } /* XXX uintptr_t is a bandaid for ia64; to be fixed */ sc->sc_st = (HAL_BUS_TAG)(uintptr_t) rman_get_bustag(psc->sc_sr); sc->sc_sh = (HAL_BUS_HANDLE) rman_get_bushandle(psc->sc_sr); /* * Mark device invalid so any interrupts (shared or otherwise) * that arrive before the HAL is setup are discarded. */ sc->sc_invalid = 1; /* Copy the EEPROM data out */ sc->sc_eepromdata = malloc(ATH_EEPROM_DATA_SIZE * 2, M_TEMP, M_NOWAIT | M_ZERO); if (sc->sc_eepromdata == NULL) { device_printf(dev, "cannot allocate memory for eeprom data\n"); goto bad1; } device_printf(sc->sc_dev, "eeprom data @ %p\n", (void *) rman_get_bushandle(psc->sc_eeprom)); /* XXX why doesn't this work? -adrian */ #if 0 bus_space_read_multi_1( rman_get_bustag(psc->sc_eeprom), rman_get_bushandle(psc->sc_eeprom), 0, (u_int8_t *) sc->sc_eepromdata, ATH_EEPROM_DATA_SIZE * 2); #endif p = (void *) rman_get_bushandle(psc->sc_eeprom); memcpy(sc->sc_eepromdata, p, ATH_EEPROM_DATA_SIZE * 2); /* * Arrange interrupt line. */ rid = 0; psc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE|RF_ACTIVE); if (psc->sc_irq == NULL) { device_printf(dev, "could not map interrupt\n"); goto bad1; } if (bus_setup_intr(dev, psc->sc_irq, INTR_TYPE_NET | INTR_MPSAFE, NULL, ath_intr, sc, &psc->sc_ih)) { device_printf(dev, "could not establish interrupt\n"); goto bad2; } /* * Setup DMA descriptor area. */ if (bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */ 1, 0, /* alignment, bounds */ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ 0x3ffff, /* maxsize XXX */ ATH_MAX_SCATTER, /* nsegments */ 0x3ffff, /* maxsegsize XXX */ BUS_DMA_ALLOCNOW, /* flags */ NULL, /* lockfunc */ NULL, /* lockarg */ &sc->sc_dmat)) { device_printf(dev, "cannot allocate DMA tag\n"); goto bad3; } ATH_LOCK_INIT(sc); error = ath_attach(AR9130_DEVID, sc); if (error == 0) /* success */ return 0; ATH_LOCK_DESTROY(sc); bus_dma_tag_destroy(sc->sc_dmat); bad3: bus_teardown_intr(dev, psc->sc_irq, psc->sc_ih); bad2: bus_release_resource(dev, SYS_RES_IRQ, 0, psc->sc_irq); bad1: bus_release_resource(dev, SYS_RES_MEMORY, 0, psc->sc_eeprom); bad0: bus_release_resource(dev, SYS_RES_MEMORY, 0, psc->sc_sr); bad: /* XXX?! */ if (sc->sc_eepromdata) free(sc->sc_eepromdata, M_TEMP); return (error); }
u_char ppc_io(device_t ppcdev, int iop, u_char *addr, int cnt, u_char byte) { struct ppc_data *ppc = DEVTOSOFTC(ppcdev); switch (iop) { case PPB_OUTSB_EPP: bus_space_write_multi_1(ppc->bst, ppc->bsh, PPC_EPP_DATA, addr, cnt); break; case PPB_OUTSW_EPP: bus_space_write_multi_2(ppc->bst, ppc->bsh, PPC_EPP_DATA, (u_int16_t *)addr, cnt); break; case PPB_OUTSL_EPP: bus_space_write_multi_4(ppc->bst, ppc->bsh, PPC_EPP_DATA, (u_int32_t *)addr, cnt); break; case PPB_INSB_EPP: bus_space_read_multi_1(ppc->bst, ppc->bsh, PPC_EPP_DATA, addr, cnt); break; case PPB_INSW_EPP: bus_space_read_multi_2(ppc->bst, ppc->bsh, PPC_EPP_DATA, (u_int16_t *)addr, cnt); break; case PPB_INSL_EPP: bus_space_read_multi_4(ppc->bst, ppc->bsh, PPC_EPP_DATA, (u_int32_t *)addr, cnt); break; case PPB_RDTR: return (r_dtr(ppc)); case PPB_RSTR: return (r_str(ppc)); case PPB_RCTR: return (r_ctr(ppc)); case PPB_REPP_A: return (r_epp_A(ppc)); case PPB_REPP_D: return (r_epp_D(ppc)); case PPB_RECR: return (r_ecr(ppc)); case PPB_RFIFO: return (r_fifo(ppc)); case PPB_WDTR: w_dtr(ppc, byte); break; case PPB_WSTR: w_str(ppc, byte); break; case PPB_WCTR: w_ctr(ppc, byte); break; case PPB_WEPP_A: w_epp_A(ppc, byte); break; case PPB_WEPP_D: w_epp_D(ppc, byte); break; case PPB_WECR: w_ecr(ppc, byte); break; case PPB_WFIFO: w_fifo(ppc, byte); break; default: panic("%s: unknown I/O operation", __func__); break; } return (0); /* not significative */ }
/* * Bus read multiple operations. */ void bs_through_bs_rm_1(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset, u_int8_t *addr, bus_size_t count) { bus_space_read_multi_1(t->bs_base, bsh, offset, addr, count); }
/* * State machine to process read requests. * Initialize with MCD_S_BEGIN: calculate sizes, and set mode * MCD_S_WAITMODE: waits for status reply from set mode, set read command * MCD_S_WAITREAD: wait for read ready, read data. */ int mcdintr(void *arg) { struct mcd_softc *sc = arg; struct mcd_mbx *mbx = &sc->mbx; struct buf *bp = mbx->bp; bus_space_tag_t iot = sc->sc_iot; bus_space_handle_t ioh = sc->sc_ioh; int i; u_char x; bcd_t msf[3]; switch (mbx->state) { case MCD_S_IDLE: return 0; case MCD_S_BEGIN: tryagain: if (mbx->mode == sc->lastmode) goto firstblock; sc->lastmode = MCD_MD_UNKNOWN; bus_space_write_1(iot, ioh, MCD_COMMAND, MCD_CMDSETMODE); bus_space_write_1(iot, ioh, MCD_COMMAND, mbx->mode); mbx->count = RDELAY_WAITMODE; mbx->state = MCD_S_WAITMODE; case MCD_S_WAITMODE: callout_stop(&sc->sc_pintr_ch); for (i = 20; i; i--) { x = bus_space_read_1(iot, ioh, MCD_XFER); if ((x & MCD_XF_STATUSUNAVAIL) == 0) break; delay(50); } if (i == 0) goto hold; sc->status = bus_space_read_1(iot, ioh, MCD_STATUS); mcd_setflags(sc); if ((sc->flags & MCDF_LOADED) == 0) goto changed; MCD_TRACE("doread: got WAITMODE delay=%d\n", RDELAY_WAITMODE - mbx->count); sc->lastmode = mbx->mode; firstblock: MCD_TRACE("doread: read blkno=%d for bp=0x%p\n", (int) mbx->blkno, bp); /* Build parameter block. */ hsg2msf(mbx->blkno, msf); /* Send the read command. */ bus_space_write_1(iot, ioh, MCD_COMMAND, sc->readcmd); bus_space_write_1(iot, ioh, MCD_COMMAND, msf[0]); bus_space_write_1(iot, ioh, MCD_COMMAND, msf[1]); bus_space_write_1(iot, ioh, MCD_COMMAND, msf[2]); bus_space_write_1(iot, ioh, MCD_COMMAND, 0); bus_space_write_1(iot, ioh, MCD_COMMAND, 0); bus_space_write_1(iot, ioh, MCD_COMMAND, mbx->nblk); mbx->count = RDELAY_WAITREAD; mbx->state = MCD_S_WAITREAD; case MCD_S_WAITREAD: callout_stop(&sc->sc_pintr_ch); nextblock: loop: for (i = 20; i; i--) { x = bus_space_read_1(iot, ioh, MCD_XFER); if ((x & MCD_XF_DATAUNAVAIL) == 0) goto gotblock; if ((x & MCD_XF_STATUSUNAVAIL) == 0) break; delay(50); } if (i == 0) goto hold; sc->status = bus_space_read_1(iot, ioh, MCD_STATUS); mcd_setflags(sc); if ((sc->flags & MCDF_LOADED) == 0) goto changed; #if 0 printf("%s: got status byte %02x during read\n", device_xname(sc->sc_dev), (u_int)sc->status); #endif goto loop; gotblock: MCD_TRACE("doread: got data delay=%d\n", RDELAY_WAITREAD - mbx->count); /* Data is ready. */ bus_space_write_1(iot, ioh, MCD_CTL2, 0x04); /* XXX */ bus_space_read_multi_1(iot, ioh, MCD_RDATA, (char *)bp->b_data + mbx->skip, mbx->sz); bus_space_write_1(iot, ioh, MCD_CTL2, 0x0c); /* XXX */ mbx->blkno += 1; mbx->skip += mbx->sz; if (--mbx->nblk > 0) goto nextblock; mbx->state = MCD_S_IDLE; /* Return buffer. */ bp->b_resid = 0; disk_unbusy(&sc->sc_dk, bp->b_bcount, (bp->b_flags & B_READ)); biodone(bp); mcdstart(sc); return 1; hold: if (mbx->count-- < 0) { printf("%s: timeout in state %d", device_xname(sc->sc_dev), mbx->state); goto readerr; } #if 0 printf("%s: sleep in state %d\n", device_xname(sc->sc_dev), mbx->state); #endif callout_reset(&sc->sc_pintr_ch, hz / 100, mcd_pseudointr, sc); return -1; } readerr: if (mbx->retry-- > 0) { printf("; retrying\n"); goto tryagain; } else printf("; giving up\n"); changed: /* Invalidate the buffer. */ bp->b_error = EIO; bp->b_resid = bp->b_bcount - mbx->skip; disk_unbusy(&sc->sc_dk, (bp->b_bcount - bp->b_resid), (bp->b_flags & B_READ)); biodone(bp); mcdstart(sc); return -1; #ifdef notyet printf("%s: unit timeout; resetting\n", device_xname(sc->sc_dev)); bus_space_write_1(iot, ioh, MCD_RESET, MCD_CMDRESET); delay(300000); (void) mcd_getstat(sc, 1); (void) mcd_getstat(sc, 1); /*sc->status &= ~MCD_ST_DSKCHNG; */ sc->debug = 1; /* preventive set debug mode */ #endif }
static void wb_sdmmc_read_data(struct wb_softc *wb, uint8_t *data, int len) { bus_space_read_multi_1(wb->wb_iot, wb->wb_ioh, WB_SD_FIFO, data, len); }