VirtualBox

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

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

PC/BIOS: The index of the avail queue is supposed to be free running and only clipped to the queue size internally, bugref:9440

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