Newer
Older
honey-os / src / userland / usb / xhci / trbRing.c
#include <usb.h>

XHCITRB *enqueueCommand(TrbRing *ring, XHCITRB *trb) {
    trb->control |= ring->cycle;
    memcpy((void *)trb, (void *)&ring->trbs[ring->enqueue], sizeof(XHCITRB));
    XHCITRB *result = &ring->physical[ring->enqueue];
    ring->enqueue++;
    if (ring->enqueue == ring->size - 1) {
        if (ring->trbs[ring->enqueue].control & 1) {
            ring->trbs[ring->enqueue].control &= ~1;
        } else {
            ring->trbs[ring->enqueue].control |= 1;
        }
        if (ring->trbs[ring->enqueue].control & 1) {
            ring->cycle ^= 1;
        }
        ring->enqueue = 0;
    }
    return result;
}

XHCITRB *trbRingFetch(TrbRing *ring, uint32_t *index) {
    if ((ring->trbs[ring->dequeue].control & 1) != ring->cycle) {
        return NULL;
    }
    if (index) {
        *index = ring->dequeue;
    }
    XHCITRB *result = &ring->trbs[ring->dequeue];
    ring->dequeue++;
    if (ring->dequeue == ring->size) {
        ring->dequeue = 0;
        ring->cycle ^= -1;
    }
    return result;
}

void setupTrbRing(TrbRing *ring, uint32_t size) {
    ring->trbs = requestMemory(1, 0, 0);
    ring->physical = getPhysicalAddress((void *)ring->trbs);
    ring->cycle = true;
    ring->enqueue = 0;
    ring->dequeue = 0;
    ring->size = size;
    // define link to beginning
    ring->trbs[ring->size - 1].dataLow = U32(ring->physical);
    ring->trbs[ring->size - 1].control |= 1 << 1 | COMMAND_TYPE(6);
}

TrbRing *createTRB(XHCIController *controller, XHCIInputContext *inputContext,
                   uint32_t slotIndex) {
    TrbRing *ring = malloc(sizeof(TrbRing));
    setupTrbRing(ring, 256);
    inputContext->deviceContext.endpoints[0].transferDequeuePointerLow =
        U32(ring->physical) | 1;
    inputContext->deviceContext.endpoints[0].transferDequeuePointerHigh = 0;
    XHCIDevice *device = malloc(sizeof(XHCIDevice));
    controller->deviceContextBaseAddressArray[slotIndex] =
        U32(getPhysicalAddress((void *)device));
    return ring;
}