diff --git a/src/VBox/Devices/PC/BIOS/Makefile.kmk b/src/VBox/Devices/PC/BIOS/Makefile.kmk
index fa9cb6f..6655ecb 100644
|
a
|
b
|
ifdef VBOX_WITH_OPEN_WATCOM
|
| 68 | 68 | pcibio32.asm \ |
| 69 | 69 | apm_pm.asm \ |
| 70 | 70 | $(VBoxPcBios32_1_TARGET) \ |
| 71 | | orgs.asm |
| | 71 | orgs.asm \ |
| | 72 | ow_glue64.asm |
| 72 | 73 | |
| 73 | 74 | # For 32-bit C code in PC BIOS. |
| 74 | 75 | LIBRARIES += VBoxPcBios32 |
diff --git a/src/VBox/Devices/PC/BIOS/ahci.c b/src/VBox/Devices/PC/BIOS/ahci.c
index fd638c9..4f3a4c8 100644
|
a
|
b
|
static uint16_t ahci_cmd_data(bio_dsk_t __far *bios_dsk, uint8_t cmd)
|
| 359 | 359 | ahci->abCmd[7] = RT_BIT_32(6); /* LBA access. */ |
| 360 | 360 | |
| 361 | 361 | ahci->abCmd[8] = (bios_dsk->drqp.lba >> 24) & 0xff; |
| 362 | | ahci->abCmd[9] = 0; |
| 363 | | ahci->abCmd[10] = 0; |
| | 362 | ahci->abCmd[9] = (bios_dsk->drqp.lba >> 32) & 0xff; |
| | 363 | ahci->abCmd[10] = (bios_dsk->drqp.lba >> 40) & 0xff; |
| 364 | 364 | ahci->abCmd[11] = 0; |
| 365 | 365 | |
| 366 | 366 | ahci->abCmd[12] = (uint8_t)(n_sect & 0xff); |
| … |
… |
int ahci_read_sectors(bio_dsk_t __far *bios_dsk)
|
| 524 | 524 | if (device_id > BX_MAX_AHCI_DEVICES) |
| 525 | 525 | BX_PANIC("%s: device_id out of range %d\n", __func__, device_id); |
| 526 | 526 | |
| 527 | | DBG_AHCI("%s: %u sectors @ LBA %lu, device %d, port %d\n", __func__, |
| 528 | | bios_dsk->drqp.nsect, bios_dsk->drqp.lba, device_id, |
| 529 | | bios_dsk->ahcidev[device_id].port); |
| | 527 | DBG_AHCI("%s: %u sectors @ LBA 0x%llx, device %d, port %d\n", __func__, |
| | 528 | bios_dsk->drqp.nsect, bios_dsk->drqp.lba, |
| | 529 | device_id, bios_dsk->ahcidev[device_id].port); |
| 530 | 530 | |
| 531 | 531 | high_bits_save(bios_dsk->ahci_seg :> 0); |
| 532 | 532 | ahci_port_init(bios_dsk->ahci_seg :> 0, bios_dsk->ahcidev[device_id].port); |
| … |
… |
int ahci_write_sectors(bio_dsk_t __far *bios_dsk)
|
| 556 | 556 | if (device_id > BX_MAX_AHCI_DEVICES) |
| 557 | 557 | BX_PANIC("%s: device_id out of range %d\n", __func__, device_id); |
| 558 | 558 | |
| 559 | | DBG_AHCI("%s: %u sectors @ LBA %lu, device %d, port %d\n", __func__, |
| | 559 | DBG_AHCI("%s: %u sectors @ LBA 0x%llx, device %d, port %d\n", __func__, |
| 560 | 560 | bios_dsk->drqp.nsect, bios_dsk->drqp.lba, device_id, |
| 561 | 561 | bios_dsk->ahcidev[device_id].port); |
| 562 | 562 | |
| … |
… |
uint16_t ahci_cmd_packet(uint16_t device_id, uint8_t cmdlen, char __far *cmdbuf,
|
| 601 | 601 | DBG_AHCI("%s: reading %u %u-byte sectors\n", __func__, |
| 602 | 602 | bios_dsk->drqp.nsect, bios_dsk->drqp.sect_sz); |
| 603 | 603 | |
| 604 | | bios_dsk->drqp.lba = (uint32_t)length << 8; //@todo: xfer length limit |
| | 604 | bios_dsk->drqp.lba = length << 8; //@todo: xfer length limit |
| 605 | 605 | bios_dsk->drqp.buffer = buffer; |
| 606 | 606 | bios_dsk->drqp.nsect = length / bios_dsk->drqp.sect_sz; |
| 607 | 607 | // bios_dsk->drqp.sect_sz = 2048; |
| … |
… |
void ahci_port_detect_device(ahci_t __far *ahci, uint8_t u8Port)
|
| 689 | 689 | VBOXAHCI_PORT_READ_REG(ahci->iobase, u8Port, AHCI_REG_PORT_SIG, val); |
| 690 | 690 | if (val == 0x101) |
| 691 | 691 | { |
| 692 | | uint32_t sectors; |
| | 692 | uint64_t sectors; |
| 693 | 693 | uint16_t cylinders, heads, spt; |
| 694 | 694 | chs_t lgeo; |
| 695 | 695 | uint8_t idxCmosChsBase; |
| … |
… |
void ahci_port_detect_device(ahci_t __far *ahci, uint8_t u8Port)
|
| 712 | 712 | spt = *(uint16_t *)(abBuffer+(6*2)); // word 6 |
| 713 | 713 | sectors = *(uint32_t *)(abBuffer+(60*2)); // word 60 and word 61 |
| 714 | 714 | |
| 715 | | /** @todo update sectors to be a 64 bit number (also lba...). */ |
| 716 | 715 | if (sectors == 0x0FFFFFFF) /* For disks bigger than ~128GB */ |
| 717 | | sectors = *(uint32_t *)(abBuffer+(100*2)); // words 100 to 103 (someday) |
| | 716 | sectors = *(uint64_t *)(abBuffer+(100*2)); // words 100 to 103 |
| 718 | 717 | |
| 719 | | DBG_AHCI("AHCI: %ld sectors\n", sectors); |
| | 718 | DBG_AHCI("AHCI: 0x%llx sectors\n", sectors); |
| 720 | 719 | |
| 721 | 720 | bios_dsk->ahcidev[devcount_ahci].port = u8Port; |
| 722 | 721 | bios_dsk->devices[hd_index].type = DSK_TYPE_AHCI; |
| … |
… |
void ahci_port_detect_device(ahci_t __far *ahci, uint8_t u8Port)
|
| 758 | 757 | else |
| 759 | 758 | set_geom_lba(&lgeo, sectors); /* Default EDD-style translated LBA geometry. */ |
| 760 | 759 | |
| 761 | | BX_INFO("AHCI %d-P#%d: PCHS=%u/%u/%u LCHS=%u/%u/%u %lu sectors\n", devcount_ahci, |
| 762 | | u8Port, cylinders, heads, spt, lgeo.cylinders, lgeo.heads, lgeo.spt, sectors); |
| | 760 | BX_INFO("AHCI %d-P#%d: PCHS=%u/%u/%u LCHS=%u/%u/%u 0x%llx sectors\n", devcount_ahci, |
| | 761 | u8Port, cylinders, heads, spt, lgeo.cylinders, lgeo.heads, lgeo.spt, |
| | 762 | sectors); |
| 763 | 763 | |
| 764 | 764 | bios_dsk->devices[hd_index].lchs = lgeo; |
| 765 | 765 | |
diff --git a/src/VBox/Devices/PC/BIOS/ata.c b/src/VBox/Devices/PC/BIOS/ata.c
index 45b79e9..af3e9fe 100644
|
a
|
b
|
void BIOSCALL ata_init(void)
|
| 108 | 108 | bios_dsk->devices[device].pchs.heads = 0; |
| 109 | 109 | bios_dsk->devices[device].pchs.cylinders = 0; |
| 110 | 110 | bios_dsk->devices[device].pchs.spt = 0; |
| 111 | | bios_dsk->devices[device].sectors = 0; |
| | 111 | bios_dsk->devices[device].sectors = 0; |
| 112 | 112 | } |
| 113 | 113 | |
| 114 | 114 | // hdidmap and cdidmap init. |
| … |
… |
void ata_reset(uint16_t device)
|
| 206 | 206 | // 7 : more sectors to write |
| 207 | 207 | uint16_t ata_cmd_data_in(bio_dsk_t __far *bios_dsk, uint16_t command, uint16_t count) |
| 208 | 208 | { |
| 209 | | uint32_t lba; |
| | 209 | uint64_t lba; |
| 210 | 210 | uint16_t iobase1, iobase2, blksize, mult_blk_cnt; |
| 211 | 211 | uint16_t cylinder; |
| 212 | 212 | uint16_t head; |
| … |
… |
uint16_t ata_cmd_data_in(bio_dsk_t __far *bios_dsk, uint16_t command, uint16_t c
|
| 255 | 255 | if (sector == 0) { |
| 256 | 256 | if (lba + count >= 268435456) |
| 257 | 257 | { |
| 258 | | sector = (lba & 0xff000000L) >> 24; |
| 259 | | cylinder = 0; /* The parameter lba is just a 32 bit value. */ |
| | 258 | sector = (lba >> 24) & 0x00ff; |
| | 259 | cylinder = (lba >> 32) & 0xffff; |
| 260 | 260 | outb(iobase1 + ATA_CB_SC, (count & 0xff00) >> 8); |
| 261 | 261 | outb(iobase1 + ATA_CB_SN, sector); |
| 262 | 262 | outb(iobase1 + ATA_CB_CL, cylinder & 0x00ff); |
| … |
… |
void BIOSCALL ata_detect(void)
|
| 459 | 459 | |
| 460 | 460 | // Now we send a IDENTIFY command to ATA device |
| 461 | 461 | if (type == DSK_TYPE_ATA) { |
| 462 | | uint32_t sectors; |
| | 462 | uint64_t sectors; |
| 463 | 463 | uint16_t cylinders, heads, spt, blksize; |
| 464 | 464 | chs_t lgeo; |
| 465 | 465 | uint8_t chsgeo_base; |
| … |
… |
void BIOSCALL ata_detect(void)
|
| 483 | 483 | spt = *(uint16_t *)(buffer+(6*2)); // word 6 |
| 484 | 484 | |
| 485 | 485 | sectors = *(uint32_t *)(buffer+(60*2)); // word 60 and word 61 |
| 486 | | /** @todo update sectors to be a 64 bit number (also lba...). */ |
| 487 | 486 | if (sectors == 0x0FFFFFFF) /* For disks bigger than ~128GB */ |
| 488 | | sectors = *(uint32_t *)(buffer+(100*2)); // words 100 to 103 (someday) |
| | 487 | sectors = *(uint64_t *)(buffer+(100*2)); // words 100 to 103 |
| 489 | 488 | switch (device) |
| 490 | 489 | { |
| 491 | 490 | case 0: |
| … |
… |
void BIOSCALL ata_detect(void)
|
| 594 | 593 | |
| 595 | 594 | switch (type) { |
| 596 | 595 | case DSK_TYPE_ATA: |
| 597 | | sizeinmb = bios_dsk->devices[device].sectors; |
| 598 | | sizeinmb >>= 11; |
| | 596 | sizeinmb = (bios_dsk->devices[device].sectors >> 11); |
| 599 | 597 | case DSK_TYPE_ATAPI: |
| 600 | 598 | // Read ATA/ATAPI version |
| 601 | 599 | ataversion = ((uint16_t)(*(buffer+161))<<8) | *(buffer+160); |
| … |
… |
void BIOSCALL ata_detect(void)
|
| 682 | 680 | // 7 : more sectors to write |
| 683 | 681 | uint16_t ata_cmd_data_out(bio_dsk_t __far *bios_dsk, uint16_t command, uint16_t count) |
| 684 | 682 | { |
| 685 | | uint32_t lba; |
| | 683 | uint64_t lba; |
| 686 | 684 | char __far *buffer; |
| 687 | 685 | uint16_t iobase1, iobase2, blksize; |
| 688 | 686 | uint16_t cylinder; |
| … |
… |
uint16_t ata_cmd_data_out(bio_dsk_t __far *bios_dsk, uint16_t command, uint16_t
|
| 723 | 721 | if (sector == 0) { |
| 724 | 722 | if (lba + count >= 268435456) |
| 725 | 723 | { |
| 726 | | sector = (lba & 0xff000000L) >> 24; |
| 727 | | cylinder = 0; /* The parameter lba is just a 32 bit value. */ |
| | 724 | sector = (lba >> 24) & 0x00ff; |
| | 725 | cylinder = (lba >> 32) & 0xffff; |
| 728 | 726 | outb(iobase1 + ATA_CB_SC, (count & 0xff00) >> 8); |
| 729 | 727 | outb(iobase1 + ATA_CB_SN, sector); |
| 730 | 728 | outb(iobase1 + ATA_CB_CL, cylinder & 0x00ff); |
| … |
… |
int ata_read_sectors(bio_dsk_t __far *bios_dsk)
|
| 836 | 834 | if (bios_dsk->drqp.sector) { |
| 837 | 835 | /* CHS addressing. */ |
| 838 | 836 | bios_dsk->devices[device_id].blksize = n_sect * 0x200; |
| | 837 | BX_DEBUG_ATA("%s: reading %u sectors (CHS)\n", __func__, n_sect); |
| 839 | 838 | status = ata_cmd_data_in(bios_dsk, ATA_CMD_READ_MULTIPLE, n_sect); |
| 840 | 839 | bios_dsk->devices[device_id].blksize = 0x200; |
| 841 | 840 | } else { |
| 842 | 841 | /* LBA addressing. */ |
| 843 | | if (bios_dsk->drqp.lba + n_sect >= 268435456) |
| | 842 | if (bios_dsk->drqp.lba + n_sect >= 268435456) { |
| | 843 | BX_DEBUG_ATA("%s: reading %u sector (LBA,EXT)\n", __func__, n_sect); |
| 844 | 844 | status = ata_cmd_data_in(bios_dsk, ATA_CMD_READ_SECTORS_EXT, n_sect); |
| 845 | | else { |
| | 845 | } else { |
| 846 | 846 | bios_dsk->devices[device_id].blksize = n_sect * 0x200; |
| | 847 | BX_DEBUG_ATA("%s: reading %u sector (LBA,MULT)\n", __func__, n_sect); |
| 847 | 848 | status = ata_cmd_data_in(bios_dsk, ATA_CMD_READ_MULTIPLE, n_sect); |
| 848 | 849 | bios_dsk->devices[device_id].blksize = 0x200; |
| 849 | 850 | } |
diff --git a/src/VBox/Devices/PC/BIOS/disk.c b/src/VBox/Devices/PC/BIOS/disk.c
index 355a976..ecfb49f 100644
|
a
|
b
|
dsk_acc_t dskacc[DSKTYP_CNT] = {
|
| 98 | 98 | * Phoenix EDD 3.0. This is used as a fallback to generate sane logical |
| 99 | 99 | * geometry in case none was provided in CMOS. |
| 100 | 100 | */ |
| 101 | | void set_geom_lba(chs_t __far *lgeo, uint32_t nsectors) |
| | 101 | void set_geom_lba(chs_t __far *lgeo, uint64_t nsectors64) |
| 102 | 102 | { |
| 103 | 103 | uint32_t limit = 8257536; /* 1024 * 128 * 63 */ |
| | 104 | uint32_t nsectors; |
| 104 | 105 | unsigned heads = 255; |
| 105 | 106 | int i; |
| 106 | 107 | |
| | 108 | nsectors = (nsectors64 >> 32) ? 0xFFFFFFFFL : (uint32_t)nsectors64; |
| 107 | 109 | /* Start with ~4GB limit, go down to 504MB. */ |
| 108 | 110 | for (i = 0; i < 4; ++i) { |
| 109 | 111 | if (nsectors <= limit) |
| … |
… |
int13_success_noah:
|
| 330 | 332 | |
| 331 | 333 | void BIOSCALL int13_harddisk_ext(disk_regs_t r) |
| 332 | 334 | { |
| 333 | | uint32_t lba; |
| | 335 | uint64_t lba; |
| 334 | 336 | uint16_t ebda_seg = read_word(0x0040,0x000E); |
| 335 | 337 | uint16_t segment, offset; |
| 336 | 338 | uint16_t npc, nph, npspt; |
| … |
… |
void BIOSCALL int13_harddisk_ext(disk_regs_t r)
|
| 383 | 385 | segment = i13_ext->segment; |
| 384 | 386 | offset = i13_ext->offset; |
| 385 | 387 | |
| 386 | | BX_DEBUG_INT13_HD("%s: %d sectors from lba %lu @ %04x:%04x\n", __func__, |
| 387 | | count, i13_ext->lba1, segment, offset); |
| 388 | | |
| 389 | | // Can't use 64 bits lba |
| | 388 | // Get 64 bits lba and check |
| 390 | 389 | lba = i13_ext->lba2; |
| 391 | | if (lba != 0L) { |
| 392 | | BX_PANIC("%s: function %02x. Can't use 64bits lba\n", __func__, GET_AH()); |
| 393 | | goto int13x_fail; |
| 394 | | } |
| | 390 | lba <<= 32; |
| | 391 | lba |= i13_ext->lba1; |
| 395 | 392 | |
| 396 | | // Get 32 bits lba and check |
| 397 | | lba = i13_ext->lba1; |
| | 393 | BX_DEBUG_INT13_HD("%s: %d sectors from LBA 0x%llx @ %04x:%04x\n", __func__, |
| | 394 | count, lba, segment, offset); |
| 398 | 395 | |
| 399 | 396 | type = bios_dsk->devices[device].type; |
| 400 | 397 | if (lba >= bios_dsk->devices[device].sectors) { |
| … |
… |
void BIOSCALL int13_harddisk_ext(disk_regs_t r)
|
| 466 | 463 | dpt->heads = nph; |
| 467 | 464 | dpt->spt = npspt; |
| 468 | 465 | dpt->blksize = blksize; |
| 469 | | dpt->sector_count1 = lba; // FIXME should be Bit64 |
| 470 | | dpt->sector_count2 = 0; |
| | 466 | dpt->sector_count1 = lba; |
| | 467 | dpt->sector_count2 = lba >> 32; |
| 471 | 468 | } |
| 472 | 469 | |
| 473 | 470 | /* Fill in EDD 2.x table. */ |
diff --git a/src/VBox/Devices/PC/BIOS/ebda.h b/src/VBox/Devices/PC/BIOS/ebda.h
index dd9352d..a1cd5df 100644
|
a
|
b
|
typedef struct {
|
| 192 | 192 | uint16_t blksize; /* Disk block size. */ |
| 193 | 193 | chs_t lchs; /* Logical CHS geometry. */ |
| 194 | 194 | chs_t pchs; /* Physical CHS geometry. */ |
| 195 | | uint32_t sectors; /* Total sector count. */ |
| | 195 | uint64_t sectors; /* Total sector count. */ |
| 196 | 196 | } disk_dev_t; |
| 197 | 197 | |
| 198 | 198 | /* A structure for passing disk request information around. This structure |
| … |
… |
typedef struct {
|
| 200 | 200 | * one such structure is sufficient. |
| 201 | 201 | */ |
| 202 | 202 | typedef struct { |
| 203 | | uint32_t lba; /* Starting LBA. */ |
| | 203 | uint64_t lba; /* Starting LBA. */ |
| 204 | 204 | void __far *buffer; /* Read/write data buffer pointer. */ |
| 205 | 205 | uint8_t dev_id; /* Device ID; index into devices array. */ |
| 206 | 206 | uint16_t nsect; /* Number of sectors to be transferred. */ |
| … |
… |
int __fastcall scsi_write_sectors(bio_dsk_t __far *bios_dsk);
|
| 317 | 317 | int __fastcall ahci_read_sectors(bio_dsk_t __far *bios_dsk); |
| 318 | 318 | int __fastcall ahci_write_sectors(bio_dsk_t __far *bios_dsk); |
| 319 | 319 | |
| 320 | | extern void set_geom_lba(chs_t __far *lgeo, uint32_t nsectors); |
| | 320 | extern void set_geom_lba(chs_t __far *lgeo, uint64_t nsectors); |
| 321 | 321 | |
| 322 | 322 | // @todo: put this elsewhere (and change/eliminate?) |
| 323 | 323 | #define SET_DISK_RET_STATUS(status) write_byte(0x0040, 0x0074, status) |
diff --git a/src/VBox/Devices/PC/BIOS/ow_glue64.asm b/src/VBox/Devices/PC/BIOS/ow_glue64.asm
new file mode 100644
index 0000000..cde216f
|
-
|
+
|
|
| | 1 | ;; |
| | 2 | ;; Copyright (C) 2006-2015 Oracle Corporation |
| | 3 | ;; |
| | 4 | ;; This file is part of VirtualBox Open Source Edition (OSE), as |
| | 5 | ;; available from http://www.virtualbox.org. This file is free software; |
| | 6 | ;; you can redistribute it and/or modify it under the terms of the GNU |
| | 7 | ;; General Public License (GPL) as published by the Free Software |
| | 8 | ;; Foundation, in version 2 as it comes in the "COPYING" file of the |
| | 9 | ;; VirtualBox OSE distribution. VirtualBox OSE is distributed in the |
| | 10 | ;; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. |
| | 11 | ;; |
| | 12 | ;; -------------------------------------------------------------------- |
| | 13 | ;; |
| | 14 | ;; Shift routines necessary for the OpenWatcom compiler to link code |
| | 15 | ;; that uses shifts on 64-bit integers |
| | 16 | ;; |
| | 17 | |
| | 18 | name ow_glue64 |
| | 19 | |
| | 20 | _TEXT segment word public 'CODE' |
| | 21 | assume cs:_TEXT |
| | 22 | |
| | 23 | public __U8LS |
| | 24 | public __U8RS |
| | 25 | |
| | 26 | __U8LS proc near |
| | 27 | test si, si |
| | 28 | je short out1 |
| | 29 | loop1: |
| | 30 | sal dx, 1 |
| | 31 | rcl cx, 1 |
| | 32 | rcl bx, 1 |
| | 33 | rcl ax, 1 |
| | 34 | dec si |
| | 35 | jne short loop1 |
| | 36 | out1: |
| | 37 | retn |
| | 38 | __U8LS endp |
| | 39 | |
| | 40 | __U8RS proc near |
| | 41 | test si, si |
| | 42 | je short out2 |
| | 43 | loop2: |
| | 44 | shr ax, 1 |
| | 45 | rcr bx, 1 |
| | 46 | rcr cx, 1 |
| | 47 | rcr dx, 1 |
| | 48 | dec si |
| | 49 | jne short loop2 |
| | 50 | out2: |
| | 51 | retn |
| | 52 | __U8RS endp |
| | 53 | |
| | 54 | _TEXT ends |
| | 55 | |
| | 56 | end |
diff --git a/src/VBox/Devices/PC/BIOS/print.c b/src/VBox/Devices/PC/BIOS/print.c
index af5e85f..1d09471 100644
|
a
|
b
|
void put_str_near(uint16_t action, const char __near *s)
|
| 144 | 144 | // |
| 145 | 145 | // Supports %[format_width][length]format |
| 146 | 146 | // where format can be x,X,u,d,s,S,c |
| 147 | | // and the optional length modifier is l (ell) |
| | 147 | // and the optional length modifier is l (ell, long 32-bit) or ll |
| | 148 | // (long long, 64-bit). |
| | 149 | // Only x,X work with ll |
| 148 | 150 | //-------------------------------------------------------------------------- |
| 149 | 151 | void bios_printf(uint16_t action, const char *s, ...) |
| 150 | 152 | { |
| … |
… |
void bios_printf(uint16_t action, const char *s, ...)
|
| 189 | 191 | else if (c == 'u') { |
| 190 | 192 | put_uint(action, arg, format_width, 0); |
| 191 | 193 | } |
| | 194 | else if (c == 'l' && s[1] == 'l') { |
| | 195 | uint64_t llval; |
| | 196 | uint16_t *cp16; |
| | 197 | |
| | 198 | s += 2; |
| | 199 | c = *s; |
| | 200 | cp16 = (uint16_t *)&llval; |
| | 201 | cp16[0] = arg; |
| | 202 | cp16[1] = va_arg( args, uint16_t ); |
| | 203 | cp16[2] = va_arg( args, uint16_t ); |
| | 204 | cp16[3] = va_arg( args, uint16_t ); |
| | 205 | if (c == 'x' || c == 'X') { |
| | 206 | if (format_width == 0) |
| | 207 | format_width = 16; |
| | 208 | if (c == 'x') |
| | 209 | hexadd = 'a'; |
| | 210 | else |
| | 211 | hexadd = 'A'; |
| | 212 | for (i=format_width-1; i>=0; i--) { |
| | 213 | nibble = (llval >> (i * 4)) & 0x000f; |
| | 214 | send (action, (nibble<=9)? (nibble+'0') : (nibble-10+hexadd)); |
| | 215 | } |
| | 216 | } else { |
| | 217 | BX_PANIC("bios_printf: unknown %ll format\n"); |
| | 218 | } |
| | 219 | } |
| 192 | 220 | else if (c == 'l') { |
| 193 | 221 | s++; |
| 194 | 222 | c = *s; /* is it ld,lx,lu? */ |
diff --git a/src/VBox/Devices/PC/BIOS/scsi.c b/src/VBox/Devices/PC/BIOS/scsi.c
index 36393de..1df60c8 100644
|
a
|
b
|
|
| 48 | 48 | #define VBSCSI_MAX_DEVICES 16 /* Maximum number of devices a SCSI device can have. */ |
| 49 | 49 | |
| 50 | 50 | /* Command opcodes. */ |
| | 51 | #define SCSI_SERVICE_ACT 0x9e |
| 51 | 52 | #define SCSI_INQUIRY 0x12 |
| 52 | | #define SCSI_READ_CAPACITY 0x25 |
| | 53 | #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. */ |
| 57 | 61 | #define SCSI_TXDIR_FROM_DEVICE 0 |
| … |
… |
typedef struct {
|
| 68 | 72 | uint8_t pad2; /* Unused. */ |
| 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); |
| 77 | 90 | #pragma aux insb_discard = \ |
| … |
… |
int scsi_cmd_data_in(uint16_t io_base, uint8_t target_id, uint8_t __far *aCDB,
|
| 93 | 106 | status = inb(io_base + VBSCSI_REGISTER_STATUS); |
| 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. */ |
| 100 | 112 | outb(io_base + VBSCSI_REGISTER_COMMAND, sizes); /* Write CDB size and top bufsize bits. */ |
| … |
… |
int scsi_cmd_data_out(uint16_t io_base, uint8_t target_id, uint8_t __far *aCDB,
|
| 145 | 157 | while (status & VBSCSI_BUSY); |
| 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. */ |
| 151 | 163 | outb(io_base + VBSCSI_REGISTER_COMMAND, sizes); /* Write CDB size and top bufsize bits. */ |
| … |
… |
int scsi_cmd_data_out(uint16_t io_base, uint8_t target_id, uint8_t __far *aCDB,
|
| 184 | 196 | return 0; |
| 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. |
| 189 | 212 | * |
| … |
… |
int scsi_cmd_data_out(uint16_t io_base, uint8_t target_id, uint8_t __far *aCDB,
|
| 194 | 217 | int scsi_read_sectors(bio_dsk_t __far *bios_dsk) |
| 195 | 218 | { |
| 196 | 219 | uint8_t rc; |
| 197 | | cdb_rw10 cdb; |
| 198 | | uint16_t count; |
| | 220 | cdb_rw16 cdb; |
| | 221 | uint32_t count; |
| 199 | 222 | uint16_t io_base; |
| 200 | 223 | uint8_t target_id; |
| 201 | 224 | uint8_t device_id; |
| … |
… |
int scsi_read_sectors(bio_dsk_t __far *bios_dsk)
|
| 207 | 230 | count = bios_dsk->drqp.nsect; |
| 208 | 231 | |
| 209 | 232 | /* Prepare a CDB. */ |
| 210 | | cdb.command = SCSI_READ_10; |
| 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 | |
| 216 | 239 | |
| … |
… |
int scsi_read_sectors(bio_dsk_t __far *bios_dsk)
|
| 220 | 243 | DBG_SCSI("%s: reading %u sectors, device %d, target %d\n", __func__, |
| 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, 10, |
| | 246 | rc = scsi_cmd_data_in(io_base, target_id, (void __far *)&cdb, 16, |
| 224 | 247 | bios_dsk->drqp.buffer, (count * 512L)); |
| 225 | 248 | |
| 226 | 249 | if (!rc) |
| … |
… |
int scsi_read_sectors(bio_dsk_t __far *bios_dsk)
|
| 243 | 266 | int scsi_write_sectors(bio_dsk_t __far *bios_dsk) |
| 244 | 267 | { |
| 245 | 268 | uint8_t rc; |
| 246 | | cdb_rw10 cdb; |
| 247 | | uint16_t count; |
| | 269 | cdb_rw16 cdb; |
| | 270 | uint32_t count; |
| 248 | 271 | uint16_t io_base; |
| 249 | 272 | uint8_t target_id; |
| 250 | 273 | uint8_t device_id; |
| … |
… |
int scsi_write_sectors(bio_dsk_t __far *bios_dsk)
|
| 256 | 279 | count = bios_dsk->drqp.nsect; |
| 257 | 280 | |
| 258 | 281 | /* Prepare a CDB. */ |
| 259 | | cdb.command = SCSI_WRITE_10; |
| 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 | |
| 265 | 288 | io_base = bios_dsk->scsidev[device_id].io_base; |
| … |
… |
int scsi_write_sectors(bio_dsk_t __far *bios_dsk)
|
| 268 | 291 | DBG_SCSI("%s: writing %u sectors, device %d, target %d\n", __func__, |
| 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, 10, |
| | 294 | rc = scsi_cmd_data_out(io_base, target_id, (void __far *)&cdb, 16, |
| 272 | 295 | bios_dsk->drqp.buffer, (count * 512L)); |
| 273 | 296 | |
| 274 | 297 | if (!rc) |
| … |
… |
void scsi_enumerate_attached_devices(uint16_t io_base)
|
| 402 | 425 | for (i = 0; i < VBSCSI_MAX_DEVICES; i++) |
| 403 | 426 | { |
| 404 | 427 | uint8_t rc; |
| 405 | | uint8_t aCDB[10]; |
| | 428 | uint8_t aCDB[16]; |
| 406 | 429 | uint8_t hd_index, devcount_scsi; |
| 407 | 430 | |
| 408 | 431 | aCDB[0] = SCSI_INQUIRY; |
| … |
… |
void scsi_enumerate_attached_devices(uint16_t io_base)
|
| 427 | 450 | /* We add the disk only if the maximum is not reached yet. */ |
| 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; |
| 433 | 457 | uint8_t cmos_base; |
| 434 | 458 | |
| 435 | 459 | /* Issue a read capacity command now. */ |
| 436 | 460 | _fmemset(aCDB, 0, sizeof(aCDB)); |
| 437 | | aCDB[0] = SCSI_READ_CAPACITY; |
| | 461 | aCDB[0] = SCSI_SERVICE_ACT; |
| | 462 | aCDB[1] = SCSI_READ_CAP_16; |
| | 463 | aCDB[13] = 32; /* Allocation length. */ |
| 438 | 464 | |
| 439 | | rc = scsi_cmd_data_in(io_base, i, aCDB, 10, buffer, 8); |
| | 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. */ |
| | 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; |
| 450 | 473 | |
| 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]); |
| | 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. */ |
| 457 | 480 | if (sector_size != 512) |
| … |
… |
void scsi_enumerate_attached_devices(uint16_t io_base)
|
| 496 | 519 | { |
| 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) |
| 501 | 527 | { |
| 502 | 528 | heads = 128; |
| 503 | 529 | sectors_per_track = 32; |
| | 530 | cylinders = sectors >> 12; |
| 504 | 531 | } |
| 505 | 532 | else |
| 506 | 533 | { |
| 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 | |
| 513 | 540 | /* Calculate index into the generic disk table. */ |
| … |
… |
void scsi_enumerate_attached_devices(uint16_t io_base)
|
| 522 | 549 | bios_dsk->devices[hd_index].blksize = sector_size; |
| 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 | | else |
| 531 | | 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; |
| 545 | 570 | |
diff --git a/src/VBox/Devices/Storage/VBoxSCSI.cpp b/src/VBox/Devices/Storage/VBoxSCSI.cpp
index 04fefa5..d638d50 100644
|
a
|
b
|
int vboxscsiWriteRegister(PVBOXSCSI pVBoxSCSI, uint8_t iRegister, uint8_t uVal)
|
| 173 | 173 | } |
| 174 | 174 | else if (pVBoxSCSI->enmState == VBOXSCSISTATE_READ_CDB_SIZE_BUFHI) |
| 175 | 175 | { |
| 176 | | uint8_t cbCDB = uVal & 0x0F; |
| | 176 | uint8_t cbCDB = (uVal & 0x0F); |
| | 177 | |
| | 178 | if (cbCDB == 0) |
| | 179 | cbCDB = 16; |
| 177 | 180 | if (cbCDB > VBOXSCSI_CDB_SIZE_MAX) |
| 178 | 181 | vboxscsiReset(pVBoxSCSI, true /*fEverything*/); |
| 179 | 182 | else |
diff --git a/src/VBox/Devices/Storage/VBoxSCSI.h b/src/VBox/Devices/Storage/VBoxSCSI.h
index 4f4b5e2..776dff5 100644
|
a
|
b
|
typedef enum VBOXSCSISTATE
|
| 87 | 87 | #define VBOXSCSI_TXDIR_TO_DEVICE 1 |
| 88 | 88 | |
| 89 | 89 | /** Maximum CDB size the BIOS driver sends. */ |
| 90 | | #define VBOXSCSI_CDB_SIZE_MAX 10 |
| | 90 | #define VBOXSCSI_CDB_SIZE_MAX 16 |
| 91 | 91 | |
| 92 | 92 | typedef struct VBOXSCSI |
| 93 | 93 | { |
| … |
… |
typedef struct VBOXSCSI
|
| 100 | 100 | /** The size of the CDB we are issuing. */ |
| 101 | 101 | uint8_t cbCDB; |
| 102 | 102 | /** The command to issue. */ |
| 103 | | uint8_t abCDB[12]; |
| | 103 | uint8_t abCDB[VBOXSCSI_CDB_SIZE_MAX + 4]; |
| 104 | 104 | /** Current position in the array. */ |
| 105 | 105 | uint8_t iCDB; |
| 106 | 106 | |