17#define ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1))
25 log(
mod,
"common config BAR: %d", common_bar);
28 dev_->pci.bar[common_bar].address +
dev_->common_cfg.offset;
29 log(
mod,
"common config phys addr: 0x%x", common_phys);
32 (
volatile virtio_pci_common_cfg_t*) common_phys;
35 dev_->pci.bar[common_bar].address +
dev_->notify_cfg.offset;
37 log(
mod,
"notify config phys addr: 0x%x", notify_phys);
57 log(
mod,
"Feature negotiation failed");
61 auto device_features =
common_cfg->device_feature;
62 log(
mod,
"Device features: 0x%x", device_features);
75 device_features & 0x1;
80 log(
mod,
"Feature negotiation failed");
101 size_t vq_total_size =
105 void* vq_mem = IOUtils::DMAAlloc(vq_total_size, &vq_phys);
108 log(
mod,
"Failed to allocate virtqueue memory");
111 memset(vq_mem, 0, vq_total_size);
123 common_cfg->queue_used = vq_phys + used_offset;
128 "Virtqueue configured: desc=0x%x, avail=0x%x, used=0x%x, "
129 "notify_offset_=0x%x",
135 log(
mod,
"Queue enabled");
142 for (
volatile int i = 0; i < 100000; i++)
147 log(
mod,
"VirtIO GPU initialized successfully");
150 if (
dev_->pci.interrupt_line) {
161 sizeof(*test_cmd), &test_phys);
166 sizeof(*test_resp), &test_resp_phys);
168 if (!test_cmd || !test_resp) {
169 log(
mod,
"Failed to allocate test buffers");
174 memset(test_cmd, 0,
sizeof(*test_cmd));
177 memset(test_resp, 0,
sizeof(*test_resp));
179 log(
mod,
"Test buffers allocated: cmd=0x%x, resp=0x%x", test_cmd,
183 for (
volatile int i = 0; i < 1000000; i++)
188 (
void*) test_phys,
sizeof(*test_cmd), (
void*) test_resp_phys,
192 log(
mod,
"GPU communication test PASSED");
195 log(
mod,
"Response type: 0x%x len : %d", test_resp->
hdr.
type,
199 log(
mod,
"Display info received successfully");
200 int enabled_count = 0;
201 for (
int i = 0; i < 16; i++) {
203 log(
mod,
"Scanout %d: %dx%d at (%d,%d)",
211 if (enabled_count == 0) {
212 log(
mod,
"No enabled display modes found");
215 log(
mod,
"Unexpected response type: 0x%x",
219 log(
mod,
"GPU communication test FAILED");
224 log(
mod,
"Test resource created successfully");
226 log(
mod,
"Failed to create test resource");
237 if (isr & (1 << 0)) {
244 log(
mod,
"No free descriptors");
304 log(
mod,
"Virtqueue initialized: desc=%x, avail=%x, used=%x", vq->
desc,
312 if (num_out + num_in == 0 || num_out + num_in > vq->
num_free) {
313 log(
mod,
"Not enough descriptors: free=%d, needed=%d",
322 log(
mod,
"Building descriptor chain, head=%d, num_out=%d, num_in=%d",
323 head, num_out, num_in);
326 for (
uint16_t i = 0; i < num_out; i++) {
333 log(
mod,
"OUT desc[%d]: phys=0x%x, len=%d, flags=0x%x, next=%d",
337 if (i < num_out - 1) {
344 for (
uint16_t i = 0; i < num_in; i++) {
346 if (i == 0 && num_out == 0) {
360 log(
mod,
"IN desc[%d]: phys=0x%x, len=%d, flags=0x%x",
idx,
363 if (i < num_in - 1) {
372 log(
mod,
"Last IN desc[%d]: flags=0x%x (NEXT removed)",
prev,
374 }
else if (num_out > 0) {
376 log(
mod,
"Last OUT desc[%d]: flags=0x%x (NEXT removed)",
prev,
385 asm volatile(
"mfence" :::
"memory");
393 "Notifying queue %d at address 0x%x (notify_base=%0x%x, "
400 *notify_reg = queue_index;
403 asm volatile(
"mfence" :::
"memory");
409 asm volatile(
"" :::
"memory");
433 if (
cmd && cmd_size > 0) {
435 lengths[0] = cmd_size;
437 log(
mod,
"Command buffer: virt=%x, size=%d",
cmd, cmd_size);
441 if (resp && resp_size > 0) {
442 buffers[num_out] = resp;
443 lengths[num_out] = resp_size;
445 log(
mod,
"Response buffer: virt=%x, size=%d", resp, resp_size);
452 log(
mod,
"Failed to add buffer to virtqueue");
464 asm volatile(
"mfence" :::
"memory");
468 log(
mod,
"Added buffer head=%d to avail ring[%d], new avail->idx=%d",
474 int timeout = 5000000;
476 for (
int i = 0; i < timeout; i++) {
478 asm volatile(
"" :::
"memory");
490 "Got used element: id=%d, len=%d (expected "
492 used_id, used_len,
head);
494 if (used_id ==
head) {
513 "Command completed successfully (head=%d)",
521 "Unexpected used id=%d (expected %d), "
530 log(
mod,
"ISR triggered, re-checking used ring");
538 if (i % 100000 == 0) {
539 log(
mod,
"Still waiting for response... (i=%d)", i);
544 log(
mod,
"Timeout waiting for command response (head=%d)",
head);
545 log(
mod,
"Used ring state: last_used_idx=%d, used->idx=%d",
548 log(
mod,
"Descriptor chain for head=%d:",
head);
552 log(
mod,
" desc[%d]: addr=0x%lx, len=%d, flags=0x%x, next=%d",
static AHCIModule instance
ioforge_virtio_device * dev_
static VirtioGpu * getInstance()
uint32_t notify_multiplier_
int virtq_get_used_elem(struct virtio_gpu_queue *vq, uint16_t *id, uint32_t *len)
int virtio_gpu_create_resource(uint32_t resource_id, uint32_t width, uint32_t height)
void virtq_free_desc(struct virtio_gpu_queue *vq, uint16_t desc_idx)
uint16_t virtq_alloc_desc(struct virtio_gpu_queue *vq)
static struct virtio_gpu_queue control_queue_
void virtq_init(struct virtio_gpu_queue *vq, void *vq_mem, uint16_t queue_size, uintptr_t phys_addr)
static void fireHandler()
void virtq_kick(uint16_t queue_index)
int virtq_add_buf(struct virtio_gpu_queue *vq, void **buffers, uint32_t *lengths, uint16_t num_out, uint16_t num_in, uint16_t *head_out)
int virtio_gpu_send_command(void *cmd, uint32_t cmd_size, void *resp, uint32_t resp_size)
elf_section_map uintptr_t base
uint32_t isr_irq_register(uint8_t irq, void *handler)
#define log(mod, fmt,...)
struct virtio_pci_cap common_cfg
#define ALIGN_UP(x, align)
void memset(void *ptr, int value, size_t num)
struct virtq_avail * avail
struct virtio_gpu_rect rect
struct virtio_gpu_resp_display_info::virtio_gpu_display_one pmodes[16]
struct virtio_gpu_ctrl_hdr hdr
struct virtq_used_elem ring[64]
static volatile boolean_t interrupt_exist
#define VIRTIO_STATUS_DRIVER_OK
#define VIRTQ_DESC_F_WRITE
#define VIRTQ_DESC_F_NEXT
#define VIRTIO_GPU_QUEUE_ALIGN
#define VIRTIO_STATUS_DRIVER
#define VIRTIO_GPU_QUEUE_SIZE
#define VIRTIO_STATUS_ACKNOWLEDGE
#define VIRTIO_GPU_RESP_OK_DISPLAY_INFO
#define VIRTIO_GPU_CMD_GET_DISPLAY_INFO
#define VIRTIO_STATUS_FEATURES_OK