static int atausb_bbb_start(struct ata_request *request) { struct atausb_softc *sc = device_get_softc(device_get_parent(request->parent)); struct ata_channel *ch = device_get_softc(request->parent); sc->timeout = (request->timeout * 1000) + 5000; USETDW(sc->cbw.signature, CBWSIGNATURE); USETDW(sc->cbw.tag, UGETDW(sc->cbw.tag) + 1); USETDW(sc->cbw.transfer_length, request->bytecount); sc->cbw.flags = (request->flags & ATA_R_READ) ? CBWFLAGS_IN : CBWFLAGS_OUT; sc->cbw.lun = ch->unit; sc->cbw.length = 16; bzero(sc->cbw.cdb, 16); bcopy(request->u.atapi.ccb, sc->cbw.cdb, 12); /* XXX SOS */ sc->state = ATAUSB_S_BBB_COMMAND; if (atausb_start(sc, sc->bulkout_pipe, &sc->cbw, sizeof(struct bbb_cbw), 0, sc->transfer[ATAUSB_T_BBB_CBW])) { request->result = EIO; if (atausbdebug) device_printf(request->dev, "cannot setup USB transfer\n"); atausb_bbb_reset(sc); return ATA_OP_FINISHED; } return ATA_OP_CONTINUES; }
usbd_status uplcom_set_line_coding(struct uplcom_softc *sc, usb_cdc_line_state_t *state) { usb_device_request_t req; usbd_status err; DPRINTF(("uplcom_set_line_coding: rate=%d fmt=%d parity=%d bits=%d\n", UGETDW(state->dwDTERate), state->bCharFormat, state->bParityType, state->bDataBits)); if (memcmp(state, &sc->sc_line_state, UCDC_LINE_STATE_LENGTH) == 0) { DPRINTF(("uplcom_set_line_coding: already set\n")); return (USBD_NORMAL_COMPLETION); } req.bmRequestType = UT_WRITE_CLASS_INTERFACE; req.bRequest = UCDC_SET_LINE_CODING; USETW(req.wValue, 0); USETW(req.wIndex, sc->sc_iface_number); USETW(req.wLength, UCDC_LINE_STATE_LENGTH); err = usbd_do_request(sc->sc_udev, &req, state); if (err) { DPRINTF(("uplcom_set_line_coding: failed, err=%s\n", usbd_errstr(err))); return (err); } sc->sc_line_state = *state; return (USBD_NORMAL_COMPLETION); }
/* * Global Item */ void hid_global_item(int tag, uint8_t *buffer, size_t bufsize) { const char *name; uint32_t val = 0; int i; switch (bufsize) { case 1: val = *buffer; break; case 2: val = UGETW(buffer); break; case 4: val = UGETDW(buffer); break; default: break; } switch (tag) { case HID_GLOBAL_ITEM_USAGE_PAGE: for (usage_page = 0, i = 0 ; (size_t)i < bufsize ; i++) usage_page |= (uint32_t)(buffer[i] << (8 * i)); printf("("); if ((name = hid_get_page_name(usage_page)) != NULL) printf("%s", name); else printf("%d", usage_page); printf(")\n"); return; } if (bufsize > 0) { if (relative) printf(": %d", (int32_t)val); else printf(": %u", (uint32_t)val); } printf("\n"); }
/*------------------------------------------------------------------------* * cdce_ncm_init * * Return values: * 0: Success * Else: Failure *------------------------------------------------------------------------*/ static uint8_t cdce_ncm_init(struct cdce_softc *sc) { struct usb_ncm_parameters temp; struct usb_device_request req; struct usb_ncm_func_descriptor *ufd; uint8_t value[8]; int err; ufd = usbd_find_descriptor(sc->sc_ue.ue_udev, NULL, sc->sc_ifaces_index[1], UDESC_CS_INTERFACE, 0 - 1, UCDC_NCM_FUNC_DESC_SUBTYPE, 0 - 1); /* verify length of NCM functional descriptor */ if (ufd != NULL) { if (ufd->bLength < sizeof(*ufd)) ufd = NULL; else DPRINTFN(1, "Found NCM functional descriptor.\n"); } req.bmRequestType = UT_READ_CLASS_INTERFACE; req.bRequest = UCDC_NCM_GET_NTB_PARAMETERS; USETW(req.wValue, 0); req.wIndex[0] = sc->sc_ifaces_index[1]; req.wIndex[1] = 0; USETW(req.wLength, sizeof(temp)); err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req, &temp, 0, NULL, 1000 /* ms */); if (err) return (1); /* Read correct set of parameters according to device mode */ if (usbd_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST) { sc->sc_ncm.rx_max = UGETDW(temp.dwNtbInMaxSize); sc->sc_ncm.tx_max = UGETDW(temp.dwNtbOutMaxSize); sc->sc_ncm.tx_remainder = UGETW(temp.wNdpOutPayloadRemainder); sc->sc_ncm.tx_modulus = UGETW(temp.wNdpOutDivisor); sc->sc_ncm.tx_struct_align = UGETW(temp.wNdpOutAlignment); sc->sc_ncm.tx_nframe = UGETW(temp.wNtbOutMaxDatagrams); } else { sc->sc_ncm.rx_max = UGETDW(temp.dwNtbOutMaxSize); sc->sc_ncm.tx_max = UGETDW(temp.dwNtbInMaxSize); sc->sc_ncm.tx_remainder = UGETW(temp.wNdpInPayloadRemainder); sc->sc_ncm.tx_modulus = UGETW(temp.wNdpInDivisor); sc->sc_ncm.tx_struct_align = UGETW(temp.wNdpInAlignment); sc->sc_ncm.tx_nframe = UGETW(temp.wNtbOutMaxDatagrams); } /* Verify maximum receive length */ if ((sc->sc_ncm.rx_max < 32) || (sc->sc_ncm.rx_max > CDCE_NCM_RX_MAXLEN)) { DPRINTFN(1, "Using default maximum receive length\n"); sc->sc_ncm.rx_max = CDCE_NCM_RX_MAXLEN; } /* Verify maximum transmit length */ if ((sc->sc_ncm.tx_max < 32) || (sc->sc_ncm.tx_max > CDCE_NCM_TX_MAXLEN)) { DPRINTFN(1, "Using default maximum transmit length\n"); sc->sc_ncm.tx_max = CDCE_NCM_TX_MAXLEN; } /* * Verify that the structure alignment is: * - power of two * - not greater than the maximum transmit length * - not less than four bytes */ if ((sc->sc_ncm.tx_struct_align < 4) || (sc->sc_ncm.tx_struct_align != ((-sc->sc_ncm.tx_struct_align) & sc->sc_ncm.tx_struct_align)) || (sc->sc_ncm.tx_struct_align >= sc->sc_ncm.tx_max)) { DPRINTFN(1, "Using default other alignment: 4 bytes\n"); sc->sc_ncm.tx_struct_align = 4; } /* * Verify that the payload alignment is: * - power of two * - not greater than the maximum transmit length * - not less than four bytes */ if ((sc->sc_ncm.tx_modulus < 4) || (sc->sc_ncm.tx_modulus != ((-sc->sc_ncm.tx_modulus) & sc->sc_ncm.tx_modulus)) || (sc->sc_ncm.tx_modulus >= sc->sc_ncm.tx_max)) { DPRINTFN(1, "Using default transmit modulus: 4 bytes\n"); sc->sc_ncm.tx_modulus = 4; } /* Verify that the payload remainder */ if ((sc->sc_ncm.tx_remainder >= sc->sc_ncm.tx_modulus)) { DPRINTFN(1, "Using default transmit remainder: 0 bytes\n"); sc->sc_ncm.tx_remainder = 0; } /* * Offset the TX remainder so that IP packet payload starts at * the tx_modulus. This is not too clear in the specification. */ sc->sc_ncm.tx_remainder = (sc->sc_ncm.tx_remainder - ETHER_HDR_LEN) & (sc->sc_ncm.tx_modulus - 1); /* Verify max datagrams */ if (sc->sc_ncm.tx_nframe == 0 || sc->sc_ncm.tx_nframe > (CDCE_NCM_SUBFRAMES_MAX - 1)) { DPRINTFN(1, "Using default max " "subframes: %u units\n", CDCE_NCM_SUBFRAMES_MAX - 1); /* need to reserve one entry for zero padding */ sc->sc_ncm.tx_nframe = (CDCE_NCM_SUBFRAMES_MAX - 1); } /* Additional configuration, will fail in device side mode, which is OK. */ req.bmRequestType = UT_WRITE_CLASS_INTERFACE; req.bRequest = UCDC_NCM_SET_NTB_INPUT_SIZE; USETW(req.wValue, 0); req.wIndex[0] = sc->sc_ifaces_index[1]; req.wIndex[1] = 0; if (ufd != NULL && (ufd->bmNetworkCapabilities & UCDC_NCM_CAP_MAX_DGRAM)) { USETW(req.wLength, 8); USETDW(value, sc->sc_ncm.rx_max); USETW(value + 4, (CDCE_NCM_SUBFRAMES_MAX - 1)); USETW(value + 6, 0); } else { USETW(req.wLength, 4); USETDW(value, sc->sc_ncm.rx_max); } err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req, &value, 0, NULL, 1000 /* ms */); if (err) { DPRINTFN(1, "Setting input size " "to %u failed.\n", sc->sc_ncm.rx_max); } req.bmRequestType = UT_WRITE_CLASS_INTERFACE; req.bRequest = UCDC_NCM_SET_CRC_MODE; USETW(req.wValue, 0); /* no CRC */ req.wIndex[0] = sc->sc_ifaces_index[1]; req.wIndex[1] = 0; USETW(req.wLength, 0); err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req, NULL, 0, NULL, 1000 /* ms */); if (err) { DPRINTFN(1, "Setting CRC mode to off failed.\n"); } req.bmRequestType = UT_WRITE_CLASS_INTERFACE; req.bRequest = UCDC_NCM_SET_NTB_FORMAT; USETW(req.wValue, 0); /* NTB-16 */ req.wIndex[0] = sc->sc_ifaces_index[1]; req.wIndex[1] = 0; USETW(req.wLength, 0); err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req, NULL, 0, NULL, 1000 /* ms */); if (err) { DPRINTFN(1, "Setting NTB format to 16-bit failed.\n"); } return (0); /* success */ }
static void atausb_bbb_finish(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status err) { struct atausb_softc *sc = (struct atausb_softc *)priv; struct ata_request *request = sc->ata_request; usbd_xfer_handle next_xfer; /* device_printf(sc->dev, "BBB state %d: %s\n", sc->state, usbd_errstr(err)); */ if (sc->state == ATAUSB_S_DETACH) { device_printf(sc->dev, "WARNING - device has been removed\n"); return; } switch (sc->state) { case ATAUSB_S_BBB_COMMAND: /* command transport phase */ if (err) { if (atausbdebug) device_printf(sc->dev, "failed to send CBW\n"); request->result = EIO; atausb_bbb_reset(sc); return; } /* next is data transport phase, setup transfer */ sc->state = ATAUSB_S_BBB_DATA; if (request->flags & ATA_R_READ) { if (atausb_start(sc, sc->bulkin_pipe, request->data, request->bytecount, USBD_SHORT_XFER_OK, sc->transfer[ATAUSB_T_BBB_DATA])) { request->result = EIO; atausb_bbb_reset(sc); } return; } if (request->flags & ATA_R_WRITE) { if (atausb_start(sc, sc->bulkout_pipe, request->data, request->bytecount, 0, sc->transfer[ATAUSB_T_BBB_DATA])) { request->result = EIO; atausb_bbb_reset(sc); } return; } /* FALLTHROUGH */ case ATAUSB_S_BBB_DATA: /* data transport phase */ if (request->flags & (ATA_R_READ | ATA_R_WRITE)) { usbd_get_xfer_status(xfer, NULL, NULL, &request->donecount, NULL); if (err) { if (atausbdebug) device_printf(sc->dev, "data %s count %d failed: %s\n", (request->flags & ATA_R_READ?"read":"write"), request->bytecount, usbd_errstr(err)); if (err == USBD_STALLED) { atausb_clear_stall(sc, (request->flags & ATA_R_READ ? sc->bulkin : sc->bulkout), (request->flags & ATA_R_READ ? sc->bulkin_pipe : sc->bulkout_pipe), ATAUSB_S_BBB_DCLEAR, sc->transfer[ATAUSB_T_BBB_DCLEAR]); } else { request->result = EIO; atausb_bbb_reset(sc); } return; } } /* FALLTHROUGH */ case ATAUSB_S_BBB_DCLEAR: /* stall clear after data phase */ case ATAUSB_S_BBB_SCLEAR: /* stall clear after status phase */ if (err) { if (atausbdebug) device_printf(sc->dev, "bulk%s stall clear failed %s\n", (request->flags & ATA_R_READ ? "in" : "out"), usbd_errstr(err)); request->result = EIO; atausb_bbb_reset(sc); return; } if (sc->state == ATAUSB_S_BBB_COMMAND || sc->state == ATAUSB_S_BBB_DATA || sc->state == ATAUSB_S_BBB_DCLEAR) { /* first attempt on status transport phase setup transfer */ sc->state = ATAUSB_S_BBB_STATUS1; next_xfer = sc->transfer[ATAUSB_T_BBB_CSW1]; } else { /* second attempt of fetching status */ sc->state = ATAUSB_S_BBB_STATUS2; next_xfer = sc->transfer[ATAUSB_T_BBB_CSW2]; } if (atausb_start(sc, sc->bulkin_pipe, &sc->csw, sizeof(struct bbb_csw), USBD_SHORT_XFER_OK, next_xfer)) { request->result = EIO; atausb_bbb_reset(sc); } return; case ATAUSB_S_BBB_STATUS1: /* status transfer first attempt */ case ATAUSB_S_BBB_STATUS2: /* status transfer second attempt */ if (err) { if (atausbdebug) device_printf(sc->dev, "cannot get CSW, %s%s\n", usbd_errstr(err), sc->state == ATAUSB_S_BBB_STATUS1 ? ", retry":""); if (sc->state == ATAUSB_S_BBB_STATUS1) { atausb_clear_stall(sc, sc->bulkin, sc->bulkin_pipe, ATAUSB_S_BBB_SCLEAR, sc->transfer[ATAUSB_T_BBB_SCLEAR]); } else { request->result = EIO; atausb_bbb_reset(sc); } return; } int residue = UGETDW(sc->csw.residue); if (!residue && (request->bytecount - request->donecount)) residue = request->bytecount - request->donecount; /* check CSW and handle eventual error */ if (UGETDW(sc->csw.signature) != CSWSIGNATURE) { if (atausbdebug) device_printf(sc->dev, "bad CSW signature 0x%08x != 0x%08x\n", UGETDW(sc->csw.signature), CSWSIGNATURE); request->result = EIO; atausb_bbb_reset(sc); return; } else if (UGETDW(sc->csw.tag) != UGETDW(sc->cbw.tag)) { if (atausbdebug) device_printf(sc->dev, "bad CSW tag %d != %d\n", UGETDW(sc->csw.tag), UGETDW(sc->cbw.tag)); request->result = EIO; atausb_bbb_reset(sc); return; } else if (sc->csw.status > CSWSTATUS_PHASE) { if (atausbdebug) device_printf(sc->dev, "bad CSW status %d > %d\n", sc->csw.status, CSWSTATUS_PHASE); request->result = EIO; atausb_bbb_reset(sc); return; } else if (sc->csw.status == CSWSTATUS_PHASE) { if (atausbdebug) device_printf(sc->dev, "phase error residue = %d\n", residue); request->result = EIO; atausb_bbb_reset(sc); return; } else if (request->donecount > request->bytecount) { if (atausbdebug) device_printf(sc->dev, "buffer overrun %d > %d", request->donecount, request->bytecount); request->result = EIO; atausb_bbb_reset(sc); return; } else if (sc->csw.status == CSWSTATUS_FAILED) { if (atausbdebug) device_printf(sc->dev, "CSWSTATUS_FAILED\n"); request->error = ATA_E_ATAPI_SENSE_MASK ; sc->state = ATAUSB_S_IDLE; ata_interrupt(device_get_softc(request->parent)); return; } else { sc->state = ATAUSB_S_IDLE; ata_interrupt(device_get_softc(request->parent)); return; } /* NOT REACHED */ case ATAUSB_S_BBB_RESET1: if (err) if (atausbdebug) device_printf(sc->dev, "BBB reset failure: %s\n", usbd_errstr(err)); atausb_clear_stall(sc, sc->bulkin, sc->bulkin_pipe, ATAUSB_S_BBB_RESET2, sc->transfer[ATAUSB_T_BBB_RESET2]); return; case ATAUSB_S_BBB_RESET2: if (err) if (atausbdebug) device_printf(sc->dev, "BBB bulkin clear stall failure: %s\n", usbd_errstr(err)); atausb_clear_stall(sc, sc->bulkout, sc->bulkout_pipe, ATAUSB_S_BBB_RESET3, sc->transfer[ATAUSB_T_BBB_RESET3]); return; case ATAUSB_S_BBB_RESET3: if (err) if (atausbdebug) device_printf(sc->dev, "BBB bulk-out clear stall failure: %s\n", usbd_errstr(err)); sc->state = ATAUSB_S_IDLE; if (request) { if (err) request->result = ENXIO; else request->result = EIO; ata_interrupt(device_get_softc(request->parent)); } return; default: if (atausbdebug) device_printf(sc->dev, "unknown state %d", sc->state); } }
static uint8_t do_msc_cmd(uint8_t *pcmd, uint8_t cmdlen, void *pdata, uint32_t datalen, uint8_t isread, uint8_t isshort, uint8_t lun, uint8_t flags) { umass_bbb_cbw_t cbw; umass_bbb_csw_t csw; struct libusb20_transfer *xfer_io; uint32_t actlen; uint32_t timeout; int error; memset(&cbw, 0, sizeof(cbw)); USETDW(cbw.dCBWSignature, xfer_wrapper_sig); USETDW(cbw.dCBWTag, xfer_current_id); xfer_current_id++; USETDW(cbw.dCBWDataTransferLength, datalen); cbw.bCBWFlags = (isread ? CBWFLAGS_IN : CBWFLAGS_OUT); cbw.bCBWLUN = lun; cbw.bCDBLength = cmdlen; bcopy(pcmd, cbw.CBWCDB, cmdlen); actlen = 0; timeout = ((datalen + 299999) / 300000) * 1000; timeout += 5000; if ((error = libusb20_tr_bulk_intr_sync(xfer_out, &cbw, sizeof(cbw), &actlen, TIMEOUT_FILTER(1000)))) { printf("ERROR: CBW reception: %d\n", error); do_msc_reset(lun); return (1); } if (actlen != sizeof(cbw)) { printf("ERROR: CBW length: %d != %d\n", actlen, (int)sizeof(cbw)); do_msc_reset(lun); return (1); } if (flags & 1) datalen /= 2; if (datalen != 0) { xfer_io = isread ? xfer_in : xfer_out; if ((error = libusb20_tr_bulk_intr_sync(xfer_io, pdata, datalen, &actlen, TIMEOUT_FILTER(timeout)))) { printf("ERROR: Data transfer: %d\n", error); do_msc_reset(lun); return (1); } if ((actlen != datalen) && (!isshort)) { printf("ERROR: Short data: %d of %d bytes\n", actlen, datalen); do_msc_reset(lun); return (1); } } actlen = 0; timeout = 8; do { error = libusb20_tr_bulk_intr_sync(xfer_in, &csw, sizeof(csw), &actlen, TIMEOUT_FILTER(1000)); if (error) { if (error == LIBUSB20_TRANSFER_TIMED_OUT) { printf("TIMEOUT: Trying to get CSW again. " "%d tries left.\n", timeout); } else { break; } } else { break; } } while (--timeout); if (error) { libusb20_tr_clear_stall_sync(xfer_in); error = libusb20_tr_bulk_intr_sync(xfer_in, &csw, sizeof(csw), &actlen, TIMEOUT_FILTER(1000)); if (error) { libusb20_tr_clear_stall_sync(xfer_in); printf("ERROR: Could not read CSW: Stalled or " "timeout (%d).\n", error); do_msc_reset(lun); return (1); } } if (UGETDW(csw.dCSWSignature) != CSWSIGNATURE) { printf("ERROR: Wrong CSW signature\n"); do_msc_reset(lun); return (1); } if (actlen != sizeof(csw)) { printf("ERROR: Wrong CSW length: %d != %d\n", actlen, (int)sizeof(csw)); do_msc_reset(lun); return (1); } if (csw.bCSWStatus != 0) { printf("ERROR: CSW status: %d\n", (int)csw.bCSWStatus); return (1); } else { stats.xfer_success++; return (0); } }
/* * A frame has been uploaded: pass the resulting mbuf chain up to * the higher level protocols. */ void ugl_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status) { struct ugl_chain *c = priv; struct ugl_softc *sc = c->ugl_sc; struct ifnet *ifp = GET_IFP(sc); struct mbuf *m; int total_len = 0; unsigned int packet_len, packet_count; int s; if (usbd_is_dying(sc->sc_udev)) return; if (!(ifp->if_flags & IFF_RUNNING)) return; if (status != USBD_NORMAL_COMPLETION) { if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) return; sc->sc_rx_errs++; if (usbd_ratecheck(&sc->sc_rx_notice)) { printf("%s: %u usb errors on rx: %s\n", sc->sc_dev.dv_xname, sc->sc_rx_errs, usbd_errstr(status)); sc->sc_rx_errs = 0; } if (status == USBD_STALLED) usbd_clear_endpoint_stall_async(sc->sc_ep[UGL_ENDPT_RX]); goto done; } usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); DPRINTFN(9,("%s: %s: enter status=%d length=%d\n", sc->sc_dev.dv_xname, __func__, status, total_len)); if (total_len < offsetof(struct ugl_packet, pkt_data)) { printf("%s: bad header (length=%d)\n", sc->sc_dev.dv_xname, total_len); goto done; } packet_count = UGETDW(c->ugl_buf->pkt_count); if (packet_count != UGL_RX_FRAMES) { printf("%s: bad packet count (%d)\n", sc->sc_dev.dv_xname, packet_count); if (packet_count == 0) goto done; } packet_len = UGETDW(c->ugl_buf->pkt_length); if (total_len < packet_len) { printf("%s: bad packet size(%d), length=%d\n", sc->sc_dev.dv_xname, packet_len, total_len); if (packet_len == 0) goto done; } m = c->ugl_mbuf; memcpy(mtod(c->ugl_mbuf, char *), c->ugl_buf->pkt_data, packet_len); ifp->if_ipackets++; m->m_pkthdr.len = m->m_len = packet_len; m->m_pkthdr.rcvif = ifp; s = splnet(); /* XXX ugly */ if (ugl_newbuf(sc, c, NULL) == ENOBUFS) { ifp->if_ierrors++; goto done1; } #if NBPFILTER > 0 /* * Handle BPF listeners. Let the BPF user see the packet, but * don't pass it up to the ether_input() layer unless it's * a broadcast packet, multicast packet, matches our ethernet * address or the interface is in promiscuous mode. */ if (ifp->if_bpf) { bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN); } #endif DPRINTFN(10,("%s: %s: deliver %d\n", sc->sc_dev.dv_xname, __func__, m->m_len)); ether_input_mbuf(ifp, m); done1: splx(s); done: /* Setup new transfer. */ usbd_setup_xfer(c->ugl_xfer, sc->sc_ep[UGL_ENDPT_RX], c, c->ugl_buf, UGL_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, ugl_rxeof); usbd_transfer(c->ugl_xfer); DPRINTFN(10,("%s: %s: start rx\n", sc->sc_dev.dv_xname, __func__)); }
void ueagle_loadpage(void *xsc) { struct ueagle_softc *sc = xsc; usbd_xfer_handle xfer; struct ueagle_block_info bi; uint16_t pageno = sc->pageno; uint16_t ovl = sc->ovl; uint8_t pagecount, blockcount; uint16_t blockaddr, blocksize; uint32_t pageoffset; uint8_t *p; int i; if (usbd_is_dying(sc->sc_udev)) return; p = sc->dsp; pagecount = *p++; if (pageno >= pagecount) { printf("%s: invalid page number %u requested\n", sc->sc_dev.dv_xname, pageno); return; } p += 4 * pageno; pageoffset = UGETDW(p); if (pageoffset == 0) return; p = sc->dsp + pageoffset; blockcount = *p++; DPRINTF(("%s: sending %u blocks for fw page %u\n", sc->sc_dev.dv_xname, blockcount, pageno)); if ((xfer = usbd_alloc_xfer(sc->sc_udev)) == NULL) { printf("%s: could not allocate xfer\n", sc->sc_dev.dv_xname); return; } USETW(bi.wHdr, UEAGLE_BLOCK_INFO_HDR); USETW(bi.wOvl, ovl); USETW(bi.wOvlOffset, ovl | 0x8000); for (i = 0; i < blockcount; i++) { blockaddr = UGETW(p); p += 2; blocksize = UGETW(p); p += 2; USETW(bi.wSize, blocksize); USETW(bi.wAddress, blockaddr); USETW(bi.wLast, (i == blockcount - 1) ? 1 : 0); /* send block info through the IDMA pipe */ usbd_setup_xfer(xfer, sc->pipeh_idma, sc, &bi, sizeof bi, 0, UEAGLE_IDMA_TIMEOUT, NULL); if (usbd_sync_transfer(xfer) != 0) { printf("%s: could not transfer block info\n", sc->sc_dev.dv_xname); break; } /* send block data through the IDMA pipe */ usbd_setup_xfer(xfer, sc->pipeh_idma, sc, p, blocksize, 0, UEAGLE_IDMA_TIMEOUT, NULL); if (usbd_sync_transfer(xfer) != 0) { printf("%s: could not transfer block data\n", sc->sc_dev.dv_xname); break; } p += blocksize; } usbd_free_xfer(xfer); }