Changeset 58724 in vbox for trunk/src/VBox/Devices/PC/BIOS/scsi.c
- Timestamp:
- Nov 17, 2015 3:32:43 PM (10 years ago)
- svn:sync-xref-src-repo-rev:
- 104155
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/PC/BIOS/scsi.c
r56292 r58724 49 49 50 50 /* Command opcodes. */ 51 #define SCSI_SERVICE_ACT 0x9e 51 52 #define SCSI_INQUIRY 0x12 52 #define SCSI_READ_CAP ACITY0x2553 #define SCSI_READ_CAP_10 0x25 53 54 #define SCSI_READ_10 0x28 54 55 #define SCSI_WRITE_10 0x2a 56 #define SCSI_READ_CAP_16 0x10 /* Not an opcode by itself, sub-action for the "Service Action" */ 57 #define SCSI_READ_16 0x88 58 #define SCSI_WRITE_16 0x8a 55 59 56 60 /* Data transfer direction. */ … … 69 73 } cdb_rw10; 70 74 75 /* READ_16/WRITE_16 CDB layout. */ 76 typedef struct { 77 uint16_t command; /* Command. */ 78 uint64_t lba; /* LBA, MSB first! */ 79 uint32_t nsect32; /* Sector count, MSB first! */ 80 uint8_t pad1; /* Unused. */ 81 uint8_t pad2; /* Unused. */ 82 } cdb_rw16; 83 71 84 #pragma pack() 72 85 73 86 ct_assert(sizeof(cdb_rw10) == 10); 74 87 ct_assert(sizeof(cdb_rw16) == 16); 75 88 76 89 void insb_discard(unsigned nbytes, unsigned port); … … 94 107 while (status & VBSCSI_BUSY); 95 108 96 97 sizes = ((length >> 12) & 0xF0) | cbCDB; 109 sizes = ((length >> 12) & 0xF0) | (cbCDB == 16) ? 0 : cbCDB; 98 110 outb(io_base + VBSCSI_REGISTER_COMMAND, target_id); /* Write the target ID. */ 99 111 outb(io_base + VBSCSI_REGISTER_COMMAND, SCSI_TXDIR_FROM_DEVICE); /* Write the transfer direction. */ … … 146 158 147 159 148 sizes = ((length >> 12) & 0xF0) | cbCDB;160 sizes = ((length >> 12) & 0xF0) | (cbCDB == 16) ? 0 : cbCDB; 149 161 outb(io_base + VBSCSI_REGISTER_COMMAND, target_id); /* Write the target ID. */ 150 162 outb(io_base + VBSCSI_REGISTER_COMMAND, SCSI_TXDIR_TO_DEVICE); /* Write the transfer direction. */ … … 185 197 } 186 198 199 static uint64_t swap_64(uint64_t val) 200 { 201 uint64_t rval; 202 203 rval = swap_32(val & 0xffffffff); 204 rval <<= 32; 205 rval |= swap_32(val >> 32); 206 207 return rval; 208 } 209 187 210 /** 188 211 * Read sectors from an attached SCSI device. … … 195 218 { 196 219 uint8_t rc; 197 cdb_rw1 0cdb;198 uint 16_t count;220 cdb_rw16 cdb; 221 uint32_t count; 199 222 uint16_t io_base; 200 223 uint8_t target_id; … … 208 231 209 232 /* Prepare a CDB. */ 210 cdb.command = SCSI_READ_1 0;211 cdb.lba = swap_ 32(bios_dsk->drqp.lba);233 cdb.command = SCSI_READ_16; 234 cdb.lba = swap_64(bios_dsk->drqp.lba); 212 235 cdb.pad1 = 0; 213 cdb.nsect = swap_16(count);236 cdb.nsect32 = swap_32(count); 214 237 cdb.pad2 = 0; 215 238 … … 221 244 count, device_id, bios_dsk->scsidev[device_id].target_id); 222 245 223 rc = scsi_cmd_data_in(io_base, target_id, (void __far *)&cdb, 1 0,246 rc = scsi_cmd_data_in(io_base, target_id, (void __far *)&cdb, 16, 224 247 bios_dsk->drqp.buffer, (count * 512L)); 225 248 … … 244 267 { 245 268 uint8_t rc; 246 cdb_rw1 0cdb;247 uint 16_t count;269 cdb_rw16 cdb; 270 uint32_t count; 248 271 uint16_t io_base; 249 272 uint8_t target_id; … … 257 280 258 281 /* Prepare a CDB. */ 259 cdb.command = SCSI_WRITE_1 0;260 cdb.lba = swap_ 32(bios_dsk->drqp.lba);282 cdb.command = SCSI_WRITE_16; 283 cdb.lba = swap_64(bios_dsk->drqp.lba); 261 284 cdb.pad1 = 0; 262 cdb.nsect = swap_16(count);285 cdb.nsect32 = swap_32(count); 263 286 cdb.pad2 = 0; 264 287 … … 269 292 count, device_id, bios_dsk->scsidev[device_id].target_id); 270 293 271 rc = scsi_cmd_data_out(io_base, target_id, (void __far *)&cdb, 1 0,294 rc = scsi_cmd_data_out(io_base, target_id, (void __far *)&cdb, 16, 272 295 bios_dsk->drqp.buffer, (count * 512L)); 273 296 … … 403 426 { 404 427 uint8_t rc; 405 uint8_t aCDB[1 0];428 uint8_t aCDB[16]; 406 429 uint8_t hd_index, devcount_scsi; 407 430 … … 428 451 if (devcount_scsi < BX_MAX_SCSI_DEVICES) 429 452 { 430 uint32_t sectors, sector_size, cylinders; 453 uint64_t sectors, t; 454 uint32_t sector_size, cylinders; 431 455 uint16_t heads, sectors_per_track; 432 456 uint8_t hdcount; … … 435 459 /* Issue a read capacity command now. */ 436 460 _fmemset(aCDB, 0, sizeof(aCDB)); 437 aCDB[0] = SCSI_READ_CAPACITY; 438 439 rc = scsi_cmd_data_in(io_base, i, aCDB, 10, buffer, 8); 461 aCDB[0] = SCSI_SERVICE_ACT; 462 aCDB[1] = SCSI_READ_CAP_16; 463 aCDB[13] = 32; /* Allocation length. */ 464 465 rc = scsi_cmd_data_in(io_base, i, aCDB, 16, buffer, 32); 440 466 if (rc != 0) 441 467 BX_PANIC("%s: SCSI_READ_CAPACITY failed\n", __func__); 442 468 443 /* Build sector number and size from the buffer. */ 444 //@todo: byte swapping for dword sized items should be farmed out... 445 sectors = ((uint32_t)buffer[0] << 24) 446 | ((uint32_t)buffer[1] << 16) 447 | ((uint32_t)buffer[2] << 8) 448 | ((uint32_t)buffer[3]); 449 ++sectors; /* Returned value is the last LBA, zero-based. */ 450 451 sector_size = ((uint32_t)buffer[4] << 24) 452 | ((uint32_t)buffer[5] << 16) 453 | ((uint32_t)buffer[6] << 8) 454 | ((uint32_t)buffer[7]); 469 /* The value returned is the last addressable LBA, not 470 * the size, which what "+ 1" is for. 471 */ 472 sectors = swap_64(*(uint64_t *)buffer) + 1; 473 474 sector_size = ((uint32_t)buffer[8] << 24) 475 | ((uint32_t)buffer[9] << 16) 476 | ((uint32_t)buffer[10] << 8) 477 | ((uint32_t)buffer[11]); 455 478 456 479 /* We only support the disk if sector size is 512 bytes. */ … … 497 520 heads = 255; 498 521 sectors_per_track = 63; 522 /* Approximate x / (255 * 63) using shifts */ 523 t = (sectors >> 6) + (sectors >> 12); 524 cylinders = (t >> 8) + (t >> 16); 499 525 } 500 526 else if (sectors >= (uint32_t)2 * 1024 * 1024) … … 502 528 heads = 128; 503 529 sectors_per_track = 32; 530 cylinders = sectors >> 12; 504 531 } 505 532 else … … 507 534 heads = 64; 508 535 sectors_per_track = 32; 536 cylinders = sectors >> 11; 509 537 } 510 cylinders = (uint32_t)(sectors / (heads * sectors_per_track));511 538 } 512 539 … … 523 550 bios_dsk->devices[hd_index].translation = GEO_TRANSLATION_LBA; 524 551 525 /* Write LCHS values. */552 /* Write LCHS/PCHS values. */ 526 553 bios_dsk->devices[hd_index].lchs.heads = heads; 527 554 bios_dsk->devices[hd_index].lchs.spt = sectors_per_track; 528 if (cylinders > 1024)529 bios_dsk->devices[hd_index].lchs.cylinders = 1024;530 else531 bios_dsk->devices[hd_index].lchs.cylinders = (uint16_t)cylinders;532 533 BX_INFO("SCSI %d-ID#%d: LCHS=%u/%u/%u %lu sectors\n", devcount_scsi,534 i, (uint16_t)cylinders, heads, sectors_per_track, sectors);535 536 /* Write PCHS values. */537 555 bios_dsk->devices[hd_index].pchs.heads = heads; 538 556 bios_dsk->devices[hd_index].pchs.spt = sectors_per_track; 539 if (cylinders > 1024) 557 558 if (cylinders > 1024) { 559 bios_dsk->devices[hd_index].lchs.cylinders = 1024; 540 560 bios_dsk->devices[hd_index].pchs.cylinders = 1024; 541 else 561 } else { 562 bios_dsk->devices[hd_index].lchs.cylinders = (uint16_t)cylinders; 542 563 bios_dsk->devices[hd_index].pchs.cylinders = (uint16_t)cylinders; 564 } 565 566 BX_INFO("SCSI %d-ID#%d: LCHS=%lu/%u/%u 0x%llx sectors\n", devcount_scsi, 567 i, (uint32_t)cylinders, heads, sectors_per_track, sectors); 543 568 544 569 bios_dsk->devices[hd_index].sectors = sectors;
Note:
See TracChangeset
for help on using the changeset viewer.