Changeset 2bff2cc2 in mainline


Ignore:
Timestamp:
2018-01-18T14:00:57Z (6 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
2c0564c
Parents:
0f79283b
git-author:
Ondřej Hlavatý <aearsis@…> (2018-01-18 13:30:15)
git-committer:
Ondřej Hlavatý <aearsis@…> (2018-01-18 14:00:57)
Message:

xhci: implement sw trb ring

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

Legend:

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

    r0f79283b r2bff2cc2  
    376376        return EOK;
    377377}
     378
     379void xhci_sw_ring_init(xhci_sw_ring_t *ring, size_t size)
     380{
     381        ring->begin = calloc(size, sizeof(xhci_trb_t));
     382        ring->end = ring->begin + size;
     383
     384        ring->enqueue = ring->dequeue = ring->begin;
     385
     386        fibril_mutex_initialize(&ring->guard);
     387        fibril_condvar_initialize(&ring->enqueued_cv);
     388        fibril_condvar_initialize(&ring->dequeued_cv);
     389
     390        ring->running = true;
     391}
     392
     393int xhci_sw_ring_enqueue(xhci_sw_ring_t *ring, xhci_trb_t *trb)
     394{
     395        assert(ring);
     396        assert(trb);
     397
     398        fibril_mutex_lock(&ring->guard);
     399        while (ring->running && TRB_CYCLE(*ring->enqueue))
     400                fibril_condvar_wait(&ring->dequeued_cv, &ring->guard);
     401
     402        *ring->enqueue = *trb;
     403        TRB_SET_CYCLE(*ring->enqueue, 1);
     404        if (++ring->enqueue == ring->end)
     405                ring->enqueue = ring->begin;
     406        fibril_condvar_signal(&ring->enqueued_cv);
     407        fibril_mutex_unlock(&ring->guard);
     408
     409        return ring->running ? EOK : EINTR;
     410}
     411
     412int xhci_sw_ring_dequeue(xhci_sw_ring_t *ring, xhci_trb_t *trb)
     413{
     414        assert(ring);
     415        assert(trb);
     416
     417        fibril_mutex_lock(&ring->guard);
     418        while (ring->running && !TRB_CYCLE(*ring->dequeue))
     419                fibril_condvar_wait(&ring->enqueued_cv, &ring->guard);
     420
     421        *trb = *ring->dequeue;
     422        TRB_SET_CYCLE(*ring->dequeue, 0);
     423        if (++ring->dequeue == ring->end)
     424                ring->dequeue = ring->begin;
     425        fibril_condvar_signal(&ring->dequeued_cv);
     426        fibril_mutex_unlock(&ring->guard);
     427
     428        return ring->running ? EOK : EINTR;
     429}
     430
     431void xhci_sw_ring_stop(xhci_sw_ring_t *ring)
     432{
     433        ring->running = false;
     434        fibril_condvar_broadcast(&ring->enqueued_cv);
     435        fibril_condvar_broadcast(&ring->dequeued_cv);
     436}
     437
     438void xhci_sw_ring_fini(xhci_sw_ring_t *ring)
     439{
     440        free(ring->begin);
     441}
     442
     443/**
     444 * @}
     445 */
  • uspace/drv/bus/usb/xhci/trb_ring.h

    r0f79283b r2bff2cc2  
    119119int xhci_event_ring_dequeue(xhci_event_ring_t *, xhci_trb_t *);
    120120
     121/**
     122 * A TRB ring of which the software is both consumer and provider.
     123 */
     124typedef struct xhci_sw_ring {
     125        xhci_trb_t *begin, *end;
     126        xhci_trb_t *enqueue, *dequeue;
     127
     128        fibril_mutex_t guard;
     129        fibril_condvar_t enqueued_cv, dequeued_cv;
     130
     131        bool running;
     132} xhci_sw_ring_t;
     133
     134void xhci_sw_ring_init(xhci_sw_ring_t *, size_t);
     135
     136/* Both may block if the ring is full/empty. */
     137int xhci_sw_ring_enqueue(xhci_sw_ring_t *, xhci_trb_t *);
     138int xhci_sw_ring_dequeue(xhci_sw_ring_t *, xhci_trb_t *);
     139
     140void xhci_sw_ring_stop(xhci_sw_ring_t *);
     141void xhci_sw_ring_fini(xhci_sw_ring_t *);
     142
    121143#endif
     144
     145/**
     146 * @}
     147 */
Note: See TracChangeset for help on using the changeset viewer.