static int cfi_0002_program_page(device_t self, flash_off_t offset, const uint8_t *datap) { struct nor_softc * const sc = device_private(self); KASSERT(sc != NULL); KASSERT(sc->sc_nor_if != NULL); struct cfi *cfi = (struct cfi * const)sc->sc_nor_if->private; KASSERT(cfi != NULL); struct nor_chip * const chip = &sc->sc_chip; KASSERT(chip != NULL); KASSERT(chip->nc_page_mask != 0); KASSERT((offset & ~chip->nc_page_mask) == 0); KASSERT (chip->nc_page_size != 0); KASSERT((chip->nc_page_size & ((1 << cfi->cfi_portwidth) - 1)) == 0); CFI_0002_STATS_INC(cfi, program_page); bus_size_t count = chip->nc_page_size >> cfi->cfi_portwidth; /* #words/page */ bus_size_t sa = offset << (3 - cfi->cfi_portwidth); /* sector addr */ uint32_t wc = count - 1; /* #words - 1 */ int error = cfi_0002_busy_wait(cfi, offset, cfi_0002_time_dflt(cfi)); if (error != 0) return ETIMEDOUT; cfi_cmd(cfi, cfi->cfi_unlock_addr1, 0xaa); cfi_cmd(cfi, cfi->cfi_unlock_addr2, 0x55); cfi_cmd(cfi, sa, 0x25); /* Write To Buffer */ cfi_cmd(cfi, sa, wc); switch(cfi->cfi_portwidth) { case 0: bus_space_write_region_1(cfi->cfi_bst, cfi->cfi_bsh, offset, (const uint8_t *)datap, count); break; case 1: bus_space_write_region_2(cfi->cfi_bst, cfi->cfi_bsh, offset, (const uint16_t *)datap, count); break; case 2: bus_space_write_region_4(cfi->cfi_bst, cfi->cfi_bsh, offset, (const uint32_t *)datap, count); break; default: panic("%s: bad port width %d\n", __func__, cfi->cfi_portwidth); }; cfi_cmd(cfi, sa, 0x29); /* Write Buffer Program Confirm */ error = cfi_0002_busy_wait(cfi, offset, cfi_0002_time_write_nbyte(cfi)); return error; }
/* * Copy packet from mbuf to the board memory Currently uses an extra * buffer/extra memory copy, unless the whole packet fits in one mbuf. * * As in the test_mem function, we use word-wide writes. */ int ae_write_mbuf(struct dp8390_softc *sc, struct mbuf *m, int buf) { u_char *data, savebyte[2]; int len, wantbyte; u_short totlen = 0; wantbyte = 0; for (; m ; m = m->m_next) { data = mtod(m, u_char *); len = m->m_len; totlen += len; if (len > 0) { /* Finish the last word. */ if (wantbyte) { savebyte[1] = *data; bus_space_write_region_2(sc->sc_buft, sc->sc_bufh, buf, (u_int16_t *)savebyte, 1); buf += 2; data++; len--; wantbyte = 0; } /* Output contiguous words. */ if (len > 1) { bus_space_write_region_2( sc->sc_buft, sc->sc_bufh, buf, (u_int16_t *)data, len >> 1); buf += len & ~1; data += len & ~1; len &= 1; } /* Save last byte, if necessary. */ if (len == 1) { savebyte[0] = *data; wantbyte = 1; } } }
void bs_through_bs_wr_2(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset, const u_int16_t *addr, bus_size_t count) { bus_space_write_region_2(t->bs_base, bsh, offset, addr, count); }