/* * Shortcut for reading a register */ static inline uint32_t emu_rreg(struct emu_softc *sc, uint32_t reg) { return bus_read_register(sc->e_busdata, sc->e_buspos, reg); }
/* * Setup routine called by autoconf.c when an lhd is found. */ int config_lhd(struct lhd_softc *lh, int lhdno) { char name[32]; /* Figure out what our name is. */ snprintf(name, sizeof(name), "lhd%d", lhdno); /* Get a pointer to the on-chip buffer. */ lh->lh_buf = bus_map_area(lh->lh_busdata, lh->lh_buspos, LHD_BUFFER); /* Create the semaphores. */ lh->lh_clear = sem_create("lhd-clear", 1); if (lh->lh_clear == NULL) { return ENOMEM; } lh->lh_done = sem_create("lhd-done", 0); if (lh->lh_done == NULL) { sem_destroy(lh->lh_clear); lh->lh_clear = NULL; return ENOMEM; } /* Set up the VFS device structure. */ lh->lh_dev.d_ops = &lhd_devops; lh->lh_dev.d_blocks = bus_read_register(lh->lh_busdata, lh->lh_buspos, LHD_REG_NSECT); lh->lh_dev.d_blocksize = LHD_SECTSIZE; lh->lh_dev.d_data = lh; /* Add the VFS device structure to the VFS device list. */ return vfs_adddev(name, &lh->lh_dev, 1); }
static void lser_spin_until_write(struct lser_softc *sc) { u_int32_t val; assert(curspl>0); do { val = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ); } while ((val & LSER_IRQ_ACTIVE)==0); }
/* * The timer device also has a realtime clock on it. * This function gets called if the rtclock device is attached * to this timer. */ void ltimer_gettime(void *vlt, time_t *secs, uint32_t *nsecs) { struct ltimer_softc *lt = vlt; uint32_t secs1, secs2; int spl; /* * Read the seconds twice, on either side of the nanoseconds. * If nsecs is small, use the *later* value of seconds, in case * the nanoseconds turned over between the time we got the earlier * value and the time we got nsecs. * * Note that the clock in the ltimer device is accurate down * to a single processor cycle, so this might actually matter * now and then. * * Do it with interrupts off on the current processor to avoid * getting garbage if we get an interrupt among the register * reads. */ spl = splhigh(); secs1 = bus_read_register(lt->lt_bus, lt->lt_buspos, LT_REG_SEC); *nsecs = bus_read_register(lt->lt_bus, lt->lt_buspos, LT_REG_NSEC); secs2 = bus_read_register(lt->lt_bus, lt->lt_buspos, LT_REG_SEC); splx(spl); if (*nsecs < 5000000) { *secs = secs2; } else { *secs = secs1; } }
void lser_irq(void *vsc) { struct lser_softc *sc = vsc; uint32_t x; bool clear_to_write = false; bool got_a_read = false; uint32_t ch = 0; spinlock_acquire(&sc->ls_lock); x = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ); if (x & LSER_IRQ_ACTIVE) { x = LSER_IRQ_ENABLE; sc->ls_wbusy = 0; clear_to_write = true; bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ, x); } x = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_RIRQ); if (x & LSER_IRQ_ACTIVE) { x = LSER_IRQ_ENABLE; ch = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_CHAR); got_a_read = true; bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_RIRQ, x); } spinlock_release(&sc->ls_lock); if (clear_to_write && sc->ls_start != NULL) { sc->ls_start(sc->ls_devdata); } if (got_a_read && sc->ls_input != NULL) { sc->ls_input(sc->ls_devdata, ch); } }
int config_lser(struct lser_softc *sc, int lserno) { uint32_t x; (void)lserno; /* * Enable interrupting. */ spinlock_init(&sc->ls_lock); sc->ls_wbusy = false; x = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_RIRQ); bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_RIRQ, x | LSER_IRQ_ENABLE); x = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ); bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ, x | LSER_IRQ_ENABLE); return 0; }
static void lser_poll_until_write(struct lser_softc *sc) { uint32_t val; KASSERT(spinlock_do_i_hold(&sc->ls_lock)); do { val = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ); } while ((val & LSER_IRQ_ACTIVE) == 0); }
void lser_irq(void *vsc) { struct lser_softc *sc = vsc; u_int32_t x; int clear_to_write=0; int got_a_read=0; u_int32_t ch = 0; assert(curspl>0); x = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ); if (x & LSER_IRQ_ACTIVE) { x = LSER_IRQ_ENABLE; sc->ls_wbusy = 0; clear_to_write = 1; bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ, x); } x = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_RIRQ); if (x & LSER_IRQ_ACTIVE) { x = LSER_IRQ_ENABLE; ch = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_CHAR); got_a_read = 1; bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_RIRQ, x); } if (clear_to_write && sc->ls_start != NULL) { sc->ls_start(sc->ls_devdata); } if (got_a_read && sc->ls_input != NULL) { sc->ls_input(sc->ls_devdata, ch); } }
/* * Interrupt handler. */ void ltimer_irq(void *vlt) { struct ltimer_softc *lt = vlt; uint32_t val; val = bus_read_register(lt->lt_bus, lt->lt_buspos, LT_REG_IRQ); if (val) { /* * Only call hardclock if we're responsible for hardclock. * (Any additional timer devices are unused.) */ if (lt->lt_hardclock) { hardclock(); } /* * Likewise for timerclock. */ if (lt->lt_timerclock) { timerclock(); } } }
/* * Shortcut for reading a register. */ static inline uint32_t lhd_rdreg(struct lhd_softc *lh, uint32_t reg) { return bus_read_register(lh->lh_busdata, lh->lh_buspos, reg); }