Changeset 5ee3ce0 in mainline for uspace/drv/bus/usb/ehci/ehci_rh.c


Ignore:
Timestamp:
2014-01-25T01:07:45Z (10 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
d4673007
Parents:
ce735cc2
Message:

ehci,rh: Stop reset, resume in separate fibril.

Fire artificial interrupt when done.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/ehci/ehci_rh.c

    rce735cc2 r5ee3ce0  
    291291}
    292292
     293typedef struct {
     294        ehci_rh_t *hub;
     295        unsigned port;
     296} ehci_rh_job_t;
     297
     298static int stop_reset(void *arg)
     299{
     300        ehci_rh_job_t *job = arg;
     301        async_usleep(50000);
     302        EHCI_CLR(job->hub->registers->portsc[job->port],
     303            USB_PORTSC_PORT_RESET_FLAG);
     304        /* wait for reset to complete */
     305        while (EHCI_RD(job->hub->registers->portsc[job->port]) &
     306            USB_PORTSC_PORT_RESET_FLAG) {
     307                async_usleep(1);
     308        };
     309        /* Handle port ownership, if the port is not enabled
     310         * after reset it's a full speed device */
     311        if (!(EHCI_RD(job->hub->registers->portsc[job->port]) &
     312            USB_PORTSC_ENABLED_FLAG)) {
     313                EHCI_SET(job->hub->registers->portsc[job->port],
     314                    USB_PORTSC_PORT_OWNER_FLAG);
     315        } else {
     316                job->hub->reset_flag[job->port] = true;
     317        }
     318        ehci_rh_interrupt(job->hub);
     319        free(job);
     320        return 0;
     321}
     322
     323static int stop_resume(void *arg)
     324{
     325        ehci_rh_job_t *job = arg;
     326        async_usleep(20000);
     327        EHCI_CLR(job->hub->registers->portsc[job->port],
     328            USB_PORTSC_RESUME_FLAG);
     329        job->hub->resume_flag[job->port] = true;
     330        ehci_rh_interrupt(job->hub);
     331        free(job);
     332        return 0;
     333}
     334
     335static int delayed_job(int (*func)(void*), ehci_rh_t *rh, unsigned port)
     336{
     337        ehci_rh_job_t *job = malloc(sizeof(*job));
     338        if (!job)
     339                return ENOMEM;
     340        job->hub = rh;
     341        job->port = port;
     342        fid_t fib = fibril_create(func, job);
     343        if (!fib) {
     344                free(job);
     345                return ENOMEM;
     346        }
     347        fibril_add_ready(fib);
     348        return EOK;
     349}
     350
     351
    293352/** Port clear feature request handler.
    294353 * @param device Virtual hub device
     
    328387                EHCI_SET(hub->registers->portsc[port],
    329388                    USB_PORTSC_RESUME_FLAG);
    330                 async_usleep(20000);
    331                 EHCI_CLR(hub->registers->portsc[port],
    332                     USB_PORTSC_RESUME_FLAG);
    333                 hub->resume_flag[port] = true;
     389                delayed_job(stop_resume, hub, port);
    334390                return EOK;
    335391
     
    386442                EHCI_SET(hub->registers->portsc[port],
    387443                    USB_PORTSC_PORT_RESET_FLAG);
    388                 async_usleep(50000);
    389                 EHCI_CLR(hub->registers->portsc[port],
    390                     USB_PORTSC_PORT_RESET_FLAG);
    391                 /* wait for reset to complete */
    392                 while (EHCI_RD(hub->registers->portsc[port]) &
    393                     USB_PORTSC_PORT_RESET_FLAG) {
    394                         async_usleep(1);
    395                 };
    396                 /* Handle port ownership, if the port is not enabled
    397                  * after reset it's a full speed device */
    398                 if (!(EHCI_RD(hub->registers->portsc[port]) &
    399                     USB_PORTSC_ENABLED_FLAG)) {
    400                         EHCI_SET(hub->registers->portsc[port],
    401                             USB_PORTSC_PORT_OWNER_FLAG);
    402                 } else {
    403                         hub->reset_flag[port] = true;
    404                 }
    405 
     444                delayed_job(stop_reset, hub, port);
    406445                return EOK;
    407446        case USB_HUB_FEATURE_PORT_POWER:   /*8*/
Note: See TracChangeset for help on using the changeset viewer.