Changeset 07c08ea in mainline


Ignore:
Timestamp:
2017-08-20T13:22:44Z (7 years ago)
Author:
Petr Manek <petr.manek@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
60ac352
Parents:
d32d51d
Message:

Basic virtual implementation for the root hub.

Location:
uspace/drv/bus/usb/xhci
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/xhci/hc.c

    rd32d51d r07c08ea  
    458458        status = hc->op_regs->usbsts;
    459459
     460        /* TODO: Figure out how root hub interrupts work. */
     461        if (status | 1) {
     462                usb_log_debug2("Root hub interrupt.");
     463                xhci_rh_interrupt(&hc->rh);
     464        }
     465
    460466        if (status & XHCI_REG_MASK(XHCI_OP_HSE)) {
    461467                usb_log_error("Host controller error occured. Bad things gonna happen...");
  • uspace/drv/bus/usb/xhci/hc.h

    rd32d51d r07c08ea  
    7676        xhci_scratchpad_t *scratchpad;
    7777
    78   /* Root hub emulation */
     78        /* Root hub emulation */
    7979        xhci_rh_t rh;
    8080
  • uspace/drv/bus/usb/xhci/rh.c

    rd32d51d r07c08ea  
    4444#include "rh.h"
    4545
     46enum {
     47        HUB_STATUS_CHANGE_PIPE = 1,
     48};
     49
     50static usbvirt_device_ops_t ops;
     51
    4652int xhci_rh_init(xhci_rh_t *rh)
    4753{
    48         /* TODO: Implement me! */
    49         return EOK;
     54        return virthub_base_init(&rh->base, "xhci rh", &ops, rh, NULL,
     55            &rh->hub_descriptor.header, HUB_STATUS_CHANGE_PIPE);
    5056}
    5157
     
    229235int xhci_rh_schedule(xhci_rh_t *rh, usb_transfer_batch_t *batch)
    230236{
    231         /* TODO: Implement me! */
     237        assert(rh);
     238        assert(batch);
     239        const usb_target_t target = {{
     240                .address = batch->ep->address,
     241                .endpoint = batch->ep->endpoint,
     242        }};
     243        batch->error = virthub_base_request(&rh->base, target,
     244            usb_transfer_batch_direction(batch), (void*)batch->setup_buffer,
     245            batch->buffer, batch->buffer_size, &batch->transfered_size);
     246        if (batch->error == ENAK) {
     247                /* This is safe because only status change interrupt transfers
     248                 * return NAK. The assertion holds true because the batch
     249                 * existence prevents communication with that ep */
     250                assert(rh->unfinished_interrupt_transfer == NULL);
     251                rh->unfinished_interrupt_transfer = batch;
     252        } else {
     253                usb_transfer_batch_finish(batch, NULL);
     254                usb_transfer_batch_destroy(batch);
     255        }
     256        return EOK;
     257}
     258
     259int xhci_rh_interrupt(xhci_rh_t *rh)
     260{
     261        usb_log_debug2("Called xhci_rh_interrupt().");
     262
     263        /* TODO: atomic swap needed */
     264        usb_transfer_batch_t *batch = rh->unfinished_interrupt_transfer;
     265        rh->unfinished_interrupt_transfer = NULL;
     266        if (batch) {
     267                const usb_target_t target = {{
     268                        .address = batch->ep->address,
     269                        .endpoint = batch->ep->endpoint,
     270                }};
     271                batch->error = virthub_base_request(&rh->base, target,
     272                    usb_transfer_batch_direction(batch),
     273                    (void*)batch->setup_buffer,
     274                    batch->buffer, batch->buffer_size, &batch->transfered_size);
     275                usb_transfer_batch_finish(batch, NULL);
     276                usb_transfer_batch_destroy(batch);
     277        }
     278        return EOK;
     279}
     280
     281/** Hub status request handler.
     282 * @param device Virtual hub device
     283 * @param setup_packet USB setup stage data.
     284 * @param[out] data destination data buffer, size must be at least
     285 *             setup_packet->length bytes
     286 * @param[out] act_size Sized of the valid response part of the buffer.
     287 * @return Error code.
     288 */
     289static int req_get_status(usbvirt_device_t *device,
     290    const usb_device_request_setup_packet_t *setup_packet,
     291    uint8_t *data, size_t *act_size)
     292{
     293        /* TODO: Implement me! */
     294        usb_log_debug2("Called req_get_status().");
     295        return EOK;
     296}
     297
     298/** Hub set feature request handler.
     299 * @param device Virtual hub device
     300 * @param setup_packet USB setup stage data.
     301 * @param[out] data destination data buffer, size must be at least
     302 *             setup_packet->length bytes
     303 * @param[out] act_size Sized of the valid response part of the buffer.
     304 * @return Error code.
     305 */
     306static int req_clear_hub_feature(usbvirt_device_t *device,
     307    const usb_device_request_setup_packet_t *setup_packet,
     308    uint8_t *data, size_t *act_size)
     309{
     310        /* TODO: Implement me! */
     311        usb_log_debug2("Called req_clear_hub_feature().");
     312        return EOK;
     313}
     314
     315/** Port status request handler.
     316 * @param device Virtual hub device
     317 * @param setup_packet USB setup stage data.
     318 * @param[out] data destination data buffer, size must be at least
     319 *             setup_packet->length bytes
     320 * @param[out] act_size Sized of the valid response part of the buffer.
     321 * @return Error code.
     322 */
     323static int req_get_port_status(usbvirt_device_t *device,
     324    const usb_device_request_setup_packet_t *setup_packet,
     325    uint8_t *data, size_t *act_size)
     326{
     327        /* TODO: Implement me! */
     328        usb_log_debug2("Called req_get_port_status().");
     329        return EOK;
     330}
     331
     332/** Port clear feature request handler.
     333 * @param device Virtual hub device
     334 * @param setup_packet USB setup stage data.
     335 * @param[out] data destination data buffer, size must be at least
     336 *             setup_packet->length bytes
     337 * @param[out] act_size Sized of the valid response part of the buffer.
     338 * @return Error code.
     339 */
     340static int req_clear_port_feature(usbvirt_device_t *device,
     341    const usb_device_request_setup_packet_t *setup_packet,
     342    uint8_t *data, size_t *act_size)
     343{
     344        /* TODO: Implement me! */
     345        usb_log_debug2("Called req_clear_port_feature().");
     346        return EOK;
     347}
     348
     349/** Port set feature request handler.
     350 * @param device Virtual hub device
     351 * @param setup_packet USB setup stage data.
     352 * @param[out] data destination data buffer, size must be at least
     353 *             setup_packet->length bytes
     354 * @param[out] act_size Sized of the valid response part of the buffer.
     355 * @return Error code.
     356 */
     357static int req_set_port_feature(usbvirt_device_t *device,
     358    const usb_device_request_setup_packet_t *setup_packet,
     359    uint8_t *data, size_t *act_size)
     360{
     361        /* TODO: Implement me! */
     362        usb_log_debug2("Called req_set_port_feature().");
     363        return EOK;
     364}
     365
     366/** Status change handler.
     367 * @param device Virtual hub device
     368 * @param endpoint Endpoint number
     369 * @param tr_type Transfer type
     370 * @param buffer Response destination
     371 * @param buffer_size Bytes available in buffer
     372 * @param actual_size Size us the used part of the dest buffer.
     373 *
     374 * Produces status mask. Bit 0 indicates hub status change the other bits
     375 * represent port status change. Endian does not matter as UHCI root hubs
     376 * only need 1 byte.
     377 */
     378static int req_status_change_handler(usbvirt_device_t *device,
     379    usb_endpoint_t endpoint, usb_transfer_type_t tr_type,
     380    void *buffer, size_t buffer_size, size_t *actual_size)
     381{
     382        /* TODO: Implement me! */
     383        usb_log_debug2("Called req_status_change_handler().");
    232384        return EOK;
    233385}
     
    236388{
    237389        /* TODO: Implement me! */
    238         return EOK;
    239 }
     390        usb_log_debug2("Called xhci_rh_fini().");
     391        return EOK;
     392}
     393
     394/** XHCI root hub request handlers */
     395static const usbvirt_control_request_handler_t control_transfer_handlers[] = {
     396        {
     397                STD_REQ_IN(USB_REQUEST_RECIPIENT_DEVICE, USB_DEVREQ_GET_DESCRIPTOR),
     398                .name = "GetDescriptor",
     399                .callback = virthub_base_get_hub_descriptor,
     400        },
     401        {
     402                CLASS_REQ_IN(USB_REQUEST_RECIPIENT_DEVICE, USB_DEVREQ_GET_DESCRIPTOR),
     403                .name = "GetDescriptor",
     404                .callback = virthub_base_get_hub_descriptor,
     405        },
     406        {
     407                CLASS_REQ_IN(USB_REQUEST_RECIPIENT_DEVICE, USB_HUB_REQUEST_GET_DESCRIPTOR),
     408                .name = "GetHubDescriptor",
     409                .callback = virthub_base_get_hub_descriptor,
     410        },
     411        {
     412                CLASS_REQ_IN(USB_REQUEST_RECIPIENT_OTHER, USB_HUB_REQUEST_GET_STATUS),
     413                .name = "GetPortStatus",
     414                .callback = req_get_port_status,
     415        },
     416        {
     417                CLASS_REQ_OUT(USB_REQUEST_RECIPIENT_DEVICE, USB_HUB_REQUEST_CLEAR_FEATURE),
     418                .name = "ClearHubFeature",
     419                .callback = req_clear_hub_feature,
     420        },
     421        {
     422                CLASS_REQ_OUT(USB_REQUEST_RECIPIENT_OTHER, USB_HUB_REQUEST_CLEAR_FEATURE),
     423                .name = "ClearPortFeature",
     424                .callback = req_clear_port_feature,
     425        },
     426        {
     427                CLASS_REQ_IN(USB_REQUEST_RECIPIENT_DEVICE, USB_HUB_REQUEST_GET_STATUS),
     428                .name = "GetHubStatus",
     429                .callback = req_get_status,
     430        },
     431        {
     432                CLASS_REQ_IN(USB_REQUEST_RECIPIENT_OTHER, USB_HUB_REQUEST_GET_STATUS),
     433                .name = "GetPortStatus",
     434                .callback = req_get_port_status,
     435        },
     436        {
     437                CLASS_REQ_OUT(USB_REQUEST_RECIPIENT_DEVICE, USB_HUB_REQUEST_SET_FEATURE),
     438                .name = "SetHubFeature",
     439                .callback = req_nop,
     440        },
     441        {
     442                CLASS_REQ_OUT(USB_REQUEST_RECIPIENT_OTHER, USB_HUB_REQUEST_SET_FEATURE),
     443                .name = "SetPortFeature",
     444                .callback = req_set_port_feature,
     445        },
     446        {
     447                .callback = NULL
     448        }
     449};
     450
     451/** Virtual XHCI root hub ops */
     452static usbvirt_device_ops_t ops = {
     453        .control = control_transfer_handlers,
     454        .data_in[HUB_STATUS_CHANGE_PIPE] = req_status_change_handler,
     455};
    240456
    241457
  • uspace/drv/bus/usb/xhci/rh.h

    rd32d51d r07c08ea  
    4040#include <usbvirt/virthub_base.h>
    4141
     42enum {
     43        XHCI_MAX_PORTS = 255,
     44};
     45
    4246/* XHCI root hub instance */
    4347typedef struct {
    4448        /** Virtual hub instance */
    4549        virthub_base_t base;
     50        /** USB hub descriptor describing the XHCI root hub */
     51        struct {
     52                usb_hub_descriptor_header_t header;
     53                uint8_t rempow[STATUS_BYTES(XHCI_MAX_PORTS) * 2];
     54        } __attribute__((packed)) hub_descriptor;
     55        /** Interrupt transfer waiting for an actual interrupt to occur */
     56        usb_transfer_batch_t *unfinished_interrupt_transfer;
    4657} xhci_rh_t;
    4758
     
    5263int xhci_reset_hub_port(xhci_hc_t *, uint8_t);
    5364int xhci_rh_schedule(xhci_rh_t *, usb_transfer_batch_t *);
     65int xhci_rh_interrupt(xhci_rh_t *);
    5466
    5567#endif
Note: See TracChangeset for help on using the changeset viewer.