- Timestamp:
- May 19, 2021 1:35:28 PM (4 years ago)
- Location:
- trunk/src/VBox/Devices/PC/BIOS
- Files:
-
- 2 added
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/PC/BIOS/Makefile.kmk
r84958 r89168 67 67 ahci.c \ 68 68 virtio.c \ 69 buslogic.c \ 70 lsilogic.c \ 69 71 apm.c \ 70 72 pcibios.c \ -
trunk/src/VBox/Devices/PC/BIOS/disk.c
r83027 r89168 90 90 #ifdef VBOX_WITH_SCSI 91 91 [DSK_TYPE_SCSI] = { scsi_read_sectors, scsi_write_sectors }, 92 #endif93 #ifdef VBOX_WITH_VIRTIO_SCSI94 [DSK_TYPE_VIRTIO_SCSI] = { virtio_scsi_read_sectors, virtio_scsi_write_sectors },95 92 #endif 96 93 }; -
trunk/src/VBox/Devices/PC/BIOS/ebda.h
r82968 r89168 5 5 6 6 /* 7 * Copyright (C) 2006-202 0Oracle Corporation7 * Copyright (C) 2006-2021 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 106 106 */ 107 107 enum dsk_type_enm { 108 DSK_TYPE_NONE, /* Unknown device. */ 109 DSK_TYPE_UNKNOWN, /* Unknown ATA device. */ 110 DSK_TYPE_ATA, /* ATA disk. */ 111 DSK_TYPE_ATAPI, /* ATAPI device. */ 112 DSK_TYPE_SCSI, /* SCSI disk. */ 113 DSK_TYPE_AHCI, /* SATA disk via AHCI. */ 114 DSK_TYPE_VIRTIO_SCSI, /* SCSI disk. */ 115 DSKTYP_CNT /* Number of disk types. */ 108 DSK_TYPE_NONE, /* Unknown device. */ 109 DSK_TYPE_UNKNOWN, /* Unknown ATA device. */ 110 DSK_TYPE_ATA, /* ATA disk. */ 111 DSK_TYPE_ATAPI, /* ATAPI device. */ 112 DSK_TYPE_SCSI, /* SCSI disk. */ 113 DSK_TYPE_AHCI, /* SATA disk via AHCI. */ 114 DSKTYP_CNT /* Number of disk types. */ 116 115 }; 117 116 … … 197 196 /* SCSI specific device information. */ 198 197 typedef struct { 199 uint16_t io_base; /* Port base for HBA communication. */ 198 uint16_t hba_seg; /* Segment of HBA driver data block. */ 199 uint8_t idx_hba; /* The HBA driver to use. */ 200 200 uint8_t target_id; /* Target ID. */ 201 201 } scsi_dev_t; … … 209 209 uint8_t port; /* SATA port. */ 210 210 } ahci_dev_t; 211 212 #endif213 214 #ifdef VBOX_WITH_VIRTIO_SCSI215 216 /* VirtIO SCSI specific device information. */217 typedef struct {218 uint8_t target; /* Target ID. */219 } virtio_scsi_dev_t;220 211 221 212 #endif … … 261 252 extern uint16_t ata_cmd_packet(uint16_t device, uint8_t cmdlen, char __far *cmdbuf, 262 253 uint16_t header, uint32_t length, uint8_t inout, char __far *buffer); 263 extern uint16_t virtio_scsi_cmd_packet(uint16_t device, uint8_t cmdlen, char __far *cmdbuf,264 uint16_t skip_b, uint32_t length, uint8_t inout, char __far *buffer);265 254 266 255 extern uint16_t ata_soft_reset(uint16_t device); … … 290 279 scsi_dev_t scsidev[BX_MAX_SCSI_DEVICES]; 291 280 uint8_t scsi_devcount; /* Number of SCSI devices. */ 292 # ifdef VBOX_WITH_VIRTIO_SCSI293 uint16_t virtio_seg; /* Segment of VirtIO data block. */294 # endif295 281 #endif 296 282 … … 400 386 int __fastcall ahci_write_sectors(bio_dsk_t __far *bios_dsk); 401 387 402 int __fastcall virtio_scsi_read_sectors(bio_dsk_t __far *bios_dsk);403 int __fastcall virtio_scsi_write_sectors(bio_dsk_t __far *bios_dsk);404 405 388 extern void set_geom_lba(chs_t __far *lgeo, uint64_t nsectors); 406 389 extern int edd_fill_dpt(dpt_t __far *dpt, bio_dsk_t __far *bios_dsk, uint8_t device); -
trunk/src/VBox/Devices/PC/BIOS/eltorito.c
r82968 r89168 121 121 [DSK_TYPE_SCSI] = { scsi_cmd_packet }, 122 122 #endif 123 #ifdef VBOX_WITH_VIRTIO_SCSI124 [DSK_TYPE_VIRTIO_SCSI] = { virtio_scsi_cmd_packet },125 #endif126 123 }; 127 124 -
trunk/src/VBox/Devices/PC/BIOS/orgs.asm
r84901 r89168 142 142 extrn _ahci_init:near 143 143 endif 144 ifdef VBOX_WITH_VIRTIO_SCSI145 extrn _virtio_scsi_init:near146 endif147 144 if VBOX_BIOS_CPU ge 80286 148 145 extrn _int15_blkmove:near … … 647 644 endif 648 645 649 ifdef VBOX_WITH_VIRTIO_SCSI650 ; VirtIO-SCSI driver setup651 call _virtio_scsi_init652 endif653 654 646 ;; floppy setup 655 647 call floppy_post -
trunk/src/VBox/Devices/PC/BIOS/scsi.c
r82968 r89168 31 31 #endif 32 32 33 #define VBSCSI_BUSY (1 << 0) 34 #define VBSCSI_ERROR (1 << 1) 35 36 /* The I/O port of the BusLogic SCSI adapter. */ 37 #define BUSLOGIC_BIOS_IO_PORT 0x430 38 /* The I/O port of the LsiLogic SCSI adapter. */ 39 #define LSILOGIC_BIOS_IO_PORT 0x434 40 /* The I/O port of the LsiLogic SAS adapter. */ 41 #define LSILOGIC_SAS_BIOS_IO_PORT 0x438 42 43 #define VBSCSI_REGISTER_STATUS 0 44 #define VBSCSI_REGISTER_COMMAND 0 45 #define VBSCSI_REGISTER_DATA_IN 1 46 #define VBSCSI_REGISTER_IDENTIFY 2 47 #define VBSCSI_REGISTER_RESET 3 48 #define VBSCSI_REGISTER_DEVSTAT 3 49 50 #define VBSCSI_MAX_DEVICES 16 /* Maximum number of devices a SCSI device can have. */ 51 52 /* Data transfer direction. */ 53 #define SCSI_TXDIR_FROM_DEVICE 0 54 #define SCSI_TXDIR_TO_DEVICE 1 55 56 void insb_discard(unsigned nbytes, unsigned port); 57 #pragma aux insb_discard = \ 58 ".286" \ 59 "again:" \ 60 "in al,dx" \ 61 "loop again" \ 62 parm [cx] [dx] modify exact [cx ax] nomemory; 63 64 65 int scsi_cmd_data_in(uint16_t io_base, uint8_t target_id, uint8_t __far *aCDB, 66 uint8_t cbCDB, uint8_t __far *buffer, uint32_t length) 67 { 68 /* Check that the adapter is ready. */ 69 uint8_t status, sizes; 70 uint16_t i; 71 72 do 73 status = inb(io_base + VBSCSI_REGISTER_STATUS); 74 while (status & VBSCSI_BUSY); 75 76 sizes = ((length >> 12) & 0xF0) | ((cbCDB == 16) ? 0 : cbCDB); 77 outb(io_base + VBSCSI_REGISTER_COMMAND, target_id); /* Write the target ID. */ 78 outb(io_base + VBSCSI_REGISTER_COMMAND, SCSI_TXDIR_FROM_DEVICE); /* Write the transfer direction. */ 79 outb(io_base + VBSCSI_REGISTER_COMMAND, sizes); /* Write CDB size and top bufsize bits. */ 80 outb(io_base + VBSCSI_REGISTER_COMMAND, length); /* Write the buffer size. */ 81 outb(io_base + VBSCSI_REGISTER_COMMAND, (length >> 8)); 82 for (i = 0; i < cbCDB; i++) /* Write the CDB. */ 83 outb(io_base + VBSCSI_REGISTER_COMMAND, aCDB[i]); 84 85 /* Now wait for the command to complete. */ 86 do 87 status = inb(io_base + VBSCSI_REGISTER_STATUS); 88 while (status & VBSCSI_BUSY); 89 90 /* If any error occurred, inform the caller and don't bother reading the data. */ 91 if (status & VBSCSI_ERROR) { 92 outb(io_base + VBSCSI_REGISTER_RESET, 0); 93 94 status = inb(io_base + VBSCSI_REGISTER_DEVSTAT); 95 DBG_SCSI("%s: read failed, device status %02X\n", __func__, status); 96 return 4; /* Sector not found */ 97 } 98 99 /* Read in the data. The transfer length may be exactly 64K or more, 100 * which needs a bit of care when we're using 16-bit 'rep ins'. 101 */ 102 while (length > 32768) { 103 DBG_SCSI("%s: reading 32K to %X:%X\n", __func__, FP_SEG(buffer), FP_OFF(buffer)); 104 rep_insb(buffer, 32768, io_base + VBSCSI_REGISTER_DATA_IN); 105 length -= 32768; 106 buffer = (FP_SEG(buffer) + (32768 >> 4)) :> FP_OFF(buffer); 107 } 108 109 DBG_SCSI("%s: reading %ld bytes to %X:%X\n", __func__, length, FP_SEG(buffer), FP_OFF(buffer)); 110 rep_insb(buffer, length, io_base + VBSCSI_REGISTER_DATA_IN); 111 112 return 0; 113 } 114 115 int scsi_cmd_data_out(uint16_t io_base, uint8_t target_id, uint8_t __far *aCDB, 116 uint8_t cbCDB, uint8_t __far *buffer, uint32_t length) 117 { 118 /* Check that the adapter is ready. */ 119 uint8_t status, sizes; 120 uint16_t i; 121 122 do 123 status = inb(io_base + VBSCSI_REGISTER_STATUS); 124 while (status & VBSCSI_BUSY); 125 126 127 sizes = ((length >> 12) & 0xF0) | ((cbCDB == 16) ? 0 : cbCDB); 128 outb(io_base + VBSCSI_REGISTER_COMMAND, target_id); /* Write the target ID. */ 129 outb(io_base + VBSCSI_REGISTER_COMMAND, SCSI_TXDIR_TO_DEVICE); /* Write the transfer direction. */ 130 outb(io_base + VBSCSI_REGISTER_COMMAND, sizes); /* Write CDB size and top bufsize bits. */ 131 outb(io_base + VBSCSI_REGISTER_COMMAND, length); /* Write the buffer size. */ 132 outb(io_base + VBSCSI_REGISTER_COMMAND, (length >> 8)); 133 for (i = 0; i < cbCDB; i++) /* Write the CDB. */ 134 outb(io_base + VBSCSI_REGISTER_COMMAND, aCDB[i]); 135 136 /* Write out the data. The transfer length may be exactly 64K or more, 137 * which needs a bit of care when we're using 16-bit 'rep outs'. 138 */ 139 while (length > 32768) { 140 DBG_SCSI("%s: writing 32K from %X:%X\n", __func__, FP_SEG(buffer), FP_OFF(buffer)); 141 rep_outsb(buffer, 32768, io_base + VBSCSI_REGISTER_DATA_IN); 142 length -= 32768; 143 buffer = (FP_SEG(buffer) + (32768 >> 4)) :> FP_OFF(buffer); 144 } 145 146 DBG_SCSI("%s: writing %ld bytes from %X:%X\n", __func__, length, FP_SEG(buffer), FP_OFF(buffer)); 147 rep_outsb(buffer, length, io_base + VBSCSI_REGISTER_DATA_IN); 148 149 /* Now wait for the command to complete. */ 150 do 151 status = inb(io_base + VBSCSI_REGISTER_STATUS); 152 while (status & VBSCSI_BUSY); 153 154 /* If any error occurred, inform the caller. */ 155 if (status & VBSCSI_ERROR) { 156 outb(io_base + VBSCSI_REGISTER_RESET, 0); 157 158 status = inb(io_base + VBSCSI_REGISTER_DEVSTAT); 159 DBG_SCSI("%s: write failed, device status %02X\n", __func__, status); 160 return 4; /* Sector not found */ 161 } 162 163 return 0; 33 #define VBSCSI_MAX_DEVICES 16 /* Maximum number of devices a SCSI device currently supported. */ 34 35 #define VBOX_SCSI_NO_HBA 0xffff 36 37 typedef int (* scsi_hba_init)(void __far *pvHba, uint8_t u8Bus, uint8_t u8DevFn); 38 typedef int (* scsi_hba_cmd_data_out)(void __far *pvHba, uint8_t idTgt, uint8_t __far *aCDB, 39 uint8_t cbCDB, uint8_t __far *buffer, uint32_t length); 40 typedef int (* scsi_hba_cmd_data_in)(void __far *pvHba, uint8_t idTgt, uint8_t __far *aCDB, 41 uint8_t cbCDB, uint8_t __far *buffer, uint32_t length, uint16_t skip_a, 42 uint16_t skip_b); 43 44 typedef struct 45 { 46 uint16_t idPciVendor; 47 uint16_t idPciDevice; 48 scsi_hba_init init; 49 scsi_hba_cmd_data_out cmd_data_out; 50 scsi_hba_cmd_data_in cmd_data_in; 51 } scsi_hba_t; 52 53 /* Machinery to save/restore high bits of EAX. 32-bit port I/O needs to use 54 * EAX, but saving/restoring EAX around each port access would be inefficient. 55 * Instead, each externally callable routine must save the high bits before 56 * modifying them and restore the high bits before exiting. 57 */ 58 59 /* Note: Reading high EAX bits destroys them - *must* be restored later. */ 60 uint16_t eax_hi_rd(void); 61 #pragma aux eax_hi_rd = \ 62 ".386" \ 63 "shr eax, 16" \ 64 value [ax] modify nomemory; 65 66 void eax_hi_wr(uint16_t); 67 #pragma aux eax_hi_wr = \ 68 ".386" \ 69 "shl eax, 16" \ 70 parm [ax] modify nomemory; 71 72 void inline high_bits_save(uint16_t __far *pu16EaxHi) 73 { 74 *pu16EaxHi = eax_hi_rd(); 75 } 76 77 void inline high_bits_restore(uint16_t u16EaxHi) 78 { 79 eax_hi_wr(u16EaxHi); 80 } 81 82 /* Pointers to the HBA specific access routines. */ 83 scsi_hba_t hbaacc[] = 84 { 85 { 0x1000, 0x0030, lsilogic_scsi_init, lsilogic_scsi_cmd_data_out, lsilogic_scsi_cmd_data_in }, /* SPI */ 86 { 0x1000, 0x0054, lsilogic_scsi_init, lsilogic_scsi_cmd_data_out, lsilogic_scsi_cmd_data_in }, /* SAS */ 87 { 0x104b, 0x1040, buslogic_scsi_init, buslogic_scsi_cmd_data_out, buslogic_scsi_cmd_data_in }, 88 #ifdef VBOX_WITH_VIRTIO_SCSI 89 { 0x1af4, 0x1048, virtio_scsi_init, virtio_scsi_cmd_data_out, virtio_scsi_cmd_data_in } 90 #endif 91 }; 92 93 /** 94 * Allocates 1K of conventional memory. 95 */ 96 static uint16_t scsi_hba_mem_alloc(void) 97 { 98 uint16_t base_mem_kb; 99 uint16_t hba_seg; 100 101 base_mem_kb = read_word(0x00, 0x0413); 102 103 DBG_SCSI("SCSI: %dK of base mem\n", base_mem_kb); 104 105 if (base_mem_kb == 0) 106 return 0; 107 108 base_mem_kb--; /* Allocate one block. */ 109 hba_seg = (((uint32_t)base_mem_kb * 1024) >> 4); /* Calculate start segment. */ 110 111 write_word(0x00, 0x0413, base_mem_kb); 112 113 return hba_seg; 164 114 } 165 115 … … 176 126 cdb_rw16 cdb; 177 127 uint32_t count; 178 uint16_t io_base; 128 uint16_t hba_seg; 129 uint8_t idx_hba; 179 130 uint8_t target_id; 180 131 uint8_t device_id; 132 uint16_t eax_hi; 181 133 182 134 device_id = VBOX_GET_SCSI_DEVICE(bios_dsk->drqp.dev_id); … … 185 137 186 138 count = bios_dsk->drqp.nsect; 139 140 high_bits_save(&eax_hi); 187 141 188 142 /* Prepare a CDB. */ … … 194 148 195 149 196 io_base = bios_dsk->scsidev[device_id].io_base; 150 hba_seg = bios_dsk->scsidev[device_id].hba_seg; 151 idx_hba = bios_dsk->scsidev[device_id].idx_hba; 197 152 target_id = bios_dsk->scsidev[device_id].target_id; 198 153 … … 200 155 count, device_id, bios_dsk->scsidev[device_id].target_id); 201 156 202 rc = scsi_cmd_data_in(io_base, target_id, (void __far *)&cdb, 16, 203 bios_dsk->drqp.buffer, (count * 512L)); 204 157 rc = hbaacc[idx_hba].cmd_data_in(hba_seg :> 0, target_id, (void __far *)&cdb, 16, 158 bios_dsk->drqp.buffer, (count * 512L), 0, 0); 205 159 if (!rc) 206 160 { … … 209 163 } 210 164 DBG_SCSI("%s: transferred %u sectors\n", __func__, bios_dsk->drqp.nsect); 165 high_bits_restore(eax_hi); 211 166 212 167 return rc; … … 225 180 cdb_rw16 cdb; 226 181 uint32_t count; 227 uint16_t io_base; 182 uint16_t hba_seg; 183 uint8_t idx_hba; 228 184 uint8_t target_id; 229 185 uint8_t device_id; 186 uint16_t eax_hi; 230 187 231 188 device_id = VBOX_GET_SCSI_DEVICE(bios_dsk->drqp.dev_id); … … 234 191 235 192 count = bios_dsk->drqp.nsect; 193 194 high_bits_save(&eax_hi); 236 195 237 196 /* Prepare a CDB. */ … … 242 201 cdb.pad2 = 0; 243 202 244 io_base = bios_dsk->scsidev[device_id].io_base; 203 hba_seg = bios_dsk->scsidev[device_id].hba_seg; 204 idx_hba = bios_dsk->scsidev[device_id].idx_hba; 245 205 target_id = bios_dsk->scsidev[device_id].target_id; 246 206 … … 248 208 count, device_id, bios_dsk->scsidev[device_id].target_id); 249 209 250 rc = scsi_cmd_data_out(io_base, target_id, (void __far *)&cdb, 16, 251 bios_dsk->drqp.buffer, (count * 512L)); 252 210 rc = hbaacc[idx_hba].cmd_data_out(hba_seg :> 0, target_id, (void __far *)&cdb, 16, 211 bios_dsk->drqp.buffer, (count * 512L)); 253 212 if (!rc) 254 213 { … … 257 216 } 258 217 DBG_SCSI("%s: transferred %u sectors\n", __func__, bios_dsk->drqp.nsect); 218 high_bits_restore(eax_hi); 259 219 260 220 return rc; … … 280 240 */ 281 241 uint16_t scsi_cmd_packet(uint16_t device_id, uint8_t cmdlen, char __far *cmdbuf, 282 uint16_t before, uint32_t length, uint8_t inout, char __far *buffer)242 uint16_t skip_b, uint32_t length, uint8_t inout, char __far *buffer) 283 243 { 284 244 bio_dsk_t __far *bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk; 285 uint32_t read_len; 286 uint8_t status, sizes; 287 uint16_t i; 288 uint16_t io_base; 245 uint8_t rc; 289 246 uint8_t target_id; 247 uint16_t hba_seg; 248 uint8_t idx_hba; 249 uint16_t eax_hi; 290 250 291 251 /* Data out is currently not supported. */ … … 295 255 } 296 256 257 /* The skip length must be even. */ 258 if (skip_b & 1) { 259 DBG_SCSI("%s: skip must be even (%04x)\n", __func__, skip_b); 260 return 1; 261 } 262 297 263 /* Convert to SCSI specific device number. */ 298 264 device_id = VBOX_GET_SCSI_DEVICE(device_id); … … 304 270 bios_dsk->drqp.nsect, bios_dsk->drqp.sect_sz); 305 271 306 cmdlen -= 2; /* ATAPI uses 12-byte command packets for a READ 10. */307 308 i o_base = bios_dsk->scsidev[device_id].io_base;272 high_bits_save(&eax_hi); 273 hba_seg = bios_dsk->scsidev[device_id].hba_seg; 274 idx_hba = bios_dsk->scsidev[device_id].idx_hba; 309 275 target_id = bios_dsk->scsidev[device_id].target_id; 310 276 311 /* Wait until the adapter is ready. */ 312 do 313 status = inb(io_base + VBSCSI_REGISTER_STATUS); 314 while (status & VBSCSI_BUSY); 315 316 /* On the SCSI level, we have to transfer whole sectors. */ 317 /* NB: With proper residual length support, this should not be necessary; we should 318 * be able to avoid transferring the 'after' part of the sector. 319 */ 320 read_len = length + before + bios_dsk->drqp.skip_a; 321 322 sizes = (((read_len) >> 12) & 0xF0) | cmdlen; 323 outb(io_base + VBSCSI_REGISTER_COMMAND, target_id); /* Write the target ID. */ 324 outb(io_base + VBSCSI_REGISTER_COMMAND, SCSI_TXDIR_FROM_DEVICE); /* Write the transfer direction. */ 325 outb(io_base + VBSCSI_REGISTER_COMMAND, sizes); /* Write the CDB size. */ 326 outb(io_base + VBSCSI_REGISTER_COMMAND, read_len); /* Write the buffer size. */ 327 outb(io_base + VBSCSI_REGISTER_COMMAND, (read_len) >> 8); 328 for (i = 0; i < cmdlen; i++) /* Write the CDB. */ 329 outb(io_base + VBSCSI_REGISTER_COMMAND, cmdbuf[i]); 330 331 /* Now wait for the command to complete. */ 332 do 333 status = inb(io_base + VBSCSI_REGISTER_STATUS); 334 while (status & VBSCSI_BUSY); 335 336 /* If any error occurred, inform the caller and don't bother reading the data. */ 337 if (status & VBSCSI_ERROR) { 338 outb(io_base + VBSCSI_REGISTER_RESET, 0); 339 340 status = inb(io_base + VBSCSI_REGISTER_DEVSTAT); 341 DBG_SCSI("%s: read failed, device status %02X\n", __func__, status); 342 return 3; 343 } 344 345 /* Transfer the data read from the device. */ 346 347 if (before) /* If necessary, throw away data which needs to be skipped. */ 348 insb_discard(before, io_base + VBSCSI_REGISTER_DATA_IN); 349 350 bios_dsk->drqp.trsfbytes = length; 351 352 /* The requested length may be exactly 64K or more, which needs 353 * a bit of care when we're using 16-bit 'rep ins'. 354 */ 355 while (length > 32768) { 356 DBG_SCSI("%s: reading 32K to %X:%X\n", __func__, FP_SEG(buffer), FP_OFF(buffer)); 357 rep_insb(buffer, 32768, io_base + VBSCSI_REGISTER_DATA_IN); 358 length -= 32768; 359 buffer = (FP_SEG(buffer) + (32768 >> 4)) :> FP_OFF(buffer); 360 } 361 362 DBG_SCSI("%s: reading %ld bytes to %X:%X\n", __func__, length, FP_SEG(buffer), FP_OFF(buffer)); 363 rep_insb(buffer, length, io_base + VBSCSI_REGISTER_DATA_IN); 364 365 if (bios_dsk->drqp.skip_a) /* If necessary, throw away more data. */ 366 insb_discard(bios_dsk->drqp.skip_a, io_base + VBSCSI_REGISTER_DATA_IN); 367 368 return 0; 277 bios_dsk->drqp.lba = length << 8; /// @todo xfer length limit 278 bios_dsk->drqp.buffer = buffer; 279 bios_dsk->drqp.nsect = length / bios_dsk->drqp.sect_sz; 280 281 DBG_SCSI("%s: reading %u bytes, device %d, target %d\n", __func__, 282 length, device_id, bios_dsk->scsidev[device_id].target_id); 283 284 rc = hbaacc[idx_hba].cmd_data_in(hba_seg :> 0, target_id, (void __far *)cmdbuf, cmdlen, 285 bios_dsk->drqp.buffer, length, skip_b, bios_dsk->drqp.skip_a); 286 if (!rc) 287 bios_dsk->drqp.trsfbytes = length; 288 289 DBG_SCSI("%s: transferred %u bytes\n", __func__, length); 290 high_bits_restore(eax_hi); 291 292 return rc; 369 293 } 370 294 … … 375 299 * @param io_base The I/O base port of the controller. 376 300 */ 377 void scsi_enumerate_attached_devices(uint16_t io_base)301 static void scsi_enumerate_attached_devices(uint16_t hba_seg, uint8_t idx_hba) 378 302 { 379 303 int i; … … 397 321 aCDB[5] = 0; 398 322 399 rc = scsi_cmd_data_in(io_base, i, aCDB, 6, buffer, 5);323 rc = hbaacc[idx_hba].cmd_data_in(hba_seg :> 0, i, aCDB, 6, buffer, 5, 0, 0); 400 324 if (rc != 0) 401 BX_PANIC("%s: SCSI_INQUIRY failed\n", __func__); 325 { 326 DBG_SCSI("%s: SCSI_INQUIRY failed\n", __func__); /* Not a fatal error if the device doesn't exist. */ 327 continue; 328 } 402 329 403 330 devcount_scsi = bios_dsk->scsi_devcount; … … 424 351 aCDB[13] = 32; /* Allocation length. */ 425 352 426 rc = scsi_cmd_data_in(io_base, i, aCDB, 16, buffer, 32);353 rc = hbaacc[idx_hba].cmd_data_in(hba_seg :> 0, i, aCDB, 16, buffer, 32, 0, 0); 427 354 if (rc != 0) 428 355 BX_PANIC("%s: SCSI_READ_CAPACITY failed\n", __func__); … … 502 429 hd_index = devcount_scsi + BX_MAX_ATA_DEVICES; 503 430 504 bios_dsk->scsidev[devcount_scsi].io_base = io_base; 431 bios_dsk->scsidev[devcount_scsi].hba_seg = hba_seg; 432 bios_dsk->scsidev[devcount_scsi].idx_hba = idx_hba; 505 433 bios_dsk->scsidev[devcount_scsi].target_id = i; 506 434 bios_dsk->devices[hd_index].type = DSK_TYPE_SCSI; … … 562 490 removable = buffer[1] & 0x80 ? 1 : 0; 563 491 564 bios_dsk->scsidev[devcount_scsi].io_base = io_base; 492 bios_dsk->scsidev[devcount_scsi].hba_seg = hba_seg; 493 bios_dsk->scsidev[devcount_scsi].idx_hba = idx_hba; 565 494 bios_dsk->scsidev[devcount_scsi].target_id = i; 566 495 bios_dsk->devices[hd_index].type = DSK_TYPE_SCSI; … … 585 514 } 586 515 587 void scsi_pci_init(uint16_t vendor_id, uint16_t device_id)588 {589 uint16_t bus_dev_fn;590 591 bus_dev_fn = pci_find_device(vendor_id, device_id);592 if (bus_dev_fn == -1) {593 DBG_SCSI("%s: Adapter %x:%x not found, how come?!\n", __func__, vendor_id, device_id);594 return;595 }596 597 DBG_SCSI("%s: Adapter %x:%x found at %x, enabling BM\n", __func__, vendor_id, device_id, bus_dev_fn);598 /* Enable PCI memory, I/O, bus mastering access in command register. */599 pci_write_config_word(bus_dev_fn >> 8, (uint8_t)bus_dev_fn, 4, 0x7);600 }601 602 516 /** 603 517 * Init the SCSI driver and detect attached disks. … … 605 519 void BIOSCALL scsi_init(void) 606 520 { 607 uint8_t identifier;521 int i; 608 522 bio_dsk_t __far *bios_dsk; 609 523 610 524 bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk; 611 612 525 bios_dsk->scsi_devcount = 0; 613 526 614 identifier = 0; 615 616 /* Detect the BusLogic adapter. */ 617 outb(BUSLOGIC_BIOS_IO_PORT+VBSCSI_REGISTER_IDENTIFY, 0x55); 618 identifier = inb(BUSLOGIC_BIOS_IO_PORT+VBSCSI_REGISTER_IDENTIFY); 619 620 if (identifier == 0x55) 527 /* Walk the supported drivers and try to detect the HBA. */ 528 for (i = 0; i < sizeof(hbaacc)/sizeof(hbaacc[0]); i++) 621 529 { 622 /* Detected - Enumerate attached devices. */ 623 DBG_SCSI("%s: BusLogic SCSI adapter detected\n", __func__); 624 outb(BUSLOGIC_BIOS_IO_PORT+VBSCSI_REGISTER_RESET, 0); 625 scsi_enumerate_attached_devices(BUSLOGIC_BIOS_IO_PORT); 626 scsi_pci_init(0x104B, 0x1040); 530 uint16_t busdevfn = pci_find_device(hbaacc[i].idPciVendor, hbaacc[i].idPciDevice); 531 if (busdevfn != VBOX_SCSI_NO_HBA) 532 { 533 int rc; 534 uint8_t u8Bus, u8DevFn; 535 uint16_t hba_seg = scsi_hba_mem_alloc(); 536 if (hba_seg == 0) /* No point in trying the rest if we are out of memory. */ 537 break; 538 539 u8Bus = (busdevfn & 0xff00) >> 8; 540 u8DevFn = busdevfn & 0x00ff; 541 542 DBG_SCSI("SCSI HBA at Bus %u DevFn 0x%x (raw 0x%x)\n", u8Bus, u8DevFn, busdevfn); 543 rc = hbaacc[i].init(hba_seg :> 0, u8Bus, u8DevFn); 544 if (!rc) 545 scsi_enumerate_attached_devices(hba_seg, i); 546 /** @todo Free memory on error. */ 547 } 627 548 } 628 else 629 { 630 DBG_SCSI("%s: BusLogic SCSI adapter not detected\n", __func__); 631 } 632 633 /* Detect the LSI Logic parallel SCSI adapter. */ 634 outb(LSILOGIC_BIOS_IO_PORT+VBSCSI_REGISTER_IDENTIFY, 0x55); 635 identifier = inb(LSILOGIC_BIOS_IO_PORT+VBSCSI_REGISTER_IDENTIFY); 636 637 if (identifier == 0x55) 638 { 639 /* Detected - Enumerate attached devices. */ 640 DBG_SCSI("%s: LSI Logic SCSI adapter detected\n", __func__); 641 outb(LSILOGIC_BIOS_IO_PORT+VBSCSI_REGISTER_RESET, 0); 642 scsi_enumerate_attached_devices(LSILOGIC_BIOS_IO_PORT); 643 scsi_pci_init(0x1000, 0x0030); 644 } 645 else 646 { 647 DBG_SCSI("%s: LSI Logic SCSI adapter not detected\n", __func__); 648 } 649 650 /* Detect the LSI Logic SAS adapter. */ 651 outb(LSILOGIC_SAS_BIOS_IO_PORT+VBSCSI_REGISTER_IDENTIFY, 0x55); 652 identifier = inb(LSILOGIC_SAS_BIOS_IO_PORT+VBSCSI_REGISTER_IDENTIFY); 653 654 if (identifier == 0x55) 655 { 656 /* Detected - Enumerate attached devices. */ 657 DBG_SCSI("%s: LSI Logic SAS adapter detected\n", __func__); 658 outb(LSILOGIC_SAS_BIOS_IO_PORT+VBSCSI_REGISTER_RESET, 0); 659 scsi_enumerate_attached_devices(LSILOGIC_SAS_BIOS_IO_PORT); 660 scsi_pci_init(0x1000, 0x0054); 661 } 662 else 663 { 664 DBG_SCSI("%s: LSI Logic SAS adapter not detected\n", __func__); 665 } 666 } 549 } -
trunk/src/VBox/Devices/PC/BIOS/scsi.h
r82968 r89168 57 57 ct_assert(sizeof(cdb_rw16) == 16); 58 58 59 extern int lsilogic_scsi_init(void __far *pvHba, uint8_t u8Bus, uint8_t u8DevFn); 60 extern int lsilogic_scsi_cmd_data_out(void __far *pvHba, uint8_t idTgt, uint8_t __far *aCDB, 61 uint8_t cbCDB, uint8_t __far *buffer, uint32_t length); 62 extern int lsilogic_scsi_cmd_data_in(void __far *pvHba, uint8_t idTgt, uint8_t __far *aCDB, 63 uint8_t cbCDB, uint8_t __far *buffer, uint32_t length, uint16_t skip_a, 64 uint16_t skip_b); 65 66 extern int buslogic_scsi_init(void __far *pvHba, uint8_t u8Bus, uint8_t u8DevFn); 67 extern int buslogic_scsi_cmd_data_out(void __far *pvHba, uint8_t idTgt, uint8_t __far *aCDB, 68 uint8_t cbCDB, uint8_t __far *buffer, uint32_t length); 69 extern int buslogic_scsi_cmd_data_in(void __far *pvHba, uint8_t idTgt, uint8_t __far *aCDB, 70 uint8_t cbCDB, uint8_t __far *buffer, uint32_t length, uint16_t skip_a, 71 uint16_t skip_b); 72 73 extern int virtio_scsi_init(void __far *pvHba, uint8_t u8Bus, uint8_t u8DevFn); 74 extern int virtio_scsi_cmd_data_out(void __far *pvHba, uint8_t idTgt, uint8_t __far *aCDB, 75 uint8_t cbCDB, uint8_t __far *buffer, uint32_t length); 76 extern int virtio_scsi_cmd_data_in(void __far *pvHba, uint8_t idTgt, uint8_t __far *aCDB, 77 uint8_t cbCDB, uint8_t __far *buffer, uint32_t length, uint16_t skip_a, 78 uint16_t skip_b); 79 59 80 #endif /* !VBOX_INCLUDED_SRC_PC_BIOS_scsi_h */ 60 81 -
trunk/src/VBox/Devices/PC/BIOS/virtio.c
r82968 r89168 31 31 # define DBG_VIRTIO(...) 32 32 #endif 33 34 #define VBSCSI_MAX_DEVICES 16 /* Maximum number of devices a SCSI device currently supported. */35 33 36 34 /* The maximum CDB size. */ … … 225 223 226 224 #define PCI_CAP_ID_VNDR 0x09 227 #define VBOX_VIRTIO_NO_DEVICE 0xffff228 225 229 226 #define VBOX_VIRTIO_NIL_CFG 0xff … … 280 277 #define VIRTIO_SCSI_STS_RESPONSE_OK 0x00 281 278 282 /* Machinery to save/restore high bits of EAX. 32-bit port I/O needs to use283 * EAX, but saving/restoring EAX around each port access would be inefficient.284 * Instead, each externally callable routine must save the high bits before285 * modifying them and restore the high bits before exiting.286 */287 288 /* Note: Reading high EAX bits destroys them - *must* be restored later. */289 uint16_t eax_hi_rd(void);290 #pragma aux eax_hi_rd = \291 ".386" \292 "shr eax, 16" \293 value [ax] modify nomemory;294 295 void eax_hi_wr(uint16_t);296 #pragma aux eax_hi_wr = \297 ".386" \298 "shl eax, 16" \299 parm [ax] modify nomemory;300 301 void inline high_bits_save(virtio_t __far *virtio)302 {303 virtio->saved_eax_hi = eax_hi_rd();304 }305 306 void inline high_bits_restore(virtio_t __far *virtio)307 {308 eax_hi_wr(virtio->saved_eax_hi);309 }310 311 279 static void virtio_reg_set_bar_offset_length(virtio_t __far *virtio, uint8_t u8Bar, uint32_t offReg, uint32_t cb) 312 280 { … … 403 371 404 372 /** 405 * Allocates 1K of conventional memory.406 */407 static 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 373 * Converts a segment:offset pair into a 32bit physical address. 429 374 */ … … 433 378 } 434 379 435 int 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 { 380 int virtio_scsi_cmd_data_out(void __far *pvHba, uint8_t idTgt, uint8_t __far *aCDB, 381 uint8_t cbCDB, uint8_t __far *buffer, uint32_t length) 382 { 383 virtio_t __far *virtio = (virtio_t __far *)pvHba; 438 384 uint16_t idxUsedOld = virtio->Queue.UsedRing.idxNextUsed; 439 385 … … 488 434 } 489 435 490 int virtio_scsi_cmd_data_in(v irtio_t __far *virtio, uint8_t idTgt, uint8_t __far *aCDB,436 int virtio_scsi_cmd_data_in(void __far *pvHba, uint8_t idTgt, uint8_t __far *aCDB, 491 437 uint8_t cbCDB, uint8_t __far *buffer, uint32_t length, uint16_t skip_a, 492 438 uint16_t skip_b) 493 439 { 440 virtio_t __far *virtio = (virtio_t __far *)pvHba; 494 441 uint16_t idxUsedOld = virtio->Queue.UsedRing.idxNextUsed; 495 442 uint8_t idxDesc = 0; … … 575 522 576 523 /** 577 * Read sectors from an attached VirtIO SCSI device.578 *579 * @returns status code.580 * @param bios_dsk Pointer to disk request packet (in the581 * EBDA).582 */583 int 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 the630 * EBDA).631 */632 int 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 0x02675 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 */688 uint16_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 limit720 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 737 static int virtio_scsi_detect_devices(virtio_t __far *virtio)738 {739 int i;740 uint8_t buffer[0x0200];741 bio_dsk_t __far *bios_dsk;742 743 bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;744 745 /* Go through target devices. */746 for (i = 0; i < VBSCSI_MAX_DEVICES; i++)747 {748 uint8_t rc;749 uint8_t aCDB[16];750 uint8_t hd_index, devcount_scsi;751 752 aCDB[0] = SCSI_INQUIRY;753 aCDB[1] = 0;754 aCDB[2] = 0;755 aCDB[3] = 0;756 aCDB[4] = 5; /* Allocation length. */757 aCDB[5] = 0;758 759 _fmemset(buffer, 0, sizeof(buffer));760 761 rc = virtio_scsi_cmd_data_in(virtio, i, aCDB, 6, buffer, 5, 0, 0);762 if (!rc)763 {764 devcount_scsi = bios_dsk->scsi_devcount;765 766 /* Check the attached device. */767 if ( ((buffer[0] & 0xe0) == 0)768 && ((buffer[0] & 0x1f) == 0x00))769 {770 DBG_VIRTIO("%s: Disk detected at %d\n", __func__, i);771 772 /* We add the disk only if the maximum is not reached yet. */773 if (devcount_scsi < BX_MAX_SCSI_DEVICES)774 {775 uint64_t sectors, t;776 uint32_t sector_size, cylinders;777 uint16_t heads, sectors_per_track;778 uint8_t hdcount;779 uint8_t cmos_base;780 781 /* Issue a read capacity command now. */782 _fmemset(aCDB, 0, sizeof(aCDB));783 aCDB[0] = SCSI_SERVICE_ACT;784 aCDB[1] = SCSI_READ_CAP_16;785 aCDB[13] = 32; /* Allocation length. */786 787 rc = virtio_scsi_cmd_data_in(virtio, i, aCDB, 16, buffer, 32, 0, 0);788 if (rc != 0)789 BX_PANIC("%s: SCSI_READ_CAPACITY failed\n", __func__);790 791 /* The value returned is the last addressable LBA, not792 * the size, which what "+ 1" is for.793 */794 sectors = swap_64(*(uint64_t *)buffer) + 1;795 796 sector_size = ((uint32_t)buffer[8] << 24)797 | ((uint32_t)buffer[9] << 16)798 | ((uint32_t)buffer[10] << 8)799 | ((uint32_t)buffer[11]);800 801 /* We only support the disk if sector size is 512 bytes. */802 if (sector_size != 512)803 {804 /* Leave a log entry. */805 BX_INFO("Disk %d has an unsupported sector size of %u\n", i, sector_size);806 continue;807 }808 809 /* Get logical CHS geometry. */810 switch (devcount_scsi)811 {812 case 0:813 cmos_base = 0x90;814 break;815 case 1:816 cmos_base = 0x98;817 break;818 case 2:819 cmos_base = 0xA0;820 break;821 case 3:822 cmos_base = 0xA8;823 break;824 default:825 cmos_base = 0;826 }827 828 if (cmos_base && inb_cmos(cmos_base + 7))829 {830 /* If provided, grab the logical geometry from CMOS. */831 cylinders = inb_cmos(cmos_base + 0) + (inb_cmos(cmos_base + 1) << 8);832 heads = inb_cmos(cmos_base + 2);833 sectors_per_track = inb_cmos(cmos_base + 7);834 }835 else836 {837 /* Calculate default logical geometry. NB: Very different838 * from default ATA/SATA logical geometry!839 */840 if (sectors >= (uint32_t)4 * 1024 * 1024)841 {842 heads = 255;843 sectors_per_track = 63;844 /* Approximate x / (255 * 63) using shifts */845 t = (sectors >> 6) + (sectors >> 12);846 cylinders = (t >> 8) + (t >> 16);847 }848 else if (sectors >= (uint32_t)2 * 1024 * 1024)849 {850 heads = 128;851 sectors_per_track = 32;852 cylinders = sectors >> 12;853 }854 else855 {856 heads = 64;857 sectors_per_track = 32;858 cylinders = sectors >> 11;859 }860 }861 862 /* Calculate index into the generic disk table. */863 hd_index = devcount_scsi + BX_MAX_ATA_DEVICES;864 865 bios_dsk->scsidev[devcount_scsi].target_id = i;866 bios_dsk->devices[hd_index].type = DSK_TYPE_VIRTIO_SCSI;867 bios_dsk->devices[hd_index].device = DSK_DEVICE_HD;868 bios_dsk->devices[hd_index].removable = 0;869 bios_dsk->devices[hd_index].lock = 0;870 bios_dsk->devices[hd_index].blksize = sector_size;871 bios_dsk->devices[hd_index].translation = GEO_TRANSLATION_LBA;872 873 /* Write LCHS/PCHS values. */874 bios_dsk->devices[hd_index].lchs.heads = heads;875 bios_dsk->devices[hd_index].lchs.spt = sectors_per_track;876 bios_dsk->devices[hd_index].pchs.heads = heads;877 bios_dsk->devices[hd_index].pchs.spt = sectors_per_track;878 879 if (cylinders > 1024) {880 bios_dsk->devices[hd_index].lchs.cylinders = 1024;881 bios_dsk->devices[hd_index].pchs.cylinders = 1024;882 } else {883 bios_dsk->devices[hd_index].lchs.cylinders = (uint16_t)cylinders;884 bios_dsk->devices[hd_index].pchs.cylinders = (uint16_t)cylinders;885 }886 887 BX_INFO("SCSI %d-ID#%d: LCHS=%lu/%u/%u 0x%llx sectors\n", devcount_scsi,888 i, (uint32_t)cylinders, heads, sectors_per_track, sectors);889 890 bios_dsk->devices[hd_index].sectors = sectors;891 892 /* Store the id of the disk in the ata hdidmap. */893 hdcount = bios_dsk->hdcount;894 bios_dsk->hdidmap[hdcount] = devcount_scsi + BX_MAX_ATA_DEVICES;895 hdcount++;896 bios_dsk->hdcount = hdcount;897 898 /* Update hdcount in the BDA. */899 hdcount = read_byte(0x40, 0x75);900 hdcount++;901 write_byte(0x40, 0x75, hdcount);902 903 devcount_scsi++;904 }905 else906 {907 /* We reached the maximum of SCSI disks we can boot from. We can quit detecting. */908 break;909 }910 }911 else if ( ((buffer[0] & 0xe0) == 0)912 && ((buffer[0] & 0x1f) == 0x05))913 {914 uint8_t cdcount;915 uint8_t removable;916 917 BX_INFO("SCSI %d-ID#%d: CD/DVD-ROM\n", devcount_scsi, i);918 919 /* Calculate index into the generic device table. */920 hd_index = devcount_scsi + BX_MAX_ATA_DEVICES;921 922 removable = buffer[1] & 0x80 ? 1 : 0;923 924 bios_dsk->scsidev[devcount_scsi].target_id = i;925 bios_dsk->devices[hd_index].type = DSK_TYPE_VIRTIO_SCSI;926 bios_dsk->devices[hd_index].device = DSK_DEVICE_CDROM;927 bios_dsk->devices[hd_index].removable = removable;928 bios_dsk->devices[hd_index].blksize = 2048;929 bios_dsk->devices[hd_index].translation = GEO_TRANSLATION_NONE;930 931 /* Store the ID of the device in the BIOS cdidmap. */932 cdcount = bios_dsk->cdcount;933 bios_dsk->cdidmap[cdcount] = devcount_scsi + BX_MAX_ATA_DEVICES;934 cdcount++;935 bios_dsk->cdcount = cdcount;936 937 devcount_scsi++;938 }939 else940 DBG_VIRTIO("%s: No supported device detected at %d\n", __func__, i);941 }942 else943 DBG_VIRTIO("%s: INQUIRY failed with %u\n", __func__, rc);944 945 bios_dsk->scsi_devcount = devcount_scsi;946 }947 948 return 0;949 }950 951 /**952 524 * Initializes the VirtIO SCSI HBA and detects attached devices. 953 525 */ 954 static int virtio_scsi_hba_init(uint8_t u8Bus, uint8_t u8DevFn, uint8_t u8PciCapOffVirtIo) 955 { 956 uint8_t u8PciCapOff; 957 uint16_t ebda_seg; 958 uint16_t virtio_seg; 959 uint8_t u8DevStat; 960 bio_dsk_t __far *bios_dsk; 961 virtio_t __far *virtio; 962 963 ebda_seg = read_word(0x0040, 0x000E); 964 bios_dsk = ebda_seg :> &EbdaData->bdisk; 965 966 /* Allocate 1K of base memory. */ 967 virtio_seg = virtio_mem_alloc(); 968 if (virtio_seg == 0) 969 { 970 DBG_VIRTIO("VirtIO: Could not allocate 1K of memory, can't boot from controller\n"); 971 return 0; 972 } 973 DBG_VIRTIO("VirtIO: virtio_seg=%04x, size=%04x, pointer at EBDA:%04x (EBDA size=%04x)\n", 974 virtio_seg, sizeof(virtio_t), (uint16_t)&EbdaData->bdisk.virtio_seg, sizeof(ebda_data_t)); 975 976 bios_dsk->virtio_seg = virtio_seg; 977 978 virtio = virtio_seg :> 0; 526 static int virtio_scsi_hba_init(virtio_t __far *virtio, uint8_t u8Bus, uint8_t u8DevFn, uint8_t u8PciCapOffVirtIo) 527 { 528 uint8_t u8PciCapOff; 529 uint8_t u8DevStat; 530 979 531 virtio->u8Bus = u8Bus; 980 532 virtio->u8DevFn = u8DevFn; … … 1054 606 { 1055 607 DBG_VIRTIO("VirtIO-SCSI: Invalid SCSI device configuration, ignoring device\n"); 1056 return 0;608 return 1; 1057 609 } 1058 610 … … 1067 619 { 1068 620 DBG_VIRTIO("VirtIO-SCSI: Device doesn't accept our feature set, ignoring device\n"); 1069 return 0;621 return 1; 1070 622 } 1071 623 … … 1104 656 virtio_reg_common_write_u8(virtio, VIRTIO_COMMON_REG_DEV_STS, u8DevStat); 1105 657 1106 return virtio_scsi_detect_devices(virtio);658 return 0; 1107 659 } 1108 660 … … 1110 662 * Init the VirtIO SCSI driver and detect attached disks. 1111 663 */ 1112 void BIOSCALL virtio_scsi_init(void) 1113 { 1114 uint16_t busdevfn; 1115 1116 busdevfn = pci_find_device(0x1af4, 0x1048); 1117 if (busdevfn != VBOX_VIRTIO_NO_DEVICE) 664 int virtio_scsi_init(void __far *pvHba, uint8_t u8Bus, uint8_t u8DevFn) 665 { 666 virtio_t __far *virtio = (virtio_t __far *)pvHba; 667 uint8_t u8PciCapOff; 668 uint8_t u8PciCapOffVirtIo = VBOX_VIRTIO_NIL_CFG; 669 uint8_t u8PciCapVirtioSeen = 0; 670 671 /* Examine the capability list and search for the VirtIO specific capabilities. */ 672 u8PciCapOff = pci_read_config_byte(u8Bus, u8DevFn, PCI_CONFIG_CAP); 673 674 while (u8PciCapOff != 0) 1118 675 { 1119 uint8_t u8Bus, u8DevFn; 1120 uint8_t u8PciCapOff; 1121 uint8_t u8PciCapOffVirtIo = VBOX_VIRTIO_NIL_CFG; 1122 uint8_t u8PciCapVirtioSeen = 0; 1123 1124 u8Bus = (busdevfn & 0xff00) >> 8; 1125 u8DevFn = busdevfn & 0x00ff; 1126 1127 DBG_VIRTIO("VirtIO SCSI HBA at Bus %u DevFn 0x%x (raw 0x%x)\n", u8Bus, u8DevFn, busdevfn); 1128 1129 /* Examine the capability list and search for the VirtIO specific capabilities. */ 1130 u8PciCapOff = pci_read_config_byte(u8Bus, u8DevFn, PCI_CONFIG_CAP); 1131 1132 while (u8PciCapOff != 0) 676 uint8_t u8PciCapId = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff); 677 uint8_t cbPciCap = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 2); /* Capability length. */ 678 679 DBG_VIRTIO("Capability ID 0x%x at 0x%x\n", u8PciCapId, u8PciCapOff); 680 681 if ( u8PciCapId == PCI_CAP_ID_VNDR 682 && cbPciCap >= sizeof(virtio_pci_cap_t)) 1133 683 { 1134 uint8_t u8PciCapId = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff); 1135 uint8_t cbPciCap = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 2); /* Capability length. */ 1136 1137 DBG_VIRTIO("Capability ID 0x%x at 0x%x\n", u8PciCapId, u8PciCapOff); 1138 1139 if ( u8PciCapId == PCI_CAP_ID_VNDR 1140 && cbPciCap >= sizeof(virtio_pci_cap_t)) 684 /* Read in the config type and see what we got. */ 685 uint8_t u8PciVirtioCfg = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 3); 686 687 if (u8PciCapOffVirtIo == VBOX_VIRTIO_NIL_CFG) 688 u8PciCapOffVirtIo = u8PciCapOff; 689 690 DBG_VIRTIO("VirtIO: CFG ID 0x%x\n", u8PciVirtioCfg); 691 switch (u8PciVirtioCfg) 1141 692 { 1142 /* Read in the config type and see what we got. */ 1143 uint8_t u8PciVirtioCfg = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 3); 1144 1145 if (u8PciCapOffVirtIo == VBOX_VIRTIO_NIL_CFG) 1146 u8PciCapOffVirtIo = u8PciCapOff; 1147 1148 DBG_VIRTIO("VirtIO: CFG ID 0x%x\n", u8PciVirtioCfg); 1149 switch (u8PciVirtioCfg) 1150 { 1151 case VIRTIO_PCI_CAP_COMMON_CFG: 1152 case VIRTIO_PCI_CAP_NOTIFY_CFG: 1153 case VIRTIO_PCI_CAP_ISR_CFG: 1154 case VIRTIO_PCI_CAP_DEVICE_CFG: 1155 case VIRTIO_PCI_CAP_PCI_CFG: 1156 u8PciCapVirtioSeen |= 1 << (u8PciVirtioCfg - 1); 1157 break; 1158 default: 1159 DBG_VIRTIO("VirtIO SCSI HBA with unknown PCI capability type 0x%x\n", u8PciVirtioCfg); 1160 } 693 case VIRTIO_PCI_CAP_COMMON_CFG: 694 case VIRTIO_PCI_CAP_NOTIFY_CFG: 695 case VIRTIO_PCI_CAP_ISR_CFG: 696 case VIRTIO_PCI_CAP_DEVICE_CFG: 697 case VIRTIO_PCI_CAP_PCI_CFG: 698 u8PciCapVirtioSeen |= 1 << (u8PciVirtioCfg - 1); 699 break; 700 default: 701 DBG_VIRTIO("VirtIO SCSI HBA with unknown PCI capability type 0x%x\n", u8PciVirtioCfg); 1161 702 } 1162 1163 u8PciCapOff = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 1);1164 703 } 1165 704 1166 /* Initialize the controller if all required PCI capabilities where found. */ 1167 if ( u8PciCapOffVirtIo != VBOX_VIRTIO_NIL_CFG 1168 && u8PciCapVirtioSeen == 0x1f) 1169 { 1170 int rc; 1171 1172 DBG_VIRTIO("VirtIO SCSI HBA with all required capabilities at 0x%x\n", u8PciCapOffVirtIo); 1173 1174 /* Enable PCI memory, I/O, bus mastering access in command register. */ 1175 pci_write_config_word(u8Bus, u8DevFn, 4, 0x7); 1176 1177 rc = virtio_scsi_hba_init(u8Bus, u8DevFn, u8PciCapOffVirtIo); 1178 } 1179 else 1180 DBG_VIRTIO("VirtIO SCSI HBA with no usable PCI config access!\n"); 705 u8PciCapOff = pci_read_config_byte(u8Bus, u8DevFn, u8PciCapOff + 1); 706 } 707 708 /* Initialize the controller if all required PCI capabilities where found. */ 709 if ( u8PciCapOffVirtIo != VBOX_VIRTIO_NIL_CFG 710 && u8PciCapVirtioSeen == 0x1f) 711 { 712 DBG_VIRTIO("VirtIO SCSI HBA with all required capabilities at 0x%x\n", u8PciCapOffVirtIo); 713 714 /* Enable PCI memory, I/O, bus mastering access in command register. */ 715 pci_write_config_word(u8Bus, u8DevFn, 4, 0x7); 716 717 return virtio_scsi_hba_init(virtio, u8Bus, u8DevFn, u8PciCapOffVirtIo); 1181 718 } 1182 719 else 1183 DBG_VIRTIO("No VirtIO SCSI HBA!\n"); 1184 } 720 DBG_VIRTIO("VirtIO SCSI HBA with no usable PCI config access!\n"); 721 722 return 1; 723 }
Note:
See TracChangeset
for help on using the changeset viewer.