VirtualBox

source: vbox/trunk/src/VBox/Devices/PC/BIOS/virtio.c@ 87766

Last change on this file since 87766 was 82968, checked in by vboxsync, 5 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 44.4 KB
Line 
1/* $Id: virtio.c 82968 2020-02-04 10:35:17Z vboxsync $ */
2/** @file
3 * VirtIO-SCSI host adapter driver to boot from disks.
4 */
5
6/*
7 * Copyright (C) 2019-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include <stdint.h>
19#include <string.h>
20#include "biosint.h"
21#include "ebda.h"
22#include "inlines.h"
23#include "pciutil.h"
24#include "vds.h"
25#include "scsi.h"
26
27//#define DEBUG_VIRTIO 1
28#if DEBUG_VIRTIO
29# define DBG_VIRTIO(...) BX_INFO(__VA_ARGS__)
30#else
31# define DBG_VIRTIO(...)
32#endif
33
34#define VBSCSI_MAX_DEVICES 16 /* Maximum number of devices a SCSI device currently supported. */
35
36/* The maximum CDB size. */
37#define VIRTIO_SCSI_CDB_SZ 16
38/** Maximum sense data to return. */
39#define VIRTIO_SCSI_SENSE_SZ 32
40
41#define VIRTIO_SCSI_RING_ELEM 3
42
43/**
44 * VirtIO queue descriptor.
45 */
46typedef struct
47{
48 /** 64bit guest physical address of the buffer, split into high and low part because we work in real mode. */
49 uint32_t GCPhysBufLow;
50 uint32_t GCPhysBufHigh;
51 /** Length of the buffer in bytes. */
52 uint32_t cbBuf;
53 /** Flags for the buffer. */
54 uint16_t fFlags;
55 /** Next field where the buffer is continued if _NEXT flag is set. */
56 uint16_t idxNext;
57} virtio_q_desc_t;
58
59#define VIRTIO_Q_DESC_F_NEXT 0x1
60#define VIRTIO_Q_DESC_F_WRITE 0x2
61#define VIRTIO_Q_DESC_F_INDIRECT 0x4
62
63/**
64 * VirtIO available ring.
65 */
66typedef struct
67{
68 /** Flags. */
69 volatile uint16_t fFlags;
70 /** Next index to write an available buffer by the driver. */
71 volatile uint16_t idxNextFree;
72 /** The ring - we only provide one entry. */
73 volatile uint16_t au16Ring[VIRTIO_SCSI_RING_ELEM];
74 /** Used event index. */
75 volatile uint16_t u16EvtUsed;
76} virtio_q_avail_t;
77
78/**
79 * VirtIO queue used element.
80 */
81typedef struct
82{
83 /** Index of the start of the descriptor chain. */
84 uint32_t u32Id;
85 /** Number of bytes used in the descriptor chain. */
86 uint32_t cbUsed;
87} virtio_q_used_elem_t;
88
89/**
90 * VirtIo used ring.
91 */
92typedef struct
93{
94 /** Flags. */
95 volatile uint16_t fFlags;
96 /** Index where the next entry would be written by the device. */
97 volatile uint16_t idxNextUsed;
98 /** The used ring. */
99 virtio_q_used_elem_t aRing[VIRTIO_SCSI_RING_ELEM];
100} virtio_q_used_t;
101
102/**
103 * VirtIO queue structure we are using, needs to be aligned on a 16byte boundary.
104 */
105typedef struct
106{
107 /** The descriptor table, using 5 max. */
108 virtio_q_desc_t aDescTbl[5];
109 /** Available ring. */
110 virtio_q_avail_t AvailRing;
111 /** Used ring. */
112 virtio_q_used_t UsedRing;
113 /** The notification offset for the queue. */
114 uint32_t offNotify;
115} virtio_q_t;
116
117/**
118 * VirtIO SCSI request structure passed in the queue.
119 */
120typedef struct
121{
122 /** The LUN to address. */
123 uint8_t au8Lun[8];
124 /** Request ID - split into low and high part. */
125 uint32_t u32IdLow;
126 uint32_t u32IdHigh;
127 /** Task attributes. */
128 uint8_t u8TaskAttr;
129 /** Priority. */
130 uint8_t u8Prio;
131 /** CRN value, usually 0. */
132 uint8_t u8Crn;
133 /** The CDB. */
134 uint8_t abCdb[VIRTIO_SCSI_CDB_SZ];
135} virtio_scsi_req_hdr_t;
136
137/**
138 * VirtIO SCSI status structure filled by the device.
139 */
140typedef struct
141{
142 /** Returned sense length. */
143 uint32_t cbSense;
144 /** Residual amount of bytes left. */
145 uint32_t cbResidual;
146 /** Status qualifier. */
147 uint16_t u16StatusQual;
148 /** Status code. */
149 uint8_t u8Status;
150 /** Response code. */
151 uint8_t u8Response;
152 /** Sense data. */
153 uint8_t abSense[VIRTIO_SCSI_SENSE_SZ];
154} virtio_scsi_req_sts_t;
155
156/**
157 * VirtIO config for the different data structures.
158 */
159typedef struct
160{
161 /** BAR where to find it. */
162 uint8_t u8Bar;
163 /** Padding. */
164 uint8_t abPad[3];
165 /** Offset within the bar. */
166 uint32_t u32Offset;
167 /** Length of the structure in bytes. */
168 uint32_t u32Length;
169} virtio_bar_cfg_t;
170
171/**
172 * VirtIO PCI capability structure.
173 */
174typedef struct
175{
176 /** Capability typem should always be PCI_CAP_ID_VNDR*/
177 uint8_t u8PciCapId;
178 /** Offset where to find the next capability or 0 if last capability. */
179 uint8_t u8PciCapNext;
180 /** Size of the capability in bytes. */
181 uint8_t u8PciCapLen;
182 /** VirtIO capability type. */
183 uint8_t u8VirtIoCfgType;
184 /** BAR where to find it. */
185 uint8_t u8Bar;
186 /** Padding. */
187 uint8_t abPad[3];
188 /** Offset within the bar. */
189 uint32_t u32Offset;
190 /** Length of the structure in bytes. */
191 uint32_t u32Length;
192} virtio_pci_cap_t;
193
194/**
195 * VirtIO-SCSI controller data.
196 */
197typedef struct
198{
199 /** The queue used - must be first for alignment reasons. */
200 virtio_q_t Queue;
201 /** The BAR configs read from the PCI configuration space, see VIRTIO_PCI_CAP_*_CFG,
202 * only use 4 because VIRTIO_PCI_CAP_PCI_CFG is not part of this. */
203 virtio_bar_cfg_t aBarCfgs[4];
204 /** The start offset in the PCI configuration space where to find the VIRTIO_PCI_CAP_PCI_CFG
205 * capability for the alternate access method to the registers. */
206 uint8_t u8PciCfgOff;
207 /** The notification offset multiplier. */
208 uint32_t u32NotifyOffMult;
209 /** PCI bus where the device is located. */
210 uint8_t u8Bus;
211 /** Device/Function number. */
212 uint8_t u8DevFn;
213 /** Saved high bits of EAX. */
214 uint16_t saved_eax_hi;
215 /** The current executed command structure. */
216 virtio_scsi_req_hdr_t ScsiReqHdr;
217 virtio_scsi_req_sts_t ScsiReqSts;
218} virtio_t;
219
220/* The VirtIO specific data must fit into 1KB (statically allocated). */
221ct_assert(sizeof(virtio_t) <= 1024);
222
223/** PCI configuration fields. */
224#define PCI_CONFIG_CAP 0x34
225
226#define PCI_CAP_ID_VNDR 0x09
227#define VBOX_VIRTIO_NO_DEVICE 0xffff
228
229#define VBOX_VIRTIO_NIL_CFG 0xff
230
231#define VIRTIO_PCI_CAP_COMMON_CFG 0x01
232#define VIRTIO_PCI_CAP_NOTIFY_CFG 0x02
233#define VIRTIO_PCI_CAP_ISR_CFG 0x03
234#define VIRTIO_PCI_CAP_DEVICE_CFG 0x04
235#define VIRTIO_PCI_CAP_PCI_CFG 0x05
236
237#define RT_BIT_32(bit) ((uint32_t)(1L << (bit)))
238
239#define VIRTIO_COMMON_REG_DEV_FEAT_SLCT 0x00
240#define VIRTIO_COMMON_REG_DEV_FEAT 0x04
241# define VIRTIO_CMN_REG_DEV_FEAT_SCSI_INOUT 0x01
242#define VIRTIO_COMMON_REG_DRV_FEAT_SLCT 0x08
243#define VIRTIO_COMMON_REG_DRV_FEAT 0x0c
244#define VIRTIO_COMMON_REG_MSIX_CFG 0x10
245#define VIRTIO_COMMON_REG_NUM_QUEUES 0x12
246#define VIRTIO_COMMON_REG_DEV_STS 0x14
247# define VIRTIO_CMN_REG_DEV_STS_F_RST 0x00
248# define VIRTIO_CMN_REG_DEV_STS_F_ACK 0x01
249# define VIRTIO_CMN_REG_DEV_STS_F_DRV 0x02
250# define VIRTIO_CMN_REG_DEV_STS_F_DRV_OK 0x04
251# define VIRTIO_CMN_REG_DEV_STS_F_FEAT_OK 0x08
252# define VIRTIO_CMN_REG_DEV_STS_F_DEV_RST 0x40
253# define VIRTIO_CMN_REG_DEV_STS_F_FAILED 0x80
254#define VIRTIO_COMMON_REG_CFG_GEN 0x15
255
256#define VIRTIO_COMMON_REG_Q_SELECT 0x16
257#define VIRTIO_COMMON_REG_Q_SIZE 0x18
258#define VIRTIO_COMMON_REG_Q_MSIX_VEC 0x1a
259#define VIRTIO_COMMON_REG_Q_ENABLE 0x1c
260#define VIRTIO_COMMON_REG_Q_NOTIFY_OFF 0x1e
261#define VIRTIO_COMMON_REG_Q_DESC 0x20
262#define VIRTIO_COMMON_REG_Q_DRIVER 0x28
263#define VIRTIO_COMMON_REG_Q_DEVICE 0x30
264
265#define VIRTIO_DEV_CFG_REG_Q_NUM 0x00
266#define VIRTIO_DEV_CFG_REG_SEG_MAX 0x04
267#define VIRTIO_DEV_CFG_REG_SECT_MAX 0x08
268#define VIRTIO_DEV_CFG_REG_CMD_PER_LUN 0x0c
269#define VIRTIO_DEV_CFG_REG_EVT_INFO_SZ 0x10
270#define VIRTIO_DEV_CFG_REG_SENSE_SZ 0x14
271#define VIRTIO_DEV_CFG_REG_CDB_SZ 0x18
272#define VIRTIO_DEV_CFG_REG_MAX_CHANNEL 0x1c
273#define VIRTIO_DEV_CFG_REG_MAX_TGT 0x1e
274#define VIRTIO_DEV_CFG_REG_MAX_LUN 0x20
275
276#define VIRTIO_SCSI_Q_CONTROL 0x00
277#define VIRTIO_SCSI_Q_EVENT 0x01
278#define VIRTIO_SCSI_Q_REQUEST 0x02
279
280#define VIRTIO_SCSI_STS_RESPONSE_OK 0x00
281
282/* Machinery to save/restore high bits of EAX. 32-bit port I/O needs to use
283 * EAX, but saving/restoring EAX around each port access would be inefficient.
284 * Instead, each externally callable routine must save the high bits before
285 * modifying them and restore the high bits before exiting.
286 */
287
288/* Note: Reading high EAX bits destroys them - *must* be restored later. */
289uint16_t eax_hi_rd(void);
290#pragma aux eax_hi_rd = \
291 ".386" \
292 "shr eax, 16" \
293 value [ax] modify nomemory;
294
295void eax_hi_wr(uint16_t);
296#pragma aux eax_hi_wr = \
297 ".386" \
298 "shl eax, 16" \
299 parm [ax] modify nomemory;
300
301void inline high_bits_save(virtio_t __far *virtio)
302{
303 virtio->saved_eax_hi = eax_hi_rd();
304}
305
306void inline high_bits_restore(virtio_t __far *virtio)
307{
308 eax_hi_wr(virtio->saved_eax_hi);
309}
310
311static void virtio_reg_set_bar_offset_length(virtio_t __far *virtio, uint8_t u8Bar, uint32_t offReg, uint32_t cb)
312{
313 pci_write_config_byte(virtio->u8Bus, virtio->u8DevFn, virtio->u8PciCfgOff + 4, u8Bar);
314 pci_write_config_dword(virtio->u8Bus, virtio->u8DevFn, virtio->u8PciCfgOff + 8, offReg);
315 pci_write_config_dword(virtio->u8Bus, virtio->u8DevFn, virtio->u8PciCfgOff + 12, cb);
316}
317
318static void virtio_reg_common_access_prepare(virtio_t __far *virtio, uint16_t offReg, uint32_t cbAcc)
319{
320 virtio_reg_set_bar_offset_length(virtio,
321 virtio->aBarCfgs[VIRTIO_PCI_CAP_COMMON_CFG - 1].u8Bar,
322 virtio->aBarCfgs[VIRTIO_PCI_CAP_COMMON_CFG - 1].u32Offset + offReg,
323 cbAcc);
324}
325
326static void virtio_reg_dev_access_prepare(virtio_t __far *virtio, uint16_t offReg, uint32_t cbAcc)
327{
328 virtio_reg_set_bar_offset_length(virtio,
329 virtio->aBarCfgs[VIRTIO_PCI_CAP_DEVICE_CFG - 1].u8Bar,
330 virtio->aBarCfgs[VIRTIO_PCI_CAP_DEVICE_CFG - 1].u32Offset + offReg,
331 cbAcc);
332}
333
334static void virtio_reg_notify_access_prepare(virtio_t __far *virtio, uint16_t offReg, uint32_t cbAcc)
335{
336 virtio_reg_set_bar_offset_length(virtio,
337 virtio->aBarCfgs[VIRTIO_PCI_CAP_NOTIFY_CFG - 1].u8Bar,
338 virtio->aBarCfgs[VIRTIO_PCI_CAP_NOTIFY_CFG - 1].u32Offset + offReg,
339 cbAcc);
340}
341
342static void virtio_reg_isr_prepare(virtio_t __far *virtio, uint32_t cbAcc)
343{
344 virtio_reg_set_bar_offset_length(virtio,
345 virtio->aBarCfgs[VIRTIO_PCI_CAP_ISR_CFG - 1].u8Bar,
346 virtio->aBarCfgs[VIRTIO_PCI_CAP_ISR_CFG - 1].u32Offset,
347 cbAcc);
348}
349
350static uint8_t virtio_reg_common_read_u8(virtio_t __far *virtio, uint16_t offReg)
351{
352 virtio_reg_common_access_prepare(virtio, offReg, sizeof(uint8_t));
353 return pci_read_config_byte(virtio->u8Bus, virtio->u8DevFn, virtio->u8PciCfgOff + sizeof(virtio_pci_cap_t));
354}
355
356static void virtio_reg_common_write_u8(virtio_t __far *virtio, uint16_t offReg, uint8_t u8Val)
357{
358 virtio_reg_common_access_prepare(virtio, offReg, sizeof(uint8_t));
359 pci_write_config_byte(virtio->u8Bus, virtio->u8DevFn, virtio->u8PciCfgOff + sizeof(virtio_pci_cap_t), u8Val);
360}
361
362static uint16_t virtio_reg_common_read_u16(virtio_t __far *virtio, uint16_t offReg)
363{
364 virtio_reg_common_access_prepare(virtio, offReg, sizeof(uint16_t));
365 return pci_read_config_word(virtio->u8Bus, virtio->u8DevFn, virtio->u8PciCfgOff + sizeof(virtio_pci_cap_t));
366}
367
368static void virtio_reg_common_write_u16(virtio_t __far *virtio, uint16_t offReg, uint16_t u16Val)
369{
370 virtio_reg_common_access_prepare(virtio, offReg, sizeof(uint16_t));
371 pci_write_config_word(virtio->u8Bus, virtio->u8DevFn, virtio->u8PciCfgOff + sizeof(virtio_pci_cap_t), u16Val);
372}
373
374static void virtio_reg_common_write_u32(virtio_t __far *virtio, uint16_t offReg, uint32_t u32Val)
375{
376 virtio_reg_common_access_prepare(virtio, offReg, sizeof(uint32_t));
377 pci_write_config_dword(virtio->u8Bus, virtio->u8DevFn, virtio->u8PciCfgOff + sizeof(virtio_pci_cap_t), u32Val);
378}
379
380static uint32_t virtio_reg_dev_cfg_read_u32(virtio_t __far *virtio, uint16_t offReg)
381{
382 virtio_reg_dev_access_prepare(virtio, offReg, sizeof(uint32_t));
383 return pci_read_config_dword(virtio->u8Bus, virtio->u8DevFn, virtio->u8PciCfgOff + sizeof(virtio_pci_cap_t));
384}
385
386static void virtio_reg_dev_cfg_write_u32(virtio_t __far *virtio, uint16_t offReg, uint32_t u32Val)
387{
388 virtio_reg_dev_access_prepare(virtio, offReg, sizeof(uint32_t));
389 pci_write_config_dword(virtio->u8Bus, virtio->u8DevFn, virtio->u8PciCfgOff + sizeof(virtio_pci_cap_t), u32Val);
390}
391
392static void virtio_reg_notify_write_u16(virtio_t __far *virtio, uint16_t offReg, uint16_t u16Val)
393{
394 virtio_reg_notify_access_prepare(virtio, offReg, sizeof(uint16_t));
395 pci_write_config_word(virtio->u8Bus, virtio->u8DevFn, virtio->u8PciCfgOff + sizeof(virtio_pci_cap_t), u16Val);
396}
397
398static uint8_t virtio_reg_isr_read_u8(virtio_t __far *virtio)
399{
400 virtio_reg_isr_prepare(virtio, sizeof(uint8_t));
401 return pci_read_config_byte(virtio->u8Bus, virtio->u8DevFn, virtio->u8PciCfgOff + sizeof(virtio_pci_cap_t));
402}
403
404/**
405 * Allocates 1K of conventional memory.
406 */
407static uint16_t virtio_mem_alloc(void)
408{
409 uint16_t base_mem_kb;
410 uint16_t virtio_seg;
411
412 base_mem_kb = read_word(0x00, 0x0413);
413
414 DBG_VIRTIO("VirtIO: %dK of base mem\n", base_mem_kb);
415
416 if (base_mem_kb == 0)
417 return 0;
418
419 base_mem_kb--; /* Allocate one block. */
420 virtio_seg = (((uint32_t)base_mem_kb * 1024) >> 4); /* Calculate start segment. */
421
422 write_word(0x00, 0x0413, base_mem_kb);
423
424 return virtio_seg;
425}
426
427/**
428 * Converts a segment:offset pair into a 32bit physical address.
429 */
430static uint32_t virtio_addr_to_phys(void __far *ptr)
431{
432 return ((uint32_t)FP_SEG(ptr) << 4) + FP_OFF(ptr);
433}
434
435int virtio_scsi_cmd_data_out(virtio_t __far *virtio, uint8_t idTgt, uint8_t __far *aCDB,
436 uint8_t cbCDB, uint8_t __far *buffer, uint32_t length)
437{
438 uint16_t idxUsedOld = virtio->Queue.UsedRing.idxNextUsed;
439
440 _fmemset(&virtio->ScsiReqHdr, 0, sizeof(virtio->ScsiReqHdr));
441 _fmemset(&virtio->ScsiReqSts, 0, sizeof(virtio->ScsiReqSts));
442
443 virtio->ScsiReqHdr.au8Lun[0] = 0x1;
444 virtio->ScsiReqHdr.au8Lun[1] = idTgt;
445 virtio->ScsiReqHdr.au8Lun[2] = 0;
446 virtio->ScsiReqHdr.au8Lun[3] = 0;
447 _fmemcpy(&virtio->ScsiReqHdr.abCdb[0], aCDB, cbCDB);
448
449 /* Fill in the descriptors. */
450 virtio->Queue.aDescTbl[0].GCPhysBufLow = virtio_addr_to_phys(&virtio->ScsiReqHdr);
451 virtio->Queue.aDescTbl[0].GCPhysBufHigh = 0;
452 virtio->Queue.aDescTbl[0].cbBuf = sizeof(virtio->ScsiReqHdr);
453 virtio->Queue.aDescTbl[0].fFlags = VIRTIO_Q_DESC_F_NEXT;
454 virtio->Queue.aDescTbl[0].idxNext = 1;
455
456 virtio->Queue.aDescTbl[1].GCPhysBufLow = virtio_addr_to_phys(buffer);
457 virtio->Queue.aDescTbl[1].GCPhysBufHigh = 0;
458 virtio->Queue.aDescTbl[1].cbBuf = length;
459 virtio->Queue.aDescTbl[1].fFlags = VIRTIO_Q_DESC_F_NEXT;
460 virtio->Queue.aDescTbl[1].idxNext = 2;
461
462 virtio->Queue.aDescTbl[2].GCPhysBufLow = virtio_addr_to_phys(&virtio->ScsiReqSts);
463 virtio->Queue.aDescTbl[2].GCPhysBufHigh = 0;
464 virtio->Queue.aDescTbl[2].cbBuf = sizeof(virtio->ScsiReqSts);
465 virtio->Queue.aDescTbl[2].fFlags = VIRTIO_Q_DESC_F_WRITE; /* End of chain. */
466 virtio->Queue.aDescTbl[2].idxNext = 0;
467
468 /* Put it into the queue. */
469 virtio->Queue.AvailRing.au16Ring[virtio->Queue.AvailRing.idxNextFree % VIRTIO_SCSI_RING_ELEM] = 0;
470 virtio->Queue.AvailRing.idxNextFree++;
471
472 /* Notify the device about the new command. */
473 DBG_VIRTIO("VirtIO: Submitting new request, Queue.offNotify=0x%x\n", virtio->Queue.offNotify);
474 virtio_reg_notify_write_u16(virtio, virtio->Queue.offNotify, VIRTIO_SCSI_Q_REQUEST);
475
476 /* Wait for it to complete. */
477 while (idxUsedOld == virtio->Queue.UsedRing.idxNextUsed);
478
479 DBG_VIRTIO("VirtIO: Request complete u8Response=%u\n", virtio->ScsiReqSts.u8Response);
480
481 /* Read ISR register to de-assert the interrupt, don't need to do anything with it. */
482 virtio_reg_isr_read_u8(virtio);
483
484 if (virtio->ScsiReqSts.u8Response != VIRTIO_SCSI_STS_RESPONSE_OK)
485 return 4;
486
487 return 0;
488}
489
490int virtio_scsi_cmd_data_in(virtio_t __far *virtio, uint8_t idTgt, uint8_t __far *aCDB,
491 uint8_t cbCDB, uint8_t __far *buffer, uint32_t length, uint16_t skip_a,
492 uint16_t skip_b)
493{
494 uint16_t idxUsedOld = virtio->Queue.UsedRing.idxNextUsed;
495 uint8_t idxDesc = 0;
496
497 _fmemset(&virtio->ScsiReqHdr, 0, sizeof(virtio->ScsiReqHdr));
498 _fmemset(&virtio->ScsiReqSts, 0, sizeof(virtio->ScsiReqSts));
499
500 virtio->ScsiReqHdr.au8Lun[0] = 0x1;
501 virtio->ScsiReqHdr.au8Lun[1] = idTgt;
502 virtio->ScsiReqHdr.au8Lun[2] = 0;
503 virtio->ScsiReqHdr.au8Lun[3] = 0;
504 _fmemcpy(&virtio->ScsiReqHdr.abCdb[0], aCDB, cbCDB);
505
506 /* Fill in the descriptors. */
507 virtio->Queue.aDescTbl[idxDesc].GCPhysBufLow = virtio_addr_to_phys(&virtio->ScsiReqHdr);
508 virtio->Queue.aDescTbl[idxDesc].GCPhysBufHigh = 0;
509 virtio->Queue.aDescTbl[idxDesc].cbBuf = sizeof(virtio->ScsiReqHdr);
510 virtio->Queue.aDescTbl[idxDesc].fFlags = VIRTIO_Q_DESC_F_NEXT;
511 virtio->Queue.aDescTbl[idxDesc].idxNext = 1;
512 idxDesc++;
513
514 /* No data out buffer, the status comes right after this in the next descriptor. */
515 virtio->Queue.aDescTbl[idxDesc].GCPhysBufLow = virtio_addr_to_phys(&virtio->ScsiReqSts);
516 virtio->Queue.aDescTbl[idxDesc].GCPhysBufHigh = 0;
517 virtio->Queue.aDescTbl[idxDesc].cbBuf = sizeof(virtio->ScsiReqSts);
518 virtio->Queue.aDescTbl[idxDesc].fFlags = VIRTIO_Q_DESC_F_WRITE | VIRTIO_Q_DESC_F_NEXT;
519 virtio->Queue.aDescTbl[idxDesc].idxNext = 2;
520 idxDesc++;
521
522 /* Prepend a sinkhole if data is skipped upfront. */
523 if (skip_b)
524 {
525 virtio->Queue.aDescTbl[idxDesc].GCPhysBufLow = 0; /* See ahci.c:sink_buf_phys */
526 virtio->Queue.aDescTbl[idxDesc].GCPhysBufHigh = 0;
527 virtio->Queue.aDescTbl[idxDesc].cbBuf = skip_b;
528 virtio->Queue.aDescTbl[idxDesc].fFlags = VIRTIO_Q_DESC_F_WRITE | VIRTIO_Q_DESC_F_NEXT;
529 virtio->Queue.aDescTbl[idxDesc].idxNext = idxDesc + 1;
530 idxDesc++;
531 }
532
533 virtio->Queue.aDescTbl[idxDesc].GCPhysBufLow = virtio_addr_to_phys(buffer);
534 virtio->Queue.aDescTbl[idxDesc].GCPhysBufHigh = 0;
535 virtio->Queue.aDescTbl[idxDesc].cbBuf = length;
536 virtio->Queue.aDescTbl[idxDesc].fFlags = VIRTIO_Q_DESC_F_WRITE; /* End of chain. */
537 virtio->Queue.aDescTbl[idxDesc].idxNext = skip_a ? idxDesc + 1 : 0;
538 idxDesc++;
539
540 /* Append a sinkhole if data is skipped at the end. */
541 if (skip_a)
542 {
543 virtio->Queue.aDescTbl[idxDesc - 1].fFlags |= VIRTIO_Q_DESC_F_NEXT;
544 virtio->Queue.aDescTbl[idxDesc - 1].idxNext = idxDesc;
545
546 virtio->Queue.aDescTbl[idxDesc].GCPhysBufLow = 0; /* See ahci.c:sink_buf_phys */
547 virtio->Queue.aDescTbl[idxDesc].GCPhysBufHigh = 0;
548 virtio->Queue.aDescTbl[idxDesc].cbBuf = skip_a;
549 virtio->Queue.aDescTbl[idxDesc].fFlags = VIRTIO_Q_DESC_F_WRITE; /* End of chain. */
550 virtio->Queue.aDescTbl[idxDesc].idxNext = 0;
551 }
552
553 /* Put it into the queue, the index is supposed to be free-running and clipped to the ring size
554 * internally. The free running index is what the driver sees. */
555 virtio->Queue.AvailRing.au16Ring[virtio->Queue.AvailRing.idxNextFree % VIRTIO_SCSI_RING_ELEM] = 0;
556 virtio->Queue.AvailRing.idxNextFree++;
557
558 /* Notify the device about the new command. */
559 DBG_VIRTIO("VirtIO: Submitting new request, Queue.offNotify=0x%x\n", virtio->Queue.offNotify);
560 virtio_reg_notify_write_u16(virtio, virtio->Queue.offNotify, VIRTIO_SCSI_Q_REQUEST);
561
562 /* Wait for it to complete. */
563 while (idxUsedOld == virtio->Queue.UsedRing.idxNextUsed);
564
565 DBG_VIRTIO("VirtIO: Request complete u8Response=%u\n", virtio->ScsiReqSts.u8Response);
566
567 /* Read ISR register to de-assert the interrupt, don't need to do anything with it. */
568 virtio_reg_isr_read_u8(virtio);
569
570 if (virtio->ScsiReqSts.u8Response != VIRTIO_SCSI_STS_RESPONSE_OK)
571 return 4;
572
573 return 0;
574}
575
576/**
577 * Read sectors from an attached VirtIO SCSI device.
578 *
579 * @returns status code.
580 * @param bios_dsk Pointer to disk request packet (in the
581 * EBDA).
582 */
583int virtio_scsi_read_sectors(bio_dsk_t __far *bios_dsk)
584{
585 uint8_t rc;
586 cdb_rw16 cdb;
587 uint32_t count;
588 uint8_t target_id;
589 uint8_t device_id;
590
591 device_id = VBOX_GET_SCSI_DEVICE(bios_dsk->drqp.dev_id);
592 if (device_id > BX_MAX_SCSI_DEVICES)
593 BX_PANIC("%s: device_id out of range %d\n", __func__, device_id);
594
595 count = bios_dsk->drqp.nsect;
596
597 high_bits_save(bios_dsk->virtio_seg :> 0);
598 /* Prepare a CDB. */
599 cdb.command = SCSI_READ_16;
600 cdb.lba = swap_64(bios_dsk->drqp.lba);
601 cdb.pad1 = 0;
602 cdb.nsect32 = swap_32(count);
603 cdb.pad2 = 0;
604
605
606 target_id = bios_dsk->scsidev[device_id].target_id;
607
608 DBG_VIRTIO("%s: reading %u sectors, device %d, target %d\n", __func__,
609 count, device_id, bios_dsk->scsidev[device_id].target_id);
610
611 rc = virtio_scsi_cmd_data_in(bios_dsk->virtio_seg :> 0, target_id, (void __far *)&cdb, 16,
612 bios_dsk->drqp.buffer, (count * 512L), 0, 0);
613
614 if (!rc)
615 {
616 bios_dsk->drqp.trsfsectors = count;
617 bios_dsk->drqp.trsfbytes = count * 512L;
618 }
619 DBG_VIRTIO("%s: transferred %u sectors\n", __func__, bios_dsk->drqp.nsect);
620 high_bits_restore(bios_dsk->virtio_seg :> 0);
621
622 return rc;
623}
624
625/**
626 * Write sectors to an attached VirtIO SCSI device.
627 *
628 * @returns status code.
629 * @param bios_dsk Pointer to disk request packet (in the
630 * EBDA).
631 */
632int virtio_scsi_write_sectors(bio_dsk_t __far *bios_dsk)
633{
634 uint8_t rc;
635 cdb_rw16 cdb;
636 uint32_t count;
637 uint8_t target_id;
638 uint8_t device_id;
639
640 device_id = VBOX_GET_SCSI_DEVICE(bios_dsk->drqp.dev_id);
641 if (device_id > BX_MAX_SCSI_DEVICES)
642 BX_PANIC("%s: device_id out of range %d\n", __func__, device_id);
643
644 count = bios_dsk->drqp.nsect;
645
646 high_bits_save(bios_dsk->virtio_seg :> 0);
647
648 /* Prepare a CDB. */
649 cdb.command = SCSI_WRITE_16;
650 cdb.lba = swap_64(bios_dsk->drqp.lba);
651 cdb.pad1 = 0;
652 cdb.nsect32 = swap_32(count);
653 cdb.pad2 = 0;
654
655 target_id = bios_dsk->scsidev[device_id].target_id;
656
657 DBG_VIRTIO("%s: writing %u sectors, device %d, target %d\n", __func__,
658 count, device_id, bios_dsk->scsidev[device_id].target_id);
659
660 rc = virtio_scsi_cmd_data_out(bios_dsk->virtio_seg :> 0, target_id, (void __far *)&cdb, 16,
661 bios_dsk->drqp.buffer, (count * 512L));
662
663 if (!rc)
664 {
665 bios_dsk->drqp.trsfsectors = count;
666 bios_dsk->drqp.trsfbytes = (count * 512L);
667 }
668 DBG_VIRTIO("%s: transferred %u sectors\n", __func__, bios_dsk->drqp.nsect);
669 high_bits_restore(bios_dsk->virtio_seg :> 0);
670
671 return rc;
672}
673
674#define ATA_DATA_OUT 0x02
675
676/**
677 * Perform a "packet style" read with supplied CDB.
678 *
679 * @returns status code.
680 * @param device_id ID of the device to access.
681 * @param cmdlen Length of the CDB.
682 * @param cmdbuf The CDB buffer.
683 * @param skip_b How much to skip before reading into the provided data buffer.
684 * @param length How much to transfer.
685 * @param inout Read/Write direction indicator.
686 * @param buffer Data buffer to store the data from the device in.
687 */
688uint16_t virtio_scsi_cmd_packet(uint16_t device_id, uint8_t cmdlen, char __far *cmdbuf,
689 uint16_t skip_b, uint32_t length, uint8_t inout, char __far *buffer)
690{
691 bio_dsk_t __far *bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;
692 uint8_t rc;
693 uint8_t target_id;
694
695 /* Data out is currently not supported. */
696 if (inout == ATA_DATA_OUT) {
697 BX_INFO("%s: DATA_OUT not supported yet\n", __func__);
698 return 1;
699 }
700
701 /* The skip length must be even. */
702 if (skip_b & 1) {
703 DBG_VIRTIO("%s: skip must be even (%04x)\n", __func__, skip_b);
704 return 1;
705 }
706
707 /* Convert to SCSI specific device number. */
708 device_id = VBOX_GET_SCSI_DEVICE(device_id);
709
710 DBG_VIRTIO("%s: reading %lu bytes, skip %u/%u, device %d, target %d\n", __func__,
711 length, bios_dsk->drqp.skip_b, bios_dsk->drqp.skip_a,
712 device_id, bios_dsk->scsidev[device_id].target_id);
713 DBG_VIRTIO("%s: reading %u %u-byte sectors\n", __func__,
714 bios_dsk->drqp.nsect, bios_dsk->drqp.sect_sz);
715
716 high_bits_save(bios_dsk->virtio_seg :> 0);
717 target_id = bios_dsk->scsidev[device_id].target_id;
718
719 bios_dsk->drqp.lba = length << 8; /// @todo xfer length limit
720 bios_dsk->drqp.buffer = buffer;
721 bios_dsk->drqp.nsect = length / bios_dsk->drqp.sect_sz;
722
723 DBG_VIRTIO("%s: reading %u bytes, device %d, target %d\n", __func__,
724 length, device_id, bios_dsk->scsidev[device_id].target_id);
725
726 rc = virtio_scsi_cmd_data_in(bios_dsk->virtio_seg :> 0, target_id, (void __far *)cmdbuf, cmdlen,
727 bios_dsk->drqp.buffer, length, skip_b, bios_dsk->drqp.skip_a);
728 if (!rc)
729 bios_dsk->drqp.trsfbytes = length;
730
731 DBG_VIRTIO("%s: transferred %u bytes\n", __func__, length);
732 high_bits_restore(bios_dsk->virtio_seg :> 0);
733
734 return rc;
735}
736
737static int virtio_scsi_detect_devices(virtio_t __far *virtio)
738{
739 int i;
740 uint8_t buffer[0x0200];
741 bio_dsk_t __far *bios_dsk;
742
743 bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;
744
745 /* Go through target devices. */
746 for (i = 0; i < VBSCSI_MAX_DEVICES; i++)
747 {
748 uint8_t rc;
749 uint8_t aCDB[16];
750 uint8_t hd_index, devcount_scsi;
751
752 aCDB[0] = SCSI_INQUIRY;
753 aCDB[1] = 0;
754 aCDB[2] = 0;
755 aCDB[3] = 0;
756 aCDB[4] = 5; /* Allocation length. */
757 aCDB[5] = 0;
758
759 _fmemset(buffer, 0, sizeof(buffer));
760
761 rc = virtio_scsi_cmd_data_in(virtio, i, aCDB, 6, buffer, 5, 0, 0);
762 if (!rc)
763 {
764 devcount_scsi = bios_dsk->scsi_devcount;
765
766 /* Check the attached device. */
767 if ( ((buffer[0] & 0xe0) == 0)
768 && ((buffer[0] & 0x1f) == 0x00))
769 {
770 DBG_VIRTIO("%s: Disk detected at %d\n", __func__, i);
771
772 /* We add the disk only if the maximum is not reached yet. */
773 if (devcount_scsi < BX_MAX_SCSI_DEVICES)
774 {
775 uint64_t sectors, t;
776 uint32_t sector_size, cylinders;
777 uint16_t heads, sectors_per_track;
778 uint8_t hdcount;
779 uint8_t cmos_base;
780
781 /* Issue a read capacity command now. */
782 _fmemset(aCDB, 0, sizeof(aCDB));
783 aCDB[0] = SCSI_SERVICE_ACT;
784 aCDB[1] = SCSI_READ_CAP_16;
785 aCDB[13] = 32; /* Allocation length. */
786
787 rc = virtio_scsi_cmd_data_in(virtio, i, aCDB, 16, buffer, 32, 0, 0);
788 if (rc != 0)
789 BX_PANIC("%s: SCSI_READ_CAPACITY failed\n", __func__);
790
791 /* The value returned is the last addressable LBA, not
792 * the size, which what "+ 1" is for.
793 */
794 sectors = swap_64(*(uint64_t *)buffer) + 1;
795
796 sector_size = ((uint32_t)buffer[8] << 24)
797 | ((uint32_t)buffer[9] << 16)
798 | ((uint32_t)buffer[10] << 8)
799 | ((uint32_t)buffer[11]);
800
801 /* We only support the disk if sector size is 512 bytes. */
802 if (sector_size != 512)
803 {
804 /* Leave a log entry. */
805 BX_INFO("Disk %d has an unsupported sector size of %u\n", i, sector_size);
806 continue;
807 }
808
809 /* Get logical CHS geometry. */
810 switch (devcount_scsi)
811 {
812 case 0:
813 cmos_base = 0x90;
814 break;
815 case 1:
816 cmos_base = 0x98;
817 break;
818 case 2:
819 cmos_base = 0xA0;
820 break;
821 case 3:
822 cmos_base = 0xA8;
823 break;
824 default:
825 cmos_base = 0;
826 }
827
828 if (cmos_base && inb_cmos(cmos_base + 7))
829 {
830 /* If provided, grab the logical geometry from CMOS. */
831 cylinders = inb_cmos(cmos_base + 0) + (inb_cmos(cmos_base + 1) << 8);
832 heads = inb_cmos(cmos_base + 2);
833 sectors_per_track = inb_cmos(cmos_base + 7);
834 }
835 else
836 {
837 /* Calculate default logical geometry. NB: Very different
838 * from default ATA/SATA logical geometry!
839 */
840 if (sectors >= (uint32_t)4 * 1024 * 1024)
841 {
842 heads = 255;
843 sectors_per_track = 63;
844 /* Approximate x / (255 * 63) using shifts */
845 t = (sectors >> 6) + (sectors >> 12);
846 cylinders = (t >> 8) + (t >> 16);
847 }
848 else if (sectors >= (uint32_t)2 * 1024 * 1024)
849 {
850 heads = 128;
851 sectors_per_track = 32;
852 cylinders = sectors >> 12;
853 }
854 else
855 {
856 heads = 64;
857 sectors_per_track = 32;
858 cylinders = sectors >> 11;
859 }
860 }
861
862 /* Calculate index into the generic disk table. */
863 hd_index = devcount_scsi + BX_MAX_ATA_DEVICES;
864
865 bios_dsk->scsidev[devcount_scsi].target_id = i;
866 bios_dsk->devices[hd_index].type = DSK_TYPE_VIRTIO_SCSI;
867 bios_dsk->devices[hd_index].device = DSK_DEVICE_HD;
868 bios_dsk->devices[hd_index].removable = 0;
869 bios_dsk->devices[hd_index].lock = 0;
870 bios_dsk->devices[hd_index].blksize = sector_size;
871 bios_dsk->devices[hd_index].translation = GEO_TRANSLATION_LBA;
872
873 /* Write LCHS/PCHS values. */
874 bios_dsk->devices[hd_index].lchs.heads = heads;
875 bios_dsk->devices[hd_index].lchs.spt = sectors_per_track;
876 bios_dsk->devices[hd_index].pchs.heads = heads;
877 bios_dsk->devices[hd_index].pchs.spt = sectors_per_track;
878
879 if (cylinders > 1024) {
880 bios_dsk->devices[hd_index].lchs.cylinders = 1024;
881 bios_dsk->devices[hd_index].pchs.cylinders = 1024;
882 } else {
883 bios_dsk->devices[hd_index].lchs.cylinders = (uint16_t)cylinders;
884 bios_dsk->devices[hd_index].pchs.cylinders = (uint16_t)cylinders;
885 }
886
887 BX_INFO("SCSI %d-ID#%d: LCHS=%lu/%u/%u 0x%llx sectors\n", devcount_scsi,
888 i, (uint32_t)cylinders, heads, sectors_per_track, sectors);
889
890 bios_dsk->devices[hd_index].sectors = sectors;
891
892 /* Store the id of the disk in the ata hdidmap. */
893 hdcount = bios_dsk->hdcount;
894 bios_dsk->hdidmap[hdcount] = devcount_scsi + BX_MAX_ATA_DEVICES;
895 hdcount++;
896 bios_dsk->hdcount = hdcount;
897
898 /* Update hdcount in the BDA. */
899 hdcount = read_byte(0x40, 0x75);
900 hdcount++;
901 write_byte(0x40, 0x75, hdcount);
902
903 devcount_scsi++;
904 }
905 else
906 {
907 /* We reached the maximum of SCSI disks we can boot from. We can quit detecting. */
908 break;
909 }
910 }
911 else if ( ((buffer[0] & 0xe0) == 0)
912 && ((buffer[0] & 0x1f) == 0x05))
913 {
914 uint8_t cdcount;
915 uint8_t removable;
916
917 BX_INFO("SCSI %d-ID#%d: CD/DVD-ROM\n", devcount_scsi, i);
918
919 /* Calculate index into the generic device table. */
920 hd_index = devcount_scsi + BX_MAX_ATA_DEVICES;
921
922 removable = buffer[1] & 0x80 ? 1 : 0;
923
924 bios_dsk->scsidev[devcount_scsi].target_id = i;
925 bios_dsk->devices[hd_index].type = DSK_TYPE_VIRTIO_SCSI;
926 bios_dsk->devices[hd_index].device = DSK_DEVICE_CDROM;
927 bios_dsk->devices[hd_index].removable = removable;
928 bios_dsk->devices[hd_index].blksize = 2048;
929 bios_dsk->devices[hd_index].translation = GEO_TRANSLATION_NONE;
930
931 /* Store the ID of the device in the BIOS cdidmap. */
932 cdcount = bios_dsk->cdcount;
933 bios_dsk->cdidmap[cdcount] = devcount_scsi + BX_MAX_ATA_DEVICES;
934 cdcount++;
935 bios_dsk->cdcount = cdcount;
936
937 devcount_scsi++;
938 }
939 else
940 DBG_VIRTIO("%s: No supported device detected at %d\n", __func__, i);
941 }
942 else
943 DBG_VIRTIO("%s: INQUIRY failed with %u\n", __func__, rc);
944
945 bios_dsk->scsi_devcount = devcount_scsi;
946 }
947
948 return 0;
949}
950
951/**
952 * Initializes the VirtIO SCSI HBA and detects attached devices.
953 */
954static int virtio_scsi_hba_init(uint8_t u8Bus, uint8_t u8DevFn, uint8_t u8PciCapOffVirtIo)
955{
956 uint8_t u8PciCapOff;
957 uint16_t ebda_seg;
958 uint16_t virtio_seg;
959 uint8_t u8DevStat;
960 bio_dsk_t __far *bios_dsk;
961 virtio_t __far *virtio;
962
963 ebda_seg = read_word(0x0040, 0x000E);
964 bios_dsk = ebda_seg :> &EbdaData->bdisk;
965
966 /* Allocate 1K of base memory. */
967 virtio_seg = virtio_mem_alloc();
968 if (virtio_seg == 0)
969 {
970 DBG_VIRTIO("VirtIO: Could not allocate 1K of memory, can't boot from controller\n");
971 return 0;
972 }
973 DBG_VIRTIO("VirtIO: virtio_seg=%04x, size=%04x, pointer at EBDA:%04x (EBDA size=%04x)\n",
974 virtio_seg, sizeof(virtio_t), (uint16_t)&EbdaData->bdisk.virtio_seg, sizeof(ebda_data_t));
975
976 bios_dsk->virtio_seg = virtio_seg;
977
978 virtio = virtio_seg :> 0;
979 virtio->u8Bus = u8Bus;
980 virtio->u8DevFn = u8DevFn;
981
982 /*
983 * Go through the config space again, read the complete config capabilities
984 * this time and fill in the data.
985 */
986 u8PciCapOff = u8PciCapOffVirtIo;
987 while (u8PciCapOff != 0)
988 {
989 uint8_t u8PciCapId = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff);
990 uint8_t cbPciCap = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 2); /* Capability length. */
991
992 DBG_VIRTIO("Capability ID 0x%x at 0x%x\n", u8PciCapId, u8PciCapOff);
993
994 if ( u8PciCapId == PCI_CAP_ID_VNDR
995 && cbPciCap >= sizeof(virtio_pci_cap_t))
996 {
997 /* Read in the config type and see what we got. */
998 uint8_t u8PciVirtioCfg = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 3);
999
1000 DBG_VIRTIO("VirtIO: CFG ID 0x%x\n", u8PciVirtioCfg);
1001 switch (u8PciVirtioCfg)
1002 {
1003 case VIRTIO_PCI_CAP_COMMON_CFG:
1004 case VIRTIO_PCI_CAP_NOTIFY_CFG:
1005 case VIRTIO_PCI_CAP_ISR_CFG:
1006 case VIRTIO_PCI_CAP_DEVICE_CFG:
1007 {
1008 virtio_bar_cfg_t __far *pBarCfg = &virtio->aBarCfgs[u8PciVirtioCfg - 1];
1009
1010 pBarCfg->u8Bar = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 4);
1011 pBarCfg->u32Offset = pci_read_config_dword(u8Bus, u8DevFn, u8PciCapOff + 8);
1012 pBarCfg->u32Length = pci_read_config_dword(u8Bus, u8DevFn, u8PciCapOff + 12);
1013 if (u8PciVirtioCfg == VIRTIO_PCI_CAP_NOTIFY_CFG)
1014 {
1015 virtio->u32NotifyOffMult = pci_read_config_dword(u8Bus, u8DevFn, u8PciCapOff + 16);
1016 DBG_VIRTIO("VirtIO: u32NotifyOffMult 0x%x\n", virtio->u32NotifyOffMult);
1017 }
1018 break;
1019 }
1020 case VIRTIO_PCI_CAP_PCI_CFG:
1021 virtio->u8PciCfgOff = u8PciCapOff;
1022 DBG_VIRTIO("VirtIO PCI CAP window offset: %x\n", u8PciCapOff);
1023 break;
1024 default:
1025 DBG_VIRTIO("VirtIO SCSI HBA with unknown PCI capability type 0x%x\n", u8PciVirtioCfg);
1026 break;
1027 }
1028 }
1029
1030 u8PciCapOff = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 1);
1031 }
1032
1033 /* Reset the device. */
1034 u8DevStat = VIRTIO_CMN_REG_DEV_STS_F_RST;
1035 virtio_reg_common_write_u8(virtio, VIRTIO_COMMON_REG_DEV_STS, u8DevStat);
1036 /* Acknowledge presence. */
1037 u8DevStat |= VIRTIO_CMN_REG_DEV_STS_F_ACK;
1038 virtio_reg_common_write_u8(virtio, VIRTIO_COMMON_REG_DEV_STS, u8DevStat);
1039 /* Our driver knows how to operate the device. */
1040 u8DevStat |= VIRTIO_CMN_REG_DEV_STS_F_DRV;
1041 virtio_reg_common_write_u8(virtio, VIRTIO_COMMON_REG_DEV_STS, u8DevStat);
1042
1043#if 0
1044 /* Read the feature bits and only program the VIRTIO_CMN_REG_DEV_FEAT_SCSI_INOUT bit if available. */
1045 fFeatures = virtio_reg_common_read_u32(virtio, VIRTIO_COMMON_REG_DEV_FEAT);
1046 fFeatures &= VIRTIO_CMN_REG_DEV_FEAT_SCSI_INOUT;
1047#endif
1048
1049 /* Check that the device is sane. */
1050 if ( virtio_reg_dev_cfg_read_u32(virtio, VIRTIO_DEV_CFG_REG_Q_NUM) < 1
1051 || virtio_reg_dev_cfg_read_u32(virtio, VIRTIO_DEV_CFG_REG_CDB_SZ) < 16
1052 || virtio_reg_dev_cfg_read_u32(virtio, VIRTIO_DEV_CFG_REG_SENSE_SZ) < 32
1053 || virtio_reg_dev_cfg_read_u32(virtio, VIRTIO_DEV_CFG_REG_SECT_MAX) < 1)
1054 {
1055 DBG_VIRTIO("VirtIO-SCSI: Invalid SCSI device configuration, ignoring device\n");
1056 return 0;
1057 }
1058
1059 virtio_reg_common_write_u32(virtio, VIRTIO_COMMON_REG_DRV_FEAT, VIRTIO_CMN_REG_DEV_FEAT_SCSI_INOUT);
1060
1061 /* Set the features OK bit. */
1062 u8DevStat |= VIRTIO_CMN_REG_DEV_STS_F_FEAT_OK;
1063 virtio_reg_common_write_u8(virtio, VIRTIO_COMMON_REG_DEV_STS, u8DevStat);
1064
1065 /* Read again and check the the okay bit is still set. */
1066 if (!(virtio_reg_common_read_u8(virtio, VIRTIO_COMMON_REG_DEV_STS) & VIRTIO_CMN_REG_DEV_STS_F_FEAT_OK))
1067 {
1068 DBG_VIRTIO("VirtIO-SCSI: Device doesn't accept our feature set, ignoring device\n");
1069 return 0;
1070 }
1071
1072 /* Disable event and control queue. */
1073 virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_SELECT, VIRTIO_SCSI_Q_CONTROL);
1074 virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_SIZE, 0);
1075 virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_ENABLE, 0);
1076
1077 virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_SELECT, VIRTIO_SCSI_Q_EVENT);
1078 virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_SIZE, 0);
1079 virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_ENABLE, 0);
1080
1081 /* Setup the request queue. */
1082 virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_SELECT, VIRTIO_SCSI_Q_REQUEST);
1083 virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_SIZE, VIRTIO_SCSI_RING_ELEM);
1084 virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_ENABLE, 1);
1085
1086 /* Set queue area addresses (only low part, leave high part 0). */
1087 virtio_reg_common_write_u32(virtio, VIRTIO_COMMON_REG_Q_DESC, virtio_addr_to_phys(&virtio->Queue.aDescTbl[0]));
1088 virtio_reg_common_write_u32(virtio, VIRTIO_COMMON_REG_Q_DESC + 4, 0);
1089
1090 virtio_reg_common_write_u32(virtio, VIRTIO_COMMON_REG_Q_DRIVER, virtio_addr_to_phys(&virtio->Queue.AvailRing));
1091 virtio_reg_common_write_u32(virtio, VIRTIO_COMMON_REG_Q_DRIVER + 4, 0);
1092
1093 virtio_reg_common_write_u32(virtio, VIRTIO_COMMON_REG_Q_DEVICE, virtio_addr_to_phys(&virtio->Queue.UsedRing));
1094 virtio_reg_common_write_u32(virtio, VIRTIO_COMMON_REG_Q_DEVICE + 4, 0);
1095
1096 virtio_reg_dev_cfg_write_u32(virtio, VIRTIO_DEV_CFG_REG_CDB_SZ, VIRTIO_SCSI_CDB_SZ);
1097 virtio_reg_dev_cfg_write_u32(virtio, VIRTIO_DEV_CFG_REG_SENSE_SZ, VIRTIO_SCSI_SENSE_SZ);
1098
1099 DBG_VIRTIO("VirtIO: Q notify offset 0x%x\n", virtio_reg_common_read_u16(virtio, VIRTIO_COMMON_REG_Q_NOTIFY_OFF));
1100 virtio->Queue.offNotify = virtio_reg_common_read_u16(virtio, VIRTIO_COMMON_REG_Q_NOTIFY_OFF) * virtio->u32NotifyOffMult;
1101
1102 /* Bring the device into operational mode. */
1103 u8DevStat |= VIRTIO_CMN_REG_DEV_STS_F_DRV_OK;
1104 virtio_reg_common_write_u8(virtio, VIRTIO_COMMON_REG_DEV_STS, u8DevStat);
1105
1106 return virtio_scsi_detect_devices(virtio);
1107}
1108
1109/**
1110 * Init the VirtIO SCSI driver and detect attached disks.
1111 */
1112void BIOSCALL virtio_scsi_init(void)
1113{
1114 uint16_t busdevfn;
1115
1116 busdevfn = pci_find_device(0x1af4, 0x1048);
1117 if (busdevfn != VBOX_VIRTIO_NO_DEVICE)
1118 {
1119 uint8_t u8Bus, u8DevFn;
1120 uint8_t u8PciCapOff;
1121 uint8_t u8PciCapOffVirtIo = VBOX_VIRTIO_NIL_CFG;
1122 uint8_t u8PciCapVirtioSeen = 0;
1123
1124 u8Bus = (busdevfn & 0xff00) >> 8;
1125 u8DevFn = busdevfn & 0x00ff;
1126
1127 DBG_VIRTIO("VirtIO SCSI HBA at Bus %u DevFn 0x%x (raw 0x%x)\n", u8Bus, u8DevFn, busdevfn);
1128
1129 /* Examine the capability list and search for the VirtIO specific capabilities. */
1130 u8PciCapOff = pci_read_config_byte(u8Bus, u8DevFn, PCI_CONFIG_CAP);
1131
1132 while (u8PciCapOff != 0)
1133 {
1134 uint8_t u8PciCapId = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff);
1135 uint8_t cbPciCap = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 2); /* Capability length. */
1136
1137 DBG_VIRTIO("Capability ID 0x%x at 0x%x\n", u8PciCapId, u8PciCapOff);
1138
1139 if ( u8PciCapId == PCI_CAP_ID_VNDR
1140 && cbPciCap >= sizeof(virtio_pci_cap_t))
1141 {
1142 /* Read in the config type and see what we got. */
1143 uint8_t u8PciVirtioCfg = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 3);
1144
1145 if (u8PciCapOffVirtIo == VBOX_VIRTIO_NIL_CFG)
1146 u8PciCapOffVirtIo = u8PciCapOff;
1147
1148 DBG_VIRTIO("VirtIO: CFG ID 0x%x\n", u8PciVirtioCfg);
1149 switch (u8PciVirtioCfg)
1150 {
1151 case VIRTIO_PCI_CAP_COMMON_CFG:
1152 case VIRTIO_PCI_CAP_NOTIFY_CFG:
1153 case VIRTIO_PCI_CAP_ISR_CFG:
1154 case VIRTIO_PCI_CAP_DEVICE_CFG:
1155 case VIRTIO_PCI_CAP_PCI_CFG:
1156 u8PciCapVirtioSeen |= 1 << (u8PciVirtioCfg - 1);
1157 break;
1158 default:
1159 DBG_VIRTIO("VirtIO SCSI HBA with unknown PCI capability type 0x%x\n", u8PciVirtioCfg);
1160 }
1161 }
1162
1163 u8PciCapOff = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 1);
1164 }
1165
1166 /* Initialize the controller if all required PCI capabilities where found. */
1167 if ( u8PciCapOffVirtIo != VBOX_VIRTIO_NIL_CFG
1168 && u8PciCapVirtioSeen == 0x1f)
1169 {
1170 int rc;
1171
1172 DBG_VIRTIO("VirtIO SCSI HBA with all required capabilities at 0x%x\n", u8PciCapOffVirtIo);
1173
1174 /* Enable PCI memory, I/O, bus mastering access in command register. */
1175 pci_write_config_word(u8Bus, u8DevFn, 4, 0x7);
1176
1177 rc = virtio_scsi_hba_init(u8Bus, u8DevFn, u8PciCapOffVirtIo);
1178 }
1179 else
1180 DBG_VIRTIO("VirtIO SCSI HBA with no usable PCI config access!\n");
1181 }
1182 else
1183 DBG_VIRTIO("No VirtIO SCSI HBA!\n");
1184}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette