1 /*
2 * Copyright 2013, 2018, Jérôme Duval, jerome.duval@gmail.com.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7 #include <new>
8 #include <stdio.h>
9 #include <string.h>
10
11 #include <bus/PCI.h>
12 #include <SupportDefs.h>
13
14 #include <cpu.h>
15 #include <kernel.h>
16 #include <virtio.h>
17
18 #include "virtio_pci.h"
19
20
21 //#define TRACE_VIRTIO
22 #ifdef TRACE_VIRTIO
23 # define TRACE(x...) dprintf("\33[33mvirtio_pci:\33[0m " x)
24 #else
25 # define TRACE(x...) ;
26 #endif
27 #define TRACE_ALWAYS(x...) dprintf("\33[33mvirtio_pci:\33[0m " x)
28 #define ERROR(x...) dprintf("\33[33mvirtio_pci:\33[0m " x)
29 #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
30
31
32 #define VIRTIO_PCI_DEVICE_MODULE_NAME "busses/virtio/virtio_pci/driver_v1"
33 #define VIRTIO_PCI_SIM_MODULE_NAME "busses/virtio/virtio_pci/device/v1"
34
35 #define VIRTIO_PCI_CONTROLLER_TYPE_NAME "virtio pci controller"
36
37 typedef enum {
38 VIRTIO_IRQ_LEGACY,
39 VIRTIO_IRQ_MSI_X_SHARED,
40 VIRTIO_IRQ_MSI_X,
41 } virtio_irq_type;
42
43 typedef struct {
44 virtio_sim sim;
45 uint16 queue;
46 } virtio_pci_queue_cookie;
47
48 typedef struct {
49 pci_device_module_info* pci;
50 pci_device* device;
51 bool virtio1;
52 addr_t base_addr;
53 area_id registersArea[6];
54 addr_t commonCfgAddr;
55 addr_t isrAddr;
56 addr_t notifyAddr;
57 uint32 notifyOffsetMultiplier;
58 uint32 irq;
59 virtio_irq_type irq_type;
60 virtio_sim sim;
61 uint16 queue_count;
62 addr_t* notifyOffsets;
63
64 device_node* node;
65 pci_info info;
66
67 virtio_pci_queue_cookie *cookies;
68 } virtio_pci_sim_info;
69
70
71 device_manager_info* gDeviceManager;
72 virtio_for_controller_interface* gVirtio;
73
74
75 static status_t
virtio_pci_find_capability(virtio_pci_sim_info * bus,uint8 cfgType,void * buffer,size_t size)76 virtio_pci_find_capability(virtio_pci_sim_info* bus, uint8 cfgType,
77 void* buffer, size_t size)
78 {
79 uint8 capabilityOffset;
80 if (bus->pci->find_pci_capability(bus->device, PCI_cap_id_vendspec, &capabilityOffset) != B_OK)
81 return B_ENTRY_NOT_FOUND;
82
83 if (size < sizeof(virtio_pci_cap))
84 return B_RESULT_NOT_REPRESENTABLE;
85 union regs {
86 uint32 reg[8];
87 struct virtio_pci_cap capability;
88 } * v = (union regs*)buffer;
89
90 while (capabilityOffset != 0) {
91 for (int i = 0; i < 4; i++) {
92 v->reg[i] = bus->pci->read_pci_config(bus->device, capabilityOffset + i * 4, 4);
93 }
94 if (v->capability.cfg_type == cfgType)
95 break;
96 capabilityOffset = v->capability.cap_next;
97 }
98 if (capabilityOffset == 0)
99 return B_ENTRY_NOT_FOUND;
100
101 if (v->capability.length > sizeof(virtio_pci_cap)) {
102 size_t length = min_c(ROUNDUP(v->capability.length, sizeof(uint32)), size);
103 for (size_t i = 4; i < length / sizeof(uint32); i++)
104 v->reg[i] = bus->pci->read_pci_config(bus->device, capabilityOffset + i * 4, 4);
105 }
106 return B_OK;
107 }
108
109
110 static int32
virtio_pci_interrupt(void * data)111 virtio_pci_interrupt(void *data)
112 {
113 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)data;
114 uint8 isr;
115 if (bus->virtio1) {
116 uint8* isrAddr = (uint8*)bus->isrAddr;
117 isr = *isrAddr;
118 } else {
119 isr = bus->pci->read_io_8(bus->device,
120 bus->base_addr + VIRTIO_PCI_ISR);
121 }
122 if (isr == 0)
123 return B_UNHANDLED_INTERRUPT;
124
125 if (isr & VIRTIO_PCI_ISR_CONFIG)
126 gVirtio->config_interrupt_handler(bus->sim);
127
128 if (isr & VIRTIO_PCI_ISR_INTR)
129 gVirtio->queue_interrupt_handler(bus->sim, INT16_MAX);
130
131 return B_HANDLED_INTERRUPT;
132 }
133
134
135 static int32
virtio_pci_config_interrupt(void * data)136 virtio_pci_config_interrupt(void *data)
137 {
138 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)data;
139 gVirtio->config_interrupt_handler(bus->sim);
140
141 return B_HANDLED_INTERRUPT;
142 }
143
144
145 static int32
virtio_pci_queue_interrupt(void * data)146 virtio_pci_queue_interrupt(void *data)
147 {
148 virtio_pci_queue_cookie* cookie = (virtio_pci_queue_cookie*)data;
149 gVirtio->queue_interrupt_handler(cookie->sim, cookie->queue);
150
151 return B_HANDLED_INTERRUPT;
152 }
153
154
155 static int32
virtio_pci_queues_interrupt(void * data)156 virtio_pci_queues_interrupt(void *data)
157 {
158 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)data;
159 gVirtio->queue_interrupt_handler(bus->sim, INT16_MAX);
160
161 return B_HANDLED_INTERRUPT;
162 }
163
164
165 static status_t
virtio_pci_setup_msix_interrupts(virtio_pci_sim_info * bus)166 virtio_pci_setup_msix_interrupts(virtio_pci_sim_info* bus)
167 {
168 CALLED();
169 uint8 irq = 0; // first irq slot
170 if (bus->virtio1) {
171 volatile uint16 *msixVector = (uint16*)(bus->commonCfgAddr
172 + offsetof(struct virtio_pci_common_cfg, config_msix_vector));
173 *msixVector = irq;
174 } else {
175 bus->pci->write_io_16(bus->device, bus->base_addr
176 + VIRTIO_MSI_CONFIG_VECTOR, irq);
177 if (bus->pci->read_io_16(bus->device, bus->base_addr
178 + VIRTIO_MSI_CONFIG_VECTOR) == VIRTIO_MSI_NO_VECTOR) {
179 ERROR("msix config vector incorrect\n");
180 return B_BAD_VALUE;
181 }
182 }
183 if (bus->irq_type == VIRTIO_IRQ_MSI_X || bus->irq_type == VIRTIO_IRQ_MSI_X_SHARED)
184 irq++;
185
186 for (uint16 queue = 0; queue < bus->queue_count; queue++) {
187 if (bus->virtio1) {
188 volatile uint16* queueSelect = (uint16*)(bus->commonCfgAddr
189 + offsetof(struct virtio_pci_common_cfg, queue_select));
190 *queueSelect = queue;
191 volatile uint16* msixVector = (uint16*)(bus->commonCfgAddr
192 + offsetof(struct virtio_pci_common_cfg, queue_msix_vector));
193 *msixVector = irq;
194 } else {
195 bus->pci->write_io_16(bus->device, bus->base_addr
196 + VIRTIO_PCI_QUEUE_SEL, queue);
197 bus->pci->write_io_16(bus->device, bus->base_addr
198 + VIRTIO_MSI_QUEUE_VECTOR, irq);
199
200 if (bus->pci->read_io_16(bus->device, bus->base_addr
201 + VIRTIO_MSI_QUEUE_VECTOR) == VIRTIO_MSI_NO_VECTOR) {
202 ERROR("msix queue vector incorrect\n");
203 return B_BAD_VALUE;
204 }
205 }
206 if (bus->irq_type == VIRTIO_IRQ_MSI_X)
207 irq++;
208 }
209
210 return B_OK;
211 }
212
213
214 static void
set_sim(void * cookie,virtio_sim sim)215 set_sim(void* cookie, virtio_sim sim)
216 {
217 CALLED();
218 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie;
219 bus->sim = sim;
220 }
221
222
223 static status_t
read_host_features(void * cookie,uint64 * features)224 read_host_features(void* cookie, uint64 *features)
225 {
226 CALLED();
227 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie;
228
229 TRACE("read_host_features() %p node %p pci %p device %p\n", bus,
230 bus->node, bus->pci, bus->device);
231
232 if (bus->virtio1) {
233 volatile uint32 *select = (uint32*)(bus->commonCfgAddr
234 + offsetof(struct virtio_pci_common_cfg, device_feature_select));
235 volatile uint32 *feature = (uint32*)(bus->commonCfgAddr
236 + offsetof(struct virtio_pci_common_cfg, device_feature));
237 *select = 0;
238 *features = *feature;
239 *select = 1;
240 *features |= ((uint64)*feature << 32) ;
241 TRACE("read_host_features() %" B_PRIx64 "\n", *features);
242 } else {
243 *features = bus->pci->read_io_32(bus->device,
244 bus->base_addr + VIRTIO_PCI_HOST_FEATURES);
245 }
246 return B_OK;
247 }
248
249
250 static status_t
write_guest_features(void * cookie,uint64 features)251 write_guest_features(void* cookie, uint64 features)
252 {
253 CALLED();
254 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie;
255 if (bus->virtio1) {
256 volatile uint32 *select = (uint32*)(bus->commonCfgAddr
257 + offsetof(struct virtio_pci_common_cfg, device_feature_select));
258 volatile uint32 *feature = (uint32*)(bus->commonCfgAddr
259 + offsetof(struct virtio_pci_common_cfg, device_feature));
260 *select = 0;
261 *feature = features & 0xffffffff;
262 *select = 1;
263 *feature = (features >> 32) ;
264 } else {
265 bus->pci->write_io_32(bus->device, bus->base_addr
266 + VIRTIO_PCI_GUEST_FEATURES, features);
267 }
268 return B_OK;
269 }
270
271
272 static uint8
get_status(void * cookie)273 get_status(void* cookie)
274 {
275 CALLED();
276 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie;
277 if (bus->virtio1) {
278 uint8 *addr = (uint8*)(bus->commonCfgAddr
279 + offsetof(struct virtio_pci_common_cfg, device_status));
280 return *addr;
281 } else {
282 return bus->pci->read_io_8(bus->device, bus->base_addr + VIRTIO_PCI_STATUS);
283 }
284 }
285
286
287 static void
set_status(void * cookie,uint8 status)288 set_status(void* cookie, uint8 status)
289 {
290 CALLED();
291 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie;
292 if (bus->virtio1) {
293 volatile uint8 *addr = (uint8*)(bus->commonCfgAddr
294 + offsetof(struct virtio_pci_common_cfg, device_status));
295 if (status == 0) {
296 *addr = 0;
297 while (*addr != 0)
298 cpu_pause();
299 } else {
300 uint8 old = 0;
301 if (status != 0)
302 old = *addr;
303 *addr = status | old;
304 }
305 } else {
306 if (status == 0) {
307 bus->pci->write_io_8(bus->device, bus->base_addr + VIRTIO_PCI_STATUS, 0);
308 while (bus->pci->read_io_8(bus->device, bus->base_addr + VIRTIO_PCI_STATUS) != 0)
309 cpu_pause();
310 } else {
311 uint8 old = bus->pci->read_io_8(bus->device, bus->base_addr + VIRTIO_PCI_STATUS);
312 bus->pci->write_io_8(bus->device, bus->base_addr + VIRTIO_PCI_STATUS, status | old);
313 }
314 }
315 }
316
317
318 static status_t
read_device_config(void * cookie,uint8 _offset,void * _buffer,size_t bufferSize)319 read_device_config(void* cookie, uint8 _offset, void* _buffer,
320 size_t bufferSize)
321 {
322 CALLED();
323 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie;
324
325 addr_t offset = bus->base_addr + _offset;
326 if (!bus->virtio1)
327 offset += VIRTIO_PCI_CONFIG(bus);
328 uint8* buffer = (uint8*)_buffer;
329 while (bufferSize > 0) {
330 uint8 size = 4;
331 if (bufferSize == 1) {
332 size = 1;
333 if (bus->virtio1) {
334 *buffer = *(uint8*)offset;
335 } else {
336 *buffer = bus->pci->read_io_8(bus->device, offset);
337 }
338 } else if (bufferSize <= 3) {
339 size = 2;
340 if (bus->virtio1) {
341 *(uint16*)buffer = *(uint16*)offset;
342 } else {
343 *(uint16*)buffer = bus->pci->read_io_16(bus->device, offset);
344 }
345 } else {
346 if (bus->virtio1) {
347 *(uint32*)buffer = *(uint32*)offset;
348 } else {
349 *(uint32*)buffer = bus->pci->read_io_32(bus->device,
350 offset);
351 }
352 }
353 buffer += size;
354 bufferSize -= size;
355 offset += size;
356 }
357
358 return B_OK;
359 }
360
361
362 static status_t
write_device_config(void * cookie,uint8 _offset,const void * _buffer,size_t bufferSize)363 write_device_config(void* cookie, uint8 _offset, const void* _buffer,
364 size_t bufferSize)
365 {
366 CALLED();
367 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie;
368
369 addr_t offset = bus->base_addr + _offset;
370 if (!bus->virtio1)
371 offset += VIRTIO_PCI_CONFIG(bus);
372 const uint8* buffer = (const uint8*)_buffer;
373 while (bufferSize > 0) {
374 uint8 size = 4;
375 if (bufferSize == 1) {
376 size = 1;
377 if (bus->virtio1) {
378 *(uint8*)offset = *buffer;
379 } else {
380 bus->pci->write_io_8(bus->device, offset, *buffer);
381 }
382 } else if (bufferSize <= 3) {
383 size = 2;
384 if (bus->virtio1) {
385 *(uint16*)offset = *(uint16*)buffer;
386 } else {
387 bus->pci->write_io_16(bus->device, offset, *(const uint16*)buffer);
388 }
389 } else {
390 if (bus->virtio1) {
391 *(uint32*)offset = *(uint32*)buffer;
392 } else {
393 bus->pci->write_io_32(bus->device, offset, *(const uint32*)buffer);
394 }
395 }
396 buffer += size;
397 bufferSize -= size;
398 offset += size;
399 }
400 return B_OK;
401 }
402
403
404 static uint16
get_queue_ring_size(void * cookie,uint16 queue)405 get_queue_ring_size(void* cookie, uint16 queue)
406 {
407 CALLED();
408 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie;
409 if (bus->virtio1) {
410 volatile uint16* queueSelect = (uint16*)(bus->commonCfgAddr
411 + offsetof(struct virtio_pci_common_cfg, queue_select));
412 *queueSelect = queue;
413 volatile uint16* ringSize = (volatile uint16*)(bus->commonCfgAddr
414 + offsetof(struct virtio_pci_common_cfg, queue_size));
415 return *ringSize;
416 } else {
417 bus->pci->write_io_16(bus->device, bus->base_addr + VIRTIO_PCI_QUEUE_SEL,
418 queue);
419 return bus->pci->read_io_16(bus->device, bus->base_addr
420 + VIRTIO_PCI_QUEUE_NUM);
421 }
422 }
423
424
425 static status_t
setup_queue(void * cookie,uint16 queue,phys_addr_t phy,phys_addr_t phyAvail,phys_addr_t phyUsed)426 setup_queue(void* cookie, uint16 queue, phys_addr_t phy, phys_addr_t phyAvail,
427 phys_addr_t phyUsed)
428 {
429 CALLED();
430 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie;
431 if (queue >= bus->queue_count)
432 return B_BAD_VALUE;
433
434 if (bus->virtio1) {
435 volatile uint16* queueSelect = (uint16*)(bus->commonCfgAddr
436 + offsetof(struct virtio_pci_common_cfg, queue_select));
437 *queueSelect = queue;
438
439 volatile uint64* queueDesc = (volatile uint64*)(bus->commonCfgAddr
440 + offsetof(struct virtio_pci_common_cfg, queue_desc));
441 *queueDesc = phy;
442 volatile uint64* queueAvail = (volatile uint64*)(bus->commonCfgAddr
443 + offsetof(struct virtio_pci_common_cfg, queue_avail));
444 *queueAvail = phyAvail;
445 volatile uint64* queueUsed = (volatile uint64*)(bus->commonCfgAddr
446 + offsetof(struct virtio_pci_common_cfg, queue_used));
447 *queueUsed = phyUsed;
448 volatile uint16* queueEnable = (volatile uint16*)(bus->commonCfgAddr
449 + offsetof(struct virtio_pci_common_cfg, queue_enable));
450 *queueEnable = 1;
451
452 volatile uint16* queueNotifyOffset = (volatile uint16*)(bus->commonCfgAddr
453 + offsetof(struct virtio_pci_common_cfg, queue_notify_off));
454 bus->notifyOffsets[queue] = *queueNotifyOffset * bus->notifyOffsetMultiplier;
455 } else {
456 bus->pci->write_io_16(bus->device, bus->base_addr + VIRTIO_PCI_QUEUE_SEL, queue);
457 bus->pci->write_io_32(bus->device, bus->base_addr + VIRTIO_PCI_QUEUE_PFN,
458 (uint32)phy >> VIRTIO_PCI_QUEUE_ADDR_SHIFT);
459 }
460 return B_OK;
461 }
462
463
464 static status_t
setup_interrupt(void * cookie,uint16 queueCount)465 setup_interrupt(void* cookie, uint16 queueCount)
466 {
467 CALLED();
468 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie;
469 pci_info *pciInfo = &bus->info;
470
471 bus->queue_count = queueCount;
472
473 // try MSI-X
474 uint32 msixCount = bus->pci->get_msix_count(bus->device);
475 if (msixCount >= 2) {
476 uint32 vectorCount = queueCount + 1;
477 if (msixCount >= vectorCount) {
478 uint32 vector;
479 bus->cookies = new(std::nothrow)
480 virtio_pci_queue_cookie[queueCount];
481 if (bus->cookies != NULL
482 && bus->pci->configure_msix(bus->device, vectorCount,
483 &vector) == B_OK
484 && bus->pci->enable_msix(bus->device) == B_OK) {
485 TRACE_ALWAYS("using MSI-X count %" B_PRIu32 " starting at %" B_PRIu32 "\n",
486 vectorCount, vector);
487 bus->irq = vector;
488 bus->irq_type = VIRTIO_IRQ_MSI_X;
489 } else {
490 ERROR("couldn't use MSI-X\n");
491 }
492 } else {
493 uint32 vector;
494 if (bus->pci->configure_msix(bus->device, 2, &vector) == B_OK
495 && bus->pci->enable_msix(bus->device) == B_OK) {
496 TRACE_ALWAYS("using MSI-X vector shared %" B_PRIu32 "\n", vector);
497 bus->irq = vector;
498 bus->irq_type = VIRTIO_IRQ_MSI_X_SHARED;
499 } else {
500 ERROR("couldn't use MSI-X SHARED\n");
501 }
502 }
503 }
504
505 if (bus->irq_type == VIRTIO_IRQ_LEGACY) {
506 bus->irq = pciInfo->u.h0.interrupt_line;
507 if (bus->irq == 0xff)
508 bus->irq = 0;
509 TRACE_ALWAYS("using legacy interrupt %" B_PRIu32 "\n", bus->irq);
510 }
511 if (bus->irq == 0) {
512 ERROR("PCI IRQ not assigned\n");
513 delete bus;
514 return B_ERROR;
515 }
516
517 if (bus->irq_type != VIRTIO_IRQ_LEGACY) {
518 status_t status = install_io_interrupt_handler(bus->irq,
519 virtio_pci_config_interrupt, bus, 0);
520 if (status != B_OK) {
521 ERROR("can't install interrupt handler\n");
522 return status;
523 }
524 int32 irq = bus->irq + 1;
525 if (bus->irq_type == VIRTIO_IRQ_MSI_X) {
526 for (int32 queue = 0; queue < queueCount; queue++, irq++) {
527 bus->cookies[queue].sim = bus->sim;
528 bus->cookies[queue].queue = queue;
529 status_t status = install_io_interrupt_handler(irq,
530 virtio_pci_queue_interrupt, &bus->cookies[queue], 0);
531 if (status != B_OK) {
532 ERROR("can't install interrupt handler\n");
533 return status;
534 }
535 }
536 } else {
537 status_t status = install_io_interrupt_handler(irq,
538 virtio_pci_queues_interrupt, bus, 0);
539 if (status != B_OK) {
540 ERROR("can't install interrupt handler\n");
541 return status;
542 }
543 }
544 TRACE("setup_interrupt() installed MSI-X interrupt handlers\n");
545 virtio_pci_setup_msix_interrupts(bus);
546 } else {
547 // setup interrupt handler
548 status_t status = install_io_interrupt_handler(bus->irq,
549 virtio_pci_interrupt, bus, 0);
550 if (status != B_OK) {
551 ERROR("can't install interrupt handler\n");
552 return status;
553 }
554 TRACE("setup_interrupt() installed legacy interrupt handler\n");
555 }
556
557 return B_OK;
558 }
559
560
561 static status_t
free_interrupt(void * cookie)562 free_interrupt(void* cookie)
563 {
564 CALLED();
565 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie;
566
567 if (bus->irq_type != VIRTIO_IRQ_LEGACY) {
568 remove_io_interrupt_handler(bus->irq, virtio_pci_config_interrupt, bus);
569 int32 irq = bus->irq + 1;
570 if (bus->irq_type == VIRTIO_IRQ_MSI_X) {
571 for (int32 queue = 0; queue < bus->queue_count; queue++, irq++)
572 remove_io_interrupt_handler(irq, virtio_pci_queue_interrupt, &bus->cookies[queue]);
573 delete[] bus->cookies;
574 bus->cookies = NULL;
575 } else {
576 remove_io_interrupt_handler(irq, virtio_pci_queues_interrupt, bus);
577 }
578 bus->pci->disable_msi(bus->device);
579 bus->pci->unconfigure_msi(bus->device);
580 } else
581 remove_io_interrupt_handler(bus->irq, virtio_pci_interrupt, bus);
582
583 return B_OK;
584 }
585
586
587 static void
notify_queue(void * cookie,uint16 queue)588 notify_queue(void* cookie, uint16 queue)
589 {
590 CALLED();
591 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie;
592 if (queue >= bus->queue_count)
593 return;
594 if (bus->virtio1) {
595 volatile uint16* notifyAddr = (volatile uint16*)(bus->notifyAddr + bus->notifyOffsets[queue]);
596 *notifyAddr = queue;
597 } else {
598 bus->pci->write_io_16(bus->device, bus->base_addr
599 + VIRTIO_PCI_QUEUE_NOTIFY, queue);
600 }
601 }
602
603
604 // #pragma mark -
605
606
607 static status_t
init_bus(device_node * node,void ** bus_cookie)608 init_bus(device_node* node, void** bus_cookie)
609 {
610 CALLED();
611 status_t status = B_OK;
612
613 virtio_pci_sim_info* bus = new(std::nothrow) virtio_pci_sim_info;
614 if (bus == NULL) {
615 return B_NO_MEMORY;
616 }
617
618 pci_device_module_info* pci;
619 pci_device* device;
620 {
621 device_node* parent = gDeviceManager->get_parent_node(node);
622 device_node* pciParent = gDeviceManager->get_parent_node(parent);
623 gDeviceManager->get_driver(pciParent, (driver_module_info**)&pci,
624 (void**)&device);
625 gDeviceManager->put_node(pciParent);
626 gDeviceManager->put_node(parent);
627 }
628
629 bus->node = node;
630 bus->pci = pci;
631 bus->device = device;
632 bus->cookies = NULL;
633 bus->irq_type = VIRTIO_IRQ_LEGACY;
634
635 pci_info *pciInfo = &bus->info;
636 pci->get_pci_info(device, pciInfo);
637
638 bus->virtio1 = pciInfo->revision == 1;
639
640 if (bus->virtio1) {
641 struct virtio_pci_cap common, isr, deviceCap;
642 struct virtio_pci_notify_cap notify;
643 bool deviceCfgFound = false;
644 if (virtio_pci_find_capability(bus, VIRTIO_PCI_CAP_COMMON_CFG, &common,
645 sizeof(common)) != B_OK) {
646 return B_DEVICE_NOT_FOUND;
647 }
648 if (virtio_pci_find_capability(bus, VIRTIO_PCI_CAP_ISR_CFG, &isr,
649 sizeof(isr)) != B_OK) {
650 return B_DEVICE_NOT_FOUND;
651 }
652 if (virtio_pci_find_capability(bus, VIRTIO_PCI_CAP_DEVICE_CFG, &deviceCap,
653 sizeof(deviceCap)) != B_OK) {
654 memset(&deviceCap, 0, sizeof(deviceCap));
655 } else {
656 deviceCfgFound = true;
657 }
658 if (virtio_pci_find_capability(bus, VIRTIO_PCI_CAP_NOTIFY_CFG, ¬ify,
659 sizeof(notify)) != B_OK) {
660 return B_DEVICE_NOT_FOUND;
661 }
662
663 size_t bars[6] = {0};
664 if (common.length > 0)
665 bars[common.bar] = common.offset + common.length;
666 if (isr.length > 0)
667 bars[isr.bar] = max_c(bars[isr.bar], isr.offset + isr.length);
668 if (notify.cap.length > 0) {
669 bars[notify.cap.bar] = max_c(bars[notify.cap.bar], notify.cap.offset
670 + notify.cap.length);
671 }
672 if (deviceCfgFound && deviceCap.length > 0)
673 bars[deviceCap.bar] = max_c(bars[deviceCap.bar], deviceCap.offset + deviceCap.length);
674
675 size_t index = 0;
676 addr_t registers[B_COUNT_OF(bars)] = {0};
677 for (size_t i = 0; i < B_COUNT_OF(bars); i++, index++) {
678 if (bars[index] == 0) {
679 bus->registersArea[index] = -1;
680 continue;
681 }
682 phys_addr_t barAddr = pciInfo->u.h0.base_registers[i];
683 size_t barSize = pciInfo->u.h0.base_register_sizes[i];
684 if ((pciInfo->u.h0.base_register_flags[i] & PCI_address_type) == PCI_address_type_64
685 && i < (B_COUNT_OF(bars) - 1)) {
686 i++;
687 barAddr |= (uint64)pciInfo->u.h0.base_registers[i] << 32;
688 barSize |= (uint64)pciInfo->u.h0.base_register_sizes[i] << 32;
689 }
690
691 bus->registersArea[index] = map_physical_memory("Virtio PCI memory mapped registers",
692 barAddr, barSize, B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA,
693 (void**)®isters[index]);
694 }
695
696 bus->commonCfgAddr = registers[common.bar] + common.offset;
697 bus->isrAddr = registers[isr.bar] + isr.offset;
698 bus->notifyAddr = registers[notify.cap.bar] + notify.cap.offset;
699 bus->notifyOffsetMultiplier = notify.notify_off_multiplier;
700 if (deviceCfgFound)
701 bus->base_addr = registers[deviceCap.bar] + deviceCap.offset;
702
703 // enable bus master and memory
704 uint16 pcicmd = pci->read_pci_config(device, PCI_command, 2);
705 pcicmd &= ~(PCI_command_int_disable | PCI_command_io);
706 pci->write_pci_config(device, PCI_command, 2,
707 pcicmd | PCI_command_master | PCI_command_memory);
708
709 volatile uint16 *queueCount = (uint16*)(bus->commonCfgAddr
710 + offsetof(struct virtio_pci_common_cfg, num_queues));
711 bus->notifyOffsets = new addr_t[*queueCount];
712
713 } else {
714 // legacy interrupt
715 bus->base_addr = pciInfo->u.h0.base_registers[0];
716
717 // enable bus master and io
718 uint16 pcicmd = pci->read_pci_config(device, PCI_command, 2);
719 pcicmd &= ~(PCI_command_memory | PCI_command_int_disable);
720 pcicmd |= PCI_command_master | PCI_command_io;
721 pci->write_pci_config(device, PCI_command, 2, pcicmd);
722 }
723
724
725 set_status(bus, VIRTIO_CONFIG_STATUS_RESET);
726 set_status(bus, VIRTIO_CONFIG_STATUS_ACK);
727
728 TRACE("init_bus() %p node %p pci %p device %p\n", bus, node,
729 bus->pci, bus->device);
730
731 *bus_cookie = bus;
732 return status;
733 }
734
735
736 static void
uninit_bus(void * bus_cookie)737 uninit_bus(void* bus_cookie)
738 {
739 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)bus_cookie;
740 if (bus->irq_type != VIRTIO_IRQ_LEGACY) {
741 int32 irq = bus->irq + 1;
742 if (bus->irq_type == VIRTIO_IRQ_MSI_X) {
743 for (int32 queue = 0; queue < bus->queue_count; queue++, irq++)
744 remove_io_interrupt_handler(irq, virtio_pci_queue_interrupt, &bus->cookies[queue]);
745 delete[] bus->cookies;
746 } else {
747 remove_io_interrupt_handler(irq, virtio_pci_queues_interrupt, bus);
748 }
749 remove_io_interrupt_handler(bus->irq, virtio_pci_config_interrupt,
750 bus);
751
752 bus->pci->disable_msi(bus->device);
753 bus->pci->unconfigure_msi(bus->device);
754 } else
755 remove_io_interrupt_handler(bus->irq, virtio_pci_interrupt, bus);
756
757 if (bus->virtio1) {
758 for (int i = 0; i < 6; i++) {
759 if (bus->registersArea[i] >= 0)
760 delete_area(bus->registersArea[i]);
761 else
762 break;
763 }
764 delete[] bus->notifyOffsets;
765 }
766
767 delete bus;
768 }
769
770
771 static void
bus_removed(void * bus_cookie)772 bus_removed(void* bus_cookie)
773 {
774 return;
775 }
776
777
778 // #pragma mark -
779
780
781 static status_t
register_child_devices(void * cookie)782 register_child_devices(void* cookie)
783 {
784 CALLED();
785 device_node* node = (device_node*)cookie;
786 device_node* parent = gDeviceManager->get_parent_node(node);
787 pci_device_module_info* pci;
788 pci_device* device;
789 gDeviceManager->get_driver(parent, (driver_module_info**)&pci,
790 (void**)&device);
791
792 uint16 pciSubDeviceId = pci->read_pci_config(device, PCI_subsystem_id, 2);
793 uint8 pciRevision = pci->read_pci_config(device, PCI_revision, 1);
794 uint16 pciDeviceId = pci->read_pci_config(device, PCI_device_id, 2);
795
796 uint16 virtioDeviceId = pciSubDeviceId;
797 if (pciDeviceId >= VIRTIO_PCI_DEVICEID_MODERN_MIN)
798 virtioDeviceId = pciDeviceId - VIRTIO_PCI_DEVICEID_MODERN_MIN;
799
800 char prettyName[25];
801 sprintf(prettyName, "Virtio Device %" B_PRIu16, virtioDeviceId);
802
803 device_attr attrs[] = {
804 // properties of this controller for virtio bus manager
805 { B_DEVICE_PRETTY_NAME, B_STRING_TYPE,
806 { .string = prettyName }},
807 { B_DEVICE_FIXED_CHILD, B_STRING_TYPE,
808 { .string = VIRTIO_FOR_CONTROLLER_MODULE_NAME }},
809
810 // private data to identify the device
811 { VIRTIO_DEVICE_TYPE_ITEM, B_UINT16_TYPE,
812 { .ui16 = virtioDeviceId }},
813 { VIRTIO_VRING_ALIGNMENT_ITEM, B_UINT16_TYPE,
814 { .ui16 = VIRTIO_PCI_VRING_ALIGN }},
815 { VIRTIO_VERSION_ITEM, B_UINT8_TYPE,
816 { .ui8 = pciRevision }},
817 { NULL }
818 };
819
820 return gDeviceManager->register_node(node, VIRTIO_PCI_SIM_MODULE_NAME,
821 attrs, NULL, &node);
822 }
823
824
825 static status_t
init_device(device_node * node,void ** device_cookie)826 init_device(device_node* node, void** device_cookie)
827 {
828 CALLED();
829 *device_cookie = node;
830 return B_OK;
831 }
832
833
834 static status_t
register_device(device_node * parent)835 register_device(device_node* parent)
836 {
837 device_attr attrs[] = {
838 {B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {.string = "Virtio PCI"}},
839 {}
840 };
841
842 return gDeviceManager->register_node(parent, VIRTIO_PCI_DEVICE_MODULE_NAME,
843 attrs, NULL, NULL);
844 }
845
846
847 static float
supports_device(device_node * parent)848 supports_device(device_node* parent)
849 {
850 CALLED();
851 const char* bus;
852 uint16 vendorID, deviceID;
853
854 // make sure parent is a PCI Virtio device node
855 if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false) != B_OK
856 || gDeviceManager->get_attr_uint16(parent, B_DEVICE_VENDOR_ID,
857 &vendorID, false) < B_OK
858 || gDeviceManager->get_attr_uint16(parent, B_DEVICE_ID, &deviceID,
859 false) < B_OK) {
860 return -1;
861 }
862
863 if (strcmp(bus, "pci") != 0)
864 return 0.0f;
865
866 if (vendorID == VIRTIO_PCI_VENDORID) {
867 if (deviceID < VIRTIO_PCI_DEVICEID_MIN
868 || deviceID > VIRTIO_PCI_DEVICEID_MODERN_MAX) {
869 return 0.0f;
870 }
871
872 pci_device_module_info* pci;
873 pci_device* device;
874 gDeviceManager->get_driver(parent, (driver_module_info**)&pci,
875 (void**)&device);
876 uint8 pciRevision = pci->read_pci_config(device, PCI_revision,
877 1);
878 if (deviceID >= VIRTIO_PCI_DEVICEID_MIN
879 && deviceID <= VIRTIO_PCI_DEVICEID_LEGACY_MAX
880 && pciRevision != 0) {
881 return 0.0f;
882 }
883 if (deviceID >= VIRTIO_PCI_DEVICEID_MODERN_MIN
884 && deviceID <= VIRTIO_PCI_DEVICEID_MODERN_MAX
885 && pciRevision != 1)
886 return 0.0f;
887
888 TRACE("Virtio device found! vendor 0x%04x, device 0x%04x\n", vendorID,
889 deviceID);
890 return 0.8f;
891 }
892
893 return 0.0f;
894 }
895
896
897 // #pragma mark -
898
899
900 module_dependency module_dependencies[] = {
901 { VIRTIO_FOR_CONTROLLER_MODULE_NAME, (module_info**)&gVirtio },
902 { B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager },
903 {}
904 };
905
906
907 static virtio_sim_interface gVirtioPCIDeviceModule = {
908 {
909 {
910 VIRTIO_PCI_SIM_MODULE_NAME,
911 0,
912 NULL
913 },
914
915 NULL, // supports device
916 NULL, // register device
917 init_bus,
918 uninit_bus,
919 NULL, // register child devices
920 NULL, // rescan
921 bus_removed,
922 },
923
924 set_sim,
925 read_host_features,
926 write_guest_features,
927 get_status,
928 set_status,
929 read_device_config,
930 write_device_config,
931 get_queue_ring_size,
932 setup_queue,
933 setup_interrupt,
934 free_interrupt,
935 notify_queue
936 };
937
938
939 static driver_module_info sVirtioDevice = {
940 {
941 VIRTIO_PCI_DEVICE_MODULE_NAME,
942 0,
943 NULL
944 },
945
946 supports_device,
947 register_device,
948 init_device,
949 NULL, // uninit
950 register_child_devices,
951 NULL, // rescan
952 NULL, // device removed
953 };
954
955 module_info* modules[] = {
956 (module_info* )&sVirtioDevice,
957 (module_info* )&gVirtioPCIDeviceModule,
958 NULL
959 };
960