Read USB mass storage sector count and sector size!

This commit is contained in:
2026-04-06 01:00:54 +02:00
parent 90217168be
commit 1cb1bad3dd
17 changed files with 800 additions and 347 deletions

View File

@@ -27,6 +27,7 @@
#define XDRV_TYPE_RAMDRV 0
#define XDRV_TYPE_PARTDRV 1
#define XDRV_TYPE_IDEDRV 2
#define XDRV_TYPE_USBDRV 3
#define XDRV_GET_SIZE 0
#define XDRV_GET_SECTOR_SIZE 1
#define XDRV_GET_DEVICE_TYPE 2
@@ -34,6 +35,6 @@
#define XDRV_WRITE 4
/* usb controller devices */
#define XUSBCTRL_POLL_DRIVER 0
#define XUSBCTRL_POLL_DRIVER 0
#endif // _DEVICES_H

View File

@@ -26,5 +26,6 @@
#define ST_XDRV_READ_ERROR 22
#define ST_XDRV_WRITE_ERROR 23
#define ST_NOT_PARTIAL 24
#define ST_USB_CTRL_ERROR 25
#endif // _M_STATUS_H

View File

@@ -41,14 +41,19 @@ struct device* device_find (const char* key) {
uint32_t hash = hash_fnv32 (key, key_len);
spin_lock (&device_table.lock, &fdt);
hash_find (&device_table, key, key_len, hash, lengthof (device_table.device_buckets),
device_buckets, struct device, device_table_link, key, found_link);
spin_unlock (&device_table.lock, fdt);
if (found_link == NULL)
if (found_link == NULL) {
return NULL;
}
return hash_entry (found_link, struct device, device_table_link);
struct device* device = hash_entry (found_link, struct device, device_table_link);
return device;
}
struct device* device_create (int type, const char* key, device_op_func_t* ops, size_t ops_len,
@@ -93,6 +98,27 @@ struct device* device_create (int type, const char* key, device_op_func_t* ops,
return device;
}
void device_delete (const char* key, struct proc* proc, struct reschedule_ctx* rctx) {
uint64_t fdt;
size_t key_len = strlen_null (key);
uint32_t hash = hash_fnv32 (key, key_len);
spin_lock (&device_table.lock, &fdt);
struct hash_node_link* delete_link;
hash_delete (&device_table, key, strlen_null (key), hash, lengthof (device_table.device_buckets),
device_buckets, struct device, device_table_link, key, delete_link);
struct device* device = hash_entry (delete_link, struct device, device_table_link);
if (device != NULL)
device->fini (device, proc, rctx);
spin_unlock (&device_table.lock, fdt);
}
size_t device_populate_device_infos (struct device_info* infos, size_t count) {
uint64_t fdt, fd;

View File

@@ -43,6 +43,8 @@ struct device* device_create (int type, const char* key, device_op_func_t* ops,
device_init_func_t init, device_fini_func_t fini, void* arg,
struct proc* proc, struct reschedule_ctx* rctx);
void device_delete (const char* key, struct proc* proc, struct reschedule_ctx* rctx);
struct device* device_find (const char* key);
size_t device_populate_device_infos (struct device_info* infos, size_t count);

View File

@@ -1,9 +1,11 @@
c += device/storage/partdrv.c \
device/storage/ramdrv.c \
device/storage/partitions.c \
device/storage/idedrv.c
device/storage/idedrv.c \
device/storage/usbdrv.c
o += device/storage/partdrv.o \
device/storage/ramdrv.o \
device/storage/partitions.o \
device/storage/idedrv.o
device/storage/idedrv.o \
device/storage/usbdrv.o

View File

@@ -0,0 +1,239 @@
#include <device/def_device_op.h>
#include <device/device.h>
#include <device/storage/usbdrv.h>
#include <device/usb/xhci.h>
#include <devices.h>
#include <libk/endianess.h>
#include <libk/string.h>
#include <limine/requests.h>
#include <mm/malloc.h>
#include <mm/pmm.h>
#include <proc/proc.h>
#include <proc/reschedule.h>
#include <status.h>
#include <sys/debug.h>
#include <sys/stall.h>
/* REF: https://en.wikipedia.org/wiki/SCSI */
static int usb_ms_send_cbw (struct xhci* xhci, struct xhci_usb_device* usb_device,
uint8_t bulk_out_endpoint, uintptr_t cbw_phys, uint64_t* lockflags) {
return xhci_bulk_transfer (xhci, usb_device, bulk_out_endpoint, cbw_phys,
sizeof (struct usb_ms_cbw), lockflags);
}
static int usb_ms_read_data (struct xhci* xhci, struct xhci_usb_device* usb_device,
uint8_t bulk_in_endpoint, uintptr_t buffer_phys, size_t buffer_size,
uint64_t* lockflags) {
return xhci_bulk_transfer (xhci, usb_device, bulk_in_endpoint, buffer_phys, buffer_size,
lockflags);
}
static int usb_ms_read_csw (struct xhci* xhci, struct xhci_usb_device* usb_device,
uint8_t bulk_in_endpoint, uintptr_t csw_phys, uint64_t* lockflags) {
return xhci_bulk_transfer (xhci, usb_device, bulk_in_endpoint, csw_phys,
sizeof (struct usb_ms_csw), lockflags);
}
static int usb_ms_scsi_read_capacity (struct xhci* xhci, struct xhci_usb_device* usb_device,
uint8_t bulk_in_endpoint, uint8_t bulk_out_endpoint,
size_t* sector_size, size_t* sector_count,
uint64_t* lockflags) {
struct limine_hhdm_response* hhdm = limine_hhdm_request.response;
int ret;
uintptr_t cbw_phys = pmm_alloc (1);
struct usb_ms_cbw* cbw = (struct usb_ms_cbw*)(cbw_phys + (uintptr_t)hhdm->offset);
memset (cbw, 0, PAGE_SIZE);
uintptr_t data_phys = pmm_alloc (1);
uint8_t* data = (uint8_t*)(data_phys + (uintptr_t)hhdm->offset);
memset (data, 0, PAGE_SIZE);
uintptr_t csw_phys = pmm_alloc (1);
struct usb_ms_csw* csw = (struct usb_ms_csw*)(csw_phys + (uintptr_t)hhdm->offset);
memset (csw, 0, PAGE_SIZE);
uint8_t cdb[10] = {
0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
cbw->signature = USB_CBW_SIGNATURE;
cbw->tag = 0x12345678;
cbw->dir = 0x80;
cbw->lun = 0;
cbw->cmd_len = sizeof (cdb);
cbw->length = 8;
memcpy (cbw->data, cdb, sizeof (cdb));
if ((ret = usb_ms_send_cbw (xhci, usb_device, bulk_out_endpoint, cbw_phys, lockflags)) < 0) {
goto done;
}
if ((ret = usb_ms_read_data (xhci, usb_device, bulk_in_endpoint, data_phys, 8, lockflags)) < 0) {
goto done;
}
if ((ret = usb_ms_read_csw (xhci, usb_device, bulk_in_endpoint, csw_phys, lockflags)) < 0) {
goto done;
}
if (csw->status != 0 || csw->signature != USB_CSW_SIGNATURE) {
DEBUG ("Failed to read capacity/sect size. CSW status=%u residue=%u\n", csw->status,
csw->residue);
ret = -ST_USB_CTRL_ERROR;
goto done;
}
uint32_t last_lba = BE2LE32 (*(uint32_t*)&data[0]);
uint32_t blk_len = BE2LE32 (*(uint32_t*)&data[4]);
*sector_size = blk_len;
*sector_count = (size_t)last_lba + 1;
ret = ST_OK;
done:
pmm_free (cbw_phys, 1);
pmm_free (data_phys, 1);
pmm_free (csw_phys, 1);
return ret;
}
static int usb_ms_scsi_test_unit_ready (struct xhci* xhci, struct xhci_usb_device* usb_device,
uint8_t bulk_in_endpoint, uint8_t bulk_out_endpoint,
uint64_t* lockflags) {
struct limine_hhdm_response* hhdm = limine_hhdm_request.response;
int ret;
uintptr_t cbw_phys = pmm_alloc (1);
struct usb_ms_cbw* cbw = (struct usb_ms_cbw*)(cbw_phys + (uintptr_t)hhdm->offset);
memset (cbw, 0, PAGE_SIZE);
uintptr_t csw_phys = pmm_alloc (1);
struct usb_ms_csw* csw = (struct usb_ms_csw*)(csw_phys + (uintptr_t)hhdm->offset);
memset (csw, 0, PAGE_SIZE);
uint8_t cdb[10] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
cbw->signature = USB_CBW_SIGNATURE;
cbw->tag = 0x12345678;
cbw->dir = 0x00;
cbw->lun = 0;
cbw->cmd_len = sizeof (cdb);
cbw->length = 0;
memcpy (cbw->data, cdb, sizeof (cdb));
if ((ret = usb_ms_send_cbw (xhci, usb_device, bulk_out_endpoint, cbw_phys, lockflags)) < 0) {
goto done;
}
if ((ret = usb_ms_read_csw (xhci, usb_device, bulk_in_endpoint, csw_phys, lockflags)) < 0) {
goto done;
}
if (csw->status != 0 || csw->signature != USB_CSW_SIGNATURE) {
ret = -ST_USB_CTRL_ERROR;
goto done;
}
ret = ST_OK;
done:
pmm_free (cbw_phys, 1);
pmm_free (csw_phys, 1);
return ret;
}
static void usbdrv_setup_endpoints (struct usbdrv* usbdrv) {
for (size_t ep = 0; ep < usbdrv->usb_device->endpoints_count; ep++) {
struct xhci_usb_device_endpoint* endpoint = &usbdrv->usb_device->endpoints[ep];
uint8_t type = endpoint->desc.attrs & 0x03;
bool in = (endpoint->desc.endpoint_addr & 0x80) != 0;
uint32_t xhci_type = 0;
if (type == 2) {
if (in)
xhci_type = XHCI_EP_BULK_IN;
else
xhci_type = XHCI_EP_BULK_OUT;
} else if (type == 3) {
if (in)
xhci_type = XHCI_EP_INTR_IN;
else
xhci_type = XHCI_EP_INTR_OUT;
}
if (xhci_type == XHCI_EP_BULK_IN)
usbdrv->bulk_in = endpoint->desc;
else if (xhci_type == XHCI_EP_BULK_OUT)
usbdrv->bulk_out = endpoint->desc;
}
}
DEFINE_DEVICE_OP (usbdrv_read) {}
DEFINE_DEVICE_OP (usbdrv_write) {}
DEFINE_DEVICE_OP (usbdrv_get_device_type) {
if (a1 == NULL)
return -ST_BAD_ADDRESS_SPACE;
int* device_type = (int*)a1;
*device_type = XDRV_TYPE_USBDRV;
return ST_OK;
}
DEFINE_DEVICE_OP (usbdrv_get_sector_size) {}
DEFINE_DEVICE_OP (usbdrv_get_size) {}
DEFINE_DEVICE_INIT (usbdrv_init) {
int ret;
struct usbdrv_init* init = arg;
struct usbdrv* usbdrv = malloc (sizeof (*usbdrv));
if (usbdrv == NULL)
return false;
memset (usbdrv, 0, sizeof (*usbdrv));
usbdrv->xhci = init->xhci;
usbdrv->usb_device = init->usb_device;
usbdrv_setup_endpoints (usbdrv);
ret =
usb_ms_scsi_test_unit_ready (usbdrv->xhci, usbdrv->usb_device, usbdrv->bulk_in.endpoint_addr,
usbdrv->bulk_out.endpoint_addr, init->lockflags);
if (ret < 0) {
stall_ms (100);
ret = usb_ms_scsi_test_unit_ready (usbdrv->xhci, usbdrv->usb_device,
usbdrv->bulk_in.endpoint_addr,
usbdrv->bulk_out.endpoint_addr, init->lockflags);
}
if (ret < 0)
return false;
ret = usb_ms_scsi_read_capacity (usbdrv->xhci, usbdrv->usb_device, usbdrv->bulk_in.endpoint_addr,
usbdrv->bulk_out.endpoint_addr, &usbdrv->sector_size,
&usbdrv->sector_count, init->lockflags);
if (ret < 0)
return false;
DEBUG ("sector_count = %zu, sector_size = %u\n", usbdrv->sector_count, usbdrv->sector_size);
return true;
}
DEFINE_DEVICE_FINI (usbdrv_fini) {}

View File

@@ -0,0 +1,63 @@
#ifndef _KERNEL_DEVICE_STORAGE_USBDRV_H
#define _KERNEL_DEVICE_STORAGE_USBDRV_H
#include <device/def_device_op.h>
#include <device/usb/usb.h>
#include <device/usb/xhci.h>
#include <libk/std.h>
#define USB_CBW_SIGNATURE 0x43425355
/* command block wrapper */
struct usb_ms_cbw {
uint32_t signature;
uint32_t tag;
uint32_t length;
uint8_t dir;
uint8_t lun;
uint8_t cmd_len;
uint8_t data[16];
} PACKED;
#define USB_CSW_SIGNATURE 0x53425355
/* command status wrapper */
struct usb_ms_csw {
uint32_t signature;
uint32_t tag;
uint32_t residue;
uint8_t status;
} PACKED;
struct device;
struct usbdrv_init {
struct xhci* xhci;
struct xhci_usb_device* usb_device;
uint64_t* lockflags;
};
struct usbdrv {
struct xhci* xhci;
struct xhci_usb_device* usb_device;
size_t sector_size;
size_t sector_count;
struct usb_endpoint_desc bulk_in;
struct usb_endpoint_desc bulk_out;
};
DEFINE_DEVICE_INIT (usbdrv_init);
DEFINE_DEVICE_FINI (usbdrv_fini);
DEFINE_DEVICE_OP (usbdrv_read);
DEFINE_DEVICE_OP (usbdrv_write);
DEFINE_DEVICE_OP (usbdrv_get_device_type);
DEFINE_DEVICE_OP (usbdrv_get_sector_size);
DEFINE_DEVICE_OP (usbdrv_get_size);
#endif // _KERNEL_DEVICE_STORAGE_USBDRV_H

View File

@@ -1,6 +0,0 @@
#include <device/usb/mass_storage.h>
#include <device/usb/usb.h>
#include <libk/std.h>
#include <sys/debug.h>
bool usb_mass_storage_init (void) { return true; }

View File

@@ -1,8 +0,0 @@
#ifndef _KERNEL_DEVICE_USB_MASS_STORAGE_H
#define _KERNEL_DEVICE_USB_MASS_STORAGE_H
#include <libk/std.h>
bool usb_mass_storage_init (void);
#endif // _KERNEL_DEVICE_USB_MASS_STORAGE_H

View File

@@ -1,7 +1,5 @@
c += device/usb/xhci.c \
device/usb/usb.c \
device/usb/mass_storage.c
device/usb/usb.c
o += device/usb/xhci.o \
device/usb/usb.o \
device/usb/mass_storage.o
device/usb/usb.o

View File

@@ -1,6 +1,36 @@
#include <device/usb/mass_storage.h>
#include <device/def_device_op.h>
#include <device/device.h>
#include <device/storage/usbdrv.h>
#include <device/usb/usb.h>
#include <device/usb/xhci.h>
#include <devices.h>
#include <libk/lengthof.h>
#include <libk/printf.h>
#include <libk/std.h>
#include <proc/proc.h>
#include <proc/reschedule.h>
#include <sys/debug.h>
static atomic_int usb_ms_counter = 0;
static struct device* usb_ms_init (struct xhci* xhci, struct xhci_usb_device* usb_device,
struct proc* proc, struct reschedule_ctx* rctx,
uint64_t* lockflags) {
static device_op_func_t ops[] = {0};
struct usbdrv_init init = {
.xhci = xhci,
.usb_device = usb_device,
.lockflags = lockflags,
};
char key[30];
snprintf (key, sizeof (key), "usbdrv%d", atomic_fetch_add (&usb_ms_counter, 1));
return device_create (DEVICE_TYPE_DRIVE, key, ops, lengthof (ops), &usbdrv_init, &usbdrv_fini,
&init, proc, rctx);
}
struct usb_driver_info usb_driver_infos[USB_DRIVER_MAX_MATCHES] = {
{.if_class = 0x08, .if_subclass = 0x06, .if_proto = 0x50, .init = &usb_mass_storage_init},
{.if_class = 0x08, .if_subclass = 0x06, .if_proto = 0x50, .init = &usb_ms_init},
};

View File

@@ -2,7 +2,10 @@
#define _KERNEL_DEVICE_USB_H
#include <aux/compiler.h>
#include <device/device.h>
#include <libk/std.h>
#include <proc/proc.h>
#include <proc/reschedule.h>
#define USB_DRIVER_MAX_MATCHES 1
@@ -21,6 +24,9 @@
#define USB_DESC_DEV_CAPABILITY 16
#define USB_DESC_SS_USB_EP_COMP 48
struct xhci;
struct xhci_usb_device;
struct usb_desc_hdr {
uint8_t length;
uint8_t desc_type;
@@ -77,34 +83,12 @@ struct usb_endpoint_desc {
uint8_t interval;
} PACKED;
#define USB_CBW_SIGNATURE 0x43425355
/* command block wrapper */
struct usb_cbw {
uint32_t signature;
uint32_t tag;
uint32_t length;
uint8_t dir;
uint8_t lun;
uint8_t cmd_len;
uint8_t data[16];
} PACKED;
#define USB_CSW_SIGNATURE 0x53425355
/* command status wrapper */
struct usb_csw {
uint32_t signature;
uint32_t tag;
uint32_t residue;
uint8_t status;
};
struct usb_driver_info {
uint8_t if_class;
uint8_t if_subclass;
uint8_t if_proto;
bool (*init) (void);
struct device* (*init) (struct xhci* xhci, struct xhci_usb_device* usb_device, struct proc* proc,
struct reschedule_ctx* rctx, uint64_t* lockflags);
};
extern struct usb_driver_info usb_driver_infos[USB_DRIVER_MAX_MATCHES];

View File

@@ -19,293 +19,12 @@
#include <sys/spin_lock.h>
#include <sys/stall.h>
/* REF:
* https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf
*/
/* clang-format off */
/* capability registers */
#define XHCI_CAPLENGTH 0x00
#define XHCI_RSVD 0x01
#define XHCI_HCIVERSION 0x02
#define XHCI_HCSPARAMS1 0x04
#define XHCI_HCSPARAMS2 0x08
#define XHCI_HCSPARAMS3 0x0C
#define XHCI_HCCPARAMS1 0x10
#define XHCI_DBOFF 0x14
#define XHCI_RTSOFF 0x18
#define XHCI_HCCPARAMS2 0x1C
/* operational registers */
#define XHCI_USBCMD 0x00
#define XHCI_USBSTS 0x04
#define XHCI_PAGESIZE 0x08
#define XHCI_DNCTRL 0x14
#define XHCI_CRCR 0x18
#define XHCI_DCBAAP 0x30
#define XHCI_CONFIG 0x38
/* port registers */
#define XHCI_PORTSC 0x00
#define XHCI_PORTPMSC 0x04
#define XHCI_PORTLI 0x08
/* runtime registers */
#define XHCI_MFINDEX 0x00
/* + IRQ sets (0x20) */
#define XHCI_IMAN 0x00
#define XHCI_IMOD 0x04
#define XHCI_ERSTSZ 0x08
#define XHCI_ERSTBA 0x10
#define XHCI_ERDP 0x18
/* HCCPARAMS1 */
#define XHCI_HCCPARAMS1_AC64 0
#define XHCI_HCCPARAMS1_BNC 1
#define XHCI_HCCPARAMS1_CSZ 2
#define XHCI_HCCPARAMS1_PPC 3
#define XHCI_HCCPARAMS1_PIND 4
#define XHCI_HCCPARAMS1_LHRC 5
#define XHCI_HCCPARAMS1_LTC 6
#define XHCI_HCCPARAMS1_NSS 7
#define XHCI_HCCPARAMS1_PAE 8
#define XHCI_HCCPARAMS1_SPC 9
#define XHCI_HCCPARAMS1_SEC 10
#define XHCI_HCCPARAMS1_CFC 11
#define XHCI_HCCPARAMS1_MAX_PSA_SIZE 12
#define XHCI_HCCPARAMS1_XECP 16
/* XHCI extended capabilities */
#define XHCI_XECP_CAP_ID 0
#define XHCI_XECP_NEXT_PTR 8
/* USB legacy support capability */
#define XHCI_USBLEGSUP_CAP_ID 0
#define XHCI_USBLEGSUP_NEXT_PTR 8
#define XHCI_USBLEGSUP_BIOS_SEMA 16
#define XHCI_USBLEGSUP_OS_SEMA 24
/* Supported protocol capability */
#define XHCI_SUPPROTO_DW0_CAP_ID 0
#define XHCI_SUPPROTO_DW0_NEXT_PTR 8
#define XHCI_SUPPROTO_DW0_MINOR_REV 16
#define XHCI_SUPPROTO_DW0_MAJOR_REV 24
#define XHCI_SUPPROTO_DW1_NAME_STRING 0
#define XHCI_SUPPROTO_DW2_PORT_OFF 0
#define XHCI_SUPPROTO_DW2_PORT_COUNT 8
#define XHCI_SUPPROTO_DW2_PROT_DEF 16
#define XHCI_SUPPROTO_DW2_PSIC 28
#define XHCI_SUPPROTO_DW3_SLOT_TYPE 0
/* HCSPARAMS1 */
#define XHCI_HCSPARAMS1_MAX_DEV_SLOTS 0
#define XHCI_HCSPARAMS1_MAX_INTRS 8
#define XHCI_HCSPARAMS1_MAX_PORTS 24
/* HCSPARAMS2 */
#define XHCI_HCSPARAMS2_IST 0
#define XHCI_HCSPARAMS2_ERST_MAX 4
#define XHCI_HCSPARAMS2_MAX_SCRTCH_HI 21
#define XHCI_HCSPARAMS2_SPR 26
#define XHCI_HCSPARAMS2_MAX_SCRTCH_LO 27
/* event types */
#define XHCI_TRB_NORMAL 1
#define XHCI_TRB_SETUP_STAGE 2
#define XHCI_TRB_DATA_STAGE 3
#define XHCI_TRB_STATUS_STAGE 4
#define XHCI_TRB_ISOCH 5
#define XHCI_TRB_LINK 6
#define XHCI_TRB_EVENT_DATA 7
#define XHCI_TRB_NOOP 8
#define XHCI_TRB_SLOT_ENAB_CMD 9
#define XHCI_TRB_SLOT_DISB_CMD 10
#define XHCI_TRB_ADDR_DEV_CMD 11
#define XHCI_TRB_CFG_ENDP_CMD 12
#define XHCI_TRB_EVAL_CTX_CMD 13
#define XHCI_TRB_RESET_ENDP_CMD 14
#define XHCI_TRB_STOP_ENDP_CMD 15
#define XHCI_TRB_SET_DRDQP_CMD 16
#define XHCI_TRB_RESET_DEV_CMD 17
#define XHCI_TRB_FORCE_EVT_CMD 18
#define XHCI_TRB_NEGO_BANDW_CMD 19
#define XHCI_TRB_SET_LTV_CMD 20
#define XHCI_TRB_PORT_BANDW_CMD 21
#define XHCI_TRB_FORCE_HEADER 22
#define XHCI_TRB_NOOP_CMD 23
#define XHCI_TRB_GET_EXTPRP_CMD 24
#define XHCI_TRB_SET_EXTPRP_CMD 25
#define XHCI_TRB_TRANSFER_EVENT 32
#define XHCI_TRB_CMD_CMPL_EVENT 33
#define XHCI_TRB_PORT_STS_CHNG 34
#define XHCI_TRB_BANDW_RQ_EVENT 35
#define XHCI_TRB_DOORBELL_EVENT 36
#define XHCI_TRB_HOST_CTRL_EVNT 37
#define XHCI_TRB_DEV_NOTIF_EVNT 38
#define XHCI_TRB_MFINDEX_WRAP 39
/* generic TRB bits */
#define XHCI_GTRB_TRB_TYPE 10
#define XHCI_GTRB_CYCLE_BIT 0
/* command completion event TRB */
#define XHCI_CCETRB_CTRL_SLOT_ID 24
#define XHCI_CCETRB_CTRL_VFID 16
#define XHCI_CCETRB_CTRL_TRB_TYPE 10
#define XHCI_CCETRB_CTRL_CYCLEBIT 0
#define XHCI_CCETRB_STS_CMPL_CODE 24
/* transfer event TRB */
#define XHCI_TETRB_CTRL_SLOT_ID 24
#define XHCI_TETRB_CTRL_ENDPOINT 16
#define XHCI_TETRB_CTRL_TRB_TYPE 10
#define XHCI_TETRB_CTRL_EVT_DATA 2
#define XHCI_TETRB_CTRL_CYCLEBIT 0
#define XHCI_TETRB_STS_CMPL_CODE 24
/* port status change event TRB */
#define XHCI_PSCETRB_CTRL_TRB_TYPE 10
#define XHCI_PSCETRB_CTRL_CYCLEBIT 0
#define XHCI_PSCETRB_STS_CMPL_CODE 24
#define XHCI_PSCETRB_PARAM_PORT_ID 24
/* link TRB */
#define XHCI_LNKTRB_CTRL_TRB_TYPE 10
#define XHCI_LNKTRB_CTRL_IOC 5
#define XHCI_LNKTRB_CTRL_CH 4
#define XHCI_LNKTRB_CTRL_TC 1
#define XHCI_LNKTRB_CTRL_CYCLEBIT 0
#define XHCI_LNKTRB_STS_INTR_TRGT 22
/* setup stage TRB */
#define XHCI_SSTRB_CTRL_TRT 16
#define XHCI_SSTRB_CTRL_TRB_TYPE 10
#define XHCI_SSTRB_CTRL_IDT 6
#define XHCI_SSTRB_CTRL_IOC 5
#define XHCI_SSTRB_CTRL_CYCLEBIT 0
#define XHCI_SSTRB_STS_INTR_TRGT 22
#define XHCI_SSTRB_PARAM_WLENGTH 48
#define XHCI_SSTRB_PARAM_WINDEX 32
#define XHCI_SSTRB_PARAM_WVALUE 16
#define XHCI_SSTRB_PARAM_BREQUEST 8
#define XHCI_SSTRB_PARAM_BMREQUEST_TYPE 0
/* setup stage TRB transfer types */
#define XHCI_SSTRB_TRT_NO_DATA_STAGE 0
#define XHCI_SSTRB_TRT_OUT_DATA_STAGE 2
#define XHCI_SSTRB_TRT_IN_DATA_STAGE 3
/* data stage TRB */
#define XHCI_DSTRB_CTRL_DIR 16
#define XHCI_DSTRB_CTRL_TRB_TYPE 10
#define XHCI_DSTRB_CTRL_IDT 6
#define XHCI_DSTRB_CTRL_IOC 5
#define XHCI_DSTRB_CTRL_CH 4
#define XHCI_DSTRB_CTRL_NS 3
#define XHCI_DSTRB_CTRL_ISP 2
#define XHCI_DSTRB_CTRL_ENT 1
#define XHCI_DSTRB_CTRL_CYCLEBIT 0
#define XHCI_DSTRB_STS_INTR_TRGT 22
#define XHCI_DSTRB_STS_TD_SIZE 17
/* status stage TRB */
#define XHCI_STSTRB_CTRL_DIR 16
#define XHCI_STSTRB_CTRL_TRB_TYPE 10
#define XHCI_STSTRB_CTRL_IOC 5
#define XHCI_STSTRB_CTRL_CH 4
#define XHCI_STSTRB_CTRL_ENT 1
#define XHCI_STSTRB_CTRL_CYCLEBIT 0
#define XHCI_STSTRB_STS_INTR_TRGT 22
/* extended capabilities */
#define XHCI_EXTCAP_USB_LEGACY_SUPPORT 1
#define XHCI_EXTCAP_SUPPORTED_PROTOCOL 2
#define XHCI_EXTCAP_EXT_POWER_MNGMNT 3
#define XHCI_EXTCAP_IO_VIRT 4
#define XHCI_EXTCAP_MSG_INTR 5
#define XHCI_EXTCAP_LOCAL_MEMORY 6
#define XHCI_EXTCAP_USB_DEBUG 7
#define XHCI_EXTCAP_EXT_MSG_INTR 8
#define XHCI_EXTCAP_VENDOR_DEFINED 9
/* PORTSC bits */
#define XHCI_PORTSC_CCS 0
#define XHCI_PORTSC_PED 1
#define XHCI_PORTSC_OCA 3
#define XHCI_PORTSC_PR 4
#define XHCI_PORTSC_PLS 5
#define XHCI_PORTSC_PP 9
#define XHCI_PORTSC_PORTSPEED 10
#define XHCI_PORTSC_PIC 14
#define XHCI_PORTSC_LWS 16
#define XHCI_PORTSC_CSC 17
#define XHCI_PORTSC_PEC 18
#define XHCI_PORTSC_WRC 19
#define XHCI_PORTSC_OCC 20
#define XHCI_PORTSC_PRC 21
#define XHCI_PORTSC_PLC 22
#define XHCI_PORTSC_CEC 23
#define XHCI_PORTSC_CAS 24
#define XHCI_PORTSC_WCE 25
#define XCHI_PORTSC_WDE 26
#define XHCI_PORTSC_WOE 27
#define XHCI_PORTSC_DR 30
#define XHCI_PORTSC_WPR 31
/* endpoint context */
#define XHCI_EPCTX_EP_STATE 0
#define XHCI_EPCTX_MULT 8
#define XHCI_EPCTX_MAXPSTRAMS 10
#define XHCI_EPCTX_LSA 15
#define XHCI_EPCTX_INTERVAL 16
#define XHCI_EPCTX_MAX_ESIT_HI 24
#define XHCI_EPCTX_ERR_COUNT 1
#define XHCI_EPCTX_EP_TYPE 3
#define XHCI_EPCTX_HID 7
#define XHCI_EPCTX_MAX_BURST_SZ 8
#define XHCI_EPCTX_MAX_PKT_SZ 16
#define XHCI_EPCTX_DCS 0
#define XHCI_EPCTX_TR_DQ_PTR 4
#define XHCI_EPCTX_AVG_TRB_LEN 0
#define XHCI_EPCTX_MAX_ESIT_LOW 16
/* endpoint types */
#define XHCI_EP_INVALID 0
#define XHCI_EP_ISOCH_OUT 1
#define XHCI_EP_BULK_OUT 2
#define XHCI_EP_INTR_OUT 3
#define XHCI_EP_CTRL_BI 4
#define XHCI_EP_ISOCH_IN 5
#define XHCI_EP_BULK_IN 6
#define XHCI_EP_INTR_IN 7
/* slot context */
#define XHIC_SLCTX_ROUTE_STR 0
#define XHCI_SLCTX_SPEED 20
#define XHCI_SLCTX_MTT 25
#define XHCI_SLCTX_HUB 26
#define XHCI_SLCTX_CTX_ENTRIES 27
#define XHCI_SLCTX_MAXEXITLTNCY 0
#define XHCI_SLCTX_ROOTHUBPRNUM 16
#define XHCI_SLCTX_PORT_COUNT 24
#define XHCI_SLCTX_PRNT_HUB_SLT 0
#define XHCI_SLCTX_PARENT_PORT 8
#define XHCI_SLCTX_TT_THINKTIME 16
#define XHCI_SLCTX_INTR_TARGET 22
#define XHCI_SLCTX_USB_DEV_ADDR 0
#define XHCI_SLCTX_SLOT_STATE 27
/* clang-format on */
static uint8_t xhci_get_device_ctx_idx (struct usb_endpoint_desc* endpoint);
static void xhci_write8 (uintptr_t base, uint32_t reg, uint8_t value) {
*(volatile uint8_t*)(base + reg) = value;
}
static void xhci_write16 (uintptr_t base, uint32_t reg, uint16_t value) {
*(volatile uint16_t*)(base + reg) = value;
}
static void xhci_write32 (uintptr_t base, uint32_t reg, uint32_t value) {
*(volatile uint32_t*)(base + reg) = value;
}
@@ -314,10 +33,6 @@ static uint8_t xhci_read8 (uintptr_t base, uint32_t reg) {
return *(volatile uint8_t*)(base + reg);
}
static uint16_t xhci_read16 (uintptr_t base, uint32_t reg) {
return *(volatile uint16_t*)(base + reg);
}
static uint32_t xhci_read32 (uintptr_t base, uint32_t reg) {
return *(volatile uint32_t*)(base + reg);
}
@@ -347,12 +62,15 @@ static void xhci_create_usb_device (struct xhci* xhci, struct xhci_port* xhci_po
list_append (xhci->xhci_usb_devices, &usb_device->usb_devices_link);
}
static void xhci_delete_usb_device (struct xhci* xhci, struct xhci_port* xhci_port) {
struct xhci_usb_device* usb_device;
static void xhci_delete_usb_device (struct xhci* xhci, struct xhci_port* xhci_port,
struct proc* proc, struct reschedule_ctx* rctx) {
struct xhci_usb_device* usb_device = NULL;
list_find (struct xhci_usb_device, xhci->xhci_usb_devices, usb_device, xhci_port->port_value,
xhci_port->port_value, usb_devices_link);
device_delete (usb_device->device->key, proc, rctx);
list_remove (xhci->xhci_usb_devices, &usb_device->usb_devices_link);
if (usb_device->endpoint0_ring.phys != 0)
@@ -1186,20 +904,24 @@ static bool xhci_usb_device_setup_get_config_full (struct xhci* xhci,
static void xhci_poll_setup_init_ifs (struct xhci* xhci, struct xhci_usb_device* usb_device,
uint64_t* lockflags) {
struct reschedule_ctx rctx;
memset (&rctx, 0, sizeof (rctx));
for (size_t if0 = 0; if0 < usb_device->ifs_count; if0++) {
struct xhci_usb_device_if* if_ = &usb_device->ifs[if0];
for (size_t i = 0; i < USB_DRIVER_MAX_MATCHES; i++) {
struct usb_driver_info* info = &usb_driver_infos[i];
DEBUG ("%u %u / %u %u / %u %u\n", if_->desc.if_class, info->if_class, if_->desc.if_subclass,
info->if_subclass, if_->desc.if_proto, info->if_proto);
if (if_->desc.if_class == info->if_class &&
if_->desc.if_subclass == info->if_subclass &&
if_->desc.if_proto == info->if_proto) {
if (!info->init ())
struct device* device = info->init (xhci, usb_device, thiscpu->kproc, &rctx, lockflags);
if (device == NULL)
DEBUG ("USB driver failed to initialize. Skipping device!\n");
usb_device->device = device;
}
}
}
@@ -1227,7 +949,8 @@ static void xhci_poll_setup_devices (struct xhci* xhci, uint64_t* lockflags) {
}
}
static void xhci_poll_port_changes (struct xhci* xhci) {
static void xhci_poll_port_changes (struct xhci* xhci, struct proc* proc,
struct reschedule_ctx* rctx) {
struct list_node_link *port_change_link, *tmp_port_change_link;
struct xhci_port* xhci_port;
@@ -1248,7 +971,7 @@ static void xhci_poll_port_changes (struct xhci* xhci) {
} else {
DEBUG ("Device detached from port %u!\n", change->port);
xhci_delete_usb_device (xhci, xhci_port);
xhci_delete_usb_device (xhci, xhci_port, proc, rctx);
}
}
@@ -1256,10 +979,83 @@ static void xhci_poll_port_changes (struct xhci* xhci) {
}
}
int xhci_bulk_transfer (struct xhci* xhci, struct xhci_usb_device* usb_device,
uint8_t endpoint_addr, uintptr_t buffer_phys, size_t buffer_size,
uint64_t* lockflags) {
struct xhci_usb_device_endpoint* endpoint = NULL;
for (size_t ep = 0; ep < XHCI_USB_DEVICE_ENDPOINTS_MAX; ep++) {
endpoint = &usb_device->endpoints[ep];
if (endpoint->desc.endpoint_addr == endpoint_addr)
break;
}
if (endpoint == NULL)
return -ST_NOT_FOUND;
/* not bulk */
if ((endpoint->desc.attrs & 0x03) != 0x02)
return -ST_NOT_FOUND;
if (usb_device->slot_id < 0)
return -ST_NOT_FOUND;
xhci->last_cmpl_code = 0;
atomic_store (&xhci->pending, true);
uint32_t rem = buffer_size;
uint32_t current = buffer_phys;
while (rem > 0) {
uint32_t chunk = rem > 0x1FFFFU ? 0x1FFFFU : rem;
struct xhci_trb trb;
memset (&trb, 0, sizeof (trb));
trb.param = current;
trb.status = chunk;
write_memory_barrier ();
trb.ctrl = (XHCI_TRB_NORMAL << XHCI_GTRB_TRB_TYPE);
if (rem != chunk) {
trb.ctrl |= (1 << XHCI_DSTRB_CTRL_CH);
} else {
trb.ctrl |= (1 << XHCI_DSTRB_CTRL_IOC) | (1 << XHCI_DSTRB_CTRL_ISP);
}
xhci_ring_put_trb (&endpoint->transfer_ring, trb);
current += chunk;
rem -= chunk;
}
uint32_t dci = xhci_get_device_ctx_idx (&endpoint->desc);
int timeout = 100;
spin_unlock (&xhci->device->lock, *lockflags);
xhci_write32 (xhci->xhci_doorbell_base, usb_device->slot_id * 4, dci);
while (atomic_load (&xhci->pending) && --timeout > 0)
stall_ms (10);
spin_lock (&xhci->device->lock, lockflags);
if (timeout == 0) {
DEBUG ("bulk transfer timed out\n");
return -ST_TRY_AGAIN;
}
return xhci->last_cmpl_code == 1 ? ST_OK : -ST_USB_CTRL_ERROR;
}
DEFINE_DEVICE_OP (xhci_poll_driver) {
struct xhci* xhci = device->udata;
xhci_poll_port_changes (xhci);
xhci_poll_port_changes (xhci, proc, rctx);
xhci_poll_setup_devices (xhci, lockflags);
return ST_OK;
@@ -1436,7 +1232,7 @@ DEFINE_DEVICE_FINI (xhci_fini) {
list_remove (xhci->xhci_ports, &port->ports_link);
xhci_delete_usb_device (xhci, port);
xhci_delete_usb_device (xhci, port, proc, rctx);
free (port);
}

View File

@@ -3,6 +3,7 @@
#include <aux/compiler.h>
#include <device/def_device_op.h>
#include <device/device.h>
#include <device/usb/usb.h>
#include <libk/list.h>
#include <libk/std.h>
@@ -10,6 +11,285 @@
#include <proc/reschedule.h>
#include <proc/suspension_q.h>
/* REF:
* https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf
*/
/* clang-format off */
/* capability registers */
#define XHCI_CAPLENGTH 0x00
#define XHCI_RSVD 0x01
#define XHCI_HCIVERSION 0x02
#define XHCI_HCSPARAMS1 0x04
#define XHCI_HCSPARAMS2 0x08
#define XHCI_HCSPARAMS3 0x0C
#define XHCI_HCCPARAMS1 0x10
#define XHCI_DBOFF 0x14
#define XHCI_RTSOFF 0x18
#define XHCI_HCCPARAMS2 0x1C
/* operational registers */
#define XHCI_USBCMD 0x00
#define XHCI_USBSTS 0x04
#define XHCI_PAGESIZE 0x08
#define XHCI_DNCTRL 0x14
#define XHCI_CRCR 0x18
#define XHCI_DCBAAP 0x30
#define XHCI_CONFIG 0x38
/* port registers */
#define XHCI_PORTSC 0x00
#define XHCI_PORTPMSC 0x04
#define XHCI_PORTLI 0x08
/* runtime registers */
#define XHCI_MFINDEX 0x00
/* + IRQ sets (0x20) */
#define XHCI_IMAN 0x00
#define XHCI_IMOD 0x04
#define XHCI_ERSTSZ 0x08
#define XHCI_ERSTBA 0x10
#define XHCI_ERDP 0x18
/* HCCPARAMS1 */
#define XHCI_HCCPARAMS1_AC64 0
#define XHCI_HCCPARAMS1_BNC 1
#define XHCI_HCCPARAMS1_CSZ 2
#define XHCI_HCCPARAMS1_PPC 3
#define XHCI_HCCPARAMS1_PIND 4
#define XHCI_HCCPARAMS1_LHRC 5
#define XHCI_HCCPARAMS1_LTC 6
#define XHCI_HCCPARAMS1_NSS 7
#define XHCI_HCCPARAMS1_PAE 8
#define XHCI_HCCPARAMS1_SPC 9
#define XHCI_HCCPARAMS1_SEC 10
#define XHCI_HCCPARAMS1_CFC 11
#define XHCI_HCCPARAMS1_MAX_PSA_SIZE 12
#define XHCI_HCCPARAMS1_XECP 16
/* XHCI extended capabilities */
#define XHCI_XECP_CAP_ID 0
#define XHCI_XECP_NEXT_PTR 8
/* USB legacy support capability */
#define XHCI_USBLEGSUP_CAP_ID 0
#define XHCI_USBLEGSUP_NEXT_PTR 8
#define XHCI_USBLEGSUP_BIOS_SEMA 16
#define XHCI_USBLEGSUP_OS_SEMA 24
/* Supported protocol capability */
#define XHCI_SUPPROTO_DW0_CAP_ID 0
#define XHCI_SUPPROTO_DW0_NEXT_PTR 8
#define XHCI_SUPPROTO_DW0_MINOR_REV 16
#define XHCI_SUPPROTO_DW0_MAJOR_REV 24
#define XHCI_SUPPROTO_DW1_NAME_STRING 0
#define XHCI_SUPPROTO_DW2_PORT_OFF 0
#define XHCI_SUPPROTO_DW2_PORT_COUNT 8
#define XHCI_SUPPROTO_DW2_PROT_DEF 16
#define XHCI_SUPPROTO_DW2_PSIC 28
#define XHCI_SUPPROTO_DW3_SLOT_TYPE 0
/* HCSPARAMS1 */
#define XHCI_HCSPARAMS1_MAX_DEV_SLOTS 0
#define XHCI_HCSPARAMS1_MAX_INTRS 8
#define XHCI_HCSPARAMS1_MAX_PORTS 24
/* HCSPARAMS2 */
#define XHCI_HCSPARAMS2_IST 0
#define XHCI_HCSPARAMS2_ERST_MAX 4
#define XHCI_HCSPARAMS2_MAX_SCRTCH_HI 21
#define XHCI_HCSPARAMS2_SPR 26
#define XHCI_HCSPARAMS2_MAX_SCRTCH_LO 27
/* event types */
#define XHCI_TRB_NORMAL 1
#define XHCI_TRB_SETUP_STAGE 2
#define XHCI_TRB_DATA_STAGE 3
#define XHCI_TRB_STATUS_STAGE 4
#define XHCI_TRB_ISOCH 5
#define XHCI_TRB_LINK 6
#define XHCI_TRB_EVENT_DATA 7
#define XHCI_TRB_NOOP 8
#define XHCI_TRB_SLOT_ENAB_CMD 9
#define XHCI_TRB_SLOT_DISB_CMD 10
#define XHCI_TRB_ADDR_DEV_CMD 11
#define XHCI_TRB_CFG_ENDP_CMD 12
#define XHCI_TRB_EVAL_CTX_CMD 13
#define XHCI_TRB_RESET_ENDP_CMD 14
#define XHCI_TRB_STOP_ENDP_CMD 15
#define XHCI_TRB_SET_DRDQP_CMD 16
#define XHCI_TRB_RESET_DEV_CMD 17
#define XHCI_TRB_FORCE_EVT_CMD 18
#define XHCI_TRB_NEGO_BANDW_CMD 19
#define XHCI_TRB_SET_LTV_CMD 20
#define XHCI_TRB_PORT_BANDW_CMD 21
#define XHCI_TRB_FORCE_HEADER 22
#define XHCI_TRB_NOOP_CMD 23
#define XHCI_TRB_GET_EXTPRP_CMD 24
#define XHCI_TRB_SET_EXTPRP_CMD 25
#define XHCI_TRB_TRANSFER_EVENT 32
#define XHCI_TRB_CMD_CMPL_EVENT 33
#define XHCI_TRB_PORT_STS_CHNG 34
#define XHCI_TRB_BANDW_RQ_EVENT 35
#define XHCI_TRB_DOORBELL_EVENT 36
#define XHCI_TRB_HOST_CTRL_EVNT 37
#define XHCI_TRB_DEV_NOTIF_EVNT 38
#define XHCI_TRB_MFINDEX_WRAP 39
/* generic TRB bits */
#define XHCI_GTRB_TRB_TYPE 10
#define XHCI_GTRB_CYCLE_BIT 0
/* command completion event TRB */
#define XHCI_CCETRB_CTRL_SLOT_ID 24
#define XHCI_CCETRB_CTRL_VFID 16
#define XHCI_CCETRB_CTRL_TRB_TYPE 10
#define XHCI_CCETRB_CTRL_CYCLEBIT 0
#define XHCI_CCETRB_STS_CMPL_CODE 24
/* transfer event TRB */
#define XHCI_TETRB_CTRL_SLOT_ID 24
#define XHCI_TETRB_CTRL_ENDPOINT 16
#define XHCI_TETRB_CTRL_TRB_TYPE 10
#define XHCI_TETRB_CTRL_EVT_DATA 2
#define XHCI_TETRB_CTRL_CYCLEBIT 0
#define XHCI_TETRB_STS_CMPL_CODE 24
/* port status change event TRB */
#define XHCI_PSCETRB_CTRL_TRB_TYPE 10
#define XHCI_PSCETRB_CTRL_CYCLEBIT 0
#define XHCI_PSCETRB_STS_CMPL_CODE 24
#define XHCI_PSCETRB_PARAM_PORT_ID 24
/* link TRB */
#define XHCI_LNKTRB_CTRL_TRB_TYPE 10
#define XHCI_LNKTRB_CTRL_IOC 5
#define XHCI_LNKTRB_CTRL_CH 4
#define XHCI_LNKTRB_CTRL_TC 1
#define XHCI_LNKTRB_CTRL_CYCLEBIT 0
#define XHCI_LNKTRB_STS_INTR_TRGT 22
/* setup stage TRB */
#define XHCI_SSTRB_CTRL_TRT 16
#define XHCI_SSTRB_CTRL_TRB_TYPE 10
#define XHCI_SSTRB_CTRL_IDT 6
#define XHCI_SSTRB_CTRL_IOC 5
#define XHCI_SSTRB_CTRL_CYCLEBIT 0
#define XHCI_SSTRB_STS_INTR_TRGT 22
#define XHCI_SSTRB_PARAM_WLENGTH 48
#define XHCI_SSTRB_PARAM_WINDEX 32
#define XHCI_SSTRB_PARAM_WVALUE 16
#define XHCI_SSTRB_PARAM_BREQUEST 8
#define XHCI_SSTRB_PARAM_BMREQUEST_TYPE 0
/* setup stage TRB transfer types */
#define XHCI_SSTRB_TRT_NO_DATA_STAGE 0
#define XHCI_SSTRB_TRT_OUT_DATA_STAGE 2
#define XHCI_SSTRB_TRT_IN_DATA_STAGE 3
/* data stage TRB */
#define XHCI_DSTRB_CTRL_DIR 16
#define XHCI_DSTRB_CTRL_TRB_TYPE 10
#define XHCI_DSTRB_CTRL_IDT 6
#define XHCI_DSTRB_CTRL_IOC 5
#define XHCI_DSTRB_CTRL_CH 4
#define XHCI_DSTRB_CTRL_NS 3
#define XHCI_DSTRB_CTRL_ISP 2
#define XHCI_DSTRB_CTRL_ENT 1
#define XHCI_DSTRB_CTRL_CYCLEBIT 0
#define XHCI_DSTRB_STS_INTR_TRGT 22
#define XHCI_DSTRB_STS_TD_SIZE 17
/* status stage TRB */
#define XHCI_STSTRB_CTRL_DIR 16
#define XHCI_STSTRB_CTRL_TRB_TYPE 10
#define XHCI_STSTRB_CTRL_IOC 5
#define XHCI_STSTRB_CTRL_CH 4
#define XHCI_STSTRB_CTRL_ENT 1
#define XHCI_STSTRB_CTRL_CYCLEBIT 0
#define XHCI_STSTRB_STS_INTR_TRGT 22
/* extended capabilities */
#define XHCI_EXTCAP_USB_LEGACY_SUPPORT 1
#define XHCI_EXTCAP_SUPPORTED_PROTOCOL 2
#define XHCI_EXTCAP_EXT_POWER_MNGMNT 3
#define XHCI_EXTCAP_IO_VIRT 4
#define XHCI_EXTCAP_MSG_INTR 5
#define XHCI_EXTCAP_LOCAL_MEMORY 6
#define XHCI_EXTCAP_USB_DEBUG 7
#define XHCI_EXTCAP_EXT_MSG_INTR 8
#define XHCI_EXTCAP_VENDOR_DEFINED 9
/* PORTSC bits */
#define XHCI_PORTSC_CCS 0
#define XHCI_PORTSC_PED 1
#define XHCI_PORTSC_OCA 3
#define XHCI_PORTSC_PR 4
#define XHCI_PORTSC_PLS 5
#define XHCI_PORTSC_PP 9
#define XHCI_PORTSC_PORTSPEED 10
#define XHCI_PORTSC_PIC 14
#define XHCI_PORTSC_LWS 16
#define XHCI_PORTSC_CSC 17
#define XHCI_PORTSC_PEC 18
#define XHCI_PORTSC_WRC 19
#define XHCI_PORTSC_OCC 20
#define XHCI_PORTSC_PRC 21
#define XHCI_PORTSC_PLC 22
#define XHCI_PORTSC_CEC 23
#define XHCI_PORTSC_CAS 24
#define XHCI_PORTSC_WCE 25
#define XCHI_PORTSC_WDE 26
#define XHCI_PORTSC_WOE 27
#define XHCI_PORTSC_DR 30
#define XHCI_PORTSC_WPR 31
/* endpoint context */
#define XHCI_EPCTX_EP_STATE 0
#define XHCI_EPCTX_MULT 8
#define XHCI_EPCTX_MAXPSTRAMS 10
#define XHCI_EPCTX_LSA 15
#define XHCI_EPCTX_INTERVAL 16
#define XHCI_EPCTX_MAX_ESIT_HI 24
#define XHCI_EPCTX_ERR_COUNT 1
#define XHCI_EPCTX_EP_TYPE 3
#define XHCI_EPCTX_HID 7
#define XHCI_EPCTX_MAX_BURST_SZ 8
#define XHCI_EPCTX_MAX_PKT_SZ 16
#define XHCI_EPCTX_DCS 0
#define XHCI_EPCTX_TR_DQ_PTR 4
#define XHCI_EPCTX_AVG_TRB_LEN 0
#define XHCI_EPCTX_MAX_ESIT_LOW 16
/* endpoint types */
#define XHCI_EP_INVALID 0
#define XHCI_EP_ISOCH_OUT 1
#define XHCI_EP_BULK_OUT 2
#define XHCI_EP_INTR_OUT 3
#define XHCI_EP_CTRL_BI 4
#define XHCI_EP_ISOCH_IN 5
#define XHCI_EP_BULK_IN 6
#define XHCI_EP_INTR_IN 7
/* slot context */
#define XHIC_SLCTX_ROUTE_STR 0
#define XHCI_SLCTX_SPEED 20
#define XHCI_SLCTX_MTT 25
#define XHCI_SLCTX_HUB 26
#define XHCI_SLCTX_CTX_ENTRIES 27
#define XHCI_SLCTX_MAXEXITLTNCY 0
#define XHCI_SLCTX_ROOTHUBPRNUM 16
#define XHCI_SLCTX_PORT_COUNT 24
#define XHCI_SLCTX_PRNT_HUB_SLT 0
#define XHCI_SLCTX_PARENT_PORT 8
#define XHCI_SLCTX_TT_THINKTIME 16
#define XHCI_SLCTX_INTR_TARGET 22
#define XHCI_SLCTX_USB_DEV_ADDR 0
#define XHCI_SLCTX_SLOT_STATE 27
/* clang-format on */
/* event ring segment table entry */
struct xhci_erst_entry {
volatile uint64_t ptr;
@@ -88,6 +368,7 @@ struct xhci_usb_device {
struct list_node_link usb_devices_link;
struct xhci_port* xhci_port;
int slot_id;
struct device* device;
struct xhci_ring endpoint0_ring;
@@ -145,10 +426,12 @@ struct xhci {
uint8_t last_slot_id;
uint8_t last_cmpl_code;
struct list_node_link* port_changes;
spin_lock_t setup_lock;
};
int xhci_bulk_transfer (struct xhci* xhci, struct xhci_usb_device* usb_device,
uint8_t endpoint_addr, uintptr_t buffer_phys, size_t buffer_size,
uint64_t* lockflags);
DEFINE_DEVICE_INIT (xhci_init);
DEFINE_DEVICE_FINI (xhci_fini);

View File

@@ -3,4 +3,20 @@
#define BE2LE16(x) (((x) << 8) | (((x) >> 8)))
#define BE2LE32(x) \
((((x) & 0x000000FF) << 24) | \
(((x) & 0x0000FF00) << 8) | \
(((x) & 0x00FF0000) >> 8) | \
(((x) & 0xFF000000) >> 24))
#define BE2LE64(x) \
((((x) & 0x00000000000000FFULL) << 56) | \
(((x) & 0x000000000000FF00ULL) << 40) | \
(((x) & 0x0000000000FF0000ULL) << 24) | \
(((x) & 0x00000000FF000000ULL) << 8) | \
(((x) & 0x000000FF00000000ULL) >> 8) | \
(((x) & 0x0000FF0000000000ULL) >> 24) | \
(((x) & 0x00FF000000000000ULL) >> 40) | \
(((x) & 0xFF00000000000000ULL) >> 56))
#endif // _KERNEL_LIBK_ENDIANESS_H

View File

@@ -30,6 +30,31 @@ static inline uint32_t hash_fnv32 (const void* data, size_t len) {
(table)->buckets_name[__idx] = (new_link); \
} while (0)
#define hash_delete(table, key_ptr, key_size, hash_val, table_size, buckets_name, type, member, \
key_field, out_link) \
do { \
uint32_t __idx = (hash_val) % (table_size); \
struct hash_node_link* __curr = (table)->buckets_name[__idx]; \
struct hash_node_link* __prev = NULL; \
(out_link) = NULL; \
while (__curr) { \
if (__curr->hash == (hash_val)) { \
type* __entry = hash_entry (__curr, type, member); \
if (memcmp (__entry->key_field, (key_ptr), (key_size)) == 0) { \
if (__prev != NULL) { \
__prev->next = __curr->next; \
} else { \
(table)->buckets_name[__idx] = __curr->next; \
} \
(out_link) = __curr; \
break; \
} \
} \
__prev = __curr; \
__curr = __curr->next; \
} \
} while (0)
#define hash_find(table, key_ptr, key_size, hash_val, table_size, buckets_name, type, member, \
key_field, out_link) \
do { \

View File

@@ -29,6 +29,7 @@ static const char* str_status[] = {
[ST_XDRV_READ_ERROR] = "drive read error",
[ST_XDRV_WRITE_ERROR] = "drive write error",
[ST_NOT_PARTIAL] = "not a partially created process",
[ST_USB_CTRL_ERROR] = "USB controller error",
};
#endif // _LIBSYSTEM_STR_STATUS_H