/** * Process root hub request. * * @param instance Root hub instance * @param request Structure containing both request and response information * @return Error code */ void rh_request(rh_t *instance, usb_transfer_batch_t *request) { assert(instance); assert(request); switch (request->ep->transfer_type) { case USB_TRANSFER_CONTROL: usb_log_debug("Root hub got CONTROL packet\n"); control_request(instance, request); break; case USB_TRANSFER_INTERRUPT: usb_log_debug("Root hub got INTERRUPT packet\n"); fibril_mutex_lock(&instance->guard); assert(instance->unfinished_interrupt_transfer == NULL); const uint16_t mask = create_interrupt_mask(instance); if (mask == 0) { usb_log_debug("No changes(%hx)...\n", mask); instance->unfinished_interrupt_transfer = request; } else { usb_log_debug("Processing changes...\n"); interrupt_request( request, mask, instance->interrupt_mask_size); } fibril_mutex_unlock(&instance->guard); break; default: usb_log_error("Root hub got unsupported request.\n"); TRANSFER_END(request, ENOTSUP); } }
static void do_work( void ) { struct iovec vec[MAX_IOVEC]; int n, count; union { void ** v; char ** c; } iovec_pun; n = count = 0; for( ;; ) { ablk_req_head_t *cur = &ablk.ring[ ablk.req_head ]; int proceed = cur->proceed; int f, next = NEXT( ablk.req_head ); ablk_req_head_t *r = &ablk.ring[next]; /* execute request? */ if( n && (!proceed || n == MAX_IOVEC || !(r->flags & ABLK_SG_BUF)) ) { int ret; while( (ret=(*ablk.iofunc)(ablk.devs[ablk.cur_dev].bdev, vec, n)) != count ) { int s, i; for( i=0; ret > 0; i++, ret -= s, count -= s ) { s = MIN( vec[i].iov_len, ret ); vec[i].iov_len -= s; vec[i].iov_base += s; } if( ret < 0 && errno != EINTR ) { perrorm("ablk iofunc"); goto error; } } ablk.n_requests += n; /* this takes into account the engine stall interrupt */ if( (cur->flags & ABLK_RAISE_IRQ) && proceed ) irq_line_hi( ablk.irq ); n = 0; count = 0; } /* engine stall? */ if( !proceed ) break; /* flag old head slot for reuse */ cur->flags = 0; /* advance pointer to next request */ cur->proceed = 0; f = r->flags; ablk.req_head = next; /* process scatter & gather bufs */ if( (f & ABLK_SG_BUF) ) { ablk_sg_t *p = (ablk_sg_t*)r; iovec_pun.v = &(vec[n].iov_base); if( mphys_to_lvptr( p->buf, (char**)iovec_pun.c ) ) { printm("ablk: bogus sg-buf"); goto error; } vec[n++].iov_len = p->count; count += p->count; /* req_count is increased when the request is finished */ continue; } /* must be a read/write/cntrol request */ if( (unsigned int)r->unit >= ablk.ndevs ) { printm("ablk: bad unit"); goto error; } ablk.cur_dev = r->unit; /* Read / Write Request */ if( f & (ABLK_READ_REQ | ABLK_WRITE_REQ) ) { /* Schedule the next iofunc */ ablk.iofunc = (f & ABLK_WRITE_REQ)? ablk.devs[r->unit].bdev->write : ablk.devs[r->unit].bdev->read; /* r->param contains first sector */ if( ablk.devs[r->unit].bdev->seek( ablk.devs[r->unit].bdev, r->param, 0 ) < 0 ) { printm("ablk: bad lseek"); goto error; } } else if( f & ABLK_CNTRL_REQ_MASK) { ablk.iofunc = control_request( ablk.devs[r->unit].bdev, (f & ABLK_CNTRL_REQ_MASK), r->param ); if( f & ABLK_RAISE_IRQ ) irq_line_hi( ablk.irq ); } else { printm("bogus ablk command!\n"); goto error; } /* n and count have already been set to zero */ ablk.n_requests++; } /* engine stall */ ablk.active = 0; irq_line_hi( ablk.irq ); return; error: printm("ABlk engine error\n"); ablk.running = 0; ablk.active = 0; irq_line_hi( ablk.irq ); }