Changeset 39597 in vbox for trunk/src/VBox/Devices/PC/BIOS-new/ahci.c
- Timestamp:
- Dec 13, 2011 5:03:01 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/PC/BIOS-new/ahci.c
r39596 r39597 83 83 /** Current port which uses the memory to communicate with the controller. */ 84 84 uint8_t cur_port; 85 /** Current PRD index (for pre/post skip). */ 86 uint8_t cur_prd; 87 /** Physical address of the sink buffer (for pre/post skip). */ 88 uint32_t sink_buf_phys; 85 89 /** VDS EDDS DMA buffer descriptor structure. */ 86 90 vds_edds edds; … … 235 239 * Issues a command to the SATA controller and waits for completion. 236 240 */ 237 static void ahci_port_cmd_sync(ahci_t __far *ahci, uint8_t val , uint16_t cbData)241 static void ahci_port_cmd_sync(ahci_t __far *ahci, uint8_t val) 238 242 { 239 243 uint16_t io_base; … … 246 250 { 247 251 /* Prepare the command header. */ 248 ahci->aCmdHdr[0] = RT_BIT_32(16) | RT_BIT_32(7) | val;249 ahci->aCmdHdr[1] = 0; //cbData; //@todo: Is this really an input parameter?252 ahci->aCmdHdr[0] = ((uint32_t)ahci->cur_prd << 16) | RT_BIT_32(7) | val; 253 ahci->aCmdHdr[1] = 0; 250 254 ahci->aCmdHdr[2] = ahci_addr_to_phys(&ahci->abCmd[0]); 251 255 … … 286 290 uint16_t n_sect = bios_dsk->drqp.nsect; 287 291 uint16_t sectsz = bios_dsk->drqp.sect_sz; 292 uint16_t prdt_idx; 288 293 289 294 _fmemset(&ahci->abCmd[0], 0, sizeof(ahci->abCmd)); … … 310 315 /* Lock memory needed for DMA. */ 311 316 ahci->edds.num_avail = NUM_EDDS_SG; 317 DBG_AHCI("AHCI: S/G list for %lu bytes (skip %u)\n", 318 (uint32_t)n_sect * sectsz, bios_dsk->drqp.skip_a); 312 319 vds_build_sg_list(&ahci->edds, bios_dsk->drqp.buffer, (uint32_t)n_sect * sectsz); 313 320 321 prdt_idx = ahci->cur_prd; 322 314 323 /* Set up the PRDT. */ 315 ahci->aPrdt[0].phys_addr = ahci->edds.u.sg[0].phys_addr; 316 ahci->aPrdt[0].len = ahci->edds.u.sg[0].size - 1; 317 318 /* Build variable part first of command dword (reuses 'cmd'). */ 324 ahci->aPrdt[prdt_idx].len = ahci->edds.u.sg[prdt_idx].size - 1; 325 ahci->aPrdt[prdt_idx].phys_addr = ahci->edds.u.sg[prdt_idx].phys_addr; 326 ++prdt_idx; 327 328 if (bios_dsk->drqp.skip_a) { 329 ahci->aPrdt[prdt_idx].len = bios_dsk->drqp.skip_a - 1; 330 ahci->aPrdt[prdt_idx].phys_addr = ahci->sink_buf_phys; 331 ++prdt_idx; 332 } 333 334 ahci->cur_prd = prdt_idx; 335 336 /* Build variable part of first command DWORD (reuses 'cmd'). */ 319 337 if (cmd == AHCI_CMD_WRITE_DMA_EXT) 320 338 cmd = RT_BIT_32(6); /* Indicate a write to device. */ … … 327 345 cmd |= 5; /* Five DWORDs. */ 328 346 329 ahci_port_cmd_sync(ahci, cmd , n_sect * sectsz);347 ahci_port_cmd_sync(ahci, cmd); 330 348 331 349 /* Unlock the buffer again. */ … … 422 440 423 441 ahci->cur_port = u8Port; 442 ahci->cur_prd = 0; 424 443 } 425 444 … … 481 500 482 501 uint16_t ahci_cmd_packet(uint16_t device_id, uint8_t cmdlen, char __far *cmdbuf, 483 uint16_t header, uint32_t length, uint8_t inout, char __far *buffer)502 uint16_t skip_b, uint32_t length, uint8_t inout, char __far *buffer) 484 503 { 485 504 bio_dsk_t __far *bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk; … … 492 511 } 493 512 494 /* The headerlength must be even. */495 if ( header& 1) {496 DBG_AHCI("%s: header must be even (%04x)\n", __func__, header);513 /* The skip length must be even. */ 514 if (skip_b & 1) { 515 DBG_AHCI("%s: skip must be even (%04x)\n", __func__, skip_b); 497 516 return 1; 498 517 } … … 501 520 device_id = device_id - BX_MAX_ATA_DEVICES - BX_MAX_SCSI_DEVICES; 502 521 503 DBG_AHCI("%s: reading %lu bytes, header %u, device %d, port %d\n", __func__, 504 length, header, device_id, bios_dsk->ahcidev[device_id].port); 522 DBG_AHCI("%s: reading %lu bytes, skip %u/%u, device %d, port %d\n", __func__, 523 length, bios_dsk->drqp.skip_b, bios_dsk->drqp.skip_a, 524 device_id, bios_dsk->ahcidev[device_id].port); 505 525 DBG_AHCI("%s: reading %u %u-byte sectors\n", __func__, 506 526 bios_dsk->drqp.nsect, bios_dsk->drqp.sect_sz); … … 520 540 bios_dsk->drqp.trsfsectors = 0; 521 541 bios_dsk->drqp.trsfbytes = 0; 542 543 /* Set up a PRD entry to throw away the beginning of the transfer. */ 544 if (bios_dsk->drqp.skip_b) { 545 ahci->aPrdt[0].len = bios_dsk->drqp.skip_b - 1; 546 ahci->aPrdt[0].phys_addr = ahci->sink_buf_phys; 547 ahci->cur_prd++; 548 } 522 549 523 550 ahci_cmd_data(bios_dsk, ATA_CMD_PACKET); … … 761 788 ahci->iobase = io_base; 762 789 790 /* Physical address of memory used for throwing away ATAPI data when reading 512-byte 791 * blocks from 2048-byte CD sectors. 792 */ 793 ahci->sink_buf_phys = 0xCC000; //@todo: find some better place! 794 763 795 /* Reset the controller. */ 764 796 ahci_ctrl_set_bits(io_base, AHCI_REG_GHC, AHCI_GHC_HR);
Note:
See TracChangeset
for help on using the changeset viewer.