void wskbd_input(struct device *dev, u_int type, int value) { struct wskbd_softc *sc = (struct wskbd_softc *)dev; #if NWSDISPLAY > 0 int num; #endif #if NWSDISPLAY > 0 if (sc->sc_repeating) { sc->sc_repeating = 0; timeout_del(&sc->sc_repeat_ch); } /* * If /dev/wskbdN is not connected in event mode translate and * send upstream. */ if (sc->sc_translating) { #ifdef HAVE_BURNER_SUPPORT if (type == WSCONS_EVENT_KEY_DOWN && sc->sc_displaydv != NULL) wsdisplay_burn(sc->sc_displaydv, WSDISPLAY_BURN_KBD); #endif num = wskbd_translate(sc->id, type, value); if (num > 0) { if (sc->sc_displaydv != NULL) { #ifdef HAVE_SCROLLBACK_SUPPORT /* XXX - Shift_R+PGUP(release) emits PrtSc */ if (sc->id->t_symbols[0] != KS_Print_Screen) { wsscrollback(sc->sc_displaydv, WSDISPLAY_SCROLL_RESET); } #endif wsdisplay_kbdinput(sc->sc_displaydv, sc->id->t_keymap.layout, sc->id->t_symbols, num); } if (sc->sc_keyrepeat_data.del1 != 0) { sc->sc_repeating = num; timeout_add_msec(&sc->sc_repeat_ch, sc->sc_keyrepeat_data.del1); } } return; } #endif wskbd_deliver_event(sc, type, value); #if NWSDISPLAY > 0 /* Repeat key presses if enabled. */ if (type == WSCONS_EVENT_KEY_DOWN && sc->sc_keyrepeat_data.del1 != 0) { sc->sc_repeat_type = type; sc->sc_repeat_value = value; sc->sc_repeating = 1; timeout_add_msec(&sc->sc_repeat_ch, sc->sc_keyrepeat_data.del1); } #endif }
void panel_repeat(void *v) { struct panel_softc *sc = (struct panel_softc *)v; uint8_t reg; reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh, 0); #if NAUDIO > 0 && NWSKBD > 0 /* * Volume button autorepeat. */ if (sys_config.system_subtype == IP22_INDY) panel_volume_adjust(sc, reg); #endif if (hpc_is_intr_pending(sc->sc_irq)) { /* * Keep acking everything to get the interrupt finally * unlatched. */ bus_space_write_1(sc->sc_iot, sc->sc_ioh, 0, IOC_PANEL_POWER_STATE | IOC_PANEL_POWER_IRQ | IOC_PANEL_VDOWN_IRQ | IOC_PANEL_VDOWN_HOLD | IOC_PANEL_VUP_IRQ | IOC_PANEL_VUP_HOLD); bus_space_barrier(sc->sc_iot, sc->sc_ioh, 0, 1, BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); timeout_add_msec(&sc->sc_repeat_tmo, PANEL_REPEAT_NEXT); } else { hpc_intr_enable(sc->sc_ih); } }
/* * octeon_eth_tick_free * * => garbage collect send gather buffer / mbuf * => called at softclock */ void octeon_eth_tick_free(void *arg) { struct octeon_eth_softc *sc = arg; int timo; int s; s = splnet(); /* XXX */ if (sc->sc_soft_req_cnt > 0) { octeon_eth_send_queue_flush_prefetch(sc); octeon_eth_send_queue_flush_fetch(sc); octeon_eth_send_queue_flush(sc); octeon_eth_send_queue_flush_sync(sc); } /* XXX */ /* XXX ??? */ timo = hz - (100 * sc->sc_ext_callback_cnt); if (timo < 10) timo = 10; timeout_add_msec(&sc->sc_tick_free_ch, 1000 * timo / hz); /* XXX */ splx(s); }
void wskbd_repeat(void *v) { struct wskbd_softc *sc = (struct wskbd_softc *)v; int s = spltty(); if (sc->sc_repeating == 0) { /* * race condition: a "key up" event came in when wskbd_repeat() * was already called but not yet spltty()'d */ splx(s); return; } if (sc->sc_translating) { /* deliver keys */ if (sc->sc_displaydv != NULL) wsdisplay_kbdinput(sc->sc_displaydv, sc->id->t_keymap.layout, sc->id->t_symbols, sc->sc_repeating); } else { /* queue event */ wskbd_deliver_event(sc, sc->sc_repeat_type, sc->sc_repeat_value); } if (sc->sc_keyrepeat_data.delN != 0) timeout_add_msec(&sc->sc_repeat_ch, sc->sc_keyrepeat_data.delN); splx(s); }
void rdrand(void *v) { struct timeout *tmo = v; extern int has_rdrand; extern int has_rdseed; uint32_t r; uint8_t valid; int i; if (has_rdrand == 0 && has_rdseed == 0) return; for (i = 0; i < 4; i++) { if (has_rdseed) __asm volatile( "rdseed %0\n\t" "setc %1\n" : "=r" (r), "=qm" (valid) ); if (has_rdseed == 0 || valid == 0) __asm volatile( "rdrand %0\n\t" "setc %1\n" : "=r" (r), "=qm" (valid) ); if (valid) add_true_randomness(r); } if (tmo) timeout_add_msec(tmo, 10); }
void ykbec_bell(void *arg, u_int pitch, u_int period, u_int volume, int poll) { struct ykbec_softc *sc = (struct ykbec_softc *)arg; int bctrl; int s; s = spltty(); bctrl = ykbec_read(sc, REG_BEEP_CONTROL); if (volume == 0 || timeout_pending(&sc->sc_bell_tmo)) { timeout_del(&sc->sc_bell_tmo); /* inline ykbec_bell_stop(arg); */ ykbec_write(sc, REG_BEEP_CONTROL, bctrl & ~BEEP_ENABLE); } if (volume != 0) { ykbec_write(sc, REG_BEEP_CONTROL, bctrl | BEEP_ENABLE); if (poll) { delay(period * 1000); ykbec_write(sc, REG_BEEP_CONTROL, bctrl & ~BEEP_ENABLE); } else { timeout_add_msec(&sc->sc_bell_tmo, period); } } splx(s); }
/** * drm_vblank_put - give up ownership of vblank events * @dev: DRM device * @crtc: which counter to give up * * Release ownership of a given vblank counter, turning off interrupts * if possible. Disable interrupts after drm_vblank_offdelay milliseconds. */ void drm_vblank_put(struct drm_device *dev, int crtc) { BUG_ON(atomic_read(&dev->vblank_refcount[crtc]) == 0); /* Last user schedules interrupt disable */ if (atomic_dec_and_test(&dev->vblank_refcount[crtc]) && (drm_vblank_offdelay > 0)) timeout_add_msec(&dev->vblank_disable_timer, drm_vblank_offdelay); }
int panel_intr(void *v) { struct panel_softc *sc = (struct panel_softc *)v; uint8_t reg, ack; extern int allowpowerdown; reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh, 0); ack = IOC_PANEL_POWER_STATE; if (sys_config.system_subtype == IP22_INDIGO2 || (reg & IOC_PANEL_POWER_IRQ) == 0) ack |= IOC_PANEL_POWER_IRQ; if (sys_config.system_subtype == IP22_INDY) { if ((reg & IOC_PANEL_VDOWN_IRQ) == 0) ack |= IOC_PANEL_VDOWN_IRQ; if ((reg & IOC_PANEL_VUP_IRQ) == 0) ack |= IOC_PANEL_VUP_IRQ; } bus_space_write_1(sc->sc_iot, sc->sc_ioh, 0, ack); bus_space_barrier(sc->sc_iot, sc->sc_ioh, 0, 1, BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); /* * Panel interrupts are latched for about 300 msec after being * acked, and not until all buttons are depressed. * We need to temporary disable the interrupt and switch to polling, * until the interrupt can be enabled again. */ hpc_intr_disable(sc->sc_ih); /* * If the power button is down, try and issue a shutdown immediately * (if allowed). */ if (sys_config.system_subtype == IP22_INDIGO2 || (reg & IOC_PANEL_POWER_IRQ) == 0) { if (allowpowerdown == 1) { allowpowerdown = 0; prsignal(initprocess, SIGUSR2); } } #if NAUDIO > 0 && NWSKBD > 0 /* * If any of the volume buttons is down, update volume. */ if (sys_config.system_subtype == IP22_INDY) panel_volume_adjust(sc, reg); #endif timeout_add_msec(&sc->sc_repeat_tmo, PANEL_REPEAT_FIRST); return 1; }
void sunkbd_input(struct sunkbd_softc *sc, u_int8_t *buf, u_int buflen) { u_int type; int value; int s; if (sc->sc_wskbddev == NULL) return; /* why bother */ #ifdef WSDISPLAY_COMPAT_RAWKBD if (sc->sc_rawkbd) { u_char rbuf[SUNKBD_MAX_INPUT_SIZE * 2]; int c, rlen, npress; timeout_del(&sc->sc_rawrepeat_tmo); npress = rlen = 0; while (buflen-- != 0) { (*sc->sc_decode)(*buf++, &type, &value); c = sunkbd_rawmap[value]; if (c == RAWKEY_Null) continue; /* fake extended scancode if necessary */ if (c & 0x80) rbuf[rlen++] = 0xe0; rbuf[rlen] = c & 0x7f; if (type == WSCONS_EVENT_KEY_UP) rbuf[rlen] |= 0x80; else { /* remember down keys for autorepeat */ if (c & 0x80) sc->sc_rep[npress++] = 0xe0; sc->sc_rep[npress++] = c & 0x7f; } rlen++; } s = spltty(); wskbd_rawinput(sc->sc_wskbddev, rbuf, rlen); splx(s); sc->sc_nrep = npress; if (npress != 0) timeout_add_msec(&sc->sc_rawrepeat_tmo, REP_DELAY1); } else #endif { s = spltty(); while (buflen-- != 0) { (*sc->sc_decode)(*buf++, &type, &value); wskbd_input(sc->sc_wskbddev, type, value); } splx(s); } }
void sunkbd_rawrepeat(void *v) { struct sunkbd_softc *sc = v; int s; s = spltty(); wskbd_rawinput(sc->sc_wskbddev, sc->sc_rep, sc->sc_nrep); splx(s); timeout_add_msec(&sc->sc_rawrepeat_tmo, REP_DELAYN); }
void pffasttimo(void *arg) { struct timeout *to = (struct timeout *)arg; struct domain *dp; struct protosw *pr; for (dp = domains; dp; dp = dp->dom_next) for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) if (pr->pr_fasttimo) (*pr->pr_fasttimo)(); timeout_add_msec(to, 200); }
void octrng_rnd(void *arg) { struct octrng_softc *sc = arg; uint64_t value; value = bus_space_read_8(sc->sc_iot, sc->sc_ioh, OCTRNG_ENTROPY_REG); DPRINTF(("%#llX ", value)); /* WARNING: very verbose */ add_true_randomness(value); timeout_add_msec(&sc->sc_to, 10); }
/* * Send an EAPOL-Key frame to node `ni'. If MIC or encryption is required, * the PTK must be passed (otherwise it can be set to NULL.) */ int ieee80211_send_eapol_key(struct ieee80211com *ic, struct mbuf *m, struct ieee80211_node *ni, const struct ieee80211_ptk *ptk) { struct ifnet *ifp = &ic->ic_if; struct ether_header *eh; struct ieee80211_eapol_key *key; u_int16_t info; int s, len, error; M_PREPEND(m, sizeof(struct ether_header), M_DONTWAIT); if (m == NULL) return ENOMEM; /* no need to m_pullup here (ok by construction) */ eh = mtod(m, struct ether_header *); eh->ether_type = htons(ETHERTYPE_PAE); IEEE80211_ADDR_COPY(eh->ether_shost, ic->ic_myaddr); IEEE80211_ADDR_COPY(eh->ether_dhost, ni->ni_macaddr); key = (struct ieee80211_eapol_key *)&eh[1]; key->version = EAPOL_VERSION; key->type = EAPOL_KEY; key->desc = (ni->ni_rsnprotos == IEEE80211_PROTO_RSN) ? EAPOL_KEY_DESC_IEEE80211 : EAPOL_KEY_DESC_WPA; info = BE_READ_2(key->info); /* use V3 descriptor if KDF is SHA256-based */ if (ieee80211_is_sha256_akm(ni->ni_rsnakms)) info |= EAPOL_KEY_DESC_V3; /* use V2 descriptor if pairwise or group cipher is CCMP */ else if (ni->ni_rsncipher == IEEE80211_CIPHER_CCMP || ni->ni_rsngroupcipher == IEEE80211_CIPHER_CCMP) info |= EAPOL_KEY_DESC_V2; else info |= EAPOL_KEY_DESC_V1; BE_WRITE_2(key->info, info); len = m->m_len - sizeof(struct ether_header); BE_WRITE_2(key->paylen, len - sizeof(*key)); BE_WRITE_2(key->len, len - 4); #ifndef IEEE80211_STA_ONLY if (info & EAPOL_KEY_ENCRYPTED) { if (ni->ni_rsnprotos == IEEE80211_PROTO_WPA) { /* clear "Encrypted" bit for WPA */ info &= ~EAPOL_KEY_ENCRYPTED; BE_WRITE_2(key->info, info); } ieee80211_eapol_key_encrypt(ic, key, ptk->kek); if ((info & EAPOL_KEY_VERSION_MASK) != EAPOL_KEY_DESC_V1) { /* AES Key Wrap adds 8 bytes + padding */ m->m_pkthdr.len = m->m_len = sizeof(*eh) + 4 + BE_READ_2(key->len); } } #endif if (info & EAPOL_KEY_KEYMIC) ieee80211_eapol_key_mic(key, ptk->kck); len = m->m_pkthdr.len; s = splnet(); #ifndef IEEE80211_STA_ONLY /* start a 100ms timeout if an answer is expected from supplicant */ if (info & EAPOL_KEY_KEYACK) timeout_add_msec(&ni->ni_eapol_to, 100); #endif IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error); if (error == 0) { ifp->if_obytes += len; if ((ifp->if_flags & IFF_OACTIVE) == 0) (*ifp->if_start)(ifp); } splx(s); return error; }
int vnet_rx_intr(void *arg) { struct vnet_softc *sc = arg; struct ldc_conn *lc = &sc->sc_lc; uint64_t rx_head, rx_tail, rx_state; struct ldc_pkt *lp; int err; err = hv_ldc_rx_get_state(lc->lc_id, &rx_head, &rx_tail, &rx_state); if (err == H_EINVAL) return (0); if (err != H_EOK) { printf("hv_ldc_rx_get_state %d\n", err); return (0); } if (rx_state != lc->lc_rx_state) { switch (rx_state) { case LDC_CHANNEL_DOWN: DPRINTF(("Rx link down\n")); lc->lc_tx_seqid = 0; lc->lc_state = 0; lc->lc_reset(lc); break; case LDC_CHANNEL_UP: DPRINTF(("Rx link up\n")); timeout_add_msec(&sc->sc_handshake_to, 500); break; case LDC_CHANNEL_RESET: DPRINTF(("Rx link reset\n")); lc->lc_tx_seqid = 0; lc->lc_state = 0; lc->lc_reset(lc); timeout_add_msec(&sc->sc_handshake_to, 500); break; } lc->lc_rx_state = rx_state; return (1); } if (rx_head == rx_tail) return (0); lp = (struct ldc_pkt *)(lc->lc_rxq->lq_va + rx_head); switch (lp->type) { case LDC_CTRL: ldc_rx_ctrl(lc, lp); break; case LDC_DATA: ldc_rx_data(lc, lp); break; default: DPRINTF(("%0x02/%0x02/%0x02\n", lp->type, lp->stype, lp->ctrl)); ldc_reset(lc); break; } if (lc->lc_state == 0) return (1); rx_head += sizeof(*lp); rx_head &= ((lc->lc_rxq->lq_nentries * sizeof(*lp)) - 1); err = hv_ldc_rx_set_qhead(lc->lc_id, rx_head); if (err != H_EOK) printf("%s: hv_ldc_rx_set_qhead %d\n", __func__, err); return (1); }
void ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments) { struct scb *scb; struct scsi_xfer *xs; struct ahd_softc *ahd; struct ahd_initiator_tinfo *tinfo; struct ahd_tmode_tstate *tstate; u_int mask; int s; scb = (struct scb *)arg; xs = scb->xs; xs->error = CAM_REQ_INPROG; xs->status = 0; ahd = (struct ahd_softc *)xs->sc_link->adapter_softc; if (nsegments != 0) { void *sg; int op; u_int i; ahd_setup_data_scb(ahd, scb); /* Copy the segments into our SG list */ for (i = nsegments, sg = scb->sg_list; i > 0; i--) { sg = ahd_sg_setup(ahd, scb, sg, dm_segs->ds_addr, dm_segs->ds_len, /*last*/i == 1); dm_segs++; } if ((xs->flags & SCSI_DATA_IN) != 0) op = BUS_DMASYNC_PREREAD; else op = BUS_DMASYNC_PREWRITE; bus_dmamap_sync(ahd->parent_dmat, scb->dmamap, 0, scb->dmamap->dm_mapsize, op); } ahd_lock(ahd, &s); /* * Last time we need to check if this SCB needs to * be aborted. */ if (xs->flags & ITSDONE) { if (nsegments != 0) bus_dmamap_unload(ahd->parent_dmat, scb->dmamap); ahd_free_scb(ahd, scb); ahd_unlock(ahd, &s); return; } tinfo = ahd_fetch_transinfo(ahd, SCSIID_CHANNEL(ahd, scb->hscb->scsiid), SCSIID_OUR_ID(scb->hscb->scsiid), SCSIID_TARGET(ahd, scb->hscb->scsiid), &tstate); mask = SCB_GET_TARGET_MASK(ahd, scb); if ((tstate->discenable & mask) != 0) scb->hscb->control |= DISCENB; if ((tstate->tagenable & mask) != 0) scb->hscb->control |= TAG_ENB; if ((tinfo->curr.ppr_options & MSG_EXT_PPR_PROT_IUS) != 0) { scb->flags |= SCB_PACKETIZED; if (scb->hscb->task_management != 0) scb->hscb->control &= ~MK_MESSAGE; } if ((tstate->auto_negotiate & mask) != 0) { scb->flags |= SCB_AUTO_NEGOTIATE; scb->hscb->control |= MK_MESSAGE; } /* XXX with ahc there was some bus_dmamap_sync(PREREAD|PREWRITE); */ LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links); if (!(xs->flags & SCSI_POLL)) timeout_add_msec(&xs->stimeout, xs->timeout); scb->flags |= SCB_ACTIVE; if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) { /* Define a mapping from our tag to the SCB. */ ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb; ahd_pause(ahd); ahd_set_scbptr(ahd, SCB_GET_TAG(scb)); ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG); ahd_unpause(ahd); } else { ahd_queue_scb(ahd, scb); } if (!(xs->flags & SCSI_POLL)) { int target = xs->sc_link->target; int lun = SCB_GET_LUN(scb); if (ahd->inited_target[target] == 0) { struct ahd_devinfo devinfo; ahd_adapter_req_set_xfer_mode(ahd, scb); ahd_compile_devinfo(&devinfo, ahd->our_id, target, lun, 'A', /*XXX milos*/ROLE_UNKNOWN); ahd_scb_devinfo(ahd, &devinfo, scb); ahd_update_neg_request(ahd, &devinfo, tstate, tinfo, AHD_NEG_IF_NON_ASYNC); ahd->inited_target[target] = 1; } ahd_unlock(ahd, &s); return; } /* * If we can't use interrupts, poll for completion */ SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_poll\n")); do { if (ahd_poll(ahd, xs->timeout)) { if (!(xs->flags & SCSI_SILENT)) printf("cmd fail\n"); ahd_timeout(scb); break; } } while (!(xs->flags & ITSDONE)); ahd_unlock(ahd, &s); }
/* * Called from the controller. */ int fdintr(struct fdc_softc *fdc) { #define st0 fdc->sc_status[0] #define cyl fdc->sc_status[1] struct fd_softc *fd; struct buf *bp; bus_space_tag_t iot = fdc->sc_iot; bus_space_handle_t ioh = fdc->sc_ioh; bus_space_handle_t ioh_ctl = fdc->sc_ioh_ctl; int read, head, sec, i, nblks, cylin; struct fd_type *type; struct fd_formb *finfo = NULL; int fd_bsize; loop: /* Is there a transfer to this drive? If not, deactivate drive. */ fd = TAILQ_FIRST(&fdc->sc_link.fdlink.sc_drives); if (fd == NULL) { fdc->sc_state = DEVIDLE; return 1; } fd_bsize = FD_BSIZE(fd); bp = fd->sc_bp; if (bp == NULL) { fd->sc_ops = 0; TAILQ_REMOVE(&fdc->sc_link.fdlink.sc_drives, fd, sc_drivechain); goto loop; } if (bp->b_flags & B_FORMAT) finfo = (struct fd_formb *)bp->b_data; cylin = ((bp->b_blkno * DEV_BSIZE) + (bp->b_bcount - bp->b_resid)) / (fd_bsize * fd->sc_type->seccyl); switch (fdc->sc_state) { case DEVIDLE: fdc->sc_errors = 0; fd->sc_skip = 0; fd->sc_bcount = bp->b_bcount; fd->sc_blkno = bp->b_blkno / (fd_bsize / DEV_BSIZE); timeout_del(&fd->fd_motor_off_to); if ((fd->sc_flags & FD_MOTOR_WAIT) != 0) { fdc->sc_state = MOTORWAIT; return 1; } if ((fd->sc_flags & FD_MOTOR) == 0) { /* Turn on the motor, being careful about pairing. */ struct fd_softc *ofd = fdc->sc_link.fdlink.sc_fd[fd->sc_drive ^ 1]; if (ofd && ofd->sc_flags & FD_MOTOR) { timeout_del(&ofd->fd_motor_off_to); ofd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT); } fd->sc_flags |= FD_MOTOR | FD_MOTOR_WAIT; fd_set_motor(fdc, 0); fdc->sc_state = MOTORWAIT; /* Allow .25s for motor to stabilize. */ timeout_add_msec(&fd->fd_motor_on_to, 250); return 1; } /* Make sure the right drive is selected. */ fd_set_motor(fdc, 0); /* FALLTHROUGH */ case DOSEEK: doseek: if (fd->sc_cylin == cylin) goto doio; out_fdc(iot, ioh, NE7CMD_SPECIFY);/* specify command */ out_fdc(iot, ioh, fd->sc_type->steprate); out_fdc(iot, ioh, 6); /* XXX head load time == 6ms */ out_fdc(iot, ioh, NE7CMD_SEEK); /* seek function */ out_fdc(iot, ioh, fd->sc_drive); /* drive number */ out_fdc(iot, ioh, cylin * fd->sc_type->step); fd->sc_cylin = -1; fdc->sc_state = SEEKWAIT; fd->sc_dk.dk_seek++; disk_busy(&fd->sc_dk); timeout_add_sec(&fd->fdtimeout_to, 4); return 1; case DOIO: doio: type = fd->sc_type; if (finfo) fd->sc_skip = (char *)&(finfo->fd_formb_cylno(0)) - (char *)finfo; sec = fd->sc_blkno % type->seccyl; nblks = type->seccyl - sec; nblks = min(nblks, fd->sc_bcount / fd_bsize); nblks = min(nblks, FDC_MAXIOSIZE / fd_bsize); fd->sc_nblks = nblks; fd->sc_nbytes = finfo ? bp->b_bcount : nblks * fd_bsize; head = sec / type->sectrac; sec -= head * type->sectrac; #ifdef DIAGNOSTIC {int block; block = (fd->sc_cylin * type->heads + head) * type->sectrac + sec; if (block != fd->sc_blkno) { panic("fdintr: block %d != blkno %llu", block, fd->sc_blkno); }} #endif read = bp->b_flags & B_READ ? DMAMODE_READ : DMAMODE_WRITE; isadma_start(bp->b_data + fd->sc_skip, fd->sc_nbytes, fdc->sc_drq, read); bus_space_write_1(iot, ioh_ctl, fdctl, type->rate); #ifdef FD_DEBUG printf("fdintr: %s drive %d track %d head %d sec %d nblks %d\n", read ? "read" : "write", fd->sc_drive, fd->sc_cylin, head, sec, nblks); #endif if (finfo) { /* formatting */ if (out_fdc(iot, ioh, NE7CMD_FORMAT) < 0) { fdc->sc_errors = 4; fdretry(fd); goto loop; } out_fdc(iot, ioh, (head << 2) | fd->sc_drive); out_fdc(iot, ioh, finfo->fd_formb_secshift); out_fdc(iot, ioh, finfo->fd_formb_nsecs); out_fdc(iot, ioh, finfo->fd_formb_gaplen); out_fdc(iot, ioh, finfo->fd_formb_fillbyte); } else { if (read) out_fdc(iot, ioh, NE7CMD_READ); /* READ */ else out_fdc(iot, ioh, NE7CMD_WRITE);/* WRITE */ out_fdc(iot, ioh, (head << 2) | fd->sc_drive); out_fdc(iot, ioh, fd->sc_cylin); /* track */ out_fdc(iot, ioh, head); out_fdc(iot, ioh, sec + 1); /* sec +1 */ out_fdc(iot, ioh, type->secsize); /* sec size */ out_fdc(iot, ioh, type->sectrac); /* secs/track */ out_fdc(iot, ioh, type->gap1); /* gap1 size */ out_fdc(iot, ioh, type->datalen); /* data len */ } fdc->sc_state = IOCOMPLETE; disk_busy(&fd->sc_dk); /* allow 2 seconds for operation */ timeout_add_sec(&fd->fdtimeout_to, 2); return 1; /* will return later */ case SEEKWAIT: timeout_del(&fd->fdtimeout_to); fdc->sc_state = SEEKCOMPLETE; /* allow 1/50 second for heads to settle */ timeout_add_msec(&fdc->fdcpseudointr_to, 20); return 1; case SEEKCOMPLETE: disk_unbusy(&fd->sc_dk, 0, 0); /* no data on seek */ /* Make sure seek really happened. */ out_fdc(iot, ioh, NE7CMD_SENSEI); if (fdcresult(fdc) != 2 || (st0 & 0xf8) != 0x20 || cyl != cylin * fd->sc_type->step) { #ifdef FD_DEBUG fdcstatus(&fd->sc_dev, 2, "seek failed"); #endif fdretry(fd); goto loop; } fd->sc_cylin = cylin; goto doio; case IOTIMEDOUT: isadma_abort(fdc->sc_drq); case SEEKTIMEDOUT: case RECALTIMEDOUT: case RESETTIMEDOUT: fdretry(fd); goto loop; case IOCOMPLETE: /* IO DONE, post-analyze */ timeout_del(&fd->fdtimeout_to); disk_unbusy(&fd->sc_dk, (bp->b_bcount - bp->b_resid), (bp->b_flags & B_READ)); if (fdcresult(fdc) != 7 || (st0 & 0xf8) != 0) { isadma_abort(fdc->sc_drq); #ifdef FD_DEBUG fdcstatus(&fd->sc_dev, 7, bp->b_flags & B_READ ? "read failed" : "write failed"); printf("blkno %lld nblks %d\n", (long long)fd->sc_blkno, fd->sc_nblks); #endif fdretry(fd); goto loop; } read = bp->b_flags & B_READ ? DMAMODE_READ : DMAMODE_WRITE; isadma_done(fdc->sc_drq); if (fdc->sc_errors) { diskerr(bp, "fd", "soft error", LOG_PRINTF, fd->sc_skip / fd_bsize, (struct disklabel *)NULL); printf("\n"); fdc->sc_errors = 0; } fd->sc_blkno += fd->sc_nblks; fd->sc_skip += fd->sc_nbytes; fd->sc_bcount -= fd->sc_nbytes; bp->b_resid -= fd->sc_nbytes; if (!finfo && fd->sc_bcount > 0) { cylin = fd->sc_blkno / fd->sc_type->seccyl; goto doseek; } fdfinish(fd, bp); goto loop; case DORESET: /* try a reset, keep motor on */ fd_set_motor(fdc, 1); delay(100); fd_set_motor(fdc, 0); fdc->sc_state = RESETCOMPLETE; timeout_add_msec(&fd->fdtimeout_to, 500); return 1; /* will return later */ case RESETCOMPLETE: timeout_del(&fd->fdtimeout_to); /* clear the controller output buffer */ for (i = 0; i < 4; i++) { out_fdc(iot, ioh, NE7CMD_SENSEI); (void) fdcresult(fdc); } /* FALLTHROUGH */ case DORECAL: out_fdc(iot, ioh, NE7CMD_RECAL); /* recal function */ out_fdc(iot, ioh, fd->sc_drive); fdc->sc_state = RECALWAIT; timeout_add_sec(&fd->fdtimeout_to, 5); return 1; /* will return later */ case RECALWAIT: timeout_del(&fd->fdtimeout_to); fdc->sc_state = RECALCOMPLETE; /* allow 1/30 second for heads to settle */ timeout_add(&fdc->fdcpseudointr_to, hz / 30); return 1; /* will return later */ case RECALCOMPLETE: out_fdc(iot, ioh, NE7CMD_SENSEI); if (fdcresult(fdc) != 2 || (st0 & 0xf8) != 0x20 || cyl != 0) { #ifdef FD_DEBUG fdcstatus(&fd->sc_dev, 2, "recalibrate failed"); #endif fdretry(fd); goto loop; } fd->sc_cylin = 0; goto doseek; case MOTORWAIT: if (fd->sc_flags & FD_MOTOR_WAIT) return 1; /* time's not up yet */ goto doseek; default: fdcstatus(&fd->sc_dev, 0, "stray interrupt"); return 1; } #ifdef DIAGNOSTIC panic("fdintr: impossible"); #endif #undef st0 #undef cyl }