VirtualBox

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

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

PC/BIOS/VirtIoScsi: Current state

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 44.2 KB
Line 
1/* $Id: virtio.c 82164 2019-11-25 10:32:37Z vboxsync $ */
2/** @file
3 * VirtIO-SCSI host adapter driver to boot from disks.
4 */
5
6/*
7 * Copyright (C) 2019 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 uint16_t fFlags;
70 /** Next index to write an available buffer by the driver. */
71 uint16_t idxNextFree;
72 /** The ring - we only provide one entry. */
73 uint16_t au16Ring[VIRTIO_SCSI_RING_ELEM];
74 /** Used event index. */
75 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 4 max. */
108 virtio_q_desc_t aDescTbl[4];
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 uint64_t idxNext = virtio->Queue.AvailRing.idxNextFree;
440
441 _fmemset(&virtio->ScsiReqHdr, 0, sizeof(virtio->ScsiReqHdr));
442 _fmemset(&virtio->ScsiReqSts, 0, sizeof(virtio->ScsiReqSts));
443
444 virtio->ScsiReqHdr.au8Lun[0] = 0x1;
445 virtio->ScsiReqHdr.au8Lun[1] = idTgt;
446 virtio->ScsiReqHdr.au8Lun[2] = 0;
447 virtio->ScsiReqHdr.au8Lun[3] = 0;
448 _fmemcpy(&virtio->ScsiReqHdr.abCdb[0], aCDB, cbCDB);
449
450 /* Fill in the descriptors. */
451 virtio->Queue.aDescTbl[0].GCPhysBufLow = virtio_addr_to_phys(&virtio->ScsiReqHdr);
452 virtio->Queue.aDescTbl[0].GCPhysBufHigh = 0;
453 virtio->Queue.aDescTbl[0].cbBuf = sizeof(virtio->ScsiReqHdr);
454 virtio->Queue.aDescTbl[0].fFlags = VIRTIO_Q_DESC_F_NEXT;
455 virtio->Queue.aDescTbl[0].idxNext = 1;
456
457 virtio->Queue.aDescTbl[1].GCPhysBufLow = virtio_addr_to_phys(buffer);
458 virtio->Queue.aDescTbl[1].GCPhysBufHigh = 0;
459 virtio->Queue.aDescTbl[1].cbBuf = length;
460 virtio->Queue.aDescTbl[1].fFlags = VIRTIO_Q_DESC_F_NEXT;
461 virtio->Queue.aDescTbl[1].idxNext = 1;
462
463 virtio->Queue.aDescTbl[1].GCPhysBufLow = virtio_addr_to_phys(&virtio->ScsiReqSts);
464 virtio->Queue.aDescTbl[1].GCPhysBufHigh = 0;
465 virtio->Queue.aDescTbl[1].cbBuf = sizeof(virtio->ScsiReqSts);
466 virtio->Queue.aDescTbl[1].fFlags = VIRTIO_Q_DESC_F_WRITE; /* End of chain. */
467 virtio->Queue.aDescTbl[1].idxNext = 0;
468
469 /* Put it into the queue. */
470 virtio->Queue.AvailRing.au16Ring[virtio->Queue.AvailRing.idxNextFree] = 0;
471 virtio->Queue.AvailRing.idxNextFree++;
472 virtio->Queue.AvailRing.idxNextFree %= VIRTIO_SCSI_RING_ELEM;
473
474 /* Notify the device about the new command. */
475 DBG_VIRTIO("VirtIO: Submitting new request, Queue.offNotify=0x%x\n", virtio->Queue.offNotify);
476 virtio_reg_notify_write_u16(virtio, virtio->Queue.offNotify, idxNext);
477
478 /* Wait for it to complete. */
479 while (idxUsedOld == virtio->Queue.UsedRing.idxNextUsed);
480
481 DBG_VIRTIO("VirtIO: Request complete u8Response=%u\n", virtio->ScsiReqSts.u8Response);
482
483 /* Read ISR register to de-assert the interrupt, don't need to do anything with out. */
484 virtio_reg_isr_read_u8(virtio);
485
486 if (virtio->ScsiReqSts.u8Response != VIRTIO_SCSI_STS_RESPONSE_OK)
487 return 4;
488
489 return 0;
490}
491
492int virtio_scsi_cmd_data_in(virtio_t __far *virtio, uint8_t idTgt, uint8_t __far *aCDB,
493 uint8_t cbCDB, uint8_t __far *buffer, uint32_t length)
494{
495 uint16_t idxUsedOld = virtio->Queue.UsedRing.idxNextUsed;
496 uint64_t idxNext = virtio->Queue.AvailRing.idxNextFree;
497
498 _fmemset(&virtio->ScsiReqHdr, 0, sizeof(virtio->ScsiReqHdr));
499 _fmemset(&virtio->ScsiReqSts, 0, sizeof(virtio->ScsiReqSts));
500
501 virtio->ScsiReqHdr.au8Lun[0] = 0x1;
502 virtio->ScsiReqHdr.au8Lun[1] = idTgt;
503 virtio->ScsiReqHdr.au8Lun[2] = 0;
504 virtio->ScsiReqHdr.au8Lun[3] = 0;
505 _fmemcpy(&virtio->ScsiReqHdr.abCdb[0], aCDB, cbCDB);
506
507 /* Fill in the descriptors. */
508 virtio->Queue.aDescTbl[0].GCPhysBufLow = virtio_addr_to_phys(&virtio->ScsiReqHdr);
509 virtio->Queue.aDescTbl[0].GCPhysBufHigh = 0;
510 virtio->Queue.aDescTbl[0].cbBuf = sizeof(virtio->ScsiReqHdr);
511 virtio->Queue.aDescTbl[0].fFlags = VIRTIO_Q_DESC_F_NEXT;
512 virtio->Queue.aDescTbl[0].idxNext = 1;
513
514 /* No data out buffer, the status comes right after this in the next descriptor. */
515 virtio->Queue.aDescTbl[1].GCPhysBufLow = virtio_addr_to_phys(&virtio->ScsiReqSts);
516 virtio->Queue.aDescTbl[1].GCPhysBufHigh = 0;
517 virtio->Queue.aDescTbl[1].cbBuf = sizeof(virtio->ScsiReqSts);
518 virtio->Queue.aDescTbl[1].fFlags = VIRTIO_Q_DESC_F_WRITE | VIRTIO_Q_DESC_F_NEXT;
519 virtio->Queue.aDescTbl[1].idxNext = 2;
520
521 virtio->Queue.aDescTbl[2].GCPhysBufLow = virtio_addr_to_phys(buffer);
522 virtio->Queue.aDescTbl[2].GCPhysBufHigh = 0;
523 virtio->Queue.aDescTbl[2].cbBuf = length;
524 virtio->Queue.aDescTbl[2].fFlags = VIRTIO_Q_DESC_F_WRITE; /* End of chain. */
525 virtio->Queue.aDescTbl[2].idxNext = 0;
526
527 /* Put it into the queue. */
528 virtio->Queue.AvailRing.au16Ring[virtio->Queue.AvailRing.idxNextFree] = 0;
529 virtio->Queue.AvailRing.idxNextFree++;
530 virtio->Queue.AvailRing.idxNextFree %= VIRTIO_SCSI_RING_ELEM;
531
532 /* Notify the device about the new command. */
533 DBG_VIRTIO("VirtIO: Submitting new request, Queue.offNotify=0x%x\n", virtio->Queue.offNotify);
534 virtio_reg_notify_write_u16(virtio, virtio->Queue.offNotify, idxNext);
535
536 /* Wait for it to complete. */
537 while (idxUsedOld == virtio->Queue.UsedRing.idxNextUsed);
538
539 DBG_VIRTIO("VirtIO: Request complete u8Response=%u\n", virtio->ScsiReqSts.u8Response);
540
541 /* Read ISR register to de-assert the interrupt, don't need to do anything with out. */
542 virtio_reg_isr_read_u8(virtio);
543
544 if (virtio->ScsiReqSts.u8Response != VIRTIO_SCSI_STS_RESPONSE_OK)
545 return 4;
546
547 return 0;
548}
549
550/**
551 * Read sectors from an attached VirtIO SCSI device.
552 *
553 * @returns status code.
554 * @param bios_dsk Pointer to disk request packet (in the
555 * EBDA).
556 */
557int virtio_scsi_read_sectors(bio_dsk_t __far *bios_dsk)
558{
559 uint8_t rc;
560 cdb_rw16 cdb;
561 uint32_t count;
562 uint8_t target_id;
563 uint8_t device_id;
564
565 device_id = VBOX_GET_SCSI_DEVICE(bios_dsk->drqp.dev_id);
566 if (device_id > BX_MAX_SCSI_DEVICES)
567 BX_PANIC("%s: device_id out of range %d\n", __func__, device_id);
568
569 count = bios_dsk->drqp.nsect;
570
571 high_bits_save(bios_dsk->virtio_seg :> 0);
572 /* Prepare a CDB. */
573 cdb.command = SCSI_READ_16;
574 cdb.lba = swap_64(bios_dsk->drqp.lba);
575 cdb.pad1 = 0;
576 cdb.nsect32 = swap_32(count);
577 cdb.pad2 = 0;
578
579
580 target_id = bios_dsk->scsidev[device_id].target_id;
581
582 DBG_VIRTIO("%s: reading %u sectors, device %d, target %d\n", __func__,
583 count, device_id, bios_dsk->scsidev[device_id].target_id);
584
585 rc = virtio_scsi_cmd_data_in(bios_dsk->virtio_seg :> 0, target_id, (void __far *)&cdb, 16,
586 bios_dsk->drqp.buffer, (count * 512L));
587
588 if (!rc)
589 {
590 bios_dsk->drqp.trsfsectors = count;
591 bios_dsk->drqp.trsfbytes = count * 512L;
592 }
593 DBG_VIRTIO("%s: transferred %u sectors\n", __func__, bios_dsk->drqp.nsect);
594 high_bits_restore(bios_dsk->virtio_seg :> 0);
595
596 return rc;
597}
598
599/**
600 * Write sectors to an attached VirtIO SCSI device.
601 *
602 * @returns status code.
603 * @param bios_dsk Pointer to disk request packet (in the
604 * EBDA).
605 */
606int virtio_scsi_write_sectors(bio_dsk_t __far *bios_dsk)
607{
608 uint8_t rc;
609 cdb_rw16 cdb;
610 uint32_t count;
611 uint8_t target_id;
612 uint8_t device_id;
613
614 device_id = VBOX_GET_SCSI_DEVICE(bios_dsk->drqp.dev_id);
615 if (device_id > BX_MAX_SCSI_DEVICES)
616 BX_PANIC("%s: device_id out of range %d\n", __func__, device_id);
617
618 count = bios_dsk->drqp.nsect;
619
620 high_bits_save(bios_dsk->virtio_seg :> 0);
621
622 /* Prepare a CDB. */
623 cdb.command = SCSI_WRITE_16;
624 cdb.lba = swap_64(bios_dsk->drqp.lba);
625 cdb.pad1 = 0;
626 cdb.nsect32 = swap_32(count);
627 cdb.pad2 = 0;
628
629 target_id = bios_dsk->scsidev[device_id].target_id;
630
631 DBG_VIRTIO("%s: writing %u sectors, device %d, target %d\n", __func__,
632 count, device_id, bios_dsk->scsidev[device_id].target_id);
633
634 rc = virtio_scsi_cmd_data_out(bios_dsk->virtio_seg :> 0, target_id, (void __far *)&cdb, 16,
635 bios_dsk->drqp.buffer, (count * 512L));
636
637 if (!rc)
638 {
639 bios_dsk->drqp.trsfsectors = count;
640 bios_dsk->drqp.trsfbytes = (count * 512L);
641 }
642 DBG_VIRTIO("%s: transferred %u sectors\n", __func__, bios_dsk->drqp.nsect);
643 high_bits_restore(bios_dsk->virtio_seg :> 0);
644
645 return rc;
646}
647
648#if 0
649#define ATA_DATA_OUT 0x02
650
651/**
652 * Perform a "packet style" read with supplied CDB.
653 *
654 * @returns status code.
655 * @param device_id ID of the device to access.
656 * @param cmdlen Length of the CDB.
657 * @param cmdbuf The CDB buffer.
658 * @param before How much to skip before reading into the provided data buffer.
659 * @param length How much to transfer.
660 * @param inout Read/Write direction indicator.
661 * @param buffer Data buffer to store the data from the device in.
662 */
663uint16_t scsi_cmd_packet(uint16_t device_id, uint8_t cmdlen, char __far *cmdbuf,
664 uint16_t before, uint32_t length, uint8_t inout, char __far *buffer)
665{
666 bio_dsk_t __far *bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;
667 uint32_t read_len;
668 uint8_t status, sizes;
669 uint16_t i;
670 uint16_t io_base;
671 uint8_t target_id;
672
673 /* Data out is currently not supported. */
674 if (inout == ATA_DATA_OUT) {
675 BX_INFO("%s: DATA_OUT not supported yet\n", __func__);
676 return 1;
677 }
678
679 /* Convert to SCSI specific device number. */
680 device_id = VBOX_GET_SCSI_DEVICE(device_id);
681
682 DBG_VIRTIO("%s: reading %lu bytes, skip %u/%u, device %d, target %d\n", __func__,
683 length, bios_dsk->drqp.skip_b, bios_dsk->drqp.skip_a,
684 device_id, bios_dsk->scsidev[device_id].target_id);
685 DBG_VIRTIO("%s: reading %u %u-byte sectors\n", __func__,
686 bios_dsk->drqp.nsect, bios_dsk->drqp.sect_sz);
687
688 cmdlen -= 2; /* ATAPI uses 12-byte command packets for a READ 10. */
689
690 io_base = bios_dsk->scsidev[device_id].io_base;
691 target_id = bios_dsk->scsidev[device_id].target_id;
692
693 /* Wait until the adapter is ready. */
694 do
695 status = inb(io_base + VBSCSI_REGISTER_STATUS);
696 while (status & VBSCSI_BUSY);
697
698 /* On the SCSI level, we have to transfer whole sectors. */
699 /* NB: With proper residual length support, this should not be necessary; we should
700 * be able to avoid transferring the 'after' part of the sector.
701 */
702 read_len = length + before + bios_dsk->drqp.skip_a;
703
704 sizes = (((read_len) >> 12) & 0xF0) | cmdlen;
705 outb(io_base + VBSCSI_REGISTER_COMMAND, target_id); /* Write the target ID. */
706 outb(io_base + VBSCSI_REGISTER_COMMAND, SCSI_TXDIR_FROM_DEVICE); /* Write the transfer direction. */
707 outb(io_base + VBSCSI_REGISTER_COMMAND, sizes); /* Write the CDB size. */
708 outb(io_base + VBSCSI_REGISTER_COMMAND, read_len); /* Write the buffer size. */
709 outb(io_base + VBSCSI_REGISTER_COMMAND, (read_len) >> 8);
710 for (i = 0; i < cmdlen; i++) /* Write the CDB. */
711 outb(io_base + VBSCSI_REGISTER_COMMAND, cmdbuf[i]);
712
713 /* Now wait for the command to complete. */
714 do
715 status = inb(io_base + VBSCSI_REGISTER_STATUS);
716 while (status & VBSCSI_BUSY);
717
718 /* If any error occurred, inform the caller and don't bother reading the data. */
719 if (status & VBSCSI_ERROR) {
720 outb(io_base + VBSCSI_REGISTER_RESET, 0);
721
722 status = inb(io_base + VBSCSI_REGISTER_DEVSTAT);
723 DBG_SCSI("%s: read failed, device status %02X\n", __func__, status);
724 return 3;
725 }
726
727 /* Transfer the data read from the device. */
728
729 if (before) /* If necessary, throw away data which needs to be skipped. */
730 insb_discard(before, io_base + VBSCSI_REGISTER_DATA_IN);
731
732 bios_dsk->drqp.trsfbytes = length;
733
734 /* The requested length may be exactly 64K or more, which needs
735 * a bit of care when we're using 16-bit 'rep ins'.
736 */
737 while (length > 32768) {
738 DBG_SCSI("%s: reading 32K to %X:%X\n", __func__, FP_SEG(buffer), FP_OFF(buffer));
739 rep_insb(buffer, 32768, io_base + VBSCSI_REGISTER_DATA_IN);
740 length -= 32768;
741 buffer = (FP_SEG(buffer) + (32768 >> 4)) :> FP_OFF(buffer);
742 }
743
744 DBG_SCSI("%s: reading %ld bytes to %X:%X\n", __func__, length, FP_SEG(buffer), FP_OFF(buffer));
745 rep_insb(buffer, length, io_base + VBSCSI_REGISTER_DATA_IN);
746
747 if (bios_dsk->drqp.skip_a) /* If necessary, throw away more data. */
748 insb_discard(bios_dsk->drqp.skip_a, io_base + VBSCSI_REGISTER_DATA_IN);
749
750 return 0;
751}
752#endif
753
754static int virtio_scsi_detect_devices(virtio_t __far *virtio)
755{
756 int i;
757 uint8_t buffer[0x0200];
758 bio_dsk_t __far *bios_dsk;
759
760 bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;
761
762 /* Go through target devices. */
763 for (i = 0; i < VBSCSI_MAX_DEVICES; i++)
764 {
765 uint8_t rc;
766 uint8_t aCDB[16];
767 uint8_t hd_index, devcount_scsi;
768
769 aCDB[0] = SCSI_INQUIRY;
770 aCDB[1] = 0;
771 aCDB[2] = 0;
772 aCDB[3] = 0;
773 aCDB[4] = 5; /* Allocation length. */
774 aCDB[5] = 0;
775
776 rc = virtio_scsi_cmd_data_in(virtio, i, aCDB, 6, buffer, 5);
777 if (rc != 0)
778 BX_PANIC("%s: SCSI_INQUIRY failed\n", __func__);
779
780 devcount_scsi = bios_dsk->scsi_devcount;
781
782 /* Check the attached device. */
783 if ( ((buffer[0] & 0xe0) == 0)
784 && ((buffer[0] & 0x1f) == 0x00))
785 {
786 DBG_VIRTIO("%s: Disk detected at %d\n", __func__, i);
787
788 /* We add the disk only if the maximum is not reached yet. */
789 if (devcount_scsi < BX_MAX_SCSI_DEVICES)
790 {
791 uint64_t sectors, t;
792 uint32_t sector_size, cylinders;
793 uint16_t heads, sectors_per_track;
794 uint8_t hdcount;
795 uint8_t cmos_base;
796
797 /* Issue a read capacity command now. */
798 _fmemset(aCDB, 0, sizeof(aCDB));
799 aCDB[0] = SCSI_SERVICE_ACT;
800 aCDB[1] = SCSI_READ_CAP_16;
801 aCDB[13] = 32; /* Allocation length. */
802
803 rc = virtio_scsi_cmd_data_in(virtio, i, aCDB, 16, buffer, 32);
804 if (rc != 0)
805 BX_PANIC("%s: SCSI_READ_CAPACITY failed\n", __func__);
806
807 /* The value returned is the last addressable LBA, not
808 * the size, which what "+ 1" is for.
809 */
810 sectors = swap_64(*(uint64_t *)buffer) + 1;
811
812 sector_size = ((uint32_t)buffer[8] << 24)
813 | ((uint32_t)buffer[9] << 16)
814 | ((uint32_t)buffer[10] << 8)
815 | ((uint32_t)buffer[11]);
816
817 /* We only support the disk if sector size is 512 bytes. */
818 if (sector_size != 512)
819 {
820 /* Leave a log entry. */
821 BX_INFO("Disk %d has an unsupported sector size of %u\n", i, sector_size);
822 continue;
823 }
824
825 /* Get logical CHS geometry. */
826 switch (devcount_scsi)
827 {
828 case 0:
829 cmos_base = 0x90;
830 break;
831 case 1:
832 cmos_base = 0x98;
833 break;
834 case 2:
835 cmos_base = 0xA0;
836 break;
837 case 3:
838 cmos_base = 0xA8;
839 break;
840 default:
841 cmos_base = 0;
842 }
843
844 if (cmos_base && inb_cmos(cmos_base + 7))
845 {
846 /* If provided, grab the logical geometry from CMOS. */
847 cylinders = inb_cmos(cmos_base + 0) + (inb_cmos(cmos_base + 1) << 8);
848 heads = inb_cmos(cmos_base + 2);
849 sectors_per_track = inb_cmos(cmos_base + 7);
850 }
851 else
852 {
853 /* Calculate default logical geometry. NB: Very different
854 * from default ATA/SATA logical geometry!
855 */
856 if (sectors >= (uint32_t)4 * 1024 * 1024)
857 {
858 heads = 255;
859 sectors_per_track = 63;
860 /* Approximate x / (255 * 63) using shifts */
861 t = (sectors >> 6) + (sectors >> 12);
862 cylinders = (t >> 8) + (t >> 16);
863 }
864 else if (sectors >= (uint32_t)2 * 1024 * 1024)
865 {
866 heads = 128;
867 sectors_per_track = 32;
868 cylinders = sectors >> 12;
869 }
870 else
871 {
872 heads = 64;
873 sectors_per_track = 32;
874 cylinders = sectors >> 11;
875 }
876 }
877
878 /* Calculate index into the generic disk table. */
879 hd_index = devcount_scsi + BX_MAX_ATA_DEVICES;
880
881 bios_dsk->scsidev[devcount_scsi].target_id = i;
882 bios_dsk->devices[hd_index].type = DSK_TYPE_VIRTIO_SCSI;
883 bios_dsk->devices[hd_index].device = DSK_DEVICE_HD;
884 bios_dsk->devices[hd_index].removable = 0;
885 bios_dsk->devices[hd_index].lock = 0;
886 bios_dsk->devices[hd_index].blksize = sector_size;
887 bios_dsk->devices[hd_index].translation = GEO_TRANSLATION_LBA;
888
889 /* Write LCHS/PCHS values. */
890 bios_dsk->devices[hd_index].lchs.heads = heads;
891 bios_dsk->devices[hd_index].lchs.spt = sectors_per_track;
892 bios_dsk->devices[hd_index].pchs.heads = heads;
893 bios_dsk->devices[hd_index].pchs.spt = sectors_per_track;
894
895 if (cylinders > 1024) {
896 bios_dsk->devices[hd_index].lchs.cylinders = 1024;
897 bios_dsk->devices[hd_index].pchs.cylinders = 1024;
898 } else {
899 bios_dsk->devices[hd_index].lchs.cylinders = (uint16_t)cylinders;
900 bios_dsk->devices[hd_index].pchs.cylinders = (uint16_t)cylinders;
901 }
902
903 BX_INFO("SCSI %d-ID#%d: LCHS=%lu/%u/%u 0x%llx sectors\n", devcount_scsi,
904 i, (uint32_t)cylinders, heads, sectors_per_track, sectors);
905
906 bios_dsk->devices[hd_index].sectors = sectors;
907
908 /* Store the id of the disk in the ata hdidmap. */
909 hdcount = bios_dsk->hdcount;
910 bios_dsk->hdidmap[hdcount] = devcount_scsi + BX_MAX_ATA_DEVICES;
911 hdcount++;
912 bios_dsk->hdcount = hdcount;
913
914 /* Update hdcount in the BDA. */
915 hdcount = read_byte(0x40, 0x75);
916 hdcount++;
917 write_byte(0x40, 0x75, hdcount);
918
919 devcount_scsi++;
920 }
921 else
922 {
923 /* We reached the maximum of SCSI disks we can boot from. We can quit detecting. */
924 break;
925 }
926 }
927#if 0
928 else if ( ((buffer[0] & 0xe0) == 0)
929 && ((buffer[0] & 0x1f) == 0x05))
930 {
931 uint8_t cdcount;
932 uint8_t removable;
933
934 BX_INFO("SCSI %d-ID#%d: CD/DVD-ROM\n", devcount_scsi, i);
935
936 /* Calculate index into the generic device table. */
937 hd_index = devcount_scsi + BX_MAX_ATA_DEVICES;
938
939 removable = buffer[1] & 0x80 ? 1 : 0;
940
941 bios_dsk->scsidev[devcount_scsi].target_id = i;
942 bios_dsk->devices[hd_index].type = DSK_TYPE_VIRTIO_SCSI;
943 bios_dsk->devices[hd_index].device = DSK_DEVICE_CDROM;
944 bios_dsk->devices[hd_index].removable = removable;
945 bios_dsk->devices[hd_index].blksize = 2048;
946 bios_dsk->devices[hd_index].translation = GEO_TRANSLATION_NONE;
947
948 /* Store the ID of the device in the BIOS cdidmap. */
949 cdcount = bios_dsk->cdcount;
950 bios_dsk->cdidmap[cdcount] = devcount_scsi + BX_MAX_ATA_DEVICES;
951 cdcount++;
952 bios_dsk->cdcount = cdcount;
953
954 devcount_scsi++;
955 }
956#endif
957 else
958 DBG_VIRTIO("%s: No supported device detected at %d\n", __func__, i);
959
960 bios_dsk->scsi_devcount = devcount_scsi;
961 }
962
963 return 0;
964}
965
966/**
967 * Initializes the VirtIO SCSI HBA and detects attached devices.
968 */
969static int virtio_scsi_hba_init(uint8_t u8Bus, uint8_t u8DevFn, uint8_t u8PciCapOffVirtIo)
970{
971 uint8_t u8PciCapOff;
972 uint16_t ebda_seg;
973 uint16_t virtio_seg;
974 uint8_t u8DevStat;
975 bio_dsk_t __far *bios_dsk;
976 virtio_t __far *virtio;
977
978 ebda_seg = read_word(0x0040, 0x000E);
979 bios_dsk = ebda_seg :> &EbdaData->bdisk;
980
981 /* Allocate 1K of base memory. */
982 virtio_seg = virtio_mem_alloc();
983 if (virtio_seg == 0)
984 {
985 DBG_VIRTIO("VirtIO: Could not allocate 1K of memory, can't boot from controller\n");
986 return 0;
987 }
988 DBG_VIRTIO("VirtIO: virtio_seg=%04x, size=%04x, pointer at EBDA:%04x (EBDA size=%04x)\n",
989 virtio_seg, sizeof(virtio_t), (uint16_t)&EbdaData->bdisk.virtio_seg, sizeof(ebda_data_t));
990
991 bios_dsk->virtio_seg = virtio_seg;
992
993 virtio = virtio_seg :> 0;
994 virtio->u8Bus = u8Bus;
995 virtio->u8DevFn = u8DevFn;
996
997 /*
998 * Go through the config space again, read the complete config capabilities
999 * this time and fill in the data.
1000 */
1001 u8PciCapOff = u8PciCapOffVirtIo;
1002 while (u8PciCapOff != 0)
1003 {
1004 uint8_t u8PciCapId = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff);
1005 uint8_t cbPciCap = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 2); /* Capability length. */
1006
1007 DBG_VIRTIO("Capability ID 0x%x at 0x%x\n", u8PciCapId, u8PciCapOff);
1008
1009 if ( u8PciCapId == PCI_CAP_ID_VNDR
1010 && cbPciCap >= sizeof(virtio_pci_cap_t))
1011 {
1012 /* Read in the config type and see what we got. */
1013 uint8_t u8PciVirtioCfg = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 3);
1014
1015 DBG_VIRTIO("VirtIO: CFG ID 0x%x\n", u8PciVirtioCfg);
1016 switch (u8PciVirtioCfg)
1017 {
1018 case VIRTIO_PCI_CAP_COMMON_CFG:
1019 case VIRTIO_PCI_CAP_NOTIFY_CFG:
1020 case VIRTIO_PCI_CAP_ISR_CFG:
1021 case VIRTIO_PCI_CAP_DEVICE_CFG:
1022 {
1023 virtio_bar_cfg_t __far *pBarCfg = &virtio->aBarCfgs[u8PciVirtioCfg - 1];
1024
1025 pBarCfg->u8Bar = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 4);
1026 pBarCfg->u32Offset = pci_read_config_dword(u8Bus, u8DevFn, u8PciCapOff + 8);
1027 pBarCfg->u32Length = pci_read_config_dword(u8Bus, u8DevFn, u8PciCapOff + 12);
1028 if (u8PciVirtioCfg == VIRTIO_PCI_CAP_NOTIFY_CFG)
1029 {
1030 virtio->u32NotifyOffMult = pci_read_config_dword(u8Bus, u8DevFn, u8PciCapOff + 16);
1031 DBG_VIRTIO("VirtIO: u32NotifyOffMult 0x%x\n", virtio->u32NotifyOffMult);
1032 }
1033 break;
1034 }
1035 case VIRTIO_PCI_CAP_PCI_CFG:
1036 virtio->u8PciCfgOff = u8PciCapOff;
1037 DBG_VIRTIO("VirtIO PCI CAP window offset: %x\n", u8PciCapOff);
1038 break;
1039 default:
1040 DBG_VIRTIO("VirtIO SCSI HBA with unknown PCI capability type 0x%x\n", u8PciVirtioCfg);
1041 }
1042 }
1043
1044 u8PciCapOff = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 1);
1045 }
1046
1047 /* Reset the device. */
1048 u8DevStat = VIRTIO_CMN_REG_DEV_STS_F_RST;
1049 virtio_reg_common_write_u8(virtio, VIRTIO_COMMON_REG_DEV_STS, u8DevStat);
1050 /* Acknowledge presence. */
1051 u8DevStat |= VIRTIO_CMN_REG_DEV_STS_F_ACK;
1052 virtio_reg_common_write_u8(virtio, VIRTIO_COMMON_REG_DEV_STS, u8DevStat);
1053 /* Our driver knows how to operate the device. */
1054 u8DevStat |= VIRTIO_CMN_REG_DEV_STS_F_DRV;
1055 virtio_reg_common_write_u8(virtio, VIRTIO_COMMON_REG_DEV_STS, u8DevStat);
1056
1057#if 0
1058 /* Read the feature bits and only program the VIRTIO_CMN_REG_DEV_FEAT_SCSI_INOUT bit if available. */
1059 fFeatures = virtio_reg_common_read_u32(virtio, VIRTIO_COMMON_REG_DEV_FEAT);
1060 fFeatures &= VIRTIO_CMN_REG_DEV_FEAT_SCSI_INOUT;
1061#endif
1062
1063 /* Check that the device is sane. */
1064 if ( virtio_reg_dev_cfg_read_u32(virtio, VIRTIO_DEV_CFG_REG_Q_NUM) < 1
1065 || virtio_reg_dev_cfg_read_u32(virtio, VIRTIO_DEV_CFG_REG_CDB_SZ) < 16
1066 || virtio_reg_dev_cfg_read_u32(virtio, VIRTIO_DEV_CFG_REG_SENSE_SZ) < 32
1067 || virtio_reg_dev_cfg_read_u32(virtio, VIRTIO_DEV_CFG_REG_SECT_MAX) < 1)
1068 {
1069 DBG_VIRTIO("VirtIO-SCSI: Invalid SCSI device configuration, ignoring device\n");
1070 return 0;
1071 }
1072
1073 virtio_reg_common_write_u32(virtio, VIRTIO_COMMON_REG_DRV_FEAT, VIRTIO_CMN_REG_DEV_FEAT_SCSI_INOUT);
1074
1075 /* Set the features OK bit. */
1076 u8DevStat |= VIRTIO_CMN_REG_DEV_STS_F_FEAT_OK;
1077 virtio_reg_common_write_u8(virtio, VIRTIO_COMMON_REG_DEV_STS, u8DevStat);
1078
1079 /* Read again and check the the okay bit is still set. */
1080 if (!(virtio_reg_common_read_u8(virtio, VIRTIO_COMMON_REG_DEV_STS) & VIRTIO_CMN_REG_DEV_STS_F_FEAT_OK))
1081 {
1082 DBG_VIRTIO("VirtIO-SCSI: Device doesn't accept our feature set, ignoring device\n");
1083 return 0;
1084 }
1085
1086 /* Disable event and control queue. */
1087 virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_SELECT, VIRTIO_SCSI_Q_CONTROL);
1088 virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_SIZE, 0);
1089 virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_ENABLE, 0);
1090
1091 virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_SELECT, VIRTIO_SCSI_Q_EVENT);
1092 virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_SIZE, 0);
1093 virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_ENABLE, 0);
1094
1095 /* Setup the request queue. */
1096 virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_SELECT, VIRTIO_SCSI_Q_REQUEST);
1097 virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_SIZE, VIRTIO_SCSI_RING_ELEM);
1098 virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_ENABLE, 1);
1099
1100 /* Set queue area addresses (only low part, leave high part 0). */
1101 virtio_reg_common_write_u32(virtio, VIRTIO_COMMON_REG_Q_DESC, virtio_addr_to_phys(&virtio->Queue.aDescTbl[0]));
1102 virtio_reg_common_write_u32(virtio, VIRTIO_COMMON_REG_Q_DESC + 4, 0);
1103
1104 virtio_reg_common_write_u32(virtio, VIRTIO_COMMON_REG_Q_DRIVER, virtio_addr_to_phys(&virtio->Queue.AvailRing));
1105 virtio_reg_common_write_u32(virtio, VIRTIO_COMMON_REG_Q_DRIVER + 4, 0);
1106
1107 virtio_reg_common_write_u32(virtio, VIRTIO_COMMON_REG_Q_DEVICE, virtio_addr_to_phys(&virtio->Queue.UsedRing));
1108 virtio_reg_common_write_u32(virtio, VIRTIO_COMMON_REG_Q_DEVICE + 4, 0);
1109
1110 virtio_reg_dev_cfg_write_u32(virtio, VIRTIO_DEV_CFG_REG_CDB_SZ, VIRTIO_SCSI_CDB_SZ);
1111 virtio_reg_dev_cfg_write_u32(virtio, VIRTIO_DEV_CFG_REG_SENSE_SZ, VIRTIO_SCSI_SENSE_SZ);
1112
1113 DBG_VIRTIO("VirtIO: Q notify offset 0x%x\n", virtio_reg_common_read_u16(virtio, VIRTIO_COMMON_REG_Q_NOTIFY_OFF));
1114 virtio->Queue.offNotify = virtio_reg_common_read_u16(virtio, VIRTIO_COMMON_REG_Q_NOTIFY_OFF) * virtio->u32NotifyOffMult;
1115
1116 /* Bring the device into operational mode. */
1117 u8DevStat |= VIRTIO_CMN_REG_DEV_STS_F_DRV_OK;
1118 virtio_reg_common_write_u8(virtio, VIRTIO_COMMON_REG_DEV_STS, u8DevStat);
1119
1120 return virtio_scsi_detect_devices(virtio);
1121}
1122
1123/**
1124 * Init the VirtIO SCSI driver and detect attached disks.
1125 */
1126void BIOSCALL virtio_scsi_init(void)
1127{
1128 uint16_t busdevfn;
1129
1130 busdevfn = pci_find_device(0x1af4, 0x1048);
1131 if (busdevfn != VBOX_VIRTIO_NO_DEVICE)
1132 {
1133 uint8_t u8Bus, u8DevFn;
1134 uint8_t u8PciCapOff;
1135 uint8_t u8PciCapOffVirtIo = VBOX_VIRTIO_NIL_CFG;
1136 uint8_t u8PciCapVirtioSeen = 0;
1137
1138 u8Bus = (busdevfn & 0xff00) >> 8;
1139 u8DevFn = busdevfn & 0x00ff;
1140
1141 DBG_VIRTIO("VirtIO SCSI HBA at Bus %u DevFn 0x%x (raw 0x%x)\n", u8Bus, u8DevFn, busdevfn);
1142
1143 /* Examine the capability list and search for the VirtIO specific capabilities. */
1144 u8PciCapOff = pci_read_config_byte(u8Bus, u8DevFn, PCI_CONFIG_CAP);
1145
1146 while (u8PciCapOff != 0)
1147 {
1148 uint8_t u8PciCapId = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff);
1149 uint8_t cbPciCap = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 2); /* Capability length. */
1150
1151 DBG_VIRTIO("Capability ID 0x%x at 0x%x\n", u8PciCapId, u8PciCapOff);
1152
1153 if ( u8PciCapId == PCI_CAP_ID_VNDR
1154 && cbPciCap >= sizeof(virtio_pci_cap_t))
1155 {
1156 /* Read in the config type and see what we got. */
1157 uint8_t u8PciVirtioCfg = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 3);
1158
1159 if (u8PciCapOffVirtIo == VBOX_VIRTIO_NIL_CFG)
1160 u8PciCapOffVirtIo = u8PciCapOff;
1161
1162 DBG_VIRTIO("VirtIO: CFG ID 0x%x\n", u8PciVirtioCfg);
1163 switch (u8PciVirtioCfg)
1164 {
1165 case VIRTIO_PCI_CAP_COMMON_CFG:
1166 case VIRTIO_PCI_CAP_NOTIFY_CFG:
1167 case VIRTIO_PCI_CAP_ISR_CFG:
1168 case VIRTIO_PCI_CAP_DEVICE_CFG:
1169 case VIRTIO_PCI_CAP_PCI_CFG:
1170 u8PciCapVirtioSeen |= 1 << (u8PciVirtioCfg - 1);
1171 break;
1172 default:
1173 DBG_VIRTIO("VirtIO SCSI HBA with unknown PCI capability type 0x%x\n", u8PciVirtioCfg);
1174 }
1175 }
1176
1177 u8PciCapOff = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 1);
1178 }
1179
1180 /* Initialize the controller if all required PCI capabilities where found. */
1181 if ( u8PciCapOffVirtIo != VBOX_VIRTIO_NIL_CFG
1182 && u8PciCapVirtioSeen == 0x1f)
1183 {
1184 int rc;
1185
1186 DBG_VIRTIO("VirtIO SCSI HBA with all required capabilities at 0x%x\n", u8PciCapOffVirtIo);
1187
1188 /* Enable PCI memory, I/O, bus mastering access in command register. */
1189 pci_write_config_word(u8Bus, u8DevFn, 4, 0x7);
1190
1191 rc = virtio_scsi_hba_init(u8Bus, u8DevFn, u8PciCapOffVirtIo);
1192 }
1193 else
1194 DBG_VIRTIO("VirtIO SCSI HBA with no usable PCI config access!\n");
1195 }
1196 else
1197 DBG_VIRTIO("No VirtIO SCSI HBA!\n");
1198}
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