static int tun_clone_create(struct if_clone *ifc, int unit) { struct tun_softc *tp; if ((tp = tun_find_zunit(unit)) == NULL) { /* Allocate a new instance */ tp = malloc(sizeof(*tp), M_DEVBUF, M_WAITOK|M_ZERO); tp->tun_unit = unit; mutex_init(&tp->tun_lock, MUTEX_DEFAULT, IPL_NET); selinit(&tp->tun_rsel); selinit(&tp->tun_wsel); } else { /* Revive tunnel instance; clear ifp part */ (void)memset(&tp->tun_if, 0, sizeof(struct ifnet)); } if_initname(&tp->tun_if, ifc->ifc_name, unit); tunattach0(tp); tp->tun_flags |= TUN_INITED; tp->tun_osih = softint_establish(SOFTINT_CLOCK, tun_o_softintr, tp); tp->tun_isih = softint_establish(SOFTINT_CLOCK, tun_i_softintr, tp); simple_lock(&tun_softc_lock); LIST_INSERT_HEAD(&tun_softc_list, tp, tun_list); simple_unlock(&tun_softc_lock); return (0); }
void mgnscattach(device_t parent, device_t self, void *aux) { struct siop_softc *sc = device_private(self); struct zbus_args *zap; siop_regmap_p rp; struct scsipi_adapter *adapt = &sc->sc_adapter; struct scsipi_channel *chan = &sc->sc_channel; sc->sc_dev = self; printf("\n"); zap = aux; sc->sc_siopp = rp = (siop_regmap_p)((char *)zap->va + 0x8000); /* * CTEST7 = TT1 */ sc->sc_clock_freq = 33; /* Clock = 33 MHz */ sc->sc_ctest7 = SIOP_CTEST7_TT1; sc->sc_dcntl = 0x00; sc->sc_siop_si = softint_establish(SOFTINT_BIO, (void (*)(void *))siopintr, sc); /* * Fill in the scsipi_adapter. */ memset(adapt, 0, sizeof(*adapt)); adapt->adapt_dev = self; adapt->adapt_nchannels = 1; adapt->adapt_openings = 7; adapt->adapt_max_periph = 1; adapt->adapt_request = siop_scsipi_request; adapt->adapt_minphys = siop_minphys; /* * Fill in the scsipi_channel. */ memset(chan, 0, sizeof(*chan)); chan->chan_adapter = adapt; chan->chan_bustype = &scsi_bustype; chan->chan_channel = 0; chan->chan_ntargets = 8; chan->chan_nluns = 8; chan->chan_id = 7; siopinitialize(sc); sc->sc_isr.isr_intr = mgnsc_dmaintr; sc->sc_isr.isr_arg = sc; sc->sc_isr.isr_ipl = 6; add_isr (&sc->sc_isr); /* * attach all scsi units on us */ config_found(self, chan, scsiprint); }
int testcall(struct lwp *l, void *uap, register_t *retval) { printf("test: initializing\n"); mutex_init(&test_mutex, MUTEX_DEFAULT, IPL_NONE); cv_init(&test_cv, "testcv"); test_sih = softint_establish(SOFTINT_MPSAFE | SOFTINT_SERIAL, test_softint, NULL); callout_init(&test_ch, CALLOUT_MPSAFE); callout_setfunc(&test_ch, test_callout, NULL); printf("test: firing\n"); callout_schedule(&test_ch, hz / 10); printf("test: waiting\n"); mutex_enter(&test_mutex); while (!test_done) { cv_wait(&test_cv, &test_mutex); } mutex_exit(&test_mutex); printf("test: finished\n"); callout_destroy(&test_ch); softint_disestablish(test_sih); mutex_destroy(&test_mutex); cv_destroy(&test_cv); return 0; }
void audioamd_attach(struct audioamd_softc *sc, int pri) { /* * Set up glue for MI code early; we use some of it here. */ sc->sc_am7930.sc_glue = &audioamd_glue; mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_HIGH); am7930_init(&sc->sc_am7930, AUDIOAMD_POLL_MODE); auiop = &sc->sc_au; /* Copy bus tag & handle for use by am7930_trap */ sc->sc_au.au_bt = sc->sc_bt; sc->sc_au.au_bh = sc->sc_bh; (void)bus_intr_establish2(sc->sc_bt, pri, IPL_HIGH, am7930hwintr, sc, amd7930_trap); sc->sc_sicookie = softint_establish(SOFTINT_SERIAL, am7930swintr, sc); if (sc->sc_sicookie == NULL) { printf("\n%s: cannot establish software interrupt\n", sc->sc_am7930.sc_dev.dv_xname); return; } printf(" softpri %d\n", IPL_SOFTAUDIO); evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, NULL, sc->sc_am7930.sc_dev.dv_xname, "intr"); audio_attach_mi(&sa_hw_if, sc, &sc->sc_am7930.sc_dev); }
static void arcofi_dio_attach(device_t parent, device_t self, void *aux) { struct arcofi_dio_softc *adsc = device_private(self); struct arcofi_softc *sc = &adsc->sc_arcofi; struct dio_attach_args *da = aux; bus_space_tag_t iot = &adsc->sc_tag; int ipl; sc->sc_dev = self; /* XXX is it better to use sc->sc_reg[] to handle odd sparse map? */ memcpy(iot, da->da_bst, sizeof(struct bus_space_tag)); dio_set_bus_space_oddbyte(iot); sc->sc_iot = iot; if (bus_space_map(iot, da->da_addr, DIOII_SIZEOFF, 0, &sc->sc_ioh) != 0) { aprint_error(": can't map registers\n"); return; } sc->sc_sih = softint_establish(SOFTINT_AUDIO, arcofi_swintr, sc); if (sc->sc_sih == NULL) { aprint_error(": can't register soft interrupt\n"); return; } ipl = da->da_ipl; dio_intr_establish(arcofi_hwintr, sc, ipl, IPL_AUDIO); aprint_normal("\n"); arcofi_attach(sc, "dio"); }
void mfcsattach(device_t parent, device_t self, void *aux) { int unit; struct mfcs_softc *sc; struct mfc_softc *scc; struct mfc_args *ma; struct mfc_regs *rp; sc = device_private(self); sc->sc_dev = self; scc = device_private(parent); ma = aux; printf (": input fifo %d output fifo %d\n", SERIBUF_SIZE, SEROBUF_SIZE); unit = ma->unit; mfcs_active |= 1 << unit; sc->rptr = sc->wptr = sc->inbuf; sc->sc_mfc = scc; sc->sc_regs = rp = scc->sc_regs; sc->sc_duart = (struct duart_regs *) ((unit & 1) ? __UNVOLATILE(&rp->du_mr1b) : __UNVOLATILE(&rp->du_mr1a)); sc->mfcs_si = softint_establish(SOFTINT_SERIAL, mfcs_intr_soft, sc); /* * should have only one vbl routine to handle all ports? */ sc->vbl_node.function = (void (*) (void *)) mfcsmint; sc->vbl_node.data = (void *) unit; add_vbl_function(&sc->vbl_node, 1, (void *) unit); }
int vcons_init(struct vcons_data *vd, void *cookie, struct wsscreen_descr *def, struct wsdisplay_accessops *ao) { /* zero out everything so we can rely on untouched fields being 0 */ memset(vd, 0, sizeof(struct vcons_data)); vd->cookie = cookie; vd->init_screen = vcons_dummy_init_screen; vd->show_screen_cb = NULL; /* keep a copy of the accessops that we replace below with our * own wrappers */ vd->ioctl = ao->ioctl; /* configure the accessops */ ao->ioctl = vcons_ioctl; ao->alloc_screen = vcons_alloc_screen; ao->free_screen = vcons_free_screen; ao->show_screen = vcons_show_screen; #ifdef WSDISPLAY_SCROLLSUPPORT ao->scroll = vcons_scroll; #endif LIST_INIT(&vd->screens); vd->active = NULL; vd->wanted = NULL; vd->currenttype = def; callout_init(&vd->switch_callout, 0); callout_setfunc(&vd->switch_callout, vcons_do_switch, vd); #ifdef VCONS_DRAW_INTR vd->cells = 0; vd->attrs = NULL; vd->chars = NULL; vd->cursor_offset = -1; #endif /* * a lock to serialize access to the framebuffer. * when switching screens we need to make sure there's no rasops * operation in progress */ #ifdef DIAGNOSTIC vd->switch_poll_count = 0; #endif #ifdef VCONS_DRAW_INTR vd->intr_softint = softint_establish(SOFTINT_SERIAL, vcons_softintr, vd); callout_init(&vd->intr, 0); callout_setfunc(&vd->intr, vcons_intr, vd); vd->intr_valid = 1; /* XXX assume that the 'dev' arg is never dereferenced */ config_interrupts((device_t)vd, vcons_intr_enable); #endif return 0; }
static void vaudio_attach(device_t parent, device_t self, void *opaque) { struct vaudio_softc *sc = device_private(self); struct thunkbus_attach_args *taa = opaque; int error; aprint_naive("\n"); aprint_normal(": Virtual Audio (device = %s)\n", taa->u.vaudio.device); sc->sc_dev = self; pmf_device_register1(self, NULL, NULL, vaudio_shutdown); sc->sc_audiopath = taa->u.vaudio.device; sc->sc_audiofd = thunk_audio_open(sc->sc_audiopath); if (sc->sc_audiofd == -1) { aprint_error_dev(self, "couldn't open audio device: %d\n", thunk_geterrno()); return; } mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO); error = auconv_create_encodings(vaudio_audio_formats, __arraycount(vaudio_audio_formats), &sc->sc_encodings); if (error) { aprint_error_dev(self, "couldn't create encodings\n"); return; } sc->sc_play.st_softc = sc; sc->sc_play.st_sih = softint_establish(SOFTINT_SERIAL|SOFTINT_MPSAFE, vaudio_softintr_play, &sc->sc_play); callout_init(&sc->sc_play.st_callout, CALLOUT_MPSAFE); callout_setfunc(&sc->sc_play.st_callout, vaudio_intr, &sc->sc_play); sc->sc_record.st_softc = sc; sc->sc_record.st_sih = softint_establish(SOFTINT_SERIAL|SOFTINT_MPSAFE, vaudio_softintr_record, &sc->sc_record); callout_init(&sc->sc_record.st_callout, CALLOUT_MPSAFE); callout_setfunc(&sc->sc_record.st_callout, vaudio_intr, &sc->sc_record); sc->sc_audiodev = audio_attach_mi(&vaudio_hw_if, sc, self); }
void clmpcc_attach(struct clmpcc_softc *sc) { struct clmpcc_chan *ch; struct tty *tp; int chan; if ( cons_sc != NULL && sc->sc_iot == cons_sc->sc_iot && sc->sc_ioh == cons_sc->sc_ioh ) cons_sc = sc; /* Initialise the chip */ clmpcc_init(sc); printf(": Cirrus Logic CD240%c Serial Controller\n", (clmpcc_rd_msvr(sc) & CLMPCC_MSVR_PORT_ID) ? '0' : '1'); sc->sc_softintr_cookie = softint_establish(SOFTINT_SERIAL, clmpcc_softintr, sc); if (sc->sc_softintr_cookie == NULL) panic("clmpcc_attach: softintr_establish"); memset(&(sc->sc_chans[0]), 0, sizeof(sc->sc_chans)); for (chan = 0; chan < CLMPCC_NUM_CHANS; chan++) { ch = &sc->sc_chans[chan]; ch->ch_sc = sc; ch->ch_car = chan; tp = tty_alloc(); tp->t_oproc = clmpcc_start; tp->t_param = clmpcc_param; ch->ch_tty = tp; ch->ch_ibuf = malloc(clmpcc_ibuf_size * 2, M_DEVBUF, M_NOWAIT); if ( ch->ch_ibuf == NULL ) { aprint_error_dev(sc->sc_dev, "(%d): unable to allocate ring buffer\n", chan); return; } ch->ch_ibuf_end = &(ch->ch_ibuf[clmpcc_ibuf_size * 2]); ch->ch_ibuf_rd = ch->ch_ibuf_wr = ch->ch_ibuf; tty_attach(tp); } aprint_error_dev(sc->sc_dev, "%d channels available", CLMPCC_NUM_CHANS); if ( cons_sc == sc ) { printf(", console on channel %d.\n", cons_chan); SET(sc->sc_chans[cons_chan].ch_flags, CLMPCC_FLG_IS_CONSOLE); SET(sc->sc_chans[cons_chan].ch_openflags, TIOCFLAG_SOFTCAR); } else printf(".\n"); }
void time_init2(void) { TAILQ_INIT(&timer_queue); mutex_init(&timer_lock, MUTEX_DEFAULT, IPL_SCHED); timer_sih = softint_establish(SOFTINT_CLOCK | SOFTINT_MPSAFE, timer_intr, NULL); }
/* * dmover_process_init: * * Initialize the processing engine. */ void dmover_process_initialize(void) { TAILQ_INIT(&dmover_completed_q); mutex_init(&dmover_completed_q_lock, MUTEX_DEFAULT, IPL_BIO); dmover_completed_si = softint_establish(SOFTINT_CLOCK, dmover_complete, NULL); }
static void bcmrng_attach(device_t parent, device_t self, void *aux) { struct bcm2835rng_softc *sc = device_private(self); struct amba_attach_args *aaa = aux; uint32_t ctrl; aprint_naive("\n"); aprint_normal(": RNG\n"); sc->sc_dev = self; sc->sc_iot = aaa->aaa_iot; if (bus_space_map(aaa->aaa_iot, aaa->aaa_addr, BCM2835_RNG_SIZE, 0, &sc->sc_ioh)) { aprint_error_dev(sc->sc_dev, "unable to map device\n"); goto fail0; } /* discard initial numbers, broadcom says they are "less random" */ bus_space_write_4(sc->sc_iot, sc->sc_ioh, RNG_STATUS, 0x40000); /* enable rng */ ctrl = bus_space_read_4(sc->sc_iot, sc->sc_ioh, RNG_CTRL); ctrl |= RNG_CTRL_EN; bus_space_write_4(sc->sc_iot, sc->sc_ioh, RNG_CTRL, ctrl); /* set up a softint for adding data */ mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SERIAL); sc->sc_bytes_wanted = 0; sc->sc_sih = softint_establish(SOFTINT_SERIAL|SOFTINT_MPSAFE, &bcmrng_get_intr, sc); if (sc->sc_sih == NULL) { aprint_error_dev(sc->sc_dev, "unable to establish softint"); goto fail1; } /* set up an rndsource */ mutex_init(&sc->sc_rnd_lock, MUTEX_DEFAULT, IPL_SERIAL); rndsource_setcb(&sc->sc_rndsource, &bcmrng_get_cb, sc); rnd_attach_source(&sc->sc_rndsource, device_xname(self), RND_TYPE_RNG, RND_FLAG_NO_ESTIMATE|RND_FLAG_HASCB); /* get some initial entropy ASAP */ bcmrng_get_cb(RND_POOLBITS / NBBY, sc); /* Success! */ return; fail1: mutex_destroy(&sc->sc_intr_lock); bus_space_unmap(aaa->aaa_iot, sc->sc_ioh, BCM2835_RNG_SIZE); fail0: return; }
void ucom_attach(device_t parent, device_t self, void *aux) { struct ucom_softc *sc = device_private(self); struct ucom_attach_args *uca = aux; struct tty *tp; if (uca->info != NULL) aprint_normal(": %s", uca->info); aprint_normal("\n"); sc->sc_dev = self; sc->sc_udev = uca->device; sc->sc_iface = uca->iface; sc->sc_bulkout_no = uca->bulkout; sc->sc_bulkin_no = uca->bulkin; sc->sc_ibufsize = uca->ibufsize; sc->sc_ibufsizepad = uca->ibufsizepad; sc->sc_obufsize = uca->obufsize; sc->sc_opkthdrlen = uca->opkthdrlen; sc->sc_methods = uca->methods; sc->sc_parent = uca->arg; sc->sc_portno = uca->portno; sc->sc_lsr = 0; sc->sc_msr = 0; sc->sc_mcr = 0; sc->sc_tx_stopped = 0; sc->sc_swflags = 0; sc->sc_opening = 0; sc->sc_refcnt = 0; sc->sc_dying = 0; sc->sc_si = softint_establish(SOFTINT_NET, ucom_softintr, sc); tp = tty_alloc(); tp->t_oproc = ucomstart; tp->t_param = ucomparam; tp->t_hwiflow = ucomhwiflow; sc->sc_tty = tp; DPRINTF(("ucom_attach: tty_attach %p\n", tp)); tty_attach(tp); rnd_attach_source(&sc->sc_rndsource, device_xname(sc->sc_dev), RND_TYPE_TTY, RND_FLAG_DEFAULT); if (!pmf_device_register(self, NULL, NULL)) aprint_error_dev(self, "couldn't establish power handler\n"); return; }
/* alloc/free pipe */ static usbd_status alloc_pipe(struct umidi_endpoint *ep) { struct umidi_softc *sc = ep->sc; usbd_status err; usb_endpoint_descriptor_t *epd; epd = usbd_get_endpoint_descriptor(sc->sc_iface, ep->addr); /* * For output, an improvement would be to have a buffer bigger than * wMaxPacketSize by num_jacks-1 additional packet slots; that would * allow out_solicit to fill the buffer to the full packet size in * all cases. But to use usbd_alloc_buffer to get a slightly larger * buffer would not be a good way to do that, because if the addition * would make the buffer exceed USB_MEM_SMALL then a substantially * larger block may be wastefully allocated. Some flavor of double * buffering could serve the same purpose, but would increase the * code complexity, so for now I will live with the current slight * penalty of reducing max transfer size by (num_open-num_scheduled) * packet slots. */ ep->buffer_size = UGETW(epd->wMaxPacketSize); ep->buffer_size -= ep->buffer_size % UMIDI_PACKET_SIZE; DPRINTF(("%s: alloc_pipe %p, buffer size %u\n", USBDEVNAME(sc->sc_dev), ep, ep->buffer_size)); ep->num_scheduled = 0; ep->this_schedule = 0; ep->next_schedule = 0; ep->soliciting = 0; ep->armed = 0; ep->xfer = usbd_alloc_xfer(sc->sc_udev); if (ep->xfer == NULL) { err = USBD_NOMEM; goto quit; } ep->buffer = usbd_alloc_buffer(ep->xfer, ep->buffer_size); if (ep->buffer == NULL) { usbd_free_xfer(ep->xfer); err = USBD_NOMEM; goto quit; } ep->next_slot = ep->buffer; err = usbd_open_pipe(sc->sc_iface, ep->addr, 0, &ep->pipe); if (err) usbd_free_xfer(ep->xfer); ep->solicit_cookie = softint_establish(SOFTINT_CLOCK, out_solicit, ep); quit: return err; }
static void wsattach(device_t parent, device_t self, void *aux) { struct ws_softc *sc = device_private(self); struct sio_softc *siosc = device_private(parent); struct sio_attach_args *args = aux; int channel = args->channel; struct wskbddev_attach_args a; sc->sc_dev = self; sc->sc_ctl = &siosc->sc_ctl[channel]; memcpy(sc->sc_wr, ch1_regs, sizeof(ch1_regs)); siosc->sc_intrhand[channel].ih_func = wsintr; siosc->sc_intrhand[channel].ih_arg = sc; setsioreg(sc->sc_ctl, WR0, sc->sc_wr[WR0]); setsioreg(sc->sc_ctl, WR4, sc->sc_wr[WR4]); setsioreg(sc->sc_ctl, WR3, sc->sc_wr[WR3]); setsioreg(sc->sc_ctl, WR5, sc->sc_wr[WR5]); setsioreg(sc->sc_ctl, WR0, sc->sc_wr[WR0]); setsioreg(sc->sc_ctl, WR1, sc->sc_wr[WR1]); syscnputc((dev_t)1, 0x20); /* keep quiet mouse */ sc->sc_rxqhead = 0; sc->sc_rxqtail = 0; sc->sc_si = softint_establish(SOFTINT_SERIAL, wssoftintr, sc); aprint_normal("\n"); a.console = (args->hwflags == 1); a.keymap = &omkbd_keymapdata; a.accessops = &omkbd_accessops; a.accesscookie = (void *)sc; sc->sc_wskbddev = config_found_ia(self, "wskbddev", &a, wskbddevprint); #if NWSMOUSE > 0 { struct wsmousedev_attach_args b; b.accessops = &omms_accessops; b.accesscookie = (void *)sc; sc->sc_wsmousedev = config_found_ia(self, "wsmousedev", &b, wsmousedevprint); sc->sc_msreport = 0; } #endif }
void lpt_attach_subr(struct lpt_softc *sc) { bus_space_tag_t iot; bus_space_handle_t ioh; sc->sc_state = 0; iot = sc->sc_iot; ioh = sc->sc_ioh; bus_space_write_1(iot, ioh, lpt_control, LPC_NINIT); callout_init(&sc->sc_wakeup_ch, 0); sc->sc_sih = softint_establish(SOFTINT_SERIAL, lptsoftintr, sc); sc->sc_dev_ok = 1; }
void * sacc_intr_establish(sacc_chipset_tag_t *ic, int irq, int type, int level, int (*ih_fun)(void *), void *ih_arg) { int s; struct sacc_softc *sc = (struct sacc_softc *)ic; struct sacc_intrhand **p, *ih; /* no point in sleeping unless someone can free memory. */ ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK); if (ih == NULL) panic("sacc_intr_establish: can't malloc handler info"); if (irq < 0 || irq > SACCIC_LEN || !(type == IST_EDGE_RAISE || type == IST_EDGE_FALL)) panic("sacc_intr_establish: bogus irq or type"); if (sc->sc_intrhand[irq] == NULL) { sacc_intr_setpolarity(ic, irq, type); sc->sc_intrtype[irq] = type; } else if (sc->sc_intrtype[irq] != type) /* XXX we should be able to share raising and * falling edge intrs */ panic("sacc_intr_establish: type must be unique"); /* install intr handler */ /* map interrupt level to appropriate softinterrupt level */ level = SOFTINT_SERIAL; ih->ih_soft = softint_establish(level, (void (*)(void *)) ih_fun, ih_arg); ih->ih_irq = irq; ih->ih_next = NULL; s = splhigh(); for (p = &sc->sc_intrhand[irq]; *p; p = &(*p)->ih_next) continue; *p = ih; sacc_intr_calculatemasks(sc); splx(s); return ih; }
void * gemini_ipm_register(uint8_t tag, unsigned int ipl, size_t quota, void (*consume)(void *, const void *), void (*counter)(void *, size_t), void *arg) { gemini_ipm_softc_t *sc = gemini_ipm_sc; ipm_dispatch_entry_t *disp; void *ipmh = NULL; int psw; DPRINTFN(1, ("%s:%d: %d %d %ld %p %p %p\n", __FUNCTION__, __LINE__, tag, ipl, quota, consume, counter, arg)); if (sc == NULL) return NULL; /* not attached yet */ if (tag == 0) return NULL; /* tag #0 is reserved */ psw = disable_interrupts(I32_bit); disp = &sc->sc_dispatch_tab[tag]; if (disp->consume == 0) { if (sc->sc_txqavail >= quota) { sc->sc_txqavail -= quota; disp->ipl = ipl; disp->consume = consume; disp->counter = counter; disp->arg = arg; #ifdef NOTYET if (ipl > SOFTINT_LVLMASK) panic("%s: bad level %d", device_xname(sc->sc_dev), ipl); disp->sih = softint_establish(ipl, consume, arg); #endif ipmh = disp; } } restore_interrupts(psw); return ipmh; }
/* called at boot time */ void xenevtattach(int n) { struct intrhand *ih; int s; int level = IPL_HIGH; #ifdef MULTIPROCESSOR bool mpsafe = (level != IPL_VM); #endif /* MULTIPROCESSOR */ mutex_init(&devevent_lock, MUTEX_DEFAULT, IPL_HIGH); STAILQ_INIT(&devevent_pending); devevent_sih = softint_establish(SOFTINT_SERIAL, (void (*)(void *))xenevt_notify, NULL); memset(devevent, 0, sizeof(devevent)); xenevt_ev1 = 0; memset(xenevt_ev2, 0, sizeof(xenevt_ev2)); /* register a handler at splhigh, so that spllower() will call us */ ih = malloc(sizeof (struct intrhand), M_DEVBUF, M_WAITOK|M_ZERO); if (ih == NULL) panic("can't allocate xenevt interrupt source"); ih->ih_level = level; ih->ih_fun = ih->ih_realfun = xenevt_processevt; ih->ih_arg = ih->ih_realarg = NULL; ih->ih_ipl_next = NULL; ih->ih_cpu = &cpu_info_primary; #ifdef MULTIPROCESSOR if (!mpsafe) { ih->ih_fun = intr_biglock_wrapper; ih->ih_arg = ih; } #endif /* MULTIPROCESSOR */ s = splhigh(); event_set_iplhandler(ih->ih_cpu, ih, level); splx(s); }
void dt_attach(device_t parent, device_t self, void *aux) { struct ioasicdev_attach_args *d; struct dt_attach_args dta; struct dt_softc *sc; struct dt_msg *msg; int i; d = aux; sc = device_private(self); sc->sc_dev = self; dt_cninit(); msg = malloc(sizeof(*msg) * DT_BUF_CNT, M_DEVBUF, M_NOWAIT); if (msg == NULL) { printf("%s: memory exhausted\n", device_xname(self)); return; } sc->sc_sih = softint_establish(SOFTINT_SERIAL, dt_dispatch, sc); if (sc->sc_sih == NULL) { printf("%s: memory exhausted\n", device_xname(self)); free(msg, M_DEVBUF); } SIMPLEQ_INIT(&sc->sc_queue); SLIST_INIT(&sc->sc_free); for (i = 0; i < DT_BUF_CNT; i++, msg++) SLIST_INSERT_HEAD(&sc->sc_free, msg, chain.slist); ioasic_intr_establish(parent, d->iada_cookie, TC_IPL_TTY, dt_intr, sc); printf("\n"); dta.dta_addr = DT_ADDR_KBD; config_found(self, &dta, dt_print); dta.dta_addr = DT_ADDR_MOUSE; config_found(self, &dta, dt_print); }
static void ingenic_rng_attach(device_t parent, device_t self, void *aux) { struct ingenic_rng_softc * const sc = device_private(self); struct apbus_attach_args * const aa = aux; int error; sc->sc_dev = self; sc->sc_bst = aa->aa_bst; if (aa->aa_addr == 0) { aa->aa_addr = JZ_RNG; } error = bus_space_map(aa->aa_bst, aa->aa_addr, 4, 0, &sc->sc_bsh); if (error) { aprint_error_dev(self, "can't map registers for %s: %d\n", aa->aa_name, error); return; } mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SERIAL); mutex_init(&sc->sc_rnd_lock, MUTEX_DEFAULT, IPL_SERIAL); aprint_naive(": Ingenic random number generator\n"); aprint_normal(": Ingenic random number generator\n"); sc->sc_sih = softint_establish(SOFTINT_SERIAL|SOFTINT_MPSAFE, ingenic_rng_get_intr, sc); if (sc->sc_sih == NULL) { aprint_error_dev(self, "couldn't establish softint\n"); return; } rndsource_setcb(&sc->sc_rndsource, ingenic_rng_get_cb, sc); rnd_attach_source(&sc->sc_rndsource, device_xname(self), RND_TYPE_RNG, RND_FLAG_COLLECT_VALUE|RND_FLAG_HASCB); ingenic_rng_get_cb(RND_POOLBITS / NBBY, sc); }
/* * callout_init_cpu: * * Per-CPU initialization. */ void callout_init_cpu(struct cpu_info *ci) { struct callout_cpu *cc; int b; CTASSERT(sizeof(callout_impl_t) <= sizeof(callout_t)); if ((cc = ci->ci_data.cpu_callout) == NULL) { cc = kmem_zalloc(sizeof(*cc), KM_SLEEP); if (cc == NULL) panic("callout_init_cpu (1)"); cc->cc_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_SCHED); CIRCQ_INIT(&cc->cc_todo); for (b = 0; b < BUCKETS; b++) CIRCQ_INIT(&cc->cc_wheel[b]); } else { /* Boot CPU, one time only. */ callout_sih = softint_establish(SOFTINT_CLOCK | SOFTINT_MPSAFE, callout_softclock, NULL); if (callout_sih == NULL) panic("callout_init_cpu (2)"); } sleepq_init(&cc->cc_sleepq); snprintf(cc->cc_name1, sizeof(cc->cc_name1), "late/%u", cpu_index(ci)); evcnt_attach_dynamic(&cc->cc_ev_late, EVCNT_TYPE_MISC, NULL, "callout", cc->cc_name1); snprintf(cc->cc_name2, sizeof(cc->cc_name2), "wait/%u", cpu_index(ci)); evcnt_attach_dynamic(&cc->cc_ev_block, EVCNT_TYPE_MISC, NULL, "callout", cc->cc_name2); ci->ci_data.cpu_callout = cc; }
static void kbdattach(device_t parent, device_t self, void *aux) { struct kbd_softc *sc = device_private(self); struct mfp_softc *mfp = device_private(parent); int s; kbd_attached = 1; s = spltty(); /* MFP interrupt #12 is for USART receive buffer full */ intio_intr_establish(mfp->sc_intr + 12, "kbd", kbdintr, sc); sc->sc_softintr_cookie = softint_establish(SOFTINT_SERIAL, kbdsoftint, sc); kbdenable(1); sc->sc_event_mode = 0; sc->sc_events.ev_io = 0; splx(s); aprint_normal("\n"); }
/* * Keyboard and mouse share the interrupt * so don't install interrupt handler twice. */ static void pckbc_js_intr_establish(struct pckbc_softc *sc, pckbport_slot_t slot) { struct pckbc_js_softc *jsc = (struct pckbc_js_softc *)sc; void *res; if (jsc->jsc_establised) { #ifdef DEBUG aprint_verbose_dev(sc->sc_dv, "%s slot shares interrupt (already established)\n", pckbc_slot_names[slot]); #endif return; } /* * We can not choose the devic class interruptlevel freely, * so we debounce via a softinterrupt. */ jsc->jsc_int_cookie = softint_establish(SOFTINT_SERIAL, pckbcintr_soft, &jsc->jsc_pckbc); if (jsc->jsc_int_cookie == NULL) { aprint_error_dev(sc->sc_dv, "unable to establish %s soft interrupt\n", pckbc_slot_names[slot]); return; } res = bus_intr_establish(sc->id->t_iot, jsc->jsc_intr, IPL_SERIAL, jsc_pckbdintr, jsc); if (res == NULL) aprint_error_dev(sc->sc_dv, "unable to establish %s slot interrupt\n", pckbc_slot_names[slot]); else jsc->jsc_establised = 1; }
void at91usart_attach_subr(struct at91usart_softc *sc, struct at91bus_attach_args *sa) { struct tty *tp; int err; printf("\n"); if (bus_space_map(sa->sa_iot, sa->sa_addr, sa->sa_size, 0, &sc->sc_ioh)) panic("%s: Cannot map registers", device_xname(sc->sc_dev)); sc->sc_iot = sa->sa_iot; sc->sc_hwbase = sa->sa_addr; sc->sc_dmat = sa->sa_dmat; sc->sc_pid = sa->sa_pid; /* allocate fifos */ err = at91pdc_alloc_fifo(sc->sc_dmat, &sc->sc_rx_fifo, AT91USART_RING_SIZE, BUS_DMA_READ | BUS_DMA_STREAMING); if (err) panic("%s: cannot allocate rx fifo", device_xname(sc->sc_dev)); err = at91pdc_alloc_fifo(sc->sc_dmat, &sc->sc_tx_fifo, AT91USART_RING_SIZE, BUS_DMA_WRITE | BUS_DMA_STREAMING); if (err) panic("%s: cannot allocate tx fifo", device_xname(sc->sc_dev)); /* initialize uart */ at91_peripheral_clock(sc->sc_pid, 1); at91usart_writereg(sc, US_IDR, -1); at91usart_writereg(sc, US_RTOR, 12); // 12-bit timeout at91usart_writereg(sc, US_PDC + PDC_PTCR, PDC_PTCR_TXTDIS | PDC_PTCR_RXTDIS); at91_intr_establish(sa->sa_pid, IPL_TTY, INTR_HIGH_LEVEL, at91usart_intr, sc); USART_INIT(sc, 115200U); #ifdef NOTYET if (sc->sc_iot == usart_cn_sc.sc_iot && sc->sc_hwbase == usart_cn_sc.sc_hwbase) { usart_cn_sc.sc_attached = 1; /* Make sure the console is always "hardwired". */ delay(10000); /* wait for output to finish */ SET(sc->sc_hwflags, COM_HW_CONSOLE); SET(sc->sc_swflags, TIOCFLAG_SOFTCAR); SET(sc->sc_ier, USART_INT_RXRDY); USARTREG(USART_IER) = USART_INT_RXRDY; // @@@@@ } #endif // NOTYET tp = tty_alloc(); tp->t_oproc = at91usart_start; tp->t_param = at91usart_param; tp->t_hwiflow = at91usart_hwiflow; sc->sc_tty = tp; tty_attach(tp); #if NOTYET if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { int maj; /* locate the major number */ maj = cdevsw_lookup_major(&at91usart_cdevsw); cn_tab->cn_dev = makedev(maj, device_unit(sc->sc_dev)); aprint_normal("%s: console (maj %u min %u cn_dev %u)\n", device_xname(sc->sc_dev), maj, device_unit(sc->sc_dev), cn_tab->cn_dev); } #endif /* NOTYET */ sc->sc_si = softint_establish(SOFTINT_SERIAL, at91usart_soft, sc); #ifdef RND_COM rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), RND_TYPE_TTY, RND_FLAG_DEFAULT); #endif /* if there are no enable/disable functions, assume the device is always enabled */ if (!sc->enable) sc->enabled = 1; /* XXX configure register */ /* xxx_config(sc) */ SET(sc->sc_hwflags, COM_HW_DEV_OK); }
void zs_sbdio_attach(device_t parent, device_t self, void *aux) { struct zsc_softc *zsc = device_private(self); struct sbdio_attach_args *sa = aux; struct zsc_attach_args zsc_args; struct zschan *zc; struct zs_chanstate *cs; struct zsdevice *zs_addr; int s, channel; zsc->zsc_dev = self; aprint_normal("\n"); zs_addr = (void *)MIPS_PHYS_TO_KSEG1(sa->sa_addr1); zsc->zsc_flags = sa->sa_flags; /* * Initialize software state for each channel. */ for (channel = 0; channel < 2; channel++) { zsc_args.channel = channel; zsc_args.hwflags = 0; cs = &zsc->zsc_cs_store[channel]; zsc->zsc_cs[channel] = cs; cs->cs_channel = channel; cs->cs_private = NULL; cs->cs_ops = &zsops_null; if (channel == 0) zc = &zs_addr->zs_chan_a; else zc = &zs_addr->zs_chan_b; if (zc == zs_consaddr) { memcpy(cs, zs_conscs, sizeof(struct zs_chanstate)); zs_conscs = cs; zsc_args.hwflags = ZS_HWFLAG_CONSOLE; } else { cs->cs_reg_csr = &zc->zc_csr; cs->cs_reg_data = &zc->zc_data; memcpy(cs->cs_creg, zs_init_reg, 16); memcpy(cs->cs_preg, zs_init_reg, 16); cs->cs_defspeed = ZS_DEFSPEED; zsc_args.hwflags = 0; } zs_lock_init(cs); cs->cs_brg_clk = PCLK / 16; cs->cs_defcflag = zs_def_cflag; /* Make these correspond to cs_defcflag (-crtscts) */ cs->cs_rr0_dcd = ZSRR0_DCD; cs->cs_rr0_cts = 0; cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS; cs->cs_wr5_rts = 0; /* * Clear the master interrupt enable. * The INTENA is common to both channels, * so just do it on the A channel. */ if (channel == 0) { zs_write_reg(cs, 9, 0); } /* * Look for a child driver for this channel. * The child attach will setup the hardware. */ if (!config_found(self, (void *)&zsc_args, zs_print)) { /* No sub-driver. Just reset it. */ uint8_t reset = (channel == 0) ? ZSWR9_A_RESET : ZSWR9_B_RESET; s = splhigh(); zs_write_reg(cs, 9, reset); splx(s); } } zsc->zsc_si = softint_establish(SOFTINT_SERIAL, (void (*)(void *))zsc_intr_soft, zsc); intr_establish(sa->sa_irq, zshard, zsc); /* * Set the master interrupt enable and interrupt vector. * (common to both channels, do it on A) */ cs = zsc->zsc_cs[0]; s = splhigh(); /* interrupt vector */ zs_write_reg(cs, 2, zs_init_reg[2]); /* master interrupt control (enable) */ zs_write_reg(cs, 9, zs_init_reg[9]); splx(s); }
static void at91dbgu_attach(device_t parent, device_t self, void *aux) { struct at91dbgu_softc *sc = device_private(self); struct at91bus_attach_args *sa = aux; struct tty *tp; printf("\n"); sc->sc_dev = self; bus_space_map(sa->sa_iot, sa->sa_addr, sa->sa_size, 0, &sc->sc_ioh); sc->sc_iot = sa->sa_iot; sc->sc_hwbase = sa->sa_addr; DBGUREG(DBGU_IDR) = -1; at91_intr_establish(sa->sa_pid, IPL_SERIAL, INTR_HIGH_LEVEL, dbgu_intr, sc); DBGU_INIT(AT91_MSTCLK, 115200U); if (sc->sc_iot == dbgu_cn_sc.sc_iot && sc->sc_hwbase == dbgu_cn_sc.sc_hwbase) { dbgu_cn_sc.sc_attached = 1; /* Make sure the console is always "hardwired". */ delay(10000); /* wait for output to finish */ SET(sc->sc_hwflags, COM_HW_CONSOLE); SET(sc->sc_swflags, TIOCFLAG_SOFTCAR); SET(sc->sc_ier, DBGU_INT_RXRDY); DBGUREG(DBGU_IER) = DBGU_INT_RXRDY; // @@@@@ } tp = tty_alloc(); tp->t_oproc = at91dbgu_start; tp->t_param = at91dbgu_param; tp->t_hwiflow = at91dbgu_hwiflow; sc->sc_tty = tp; sc->sc_rbuf = malloc(AT91DBGU_RING_SIZE << 1, M_DEVBUF, M_NOWAIT); sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf; sc->sc_rbavail = AT91DBGU_RING_SIZE; if (sc->sc_rbuf == NULL) { printf("%s: unable to allocate ring buffer\n", device_xname(sc->sc_dev)); return; } sc->sc_ebuf = sc->sc_rbuf + (AT91DBGU_RING_SIZE << 1); sc->sc_tbc = 0; tty_attach(tp); if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { int maj; /* locate the major number */ maj = cdevsw_lookup_major(&at91dbgu_cdevsw); cn_tab->cn_dev = makedev(maj, device_unit(sc->sc_dev)); aprint_normal("%s: console (maj %u min %u cn_dev %#"PRIx64")\n", device_xname(sc->sc_dev), maj, device_unit(sc->sc_dev), cn_tab->cn_dev); } sc->sc_si = softint_establish(SOFTINT_SERIAL, at91dbgu_soft, sc); #ifdef RND_COM rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), RND_TYPE_TTY, 0); #endif /* if there are no enable/disable functions, assume the device is always enabled */ if (!sc->enable) sc->enabled = 1; /* XXX configure register */ /* xxx_config(sc) */ SET(sc->sc_hwflags, COM_HW_DEV_OK); }
static void xennet_xenbus_attach(device_t parent, device_t self, void *aux) { struct xennet_xenbus_softc *sc = device_private(self); struct xenbusdev_attach_args *xa = aux; struct ifnet *ifp = &sc->sc_ethercom.ec_if; int err; RING_IDX i; char *val, *e, *p; int s; extern int ifqmaxlen; /* XXX */ #ifdef XENNET_DEBUG char **dir; int dir_n = 0; char id_str[20]; #endif aprint_normal(": Xen Virtual Network Interface\n"); sc->sc_dev = self; #ifdef XENNET_DEBUG printf("path: %s\n", xa->xa_xbusd->xbusd_path); snprintf(id_str, sizeof(id_str), "%d", xa->xa_id); err = xenbus_directory(NULL, "device/vif", id_str, &dir_n, &dir); if (err) { aprint_error_dev(self, "xenbus_directory err %d\n", err); } else { printf("%s/\n", xa->xa_xbusd->xbusd_path); for (i = 0; i < dir_n; i++) { printf("\t/%s", dir[i]); err = xenbus_read(NULL, xa->xa_xbusd->xbusd_path, dir[i], NULL, &val); if (err) { aprint_error_dev(self, "xenbus_read err %d\n", err); } else { printf(" = %s\n", val); free(val, M_DEVBUF); } } } #endif /* XENNET_DEBUG */ sc->sc_xbusd = xa->xa_xbusd; sc->sc_xbusd->xbusd_otherend_changed = xennet_backend_changed; /* initialize free RX and RX request lists */ SLIST_INIT(&sc->sc_txreq_head); for (i = 0; i < NET_TX_RING_SIZE; i++) { sc->sc_txreqs[i].txreq_id = i; SLIST_INSERT_HEAD(&sc->sc_txreq_head, &sc->sc_txreqs[i], txreq_next); } SLIST_INIT(&sc->sc_rxreq_head); s = splvm(); for (i = 0; i < NET_RX_RING_SIZE; i++) { struct xennet_rxreq *rxreq = &sc->sc_rxreqs[i]; rxreq->rxreq_id = i; rxreq->rxreq_sc = sc; rxreq->rxreq_va = uvm_km_alloc(kernel_map, PAGE_SIZE, PAGE_SIZE, UVM_KMF_WIRED | UVM_KMF_ZERO); if (rxreq->rxreq_va == 0) break; if (!pmap_extract(pmap_kernel(), rxreq->rxreq_va, &rxreq->rxreq_pa)) panic("%s: no pa for mapped va ?", device_xname(self)); rxreq->rxreq_gntref = GRANT_INVALID_REF; SLIST_INSERT_HEAD(&sc->sc_rxreq_head, rxreq, rxreq_next); } splx(s); sc->sc_free_rxreql = i; if (sc->sc_free_rxreql == 0) { aprint_error_dev(self, "failed to allocate rx memory\n"); return; } /* read mac address */ err = xenbus_read(NULL, xa->xa_xbusd->xbusd_path, "mac", NULL, &val); if (err) { aprint_error_dev(self, "can't read mac address, err %d\n", err); return; } /* read mac address */ for (i = 0, p = val; i < 6; i++) { sc->sc_enaddr[i] = strtoul(p, &e, 16); if ((e[0] == '\0' && i != 5) && e[0] != ':') { aprint_error_dev(self, "%s is not a valid mac address\n", val); free(val, M_DEVBUF); return; } p = &e[1]; } free(val, M_DEVBUF); aprint_normal_dev(self, "MAC address %s\n", ether_sprintf(sc->sc_enaddr)); /* Initialize ifnet structure and attach interface */ strlcpy(ifp->if_xname, device_xname(self), IFNAMSIZ); ifp->if_softc = sc; ifp->if_start = xennet_start; ifp->if_ioctl = xennet_ioctl; ifp->if_watchdog = xennet_watchdog; ifp->if_init = xennet_init; ifp->if_stop = xennet_stop; ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_NOTRAILERS|IFF_MULTICAST; ifp->if_timer = 0; ifp->if_snd.ifq_maxlen = max(ifqmaxlen, NET_TX_RING_SIZE * 2); ifp->if_capabilities = IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_UDPv4_Tx; IFQ_SET_READY(&ifp->if_snd); if_attach(ifp); ether_ifattach(ifp, sc->sc_enaddr); sc->sc_softintr = softint_establish(SOFTINT_NET, xennet_softstart, sc); if (sc->sc_softintr == NULL) panic("%s: can't establish soft interrupt", device_xname(self)); /* initialise shared structures and tell backend that we are ready */ xennet_xenbus_resume(sc); }
/* * Attach a found zs. */ static void zs_attach(device_t parent, device_t self, void *aux) { struct zsc_softc *zsc = device_private(self); struct intio_attach_args *ia = aux; struct zsc_attach_args zsc_args; volatile struct zschan *zc; struct zs_chanstate *cs; int r, s, zs_unit, channel; zsc->zsc_dev = self; aprint_normal("\n"); zs_unit = device_unit(self); zsc->zsc_addr = (void *)ia->ia_addr; ia->ia_size = 8; r = intio_map_allocate_region(parent, ia, INTIO_MAP_ALLOCATE); #ifdef DIAGNOSTIC if (r) panic("zs: intio IO map corruption"); #endif /* * Initialize software state for each channel. */ for (channel = 0; channel < 2; channel++) { device_t child; zsc_args.channel = channel; zsc_args.hwflags = 0; cs = &zsc->zsc_cs_store[channel]; zsc->zsc_cs[channel] = cs; zs_lock_init(cs); cs->cs_channel = channel; cs->cs_private = NULL; cs->cs_ops = &zsops_null; cs->cs_brg_clk = PCLK / 16; if (channel == 0) zc = (volatile void *)IIOV(&zsc->zsc_addr->zs_chan_a); else zc = (volatile void *)IIOV(&zsc->zsc_addr->zs_chan_b); cs->cs_reg_csr = &zc->zc_csr; cs->cs_reg_data = &zc->zc_data; zs_init_reg[2] = ia->ia_intr; memcpy(cs->cs_creg, zs_init_reg, 16); memcpy(cs->cs_preg, zs_init_reg, 16); if (zc == conschan) { zsc_args.hwflags |= ZS_HWFLAG_CONSOLE; cs->cs_defspeed = zs_get_speed(cs); cs->cs_defcflag = zscn_def_cflag; } else { cs->cs_defspeed = 9600; cs->cs_defcflag = zs_def_cflag; } /* Make these correspond to cs_defcflag (-crtscts) */ cs->cs_rr0_dcd = ZSRR0_DCD; cs->cs_rr0_cts = 0; cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS; cs->cs_wr5_rts = 0; /* * Clear the master interrupt enable. * The INTENA is common to both channels, * so just do it on the A channel. */ if (channel == 0) { s = splzs(); zs_write_reg(cs, 9, 0); splx(s); } /* * Look for a child driver for this channel. * The child attach will setup the hardware. */ child = config_found(self, (void *)&zsc_args, zs_print); #if ZSTTY > 0 if (zc == conschan && ((child && strcmp(device_xname(child), "zstty0")) || child == NULL)) /* XXX */ panic("%s: console device mismatch", __func__); #endif if (child == NULL) { /* No sub-driver. Just reset it. */ uint8_t reset = (channel == 0) ? ZSWR9_A_RESET : ZSWR9_B_RESET; s = splzs(); zs_write_reg(cs, 9, reset); splx(s); } } /* * Now safe to install interrupt handlers. */ if (intio_intr_establish(ia->ia_intr, "zs", zshard, zsc)) panic("%s: interrupt vector busy", __func__); zsc->zsc_softintr_cookie = softint_establish(SOFTINT_SERIAL, (void (*)(void *))zsc_intr_soft, zsc); /* XXX; evcnt_attach() ? */ /* * Set the master interrupt enable and interrupt vector. * (common to both channels, do it on A) */ cs = zsc->zsc_cs[0]; s = splzs(); /* interrupt vector */ zs_write_reg(cs, 2, ia->ia_intr); /* master interrupt control (enable) */ zs_write_reg(cs, 9, zs_init_reg[9]); splx(s); }
void bppattach(device_t parent, device_t self, void *aux) { struct bpp_softc *dsc = device_private(self); struct lsi64854_softc *sc = &dsc->sc_lsi64854; struct sbus_softc *sbsc = device_private(parent); struct sbus_attach_args *sa = aux; int burst, sbusburst; int node; sc->sc_dev = self; selinit(&dsc->sc_rsel); selinit(&dsc->sc_wsel); dsc->sc_sih = softint_establish(SOFTINT_CLOCK, bppsoftintr, dsc); sc->sc_bustag = sa->sa_bustag; sc->sc_dmatag = sa->sa_dmatag; node = sa->sa_node; /* Map device registers */ if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset, sa->sa_size, 0, &sc->sc_regs) != 0) { aprint_error(": cannot map registers\n"); return; } /* * Get transfer burst size from PROM and plug it into the * controller registers. This is needed on the Sun4m; do * others need it too? */ sbusburst = sbsc->sc_burst; if (sbusburst == 0) sbusburst = SBUS_BURST_32 - 1; /* 1->16 */ burst = prom_getpropint(node, "burst-sizes", -1); if (burst == -1) /* take SBus burst sizes */ burst = sbusburst; /* Clamp at parent's burst sizes */ burst &= sbusburst; sc->sc_burst = (burst & SBUS_BURST_32) ? 32 : (burst & SBUS_BURST_16) ? 16 : 0; /* Join the Sbus device family */ dsc->sc_sd.sd_reset = NULL; sbus_establish(&dsc->sc_sd, self); /* Initialize the DMA channel */ sc->sc_channel = L64854_CHANNEL_PP; lsi64854_attach(sc); /* Establish interrupt handler */ if (sa->sa_nintr) { sc->sc_intrchain = bppintr; sc->sc_intrchainarg = dsc; (void)bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_TTY, bppintr, sc); } /* Allocate buffer XXX - should actually use dmamap_uio() */ dsc->sc_bufsz = 1024; dsc->sc_buf = malloc(dsc->sc_bufsz, M_DEVBUF, M_NOWAIT); /* XXX read default state */ { bus_space_handle_t h = sc->sc_regs; struct hwstate *hw = &dsc->sc_hwdefault; int ack_rate = sa->sa_frequency / 1000000; hw->hw_hcr = bus_space_read_2(sc->sc_bustag, h, L64854_REG_HCR); hw->hw_ocr = bus_space_read_2(sc->sc_bustag, h, L64854_REG_OCR); hw->hw_tcr = bus_space_read_1(sc->sc_bustag, h, L64854_REG_TCR); hw->hw_or = bus_space_read_1(sc->sc_bustag, h, L64854_REG_OR); DPRINTF(("bpp: hcr %x ocr %x tcr %x or %x\n", hw->hw_hcr, hw->hw_ocr, hw->hw_tcr, hw->hw_or)); /* Set these to sane values */ hw->hw_hcr = ((ack_rate<<BPP_HCR_DSS_SHFT)&BPP_HCR_DSS_MASK) | ((ack_rate<<BPP_HCR_DSW_SHFT)&BPP_HCR_DSW_MASK); hw->hw_ocr |= BPP_OCR_ACK_OP; } }