VirtualBox

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

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

PC/BIOS: Add support for CD/DVD drives attached to a Virtio SCSI controller, bugref:9440

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 43.7 KB
Line 
1/* $Id: virtio.c 82180 2019-11-25 14:53:03Z 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 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 != 0)
763 BX_PANIC("%s: SCSI_INQUIRY failed\n", __func__);
764
765 devcount_scsi = bios_dsk->scsi_devcount;
766
767 /* Check the attached device. */
768 if ( ((buffer[0] & 0xe0) == 0)
769 && ((buffer[0] & 0x1f) == 0x00))
770 {
771 DBG_VIRTIO("%s: Disk detected at %d\n", __func__, i);
772
773 /* We add the disk only if the maximum is not reached yet. */
774 if (devcount_scsi < BX_MAX_SCSI_DEVICES)
775 {
776 uint64_t sectors, t;
777 uint32_t sector_size, cylinders;
778 uint16_t heads, sectors_per_track;
779 uint8_t hdcount;
780 uint8_t cmos_base;
781
782 /* Issue a read capacity command now. */
783 _fmemset(aCDB, 0, sizeof(aCDB));
784 aCDB[0] = SCSI_SERVICE_ACT;
785 aCDB[1] = SCSI_READ_CAP_16;
786 aCDB[13] = 32; /* Allocation length. */
787
788 rc = virtio_scsi_cmd_data_in(virtio, i, aCDB, 16, buffer, 32, 0, 0);
789 if (rc != 0)
790 BX_PANIC("%s: SCSI_READ_CAPACITY failed\n", __func__);
791
792 /* The value returned is the last addressable LBA, not
793 * the size, which what "+ 1" is for.
794 */
795 sectors = swap_64(*(uint64_t *)buffer) + 1;
796
797 sector_size = ((uint32_t)buffer[8] << 24)
798 | ((uint32_t)buffer[9] << 16)
799 | ((uint32_t)buffer[10] << 8)
800 | ((uint32_t)buffer[11]);
801
802 /* We only support the disk if sector size is 512 bytes. */
803 if (sector_size != 512)
804 {
805 /* Leave a log entry. */
806 BX_INFO("Disk %d has an unsupported sector size of %u\n", i, sector_size);
807 continue;
808 }
809
810 /* Get logical CHS geometry. */
811 switch (devcount_scsi)
812 {
813 case 0:
814 cmos_base = 0x90;
815 break;
816 case 1:
817 cmos_base = 0x98;
818 break;
819 case 2:
820 cmos_base = 0xA0;
821 break;
822 case 3:
823 cmos_base = 0xA8;
824 break;
825 default:
826 cmos_base = 0;
827 }
828
829 if (cmos_base && inb_cmos(cmos_base + 7))
830 {
831 /* If provided, grab the logical geometry from CMOS. */
832 cylinders = inb_cmos(cmos_base + 0) + (inb_cmos(cmos_base + 1) << 8);
833 heads = inb_cmos(cmos_base + 2);
834 sectors_per_track = inb_cmos(cmos_base + 7);
835 }
836 else
837 {
838 /* Calculate default logical geometry. NB: Very different
839 * from default ATA/SATA logical geometry!
840 */
841 if (sectors >= (uint32_t)4 * 1024 * 1024)
842 {
843 heads = 255;
844 sectors_per_track = 63;
845 /* Approximate x / (255 * 63) using shifts */
846 t = (sectors >> 6) + (sectors >> 12);
847 cylinders = (t >> 8) + (t >> 16);
848 }
849 else if (sectors >= (uint32_t)2 * 1024 * 1024)
850 {
851 heads = 128;
852 sectors_per_track = 32;
853 cylinders = sectors >> 12;
854 }
855 else
856 {
857 heads = 64;
858 sectors_per_track = 32;
859 cylinders = sectors >> 11;
860 }
861 }
862
863 /* Calculate index into the generic disk table. */
864 hd_index = devcount_scsi + BX_MAX_ATA_DEVICES;
865
866 bios_dsk->scsidev[devcount_scsi].target_id = i;
867 bios_dsk->devices[hd_index].type = DSK_TYPE_VIRTIO_SCSI;
868 bios_dsk->devices[hd_index].device = DSK_DEVICE_HD;
869 bios_dsk->devices[hd_index].removable = 0;
870 bios_dsk->devices[hd_index].lock = 0;
871 bios_dsk->devices[hd_index].blksize = sector_size;
872 bios_dsk->devices[hd_index].translation = GEO_TRANSLATION_LBA;
873
874 /* Write LCHS/PCHS values. */
875 bios_dsk->devices[hd_index].lchs.heads = heads;
876 bios_dsk->devices[hd_index].lchs.spt = sectors_per_track;
877 bios_dsk->devices[hd_index].pchs.heads = heads;
878 bios_dsk->devices[hd_index].pchs.spt = sectors_per_track;
879
880 if (cylinders > 1024) {
881 bios_dsk->devices[hd_index].lchs.cylinders = 1024;
882 bios_dsk->devices[hd_index].pchs.cylinders = 1024;
883 } else {
884 bios_dsk->devices[hd_index].lchs.cylinders = (uint16_t)cylinders;
885 bios_dsk->devices[hd_index].pchs.cylinders = (uint16_t)cylinders;
886 }
887
888 BX_INFO("SCSI %d-ID#%d: LCHS=%lu/%u/%u 0x%llx sectors\n", devcount_scsi,
889 i, (uint32_t)cylinders, heads, sectors_per_track, sectors);
890
891 bios_dsk->devices[hd_index].sectors = sectors;
892
893 /* Store the id of the disk in the ata hdidmap. */
894 hdcount = bios_dsk->hdcount;
895 bios_dsk->hdidmap[hdcount] = devcount_scsi + BX_MAX_ATA_DEVICES;
896 hdcount++;
897 bios_dsk->hdcount = hdcount;
898
899 /* Update hdcount in the BDA. */
900 hdcount = read_byte(0x40, 0x75);
901 hdcount++;
902 write_byte(0x40, 0x75, hdcount);
903
904 devcount_scsi++;
905 }
906 else
907 {
908 /* We reached the maximum of SCSI disks we can boot from. We can quit detecting. */
909 break;
910 }
911 }
912 else if ( ((buffer[0] & 0xe0) == 0)
913 && ((buffer[0] & 0x1f) == 0x05))
914 {
915 uint8_t cdcount;
916 uint8_t removable;
917
918 BX_INFO("SCSI %d-ID#%d: CD/DVD-ROM\n", devcount_scsi, i);
919
920 /* Calculate index into the generic device table. */
921 hd_index = devcount_scsi + BX_MAX_ATA_DEVICES;
922
923 removable = buffer[1] & 0x80 ? 1 : 0;
924
925 bios_dsk->scsidev[devcount_scsi].target_id = i;
926 bios_dsk->devices[hd_index].type = DSK_TYPE_VIRTIO_SCSI;
927 bios_dsk->devices[hd_index].device = DSK_DEVICE_CDROM;
928 bios_dsk->devices[hd_index].removable = removable;
929 bios_dsk->devices[hd_index].blksize = 2048;
930 bios_dsk->devices[hd_index].translation = GEO_TRANSLATION_NONE;
931
932 /* Store the ID of the device in the BIOS cdidmap. */
933 cdcount = bios_dsk->cdcount;
934 bios_dsk->cdidmap[cdcount] = devcount_scsi + BX_MAX_ATA_DEVICES;
935 cdcount++;
936 bios_dsk->cdcount = cdcount;
937
938 devcount_scsi++;
939 }
940 else
941 DBG_VIRTIO("%s: No supported device detected at %d\n", __func__, i);
942
943 bios_dsk->scsi_devcount = devcount_scsi;
944 }
945
946 return 0;
947}
948
949/**
950 * Initializes the VirtIO SCSI HBA and detects attached devices.
951 */
952static int virtio_scsi_hba_init(uint8_t u8Bus, uint8_t u8DevFn, uint8_t u8PciCapOffVirtIo)
953{
954 uint8_t u8PciCapOff;
955 uint16_t ebda_seg;
956 uint16_t virtio_seg;
957 uint8_t u8DevStat;
958 bio_dsk_t __far *bios_dsk;
959 virtio_t __far *virtio;
960
961 ebda_seg = read_word(0x0040, 0x000E);
962 bios_dsk = ebda_seg :> &EbdaData->bdisk;
963
964 /* Allocate 1K of base memory. */
965 virtio_seg = virtio_mem_alloc();
966 if (virtio_seg == 0)
967 {
968 DBG_VIRTIO("VirtIO: Could not allocate 1K of memory, can't boot from controller\n");
969 return 0;
970 }
971 DBG_VIRTIO("VirtIO: virtio_seg=%04x, size=%04x, pointer at EBDA:%04x (EBDA size=%04x)\n",
972 virtio_seg, sizeof(virtio_t), (uint16_t)&EbdaData->bdisk.virtio_seg, sizeof(ebda_data_t));
973
974 bios_dsk->virtio_seg = virtio_seg;
975
976 virtio = virtio_seg :> 0;
977 virtio->u8Bus = u8Bus;
978 virtio->u8DevFn = u8DevFn;
979
980 /*
981 * Go through the config space again, read the complete config capabilities
982 * this time and fill in the data.
983 */
984 u8PciCapOff = u8PciCapOffVirtIo;
985 while (u8PciCapOff != 0)
986 {
987 uint8_t u8PciCapId = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff);
988 uint8_t cbPciCap = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 2); /* Capability length. */
989
990 DBG_VIRTIO("Capability ID 0x%x at 0x%x\n", u8PciCapId, u8PciCapOff);
991
992 if ( u8PciCapId == PCI_CAP_ID_VNDR
993 && cbPciCap >= sizeof(virtio_pci_cap_t))
994 {
995 /* Read in the config type and see what we got. */
996 uint8_t u8PciVirtioCfg = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 3);
997
998 DBG_VIRTIO("VirtIO: CFG ID 0x%x\n", u8PciVirtioCfg);
999 switch (u8PciVirtioCfg)
1000 {
1001 case VIRTIO_PCI_CAP_COMMON_CFG:
1002 case VIRTIO_PCI_CAP_NOTIFY_CFG:
1003 case VIRTIO_PCI_CAP_ISR_CFG:
1004 case VIRTIO_PCI_CAP_DEVICE_CFG:
1005 {
1006 virtio_bar_cfg_t __far *pBarCfg = &virtio->aBarCfgs[u8PciVirtioCfg - 1];
1007
1008 pBarCfg->u8Bar = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 4);
1009 pBarCfg->u32Offset = pci_read_config_dword(u8Bus, u8DevFn, u8PciCapOff + 8);
1010 pBarCfg->u32Length = pci_read_config_dword(u8Bus, u8DevFn, u8PciCapOff + 12);
1011 if (u8PciVirtioCfg == VIRTIO_PCI_CAP_NOTIFY_CFG)
1012 {
1013 virtio->u32NotifyOffMult = pci_read_config_dword(u8Bus, u8DevFn, u8PciCapOff + 16);
1014 DBG_VIRTIO("VirtIO: u32NotifyOffMult 0x%x\n", virtio->u32NotifyOffMult);
1015 }
1016 break;
1017 }
1018 case VIRTIO_PCI_CAP_PCI_CFG:
1019 virtio->u8PciCfgOff = u8PciCapOff;
1020 DBG_VIRTIO("VirtIO PCI CAP window offset: %x\n", u8PciCapOff);
1021 break;
1022 default:
1023 DBG_VIRTIO("VirtIO SCSI HBA with unknown PCI capability type 0x%x\n", u8PciVirtioCfg);
1024 break;
1025 }
1026 }
1027
1028 u8PciCapOff = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 1);
1029 }
1030
1031 /* Reset the device. */
1032 u8DevStat = VIRTIO_CMN_REG_DEV_STS_F_RST;
1033 virtio_reg_common_write_u8(virtio, VIRTIO_COMMON_REG_DEV_STS, u8DevStat);
1034 /* Acknowledge presence. */
1035 u8DevStat |= VIRTIO_CMN_REG_DEV_STS_F_ACK;
1036 virtio_reg_common_write_u8(virtio, VIRTIO_COMMON_REG_DEV_STS, u8DevStat);
1037 /* Our driver knows how to operate the device. */
1038 u8DevStat |= VIRTIO_CMN_REG_DEV_STS_F_DRV;
1039 virtio_reg_common_write_u8(virtio, VIRTIO_COMMON_REG_DEV_STS, u8DevStat);
1040
1041#if 0
1042 /* Read the feature bits and only program the VIRTIO_CMN_REG_DEV_FEAT_SCSI_INOUT bit if available. */
1043 fFeatures = virtio_reg_common_read_u32(virtio, VIRTIO_COMMON_REG_DEV_FEAT);
1044 fFeatures &= VIRTIO_CMN_REG_DEV_FEAT_SCSI_INOUT;
1045#endif
1046
1047 /* Check that the device is sane. */
1048 if ( virtio_reg_dev_cfg_read_u32(virtio, VIRTIO_DEV_CFG_REG_Q_NUM) < 1
1049 || virtio_reg_dev_cfg_read_u32(virtio, VIRTIO_DEV_CFG_REG_CDB_SZ) < 16
1050 || virtio_reg_dev_cfg_read_u32(virtio, VIRTIO_DEV_CFG_REG_SENSE_SZ) < 32
1051 || virtio_reg_dev_cfg_read_u32(virtio, VIRTIO_DEV_CFG_REG_SECT_MAX) < 1)
1052 {
1053 DBG_VIRTIO("VirtIO-SCSI: Invalid SCSI device configuration, ignoring device\n");
1054 return 0;
1055 }
1056
1057 virtio_reg_common_write_u32(virtio, VIRTIO_COMMON_REG_DRV_FEAT, VIRTIO_CMN_REG_DEV_FEAT_SCSI_INOUT);
1058
1059 /* Set the features OK bit. */
1060 u8DevStat |= VIRTIO_CMN_REG_DEV_STS_F_FEAT_OK;
1061 virtio_reg_common_write_u8(virtio, VIRTIO_COMMON_REG_DEV_STS, u8DevStat);
1062
1063 /* Read again and check the the okay bit is still set. */
1064 if (!(virtio_reg_common_read_u8(virtio, VIRTIO_COMMON_REG_DEV_STS) & VIRTIO_CMN_REG_DEV_STS_F_FEAT_OK))
1065 {
1066 DBG_VIRTIO("VirtIO-SCSI: Device doesn't accept our feature set, ignoring device\n");
1067 return 0;
1068 }
1069
1070 /* Disable event and control queue. */
1071 virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_SELECT, VIRTIO_SCSI_Q_CONTROL);
1072 virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_SIZE, 0);
1073 virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_ENABLE, 0);
1074
1075 virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_SELECT, VIRTIO_SCSI_Q_EVENT);
1076 virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_SIZE, 0);
1077 virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_ENABLE, 0);
1078
1079 /* Setup the request queue. */
1080 virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_SELECT, VIRTIO_SCSI_Q_REQUEST);
1081 virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_SIZE, VIRTIO_SCSI_RING_ELEM);
1082 virtio_reg_common_write_u16(virtio, VIRTIO_COMMON_REG_Q_ENABLE, 1);
1083
1084 /* Set queue area addresses (only low part, leave high part 0). */
1085 virtio_reg_common_write_u32(virtio, VIRTIO_COMMON_REG_Q_DESC, virtio_addr_to_phys(&virtio->Queue.aDescTbl[0]));
1086 virtio_reg_common_write_u32(virtio, VIRTIO_COMMON_REG_Q_DESC + 4, 0);
1087
1088 virtio_reg_common_write_u32(virtio, VIRTIO_COMMON_REG_Q_DRIVER, virtio_addr_to_phys(&virtio->Queue.AvailRing));
1089 virtio_reg_common_write_u32(virtio, VIRTIO_COMMON_REG_Q_DRIVER + 4, 0);
1090
1091 virtio_reg_common_write_u32(virtio, VIRTIO_COMMON_REG_Q_DEVICE, virtio_addr_to_phys(&virtio->Queue.UsedRing));
1092 virtio_reg_common_write_u32(virtio, VIRTIO_COMMON_REG_Q_DEVICE + 4, 0);
1093
1094 virtio_reg_dev_cfg_write_u32(virtio, VIRTIO_DEV_CFG_REG_CDB_SZ, VIRTIO_SCSI_CDB_SZ);
1095 virtio_reg_dev_cfg_write_u32(virtio, VIRTIO_DEV_CFG_REG_SENSE_SZ, VIRTIO_SCSI_SENSE_SZ);
1096
1097 DBG_VIRTIO("VirtIO: Q notify offset 0x%x\n", virtio_reg_common_read_u16(virtio, VIRTIO_COMMON_REG_Q_NOTIFY_OFF));
1098 virtio->Queue.offNotify = virtio_reg_common_read_u16(virtio, VIRTIO_COMMON_REG_Q_NOTIFY_OFF) * virtio->u32NotifyOffMult;
1099
1100 /* Bring the device into operational mode. */
1101 u8DevStat |= VIRTIO_CMN_REG_DEV_STS_F_DRV_OK;
1102 virtio_reg_common_write_u8(virtio, VIRTIO_COMMON_REG_DEV_STS, u8DevStat);
1103
1104 return virtio_scsi_detect_devices(virtio);
1105}
1106
1107/**
1108 * Init the VirtIO SCSI driver and detect attached disks.
1109 */
1110void BIOSCALL virtio_scsi_init(void)
1111{
1112 uint16_t busdevfn;
1113
1114 busdevfn = pci_find_device(0x1af4, 0x1048);
1115 if (busdevfn != VBOX_VIRTIO_NO_DEVICE)
1116 {
1117 uint8_t u8Bus, u8DevFn;
1118 uint8_t u8PciCapOff;
1119 uint8_t u8PciCapOffVirtIo = VBOX_VIRTIO_NIL_CFG;
1120 uint8_t u8PciCapVirtioSeen = 0;
1121
1122 u8Bus = (busdevfn & 0xff00) >> 8;
1123 u8DevFn = busdevfn & 0x00ff;
1124
1125 DBG_VIRTIO("VirtIO SCSI HBA at Bus %u DevFn 0x%x (raw 0x%x)\n", u8Bus, u8DevFn, busdevfn);
1126
1127 /* Examine the capability list and search for the VirtIO specific capabilities. */
1128 u8PciCapOff = pci_read_config_byte(u8Bus, u8DevFn, PCI_CONFIG_CAP);
1129
1130 while (u8PciCapOff != 0)
1131 {
1132 uint8_t u8PciCapId = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff);
1133 uint8_t cbPciCap = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 2); /* Capability length. */
1134
1135 DBG_VIRTIO("Capability ID 0x%x at 0x%x\n", u8PciCapId, u8PciCapOff);
1136
1137 if ( u8PciCapId == PCI_CAP_ID_VNDR
1138 && cbPciCap >= sizeof(virtio_pci_cap_t))
1139 {
1140 /* Read in the config type and see what we got. */
1141 uint8_t u8PciVirtioCfg = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 3);
1142
1143 if (u8PciCapOffVirtIo == VBOX_VIRTIO_NIL_CFG)
1144 u8PciCapOffVirtIo = u8PciCapOff;
1145
1146 DBG_VIRTIO("VirtIO: CFG ID 0x%x\n", u8PciVirtioCfg);
1147 switch (u8PciVirtioCfg)
1148 {
1149 case VIRTIO_PCI_CAP_COMMON_CFG:
1150 case VIRTIO_PCI_CAP_NOTIFY_CFG:
1151 case VIRTIO_PCI_CAP_ISR_CFG:
1152 case VIRTIO_PCI_CAP_DEVICE_CFG:
1153 case VIRTIO_PCI_CAP_PCI_CFG:
1154 u8PciCapVirtioSeen |= 1 << (u8PciVirtioCfg - 1);
1155 break;
1156 default:
1157 DBG_VIRTIO("VirtIO SCSI HBA with unknown PCI capability type 0x%x\n", u8PciVirtioCfg);
1158 }
1159 }
1160
1161 u8PciCapOff = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 1);
1162 }
1163
1164 /* Initialize the controller if all required PCI capabilities where found. */
1165 if ( u8PciCapOffVirtIo != VBOX_VIRTIO_NIL_CFG
1166 && u8PciCapVirtioSeen == 0x1f)
1167 {
1168 int rc;
1169
1170 DBG_VIRTIO("VirtIO SCSI HBA with all required capabilities at 0x%x\n", u8PciCapOffVirtIo);
1171
1172 /* Enable PCI memory, I/O, bus mastering access in command register. */
1173 pci_write_config_word(u8Bus, u8DevFn, 4, 0x7);
1174
1175 rc = virtio_scsi_hba_init(u8Bus, u8DevFn, u8PciCapOffVirtIo);
1176 }
1177 else
1178 DBG_VIRTIO("VirtIO SCSI HBA with no usable PCI config access!\n");
1179 }
1180 else
1181 DBG_VIRTIO("No VirtIO SCSI HBA!\n");
1182}
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