165
140
#define AHCI_REG_PORT_CI 0x38
167
142
/** Returns the absolute register offset from a given port and port register. */
168
#define VBOXAHCI_PORT_REG(port, reg) ((Bit32u)(AHCI_HBA_SIZE + (port) * AHCI_PORT_SIZE + (reg)))
143
#define AHCI_PORT_REG(port, reg) (AHCI_HBA_SIZE + (port) * AHCI_PORT_SIZE + (reg))
170
#define VBOXAHCI_REG_IDX 0
171
#define VBOXAHCI_REG_DATA 4
145
#define AHCI_REG_IDX 0
146
#define AHCI_REG_DATA 4
173
148
/** Writes the given value to a AHCI register. */
174
#define VBOXAHCI_WRITE_REG(iobase, reg, val) \
175
outl((iobase) + VBOXAHCI_REG_IDX, (Bit32u)(reg)); \
176
outl((iobase) + VBOXAHCI_REG_DATA, (Bit32u)(val))
149
#define AHCI_WRITE_REG(iobase, reg, val) \
150
outpd((iobase) + AHCI_REG_IDX, reg); \
151
outpd((iobase) + AHCI_REG_DATA, val)
178
153
/** Reads from a AHCI register. */
179
#define VBOXAHCI_READ_REG(iobase, reg, val) \
180
outl((iobase) + VBOXAHCI_REG_IDX, (Bit32u)(reg)); \
181
(val) = inl((iobase) + VBOXAHCI_REG_DATA)
154
#define AHCI_READ_REG(iobase, reg, val) \
155
outpd((iobase) + AHCI_REG_IDX, reg); \
156
(val) = inpd((iobase) + AHCI_REG_DATA)
183
158
/** Writes to the given port register. */
184
#define VBOXAHCI_PORT_WRITE_REG(iobase, port, reg, val) \
185
VBOXAHCI_WRITE_REG((iobase), VBOXAHCI_PORT_REG((port), (reg)), val)
159
#define VBOXAHCI_PORT_WRITE_REG(iobase, port, reg, val) \
160
AHCI_WRITE_REG((iobase), AHCI_PORT_REG((port), (reg)), val)
187
162
/** Reads from the given port register. */
188
#define VBOXAHCI_PORT_READ_REG(iobase, port, reg, val) \
189
VBOXAHCI_READ_REG((iobase), VBOXAHCI_PORT_REG((port), (reg)), val)
191
#define ATA_CMD_IDENTIFY_DEVICE 0xEC
192
#define AHCI_CMD_READ_DMA_EXT 0x25
193
#define AHCI_CMD_WRITE_DMA_EXT 0x35
196
* Returns the bus/device/function of a PCI device with
197
* the given classcode.
199
* @returns bus/device/fn in one 16bit integer where
200
* where the upper byte contains the bus number
201
* and lower one the device and function number.
202
* VBOX_AHCI_NO_DEVICE if no device was found.
203
* @param u16Class The classcode to search for.
205
Bit16u ahci_pci_find_classcode(u16Class)
215
mov al, #PCIBIOS_FIND_CLASS_CODE
216
mov ecx, _ahci_pci_find_classcode.u16Class + 2[bp]
217
mov si, #0 ; First controller
220
; Return from PCIBIOS
222
jne ahci_pci_find_classcode_not_found
224
mov _ahci_pci_find_classcode.u16BusDevFn + 2[bp], bx
225
jmp ahci_pci_find_classcode_done
227
ahci_pci_find_classcode_not_found:
228
mov _ahci_pci_find_classcode.u16BusDevFn + 2[bp], #VBOX_AHCI_NO_DEVICE
230
ahci_pci_find_classcode_done:
237
Bit8u ahci_pci_read_config_byte(u8Bus, u8DevFn, u8Reg)
238
Bit8u u8Bus, u8DevFn, u8Reg;
249
mov al, #PCIBIOS_READ_CONFIG_BYTE
250
mov bh, _ahci_pci_read_config_byte.u8Bus + 2[bp]
251
mov bl, _ahci_pci_read_config_byte.u8DevFn + 2[bp]
252
mov di, _ahci_pci_read_config_byte.u8Reg + 2[bp]
255
; Return from PCIBIOS
257
jne ahci_pci_read_config_byte_done
259
mov _ahci_pci_read_config_byte.u8Val + 2[bp], cl
261
ahci_pci_read_config_byte_done:
268
Bit16u ahci_pci_read_config_word(u8Bus, u8DevFn, u8Reg)
269
Bit8u u8Bus, u8DevFn, u8Reg;
280
mov al, #PCIBIOS_READ_CONFIG_WORD
281
mov bh, _ahci_pci_read_config_word.u8Bus + 2[bp]
282
mov bl, _ahci_pci_read_config_word.u8DevFn + 2[bp]
283
mov di, _ahci_pci_read_config_word.u8Reg + 2[bp]
286
; Return from PCIBIOS
288
jne ahci_pci_read_config_word_done
290
mov _ahci_pci_read_config_word.u16Val + 2[bp], cx
292
ahci_pci_read_config_word_done:
299
Bit32u ahci_pci_read_config_dword(u8Bus, u8DevFn, u8Reg)
300
Bit8u u8Bus, u8DevFn, u8Reg;
311
mov al, #PCIBIOS_READ_CONFIG_DWORD
312
mov bh, _ahci_pci_read_config_dword.u8Bus + 2[bp]
313
mov bl, _ahci_pci_read_config_dword.u8DevFn + 2[bp]
314
mov di, _ahci_pci_read_config_dword.u8Reg + 2[bp]
317
; Return from PCIBIOS
319
jne ahci_pci_read_config_dword_done
321
mov _ahci_pci_read_config_dword.u32Val + 2[bp], ecx
323
ahci_pci_read_config_dword_done:
330
#if 0 /* Disabled to save space because they are not needed. Might become useful in the future. */
332
* Returns the bus/device/function of a PCI device with
333
* the given vendor and device id.
335
* @returns bus/device/fn in one 16bit integer where
336
* where the upper byte contains the bus number
337
* and lower one the device and function number.
338
* VBOX_AHCI_NO_DEVICE if no device was found.
339
* @param u16Vendor The vendor ID.
340
* @param u16Device The device ID.
342
Bit16u ahci_pci_find_device(u16Vendor, u16Device)
353
mov al, #PCIBIOS_FIND_PCI_DEVICE
354
mov cx, _ahci_pci_find_device.u16Device + 2[bp]
355
mov dx, _ahci_pci_find_device.u16Vendor + 2[bp]
356
mov si, #0 ; First controller
359
; Return from PCIBIOS
361
jne ahci_pci_find_device_not_found
363
mov _ahci_pci_find_device.u16BusDevFn + 2[bp], bx
364
jmp ahci_pci_find_device_done
366
ahci_pci_find_device_not_found:
367
mov _ahci_pci_find_device.u16BusDevFn + 2[bp], #VBOX_AHCI_NO_DEVICE
369
ahci_pci_find_device_done:
376
void ahci_pci_write_config_byte(u8Bus, u8DevFn, u8Reg, u8Val)
377
Bit8u u8Bus, u8DevFn, u8Reg, u8Val;
384
mov al, #PCIBIOS_WRITE_CONFIG_BYTE
385
mov bh, _ahci_pci_write_config_byte.u8Bus + 2[bp]
386
mov bl, _ahci_pci_write_config_byte.u8DevFn + 2[bp]
387
mov di, _ahci_pci_write_config_byte.u8Reg + 2[bp]
388
mov cl, _ahci_pci_write_config_byte.u8Val + 2[bp]
391
; Return from PCIBIOS
396
void ahci_pci_write_config_word(u8Bus, u8DevFn, u8Reg, u16Val)
397
Bit8u u8Bus, u8DevFn, u8Reg;
405
mov al, #PCIBIOS_WRITE_CONFIG_WORD
406
mov bh, _ahci_pci_write_config_word.u8Bus + 2[bp]
407
mov bl, _ahci_pci_write_config_word.u8DevFn + 2[bp]
408
mov di, _ahci_pci_write_config_word.u8Reg + 2[bp]
409
mov cx, _ahci_pci_write_config_word.u16Val + 2[bp]
412
; Return from PCIBIOS
417
void ahci_pci_write_config_dword(u8Bus, u8DevFn, u8Reg, u32Val)
418
Bit8u u8Bus, u8DevFn, u8Reg;
426
mov al, #PCIBIOS_WRITE_CONFIG_WORD
427
mov bh, _ahci_pci_write_config_dword.u8Bus + 2[bp]
428
mov bl, _ahci_pci_write_config_dword.u8DevFn + 2[bp]
429
mov di, _ahci_pci_write_config_dword.u8Reg + 2[bp]
430
mov cx, _ahci_pci_write_config_dword.u32Val + 2[bp]
433
; Return from PCIBIOS
163
#define VBOXAHCI_PORT_READ_REG(iobase, port, reg, val) \
164
AHCI_READ_REG((iobase), AHCI_PORT_REG((port), (reg)), val)
166
#define ATA_CMD_IDENTIFY_DEVICE 0xEC
167
#define ATA_CMD_IDENTIFY_PACKET 0xA1
168
#define ATA_CMD_PACKET 0xA0
169
#define AHCI_CMD_READ_DMA_EXT 0x25
170
#define AHCI_CMD_WRITE_DMA_EXT 0x35
173
/* Warning: Destroys high bits of EAX. */
174
uint32_t inpd(uint16_t port);
181
parm [dx] value [dx ax] modify nomemory;
183
/* Warning: Destroys high bits of EAX. */
184
void outpd(uint16_t port, uint32_t val);
185
#pragma aux outpd = \
191
parm [dx] [cx ax] modify nomemory;
194
/* Machinery to save/restore high bits of EAX. 32-bit port I/O needs to use
195
* EAX, but saving/restoring EAX around each port access would be inefficient.
196
* Instead, each externally callable routine must save the high bits before
197
* modifying them and restore the high bits before exiting.
200
/* Note: Reading high EAX bits destroys them - *must* be restored later. */
201
uint16_t eax_hi_rd(void);
202
#pragma aux eax_hi_rd = \
205
value [ax] modify nomemory;
207
void eax_hi_wr(uint16_t);
208
#pragma aux eax_hi_wr = \
211
parm [ax] modify nomemory;
213
void high_bits_save(ahci_t __far *ahci)
215
ahci->saved_eax_hi = eax_hi_rd();
218
void high_bits_restore(ahci_t __far *ahci)
220
eax_hi_wr(ahci->saved_eax_hi);
440
224
* Sets a given set of bits in a register.
442
static void ahci_ctrl_set_bits(u16IoBase, u32Reg, u32Set)
444
Bit32u u32Reg, u32Set;
226
static void ahci_ctrl_set_bits(uint16_t iobase, uint16_t reg, uint32_t mask)
453
; Read from the register
454
mov eax, _ahci_ctrl_set_bits.u32Reg + 2[bp]
455
mov dx, _ahci_ctrl_set_bits.u16IoBase + 2[bp]
456
add dx, #VBOXAHCI_REG_IDX
459
mov dx, _ahci_ctrl_set_bits.u16IoBase + 2[bp]
460
add dx, #VBOXAHCI_REG_DATA
463
; Set the new bits and write the result to the register again
464
or eax, _ahci_ctrl_set_bits.u32Set + 2[bp]
228
outpd(iobase + AHCI_REG_IDX, reg);
229
outpd(iobase + AHCI_REG_DATA, inpd(iobase + AHCI_REG_DATA) | mask);
475
233
* Clears a given set of bits in a register.
477
static void ahci_ctrl_clear_bits(u16IoBase, u32Reg, u32Clear)
479
Bit32u u32Reg, u32Clear;
235
static void ahci_ctrl_clear_bits(uint16_t iobase, uint16_t reg, uint32_t mask)
489
; Read from the register
490
mov eax, _ahci_ctrl_clear_bits.u32Reg + 2[bp]
491
mov dx, _ahci_ctrl_clear_bits.u16IoBase + 2[bp]
492
add dx, #VBOXAHCI_REG_IDX
495
mov dx, _ahci_ctrl_clear_bits.u16IoBase + 2[bp]
496
add dx, #VBOXAHCI_REG_DATA
499
; Clear the bits and write the result to the register again
500
mov ecx, _ahci_ctrl_clear_bits.u32Clear + 2[bp]
237
outpd(iobase + AHCI_REG_IDX, reg);
238
outpd(iobase + AHCI_REG_DATA, inpd(iobase + AHCI_REG_DATA) & ~mask);
514
242
* Returns whether at least one of the bits in the given mask is set
515
243
* for a register.
517
static Bit8u ahci_ctrl_is_bit_set(u16IoBase, u32Reg, u32Mask)
519
Bit32u u32Reg, u32Mask;
245
static uint8_t ahci_ctrl_is_bit_set(uint16_t iobase, uint16_t reg, uint32_t mask)
528
; Read from the register
529
mov eax, _ahci_ctrl_is_bit_set.u32Reg + 2[bp]
530
mov dx, _ahci_ctrl_is_bit_set.u16IoBase + 2[bp]
531
add dx, #VBOXAHCI_REG_IDX
534
mov dx, _ahci_ctrl_is_bit_set.u16IoBase + 2[bp]
535
add dx, #VBOXAHCI_REG_DATA
539
mov edx, _ahci_ctrl_is_bit_set.u32Mask + 2[bp]
541
je ahci_ctrl_is_bit_set_not_set
542
mov al, #1 ; At least one of the bits is set
543
jmp ahci_ctrl_is_bit_set_done
545
ahci_ctrl_is_bit_set_not_set:
546
mov al, #0 ; No bit is set
548
ahci_ctrl_is_bit_set_done:
549
pop edx ; restore upper 16 bits of eax
247
outpd(iobase + AHCI_REG_IDX, reg);
248
return (inpd(iobase + AHCI_REG_DATA) & mask) != 0;
559
252
* Extracts a range of bits from a register and shifts them
562
static Bit16u ahci_ctrl_extract_bits(u32Reg, u32Mask, u8Shift)
563
Bit32u u32Reg, u32Mask, u8Shift;
255
static uint16_t ahci_ctrl_extract_bits(uint32_t val, uint32_t mask, uint8_t shift)
571
mov eax, _ahci_ctrl_extract_bits.u32Reg + 2[bp]
572
mov cl, _ahci_ctrl_extract_bits.u8Shift + 2[bp]
573
and eax, _ahci_ctrl_extract_bits.u32Mask + 2[bp]
257
return (val & mask) >> shift;
583
261
* Converts a segment:offset pair into a 32bit physical address.
585
static Bit32u ahci_addr_to_phys(u16Segment, u16Offset)
586
Bit16u u16Segment, u16Offset;
263
static uint32_t ahci_addr_to_phys(void __far *ptr)
597
mov ax, _ahci_addr_to_phys.u16Segment + 2[bp]
599
add bx, _ahci_addr_to_phys.u16Offset + 2[bp]
265
return ((uint32_t)FP_SEG(ptr) << 4) + FP_OFF(ptr);
615
269
* Issues a command to the SATA controller and waits for completion.
617
static void ahci_port_cmd_sync(SegAhci, u16IoBase, fWrite, fAtapi, cFisDWords, cbData)
271
static void ahci_port_cmd_sync(ahci_t __far *ahci, uint8_t val)
627
u8Port = read_byte(SegAhci, &AhciData->port);
276
port = ahci->cur_port;
277
io_base = ahci->iobase;
633
281
/* Prepare the command header. */
634
u32Val = (1L << 16) | RT_BIT_32(7);
636
u32Val |= RT_BIT_32(6);
639
u32Val |= RT_BIT_32(5);
641
u32Val |= cFisDWords;
643
write_dword(SegAhci, &AhciData->abCmdHdr[0], u32Val);
644
write_dword(SegAhci, &AhciData->abCmdHdr[1], (Bit32u)cbData);
645
write_dword(SegAhci, &AhciData->abCmdHdr[2],
646
ahci_addr_to_phys(SegAhci, &AhciData->abCmd[0]));
282
ahci->aCmdHdr[0] = ((uint32_t)ahci->cur_prd << 16) | RT_BIT_32(7) | val;
283
ahci->aCmdHdr[1] = 0;
284
ahci->aCmdHdr[2] = ahci_addr_to_phys(&ahci->abCmd[0]);
648
286
/* Enable Command and FIS receive engine. */
649
ahci_ctrl_set_bits(u16IoBase, VBOXAHCI_PORT_REG(u8Port, AHCI_REG_PORT_CMD),
287
ahci_ctrl_set_bits(io_base, AHCI_PORT_REG(port, AHCI_REG_PORT_CMD),
650
288
AHCI_REG_PORT_CMD_FRE | AHCI_REG_PORT_CMD_ST);
652
290
/* Queue command. */
653
VBOXAHCI_PORT_WRITE_REG(u16IoBase, u8Port, AHCI_REG_PORT_CI, 0x1L);
291
VBOXAHCI_PORT_WRITE_REG(io_base, port, AHCI_REG_PORT_CI, 0x1);
655
/* Wait for a D2H Fis. */
656
while (ahci_ctrl_is_bit_set(u16IoBase, VBOXAHCI_PORT_REG(u8Port, AHCI_REG_PORT_IS),
657
AHCI_REG_PORT_IS_DHRS) == 0)
293
/* Wait for a D2H FIS. */
294
DBG_AHCI("AHCI: Waiting for D2H FIS\n");
295
while (ahci_ctrl_is_bit_set(io_base, AHCI_PORT_REG(port, AHCI_REG_PORT_IS),
296
AHCI_REG_PORT_IS_DHRS | AHCI_REG_PORT_IS_TFES) == 0)
659
VBOXAHCI_DEBUG("AHCI: Waiting for a D2H Fis\n");
298
// This is where we'd need some kind of a yield functionality...
662
ahci_ctrl_set_bits(u16IoBase, VBOXAHCI_PORT_REG(u8Port, AHCI_REG_PORT_IS),
301
ahci_ctrl_set_bits(io_base, AHCI_PORT_REG(port, AHCI_REG_PORT_IS),
663
302
AHCI_REG_PORT_IS_DHRS); /* Acknowledge received D2H FIS. */
665
304
/* Disable command engine. */
666
ahci_ctrl_clear_bits(u16IoBase, VBOXAHCI_PORT_REG(u8Port, AHCI_REG_PORT_CMD),
305
ahci_ctrl_clear_bits(io_base, AHCI_PORT_REG(port, AHCI_REG_PORT_CMD),
667
306
AHCI_REG_PORT_CMD_ST);
669
308
/** @todo: Examine status. */
672
VBOXAHCI_DEBUG("AHCI: Invalid port given\n");
311
DBG_AHCI("AHCI: Invalid port given\n");
676
315
* Issue command to device.
678
static void ahci_cmd_data(SegAhci, u16IoBase, u8Cmd, u8Feat, u8Device, u8CylHigh, u8CylLow, u8Sect,
679
u8FeatExp, u8CylHighExp, u8CylLowExp, u8SectExp, u8SectCount, u8SectCountExp,
680
SegData, OffData, cbData, fWrite)
683
Bit8u u8Cmd, u8Feat, u8Device, u8CylHigh, u8CylLow, u8Sect, u8FeatExp,
684
u8CylHighExp, u8CylLowExp, u8SectExp, u8SectCount, u8SectCountExp;
685
Bit16u SegData, OffData, cbData;
317
static void ahci_cmd_data(bio_dsk_t __far *bios_dsk, uint8_t cmd)
688
memsetb(SegAhci, &AhciData->abCmd[0], 0, sizeof(AhciData->abCmd));
319
ahci_t __far *ahci = bios_dsk->ahci_seg :> 0;
320
uint16_t n_sect = bios_dsk->drqp.nsect;
321
uint16_t sectsz = bios_dsk->drqp.sect_sz;
324
_fmemset(&ahci->abCmd[0], 0, sizeof(ahci->abCmd));
690
326
/* Prepare the FIS. */
691
write_byte(SegAhci, &AhciData->abCmd[0], 0x27); /* FIS type H2D. */
692
write_byte(SegAhci, &AhciData->abCmd[1], 1 << 7); /* Command update. */
693
write_byte(SegAhci, &AhciData->abCmd[2], u8Cmd);
694
write_byte(SegAhci, &AhciData->abCmd[3], u8Feat);
696
write_byte(SegAhci, &AhciData->abCmd[4], u8Sect);
697
write_byte(SegAhci, &AhciData->abCmd[5], u8CylLow);
698
write_byte(SegAhci, &AhciData->abCmd[6], u8CylHigh);
699
write_byte(SegAhci, &AhciData->abCmd[7], u8Device);
701
write_byte(SegAhci, &AhciData->abCmd[8], u8SectExp);
702
write_byte(SegAhci, &AhciData->abCmd[9], u8CylLowExp);
703
write_byte(SegAhci, &AhciData->abCmd[10], u8CylHighExp);
704
write_byte(SegAhci, &AhciData->abCmd[11], u8FeatExp);
706
write_byte(SegAhci, &AhciData->abCmd[12], u8SectCount);
707
write_byte(SegAhci, &AhciData->abCmd[13], u8SectCountExp);
710
write_dword(SegAhci, &AhciData->abCmd[0x80], ahci_addr_to_phys(SegData, OffData));
711
write_dword(SegAhci, &AhciData->abCmd[0x8c], (Bit32u)(cbData - 1));
713
ahci_port_cmd_sync(SegAhci, u16IoBase, fWrite, 0, 5, cbData);
327
ahci->abCmd[0] = 0x27; /* FIS type H2D. */
328
ahci->abCmd[1] = 1 << 7; /* Command update. */
329
ahci->abCmd[2] = cmd;
332
ahci->abCmd[4] = bios_dsk->drqp.lba & 0xff;
333
ahci->abCmd[5] = (bios_dsk->drqp.lba >> 8) & 0xff;
334
ahci->abCmd[6] = (bios_dsk->drqp.lba >> 16) & 0xff;
335
ahci->abCmd[7] = RT_BIT_32(6); /* LBA access. */
337
ahci->abCmd[8] = (bios_dsk->drqp.lba >> 24) & 0xff;
342
ahci->abCmd[12] = (uint8_t)(n_sect & 0xff);
343
ahci->abCmd[13] = (uint8_t)((n_sect >> 8) & 0xff);
345
/* Lock memory needed for DMA. */
346
ahci->edds.num_avail = NUM_EDDS_SG;
347
DBG_AHCI("AHCI: S/G list for %lu bytes (skip %u)\n",
348
(uint32_t)n_sect * sectsz, bios_dsk->drqp.skip_a);
349
vds_build_sg_list(&ahci->edds, bios_dsk->drqp.buffer, (uint32_t)n_sect * sectsz);
351
prdt_idx = ahci->cur_prd;
353
/* Set up the PRDT. */
354
ahci->aPrdt[prdt_idx].len = ahci->edds.u.sg[0].size - 1;
355
ahci->aPrdt[prdt_idx].phys_addr = ahci->edds.u.sg[0].phys_addr;
358
if (bios_dsk->drqp.skip_a) {
359
ahci->aPrdt[prdt_idx].len = bios_dsk->drqp.skip_a - 1;
360
ahci->aPrdt[prdt_idx].phys_addr = ahci->sink_buf_phys;
364
ahci->cur_prd = prdt_idx;
367
for (prdt_idx = 0; prdt_idx < ahci->cur_prd; ++prdt_idx) {
368
DBG_AHCI("S/G entry %u: %5lu bytes @ %08lX\n", prdt_idx,
369
ahci->aPrdt[prdt_idx].len + 1, ahci->aPrdt[prdt_idx].phys_addr);
373
/* Build variable part of first command DWORD (reuses 'cmd'). */
374
if (cmd == AHCI_CMD_WRITE_DMA_EXT)
375
cmd = RT_BIT_32(6); /* Indicate a write to device. */
376
else if (cmd == ATA_CMD_PACKET) {
377
cmd |= RT_BIT_32(5); /* Indicate ATAPI command. */
378
ahci->abCmd[3] |= 1; /* DMA transfers. */
382
cmd |= 5; /* Five DWORDs. */
384
ahci_port_cmd_sync(ahci, cmd);
386
/* Unlock the buffer again. */
387
vds_free_sg_list(&ahci->edds);
717
391
* Deinits the curent active port.
719
static void ahci_port_deinit_current(SegAhci, u16IoBase)
393
static void ahci_port_deinit_current(ahci_t __far *ahci)
725
u8Port = read_byte(SegAhci, &AhciData->port);
398
io_base = ahci->iobase;
399
port = ahci->cur_port;
729
403
/* Put the port into an idle state. */
730
ahci_ctrl_clear_bits(u16IoBase, VBOXAHCI_PORT_REG(u8Port, AHCI_REG_PORT_CMD),
404
ahci_ctrl_clear_bits(io_base, AHCI_PORT_REG(port, AHCI_REG_PORT_CMD),
731
405
AHCI_REG_PORT_CMD_FRE | AHCI_REG_PORT_CMD_ST);
733
while (ahci_ctrl_is_bit_set(u16IoBase, VBOXAHCI_PORT_REG(u8Port, AHCI_REG_PORT_CMD),
407
while (ahci_ctrl_is_bit_set(io_base, AHCI_PORT_REG(port, AHCI_REG_PORT_CMD),
734
408
AHCI_REG_PORT_CMD_FRE | AHCI_REG_PORT_CMD_ST | AHCI_REG_PORT_CMD_FR | AHCI_REG_PORT_CMD_CR) == 1)
736
VBOXAHCI_DEBUG("AHCI: Waiting for the port to idle\n");
410
DBG_AHCI("AHCI: Waiting for the port to idle\n");
740
414
* Port idles, set up memory for commands and received FIS and program the
741
415
* address registers.
743
memsetb(SegAhci, &AhciData->abFisRecv[0], 0, 0x60);
744
memsetb(SegAhci, &AhciData->abCmdHdr[0], 0, 0x20);
745
memsetb(SegAhci, &AhciData->abCmd[0], 0, 0x84);
747
VBOXAHCI_PORT_WRITE_REG(u16IoBase, u8Port, AHCI_REG_PORT_FB, 0L);
748
VBOXAHCI_PORT_WRITE_REG(u16IoBase, u8Port, AHCI_REG_PORT_FBU, 0L);
750
VBOXAHCI_PORT_WRITE_REG(u16IoBase, u8Port, AHCI_REG_PORT_CLB, 0L);
751
VBOXAHCI_PORT_WRITE_REG(u16IoBase, u8Port, AHCI_REG_PORT_CLBU, 0L);
417
//@todo: merge memsets?
418
_fmemset(&ahci->aCmdHdr[0], 0, sizeof(ahci->aCmdHdr));
419
_fmemset(&ahci->abCmd[0], 0, sizeof(ahci->abCmd));
420
_fmemset(&ahci->abFisRecv[0], 0, sizeof(ahci->abFisRecv));
422
VBOXAHCI_PORT_WRITE_REG(io_base, port, AHCI_REG_PORT_FB, 0);
423
VBOXAHCI_PORT_WRITE_REG(io_base, port, AHCI_REG_PORT_FBU, 0);
425
VBOXAHCI_PORT_WRITE_REG(io_base, port, AHCI_REG_PORT_CLB, 0);
426
VBOXAHCI_PORT_WRITE_REG(io_base, port, AHCI_REG_PORT_CLBU, 0);
753
428
/* Disable all interrupts. */
754
VBOXAHCI_PORT_WRITE_REG(u16IoBase, u8Port, AHCI_REG_PORT_IE, 0L);
429
VBOXAHCI_PORT_WRITE_REG(io_base, port, AHCI_REG_PORT_IE, 0);
756
write_byte(SegAhci, &AhciData->port, 0xff);
431
ahci->cur_port = 0xff;
761
436
* Brings a port into a minimal state to make device detection possible
762
437
* or to queue requests.
764
static void ahci_port_init(SegAhci, u16IoBase, u8Port)
439
static void ahci_port_init(ahci_t __far *ahci, uint8_t u8Port)
771
441
/* Deinit any other port first. */
772
ahci_port_deinit_current(SegAhci, u16IoBase);
442
ahci_port_deinit_current(ahci);
774
444
/* Put the port into an idle state. */
775
ahci_ctrl_clear_bits(u16IoBase, VBOXAHCI_PORT_REG(u8Port, AHCI_REG_PORT_CMD),
445
ahci_ctrl_clear_bits(ahci->iobase, AHCI_PORT_REG(u8Port, AHCI_REG_PORT_CMD),
776
446
AHCI_REG_PORT_CMD_FRE | AHCI_REG_PORT_CMD_ST);
778
while (ahci_ctrl_is_bit_set(u16IoBase, VBOXAHCI_PORT_REG(u8Port, AHCI_REG_PORT_CMD),
448
while (ahci_ctrl_is_bit_set(ahci->iobase, AHCI_PORT_REG(u8Port, AHCI_REG_PORT_CMD),
779
449
AHCI_REG_PORT_CMD_FRE | AHCI_REG_PORT_CMD_ST | AHCI_REG_PORT_CMD_FR | AHCI_REG_PORT_CMD_CR) == 1)
781
VBOXAHCI_DEBUG("AHCI: Waiting for the port to idle\n");
451
DBG_AHCI("AHCI: Waiting for the port to idle\n");
785
455
* Port idles, set up memory for commands and received FIS and program the
786
456
* address registers.
788
memsetb(SegAhci, &AhciData->abFisRecv[0], 0, 0x60);
789
memsetb(SegAhci, &AhciData->abCmdHdr[0], 0, 0x20);
790
memsetb(SegAhci, &AhciData->abCmd[0], 0, 0x84);
792
u32PhysAddr = ahci_addr_to_phys(SegAhci, &AhciData->abFisRecv);
793
VBOXAHCI_DEBUG("AHCI: FIS receive area %lx from %x:%x\n", u32PhysAddr, SegAhci, &AhciData->abFisRecv);
794
VBOXAHCI_PORT_WRITE_REG(u16IoBase, u8Port, AHCI_REG_PORT_FB, u32PhysAddr);
795
VBOXAHCI_PORT_WRITE_REG(u16IoBase, u8Port, AHCI_REG_PORT_FBU, 0L);
797
u32PhysAddr = ahci_addr_to_phys(SegAhci, &AhciData->abCmdHdr);
798
VBOXAHCI_DEBUG("AHCI: CMD list area %lx\n", u32PhysAddr);
799
VBOXAHCI_PORT_WRITE_REG(u16IoBase, u8Port, AHCI_REG_PORT_CLB, u32PhysAddr);
800
VBOXAHCI_PORT_WRITE_REG(u16IoBase, u8Port, AHCI_REG_PORT_CLBU, 0L);
458
//@todo: just one memset?
459
_fmemset(&ahci->aCmdHdr[0], 0, sizeof(ahci->aCmdHdr));
460
_fmemset(&ahci->abCmd[0], 0, sizeof(ahci->abCmd));
461
_fmemset(&ahci->abFisRecv[0], 0, sizeof(ahci->abFisRecv));
463
DBG_AHCI("AHCI: FIS receive area %lx from %x:%x\n",
464
ahci_addr_to_phys(&ahci->abFisRecv), FP_SEG(ahci->abFisRecv), FP_OFF(ahci->abFisRecv));
465
VBOXAHCI_PORT_WRITE_REG(ahci->iobase, u8Port, AHCI_REG_PORT_FB, ahci_addr_to_phys(&ahci->abFisRecv));
466
VBOXAHCI_PORT_WRITE_REG(ahci->iobase, u8Port, AHCI_REG_PORT_FBU, 0);
468
DBG_AHCI("AHCI: CMD list area %lx\n", ahci_addr_to_phys(&ahci->aCmdHdr));
469
VBOXAHCI_PORT_WRITE_REG(ahci->iobase, u8Port, AHCI_REG_PORT_CLB, ahci_addr_to_phys(&ahci->aCmdHdr));
470
VBOXAHCI_PORT_WRITE_REG(ahci->iobase, u8Port, AHCI_REG_PORT_CLBU, 0);
802
472
/* Disable all interrupts. */
803
VBOXAHCI_PORT_WRITE_REG(u16IoBase, u8Port, AHCI_REG_PORT_IE, 0L);
804
VBOXAHCI_PORT_WRITE_REG(u16IoBase, u8Port, AHCI_REG_PORT_IS, 0xffffffffL);
473
VBOXAHCI_PORT_WRITE_REG(ahci->iobase, u8Port, AHCI_REG_PORT_IE, 0);
474
VBOXAHCI_PORT_WRITE_REG(ahci->iobase, u8Port, AHCI_REG_PORT_IS, 0xffffffff);
805
475
/* Clear all errors. */
806
VBOXAHCI_PORT_WRITE_REG(u16IoBase, u8Port, AHCI_REG_PORT_SERR, 0xffffffffL);
808
write_byte(SegAhci, &AhciData->port, u8Port);
812
* Write data to the device.
814
static void ahci_cmd_data_out(SegAhci, u16IoBase, u8Port, u8Cmd, u32Lba, u16Sectors, SegData, OffData)
815
Bit16u SegAhci, u16IoBase;
819
Bit16u SegData, OffData;
821
Bit8u u8CylLow, u8CylHigh, u8Device, u8Sect, u8CylHighExp, u8CylLowExp, u8SectExp, u8SectCount, u8SectCountExp;
823
u8SectCount = (Bit8u)(u16Sectors & 0xff);
824
u8SectCountExp = (Bit8u)((u16Sectors >> 8) & 0xff);;
825
u8Sect = (Bit8u)(u32Lba & 0xff);
826
u8SectExp = (Bit8u)((u32Lba >> 24) & 0xff);
827
u8CylLow = (Bit8u)((u32Lba >> 8) & 0xff);
829
u8CylHigh = (Bit8u)((u32Lba >> 16) & 0xff);
831
u8Device = (1 << 6); /* LBA access */
833
ahci_port_init(SegAhci, u16IoBase, u8Port);
834
ahci_cmd_data(SegAhci, u16IoBase, u8Cmd, 0, u8Device, u8CylHigh, u8CylLow,
835
u8Sect,0, u8CylHighExp, u8CylLowExp, u8SectExp, u8SectCount,
836
u8SectCountExp, SegData, OffData, u16Sectors * 512, 1);
840
* Read data from the device.
842
static void ahci_cmd_data_in(SegAhci, u16IoBase, u8Port, u8Cmd, u32Lba, u16Sectors, SegData, OffData)
843
Bit16u SegAhci, u16IoBase;
847
Bit16u SegData, OffData;
849
Bit8u u8CylLow, u8CylHigh, u8Device, u8Sect, u8CylHighExp, u8CylLowExp, u8SectExp, u8SectCount, u8SectCountExp;
851
u8SectCount = (Bit8u)(u16Sectors & 0xff);
852
u8SectCountExp = (Bit8u)((u16Sectors >> 8) & 0xff);;
853
u8Sect = (Bit8u)(u32Lba & 0xff);
854
u8SectExp = (Bit8u)((u32Lba >> 24) & 0xff);
855
u8CylLow = (Bit8u)((u32Lba >> 8) & 0xff);
857
u8CylHigh = (Bit8u)((u32Lba >> 16) & 0xff);
860
u8Device = (1 << 6); /* LBA access */
862
ahci_port_init(SegAhci, u16IoBase, u8Port);
863
ahci_cmd_data(SegAhci, u16IoBase, u8Cmd, 0, u8Device, u8CylHigh, u8CylLow,
864
u8Sect, 0, u8CylHighExp, u8CylLowExp, u8SectExp, u8SectCount,
865
u8SectCountExp, SegData, OffData, u16Sectors * 512, 0);
868
static void ahci_port_detect_device(SegAhci, u16IoBase, u8Port)
875
ahci_port_init(SegAhci, u16IoBase, u8Port);
476
VBOXAHCI_PORT_WRITE_REG(ahci->iobase, u8Port, AHCI_REG_PORT_SERR, 0xffffffff);
478
ahci->cur_port = u8Port;
483
* Read sectors from an attached AHCI device.
485
* @returns status code.
486
* @param bios_dsk Pointer to disk request packet (in the
489
int ahci_read_sectors(bio_dsk_t __far *bios_dsk)
493
device_id = VBOX_GET_AHCI_DEVICE(bios_dsk->drqp.dev_id);
494
if (device_id > BX_MAX_AHCI_DEVICES)
495
BX_PANIC("%s: device_id out of range %d\n", __func__, device_id);
497
DBG_AHCI("%s: %u sectors @ LBA %lu, device %d, port %d\n", __func__,
498
bios_dsk->drqp.nsect, bios_dsk->drqp.lba, device_id,
499
bios_dsk->ahcidev[device_id].port);
501
high_bits_save(bios_dsk->ahci_seg :> 0);
502
ahci_port_init(bios_dsk->ahci_seg :> 0, bios_dsk->ahcidev[device_id].port);
503
ahci_cmd_data(bios_dsk, AHCI_CMD_READ_DMA_EXT);
504
DBG_AHCI("%s: transferred %lu bytes\n", __func__, ((ahci_t __far *)(bios_dsk->ahci_seg :> 0))->aCmdHdr[1]);
505
bios_dsk->drqp.trsfsectors = bios_dsk->drqp.nsect;
506
#ifdef DMA_WORKAROUND
507
rep_movsw(bios_dsk->drqp.buffer, bios_dsk->drqp.buffer, bios_dsk->drqp.nsect * 512 / 2);
509
high_bits_restore(bios_dsk->ahci_seg :> 0);
514
* Write sectors to an attached AHCI device.
516
* @returns status code.
517
* @param bios_dsk Pointer to disk request packet (in the
520
int ahci_write_sectors(bio_dsk_t __far *bios_dsk)
524
device_id = VBOX_GET_AHCI_DEVICE(bios_dsk->drqp.dev_id);
525
if (device_id > BX_MAX_AHCI_DEVICES)
526
BX_PANIC("%s: device_id out of range %d\n", __func__, device_id);
528
DBG_AHCI("%s: %u sectors @ LBA %lu, device %d, port %d\n", __func__,
529
bios_dsk->drqp.nsect, bios_dsk->drqp.lba, device_id,
530
bios_dsk->ahcidev[device_id].port);
532
high_bits_save(bios_dsk->ahci_seg :> 0);
533
ahci_port_init(bios_dsk->ahci_seg :> 0, bios_dsk->ahcidev[device_id].port);
534
ahci_cmd_data(bios_dsk, AHCI_CMD_WRITE_DMA_EXT);
535
DBG_AHCI("%s: transferred %lu bytes\n", __func__, ((ahci_t __far *)(bios_dsk->ahci_seg :> 0))->aCmdHdr[1]);
536
bios_dsk->drqp.trsfsectors = bios_dsk->drqp.nsect;
537
high_bits_restore(bios_dsk->ahci_seg :> 0);
542
#define ATA_DATA_NO 0x00
543
#define ATA_DATA_IN 0x01
544
#define ATA_DATA_OUT 0x02
546
uint16_t ahci_cmd_packet(uint16_t device_id, uint8_t cmdlen, char __far *cmdbuf,
547
uint16_t skip_b, uint32_t length, uint8_t inout, char __far *buffer)
549
bio_dsk_t __far *bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;
552
/* Data out is currently not supported. */
553
if (inout == ATA_DATA_OUT) {
554
BX_INFO("%s: DATA_OUT not supported yet\n", __func__);
558
/* The skip length must be even. */
560
DBG_AHCI("%s: skip must be even (%04x)\n", __func__, skip_b);
564
/* Convert to AHCI specific device number. */
565
device_id = VBOX_GET_AHCI_DEVICE(device_id);
567
DBG_AHCI("%s: reading %lu bytes, skip %u/%u, device %d, port %d\n", __func__,
568
length, bios_dsk->drqp.skip_b, bios_dsk->drqp.skip_a,
569
device_id, bios_dsk->ahcidev[device_id].port);
570
DBG_AHCI("%s: reading %u %u-byte sectors\n", __func__,
571
bios_dsk->drqp.nsect, bios_dsk->drqp.sect_sz);
573
bios_dsk->drqp.lba = (uint32_t)length << 8; //@todo: xfer length limit
574
bios_dsk->drqp.buffer = buffer;
575
bios_dsk->drqp.nsect = length / bios_dsk->drqp.sect_sz;
576
// bios_dsk->drqp.sect_sz = 2048;
578
ahci = bios_dsk->ahci_seg :> 0;
579
high_bits_save(ahci);
581
ahci_port_init(bios_dsk->ahci_seg :> 0, bios_dsk->ahcidev[device_id].port);
583
/* Copy the ATAPI command where the HBA can fetch it. */
584
_fmemcpy(ahci->abAcmd, cmdbuf, cmdlen);
586
/* Reset transferred counts. */
587
// @todo: clear in calling code?
588
bios_dsk->drqp.trsfsectors = 0;
589
bios_dsk->drqp.trsfbytes = 0;
591
/* Set up a PRD entry to throw away the beginning of the transfer. */
592
if (bios_dsk->drqp.skip_b) {
593
ahci->aPrdt[0].len = bios_dsk->drqp.skip_b - 1;
594
ahci->aPrdt[0].phys_addr = ahci->sink_buf_phys;
598
ahci_cmd_data(bios_dsk, ATA_CMD_PACKET);
599
DBG_AHCI("%s: transferred %lu bytes\n", __func__, ahci->aCmdHdr[1]);
600
bios_dsk->drqp.trsfbytes = ahci->aCmdHdr[1];
601
#ifdef DMA_WORKAROUND
602
rep_movsw(bios_dsk->drqp.buffer, bios_dsk->drqp.buffer, bios_dsk->drqp.trsfbytes / 2);
604
high_bits_restore(ahci);
606
return ahci->aCmdHdr[1] == 0 ? 4 : 0;
607
// return 0; //@todo!!
610
static void ahci_port_detect_device(ahci_t __far *ahci, uint8_t u8Port)
613
bio_dsk_t __far *bios_dsk;
615
ahci_port_init(ahci, u8Port);
617
bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;
877
619
/* Reset connection. */
878
VBOXAHCI_PORT_WRITE_REG(u16IoBase, u8Port, AHCI_REG_PORT_SCTL, 0x01L);
620
VBOXAHCI_PORT_WRITE_REG(ahci->iobase, u8Port, AHCI_REG_PORT_SCTL, 0x01);
880
622
* According to the spec we should wait at least 1msec until the reset
881
623
* is cleared but this is a virtual controller so we don't have to.
883
VBOXAHCI_PORT_WRITE_REG(u16IoBase, u8Port, AHCI_REG_PORT_SCTL, 0x00L);
625
VBOXAHCI_PORT_WRITE_REG(ahci->iobase, u8Port, AHCI_REG_PORT_SCTL, 0);
885
627
/* Check if there is a device on the port. */
886
VBOXAHCI_PORT_READ_REG(u16IoBase, u8Port, AHCI_REG_PORT_SSTS, val);
887
if (ahci_ctrl_extract_bits(val, 0xfL, 0) == 0x3L)
628
VBOXAHCI_PORT_READ_REG(ahci->iobase, u8Port, AHCI_REG_PORT_SSTS, val);
629
if (ahci_ctrl_extract_bits(val, 0xfL, 0) == 0x3)
891
idxDevice = read_byte(SegAhci, &AhciData->cDevices);
892
VBOXAHCI_DEBUG("AHCI: Device detected on port %d\n", u8Port);
894
if (idxDevice < AHCI_MAX_STORAGE_DEVICES)
631
uint8_t abBuffer[0x0200];
632
uint8_t hdcount, devcount_ahci, hd_index;
636
devcount_ahci = bios_dsk->ahci_devcnt;
638
DBG_AHCI("AHCI: Device detected on port %d\n", u8Port);
640
//@todo: Merge common HD/CDROM detection code
641
if (devcount_ahci < BX_MAX_AHCI_DEVICES)
896
643
/* Device detected, enable FIS receive. */
897
ahci_ctrl_set_bits(u16IoBase, VBOXAHCI_PORT_REG(u8Port, AHCI_REG_PORT_CMD),
644
ahci_ctrl_set_bits(ahci->iobase, AHCI_PORT_REG(u8Port, AHCI_REG_PORT_CMD),
898
645
AHCI_REG_PORT_CMD_FRE);
900
647
/* Check signature to determine device type. */
901
VBOXAHCI_PORT_READ_REG(u16IoBase, u8Port, AHCI_REG_PORT_SIG, val);
648
VBOXAHCI_PORT_READ_REG(ahci->iobase, u8Port, AHCI_REG_PORT_SIG, val);
906
Bit8u abBuffer[0x0200];
908
Bit16u cCylinders, cHeads, cSectorsPerTrack;
910
Bit8u idxCmosChsBase;
652
uint16_t cylinders, heads, spt;
653
uint16_t lcylinders, lheads, lspt;
654
uint8_t idxCmosChsBase;
912
idxHdCurr = read_byte(SegAhci, &AhciData->cHardDisks);
913
VBOXAHCI_DEBUG("AHCI: Detected hard disk\n");
656
DBG_AHCI("AHCI: Detected hard disk\n");
915
658
/* Identify device. */
916
ahci_cmd_data(SegAhci, u16IoBase, ATA_CMD_IDENTIFY_DEVICE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, get_SS(), abBuffer, sizeof(abBuffer), 0);
918
write_byte(SegAhci, &AhciData->aDevices[idxDevice].port, u8Port);
920
fRemovable = (read_byte(get_SS(),abBuffer+0) & 0x80) ? 1 : 0;
921
cCylinders = read_word(get_SS(),abBuffer+(1*2)); // word 1
922
cHeads = read_word(get_SS(),abBuffer+(3*2)); // word 3
923
cSectorsPerTrack = read_word(get_SS(),abBuffer+(6*2)); // word 6
924
cSectors = read_dword(get_SS(),abBuffer+(60*2)); // word 60 and word 61
659
bios_dsk->drqp.lba = 0;
660
bios_dsk->drqp.buffer = &abBuffer;
661
bios_dsk->drqp.nsect = 1;
662
bios_dsk->drqp.sect_sz = 512;
663
ahci_cmd_data(bios_dsk, ATA_CMD_IDENTIFY_DEVICE);
665
/* Calculate index into the generic device table. */
666
hd_index = devcount_ahci + BX_MAX_ATA_DEVICES + BX_MAX_SCSI_DEVICES;
668
removable = *(abBuffer+0) & 0x80 ? 1 : 0;
669
cylinders = *(uint16_t *)(abBuffer+(1*2)); // word 1
670
heads = *(uint16_t *)(abBuffer+(3*2)); // word 3
671
spt = *(uint16_t *)(abBuffer+(6*2)); // word 6
672
sectors = *(uint32_t *)(abBuffer+(60*2)); // word 60 and word 61
926
674
/** @todo update sectors to be a 64 bit number (also lba...). */
927
if (cSectors == 268435455)
928
cSectors = read_dword(get_SS(),abBuffer+(100*2)); // words 100 to 103 (someday)
930
VBOXAHCI_DEBUG("AHCI: %ld sectors\n", cSectors);
932
write_byte(SegAhci, &AhciData->aDevices[idxDevice].device,ATA_DEVICE_HD);
933
write_byte(SegAhci, &AhciData->aDevices[idxDevice].removable, fRemovable);
934
write_word(SegAhci, &AhciData->aDevices[idxDevice].blksize, 512);
935
write_word(SegAhci, &AhciData->aDevices[idxDevice].pchs.heads, cHeads);
936
write_word(SegAhci, &AhciData->aDevices[idxDevice].pchs.cylinders, cCylinders);
937
write_word(SegAhci, &AhciData->aDevices[idxDevice].pchs.spt, cSectorsPerTrack);
938
write_dword(SegAhci, &AhciData->aDevices[idxDevice].cSectors, cSectors);
675
if (sectors == 0x0FFFFFFF) /* For disks bigger than ~128GB */
676
sectors = *(uint32_t *)(abBuffer+(100*2)); // words 100 to 103 (someday)
678
DBG_AHCI("AHCI: %ld sectors\n", sectors);
680
bios_dsk->ahcidev[devcount_ahci].port = u8Port;
681
bios_dsk->devices[hd_index].type = DSK_TYPE_AHCI;
682
bios_dsk->devices[hd_index].device = DSK_DEVICE_HD;
683
bios_dsk->devices[hd_index].removable = removable;
684
bios_dsk->devices[hd_index].lock = 0;
685
bios_dsk->devices[hd_index].blksize = 512;
686
bios_dsk->devices[hd_index].translation = GEO_TRANSLATION_LBA;
687
bios_dsk->devices[hd_index].sectors = sectors;
689
bios_dsk->devices[hd_index].pchs.heads = heads;
690
bios_dsk->devices[hd_index].pchs.cylinders = cylinders;
691
bios_dsk->devices[hd_index].pchs.spt = spt;
940
693
/* Get logical CHS geometry. */
694
switch (devcount_ahci)
944
697
idxCmosChsBase = 0x40;
956
709
idxCmosChsBase = 0;
958
if (idxCmosChsBase != 0)
711
if (idxCmosChsBase && inb_cmos(idxCmosChsBase+7))
960
cCylinders = inb_cmos(idxCmosChsBase) + (inb_cmos(idxCmosChsBase+1) << 8);
961
cHeads = inb_cmos(idxCmosChsBase+2);
962
cSectorsPerTrack = inb_cmos(idxCmosChsBase+7);
713
lcylinders = inb_cmos(idxCmosChsBase + 0) + (inb_cmos(idxCmosChsBase + 1) << 8);
714
lheads = inb_cmos(idxCmosChsBase + 2);
715
lspt = inb_cmos(idxCmosChsBase + 7);
968
cSectorsPerTrack = 0;
719
//@todo: What should we really do if logical geometry isn't in the CMOS?
720
lcylinders = cylinders;
970
write_word(SegAhci, &AhciData->aDevices[idxDevice].lchs.heads, cHeads);
971
write_word(SegAhci, &AhciData->aDevices[idxDevice].lchs.cylinders, cCylinders);
972
write_word(SegAhci, &AhciData->aDevices[idxDevice].lchs.spt, cSectorsPerTrack);
974
write_byte(SegAhci, &AhciData->aHdIdMap[idxHdCurr], idxDevice);
976
write_byte(SegAhci, &AhciData->cHardDisks, idxHdCurr);
724
BX_INFO("AHCI %d-P#%d: PCHS=%u/%d/%d LCHS=%u/%u/%u %ld sectors\n", devcount_ahci,
725
u8Port, cylinders, heads, spt, lcylinders, lheads, lspt, sectors);
727
bios_dsk->devices[hd_index].lchs.heads = lheads;
728
bios_dsk->devices[hd_index].lchs.cylinders = lcylinders;
729
bios_dsk->devices[hd_index].lchs.spt = lspt;
731
/* Store the ID of the disk in the BIOS hdidmap. */
732
hdcount = bios_dsk->hdcount;
733
bios_dsk->hdidmap[hdcount] = devcount_ahci + BX_MAX_ATA_DEVICES + BX_MAX_SCSI_DEVICES;
735
bios_dsk->hdcount = hdcount;
978
737
/* Update hdcount in the BDA. */
979
cHardDisksOld = read_byte(0x40, 0x75);
981
write_byte(0x40, 0x75, cHardDisksOld);
738
hdcount = read_byte(0x40, 0x75);
740
write_byte(0x40, 0x75, hdcount);
983
742
else if (val == 0xeb140101)
985
VBOXAHCI_DEBUG("AHCI: Detected ATAPI device\n");
744
DBG_AHCI("AHCI: Detected ATAPI device\n");
746
/* Identify packet device. */
747
bios_dsk->drqp.lba = 0;
748
bios_dsk->drqp.buffer = &abBuffer;
749
bios_dsk->drqp.nsect = 1;
750
bios_dsk->drqp.sect_sz = 512;
751
ahci_cmd_data(bios_dsk, ATA_CMD_IDENTIFY_PACKET);
753
/* Calculate index into the generic device table. */
754
hd_index = devcount_ahci + BX_MAX_ATA_DEVICES + BX_MAX_SCSI_DEVICES;
756
removable = *(abBuffer+0) & 0x80 ? 1 : 0;
758
bios_dsk->ahcidev[devcount_ahci].port = u8Port;
759
bios_dsk->devices[hd_index].type = DSK_TYPE_AHCI;
760
bios_dsk->devices[hd_index].device = DSK_DEVICE_CDROM;
761
bios_dsk->devices[hd_index].removable = removable;
762
bios_dsk->devices[hd_index].blksize = 2048;
764
/* Store the ID of the device in the BIOS cdidmap. */
765
cdcount = bios_dsk->cdcount;
766
bios_dsk->cdidmap[cdcount] = devcount_ahci + BX_MAX_ATA_DEVICES + BX_MAX_SCSI_DEVICES;
768
bios_dsk->cdcount = cdcount;
988
VBOXAHCI_DEBUG("AHCI: Unknown device ignoring\n");
771
DBG_AHCI("AHCI: Ignoring unknown device\n");
991
write_byte(SegAhci, &AhciData->cDevices, idxDevice);
774
bios_dsk->ahci_devcnt = devcount_ahci;
994
VBOXAHCI_DEBUG("AHCI: Reached maximum device count, skipping\n");
998
#define SET_DISK_RET_STATUS(status) write_byte(0x0040, 0x0074, status)
1003
static void ahci_int13(RET, ES, DS, DI, SI, BP, SP, BX, DX, CX, AX, IPIRET, CSIRET, FLAGSIRET, IP, CS, FLAGS)
1004
Bit16u RET, ES, DS, AX, CX, DX, BX, SP, BP, SI, DI, IPIRET, CSIRET, FLAGSIRET, IP, CS, FLAGS;
1007
Bit16u SegAhci, u16IoBase;
1009
Bit8u cHardDisksOld;
1013
Bit16u cylinder, head, sector;
1014
Bit16u segment, offset;
1015
Bit16u npc, nph, npspt, nlc, nlh, nlspt;
1019
VBOXAHCI_INT13_DEBUG("AHCI: ahci_int13 AX=%x CX=%x DX=%x BX=%x SP=%x BP=%x SI=%x DI=%x IP=%x CS=%x FLAGS=%x\n",
1020
AX, CX, DX, BX, SP, BP, SI, DI, IP, CS, FLAGS);
1022
ebda_seg = read_word(0x0040, 0x000E);
1023
SegAhci = read_word(ebda_seg, &EbdaData->SegAhci);
1024
u16IoBase = read_word(SegAhci, &AhciData->iobase);
1025
VBOXAHCI_INT13_DEBUG("AHCI: ahci_int13: SegAhci=%x u16IoBase=%x\n", SegAhci, u16IoBase);
1027
cHardDisksOld = read_byte(SegAhci, &AhciData->cHardDisksOld);
1029
/* Check if the device is controlled by us first. */
1030
if ( (GET_DL() < 0x80)
1031
|| (GET_DL() < 0x80 + cHardDisksOld)
1032
|| ((GET_DL() & 0xe0) != 0x80) /* No CD-ROM drives supported for now */)
1034
VBOXAHCI_INT13_DEBUG("AHCI: ahci_int13 device not controlled by us, forwarding to old handler (%d)\n", cHardDisksOld);
1035
/* Fill the iret frame to jump to the old handler. */
1036
IPIRET = read_word(SegAhci, &AhciData->pfnInt13Old);
1043
idxDevice = read_byte(SegAhci, &AhciData->aHdIdMap[GET_DL()-0x80-cHardDisksOld]);
1045
if (idxDevice >= AHCI_MAX_STORAGE_DEVICES)
1047
VBOXAHCI_INT13_DEBUG("AHCI: ahci_int13: function %02x, unmapped device for ELDL=%02x\n", GET_AH(), GET_DL());
1048
goto ahci_int13_fail;
1051
u8Port = read_byte(SegAhci, &AhciData->aDevices[idxDevice].port);
1055
case 0x00: /* disk controller reset */
1057
/** @todo: not really important I think. */
1058
goto ahci_int13_success;
1061
case 0x01: /* read disk status */
1063
status = read_byte(0x0040, 0x0074);
1065
SET_DISK_RET_STATUS(0);
1066
/* set CF if error status read */
1068
goto ahci_int13_fail_nostatus;
1070
goto ahci_int13_success_noah;
1073
case 0x02: // read disk sectors
1074
case 0x03: // write disk sectors
1075
case 0x04: // verify disk sectors
1078
cylinder = GET_CH();
1079
cylinder |= ( ((Bit16u) GET_CL()) << 2) & 0x300;
1080
sector = (GET_CL() & 0x3f);
1086
if ( (count > 128) || (count == 0) )
1088
BX_INFO("int13_harddisk: function %02x, count out of range!\n",GET_AH());
1089
goto ahci_int13_fail;
1092
nlc = read_word(SegAhci, &AhciData->aDevices[idxDevice].lchs.cylinders);
1093
nlh = read_word(SegAhci, &AhciData->aDevices[idxDevice].lchs.heads);
1094
nlspt = read_word(SegAhci, &AhciData->aDevices[idxDevice].lchs.spt);
1096
// sanity check on cyl heads, sec
1097
if( (cylinder >= nlc) || (head >= nlh) || (sector > nlspt ))
1099
BX_INFO("ahci_int13: function %02x, disk %02x, parameters out of range %04x/%04x/%04x!\n", GET_AH(), GET_DL(), cylinder, head, sector);
1100
goto ahci_int13_fail;
1104
if ( GET_AH() == 0x04 )
1105
goto ahci_int13_success;
1107
lba = ((((Bit32u)cylinder * (Bit32u)nlh) + (Bit32u)head) * (Bit32u)nlspt) + (Bit32u)sector - 1;
1110
if ( GET_AH() == 0x02 )
1111
ahci_cmd_data_in(SegAhci, u16IoBase, u8Port, AHCI_CMD_READ_DMA_EXT, lba, count, segment, offset);
1113
ahci_cmd_data_out(SegAhci, u16IoBase, u8Port, AHCI_CMD_WRITE_DMA_EXT, lba, count, segment, offset);
1115
// Set nb of sector transferred
1116
SET_AL(read_word(ebda_seg, &EbdaData->ata.trsfsectors));
1120
BX_INFO("int13_harddisk: function %02x, error %02x !\n",GET_AH(),status);
1122
goto ahci_int13_fail_noah;
1125
goto ahci_int13_success;
1128
case 0x05: /* format disk track */
1129
BX_INFO("format disk track called\n");
1130
goto ahci_int13_success;
1132
case 0x08: /* read disk drive parameters */
1134
// Get logical geometry from table
1135
nlc = read_word(SegAhci, &AhciData->aDevices[idxDevice].lchs.cylinders);
1136
nlh = read_word(SegAhci, &AhciData->aDevices[idxDevice].lchs.heads);
1137
nlspt = read_word(SegAhci, &AhciData->aDevices[idxDevice].lchs.spt);
1139
count = read_byte(SegAhci, &AhciData->cHardDisks); /** @todo correct? */
1140
/* Maximum cylinder number is just one less than the number of cylinders. */
1141
nlc = nlc - 1; /* 0 based , last sector not used */
1144
SET_CL(((nlc >> 2) & 0xc0) | (nlspt & 0x3f));
1146
SET_DL(count); /* FIXME returns 0, 1, or n hard drives */
1147
// FIXME should set ES & DI
1148
goto ahci_int13_success;
1151
case 0x10: /* check drive ready */
1154
goto ahci_int13_success;
1157
case 0x15: /* read disk drive size */
1159
// Get physical geometry from table
1160
npc = read_word(SegAhci, &AhciData->aDevices[idxDevice].pchs.cylinders);
1161
nph = read_word(SegAhci, &AhciData->aDevices[idxDevice].pchs.heads);
1162
npspt = read_word(SegAhci, &AhciData->aDevices[idxDevice].pchs.spt);
1164
// Compute sector count seen by int13
1165
lba = (Bit32u)npc * (Bit32u)nph * (Bit32u)npspt;
1169
SET_AH(3); // hard disk accessible
1170
goto ahci_int13_success_noah;
1174
case 0x41: // IBM/MS installation check
1176
BX=0xaa55; // install check
1177
SET_AH(0x30); // EDD 3.0
1178
CX=0x0007; // ext disk access and edd, removable supported
1179
goto ahci_int13_success_noah;
1182
case 0x42: // IBM/MS extended read
1183
case 0x43: // IBM/MS extended write
1184
case 0x44: // IBM/MS verify
1185
case 0x47: // IBM/MS extended seek
1187
count=read_word(DS, SI+(Bit16u)&Int13Ext->count);
1188
segment=read_word(DS, SI+(Bit16u)&Int13Ext->segment);
1189
offset=read_word(DS, SI+(Bit16u)&Int13Ext->offset);
1191
// Can't use 64 bits lba
1192
lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba2);
1195
BX_PANIC("int13_harddisk: function %02x. Can't use 64bits lba\n",GET_AH());
1196
goto ahci_int13_fail;
1199
// Get 32 bits lba and check
1200
lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba1);
1202
if (lba >= read_word(SegAhci, &AhciData->aDevices[idxDevice].cSectors) )
1204
BX_INFO("int13_harddisk: function %02x. LBA out of range\n",GET_AH());
1205
goto ahci_int13_fail;
1208
// If verify or seek
1209
if (( GET_AH() == 0x44 ) || ( GET_AH() == 0x47 ))
1210
goto ahci_int13_success;
1212
// Execute the command
1213
if ( GET_AH() == 0x42 )
1215
if (lba + count >= 268435456)
1216
status=ata_cmd_data_in(device, ATA_CMD_READ_SECTORS_EXT, count, 0, 0, 0, lba, segment, offset);
1219
write_word(ebda_seg,&EbdaData->ata.devices[device].blksize,count * 0x200);
1220
status=ata_cmd_data_in(device, ATA_CMD_READ_MULTIPLE, count, 0, 0, 0, lba, segment, offset);
1221
write_word(ebda_seg,&EbdaData->ata.devices[device].blksize,0x200);
1226
if (lba + count >= 268435456)
1227
status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS_EXT, count, 0, 0, 0, lba, segment, offset);
1229
status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, 0, 0, 0, lba, segment, offset);
1232
count=read_word(ebda_seg, &EbdaData->ata.trsfsectors);
1233
write_word(DS, SI+(Bit16u)&Int13Ext->count, count);
1237
BX_INFO("int13_harddisk: function %02x, error %02x !\n",GET_AH(),status);
1239
goto ahci_int13_fail_noah;
1241
goto ahci_int13_success;
1244
case 0x45: // IBM/MS lock/unlock drive
1245
case 0x49: // IBM/MS extended media change
1246
goto ahci_int13_success; // Always success for HD
1248
case 0x46: // IBM/MS eject media
1249
SET_AH(0xb2); // Volume Not Removable
1250
goto ahci_int13_fail_noah; // Always fail for HD
1253
case 0x48: // IBM/MS get drive parameters
1254
size=read_word(DS,SI+(Bit16u)&Int13DPT->size);
1256
// Buffer is too small
1258
goto ahci_int13_fail;
1265
npc = read_word(SegAhci, &AhciData->aDevices[idxDevice].pchs.cylinders);
1266
nph = read_word(SegAhci, &AhciData->aDevices[idxDevice].pchs.heads);
1267
npspt = read_word(SegAhci, &AhciData->aDevices[idxDevice].pchs.spt);
1268
lba = read_dword(SegAhci, &AhciData->aDevices[idxDevice].cSectors);
1269
blksize = read_word(SegAhci, &AhciData->aDevices[idxDevice].blksize);
1271
write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1a);
1272
write_word(DS, SI+(Bit16u)&Int13DPT->infos, 0x02); // geometry is valid
1273
write_dword(DS, SI+(Bit16u)&Int13DPT->cylinders, (Bit32u)npc);
1274
write_dword(DS, SI+(Bit16u)&Int13DPT->heads, (Bit32u)nph);
1275
write_dword(DS, SI+(Bit16u)&Int13DPT->spt, (Bit32u)npspt);
1276
write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count1, lba); // FIXME should be Bit64
1277
write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, 0L);
1278
write_word(DS, SI+(Bit16u)&Int13DPT->blksize, blksize);
1281
#if 0 /* Disable EDD 2.X and 3.x for now, don't know if it is required by any OS loader yet */
1285
Bit8u channel, dev, irq, mode, checksum, i, translation;
1286
Bit16u iobase1, iobase2, options;
1288
translation = ATA_TRANSLATION_LBA;
1290
write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1e);
1292
write_word(DS, SI+(Bit16u)&Int13DPT->dpte_segment, ebda_seg);
1293
write_word(DS, SI+(Bit16u)&Int13DPT->dpte_offset, &EbdaData->ata.dpte);
1296
channel = device / 2;
1297
iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1);
1298
iobase2 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase2);
1299
irq = read_byte(ebda_seg, &EbdaData->ata.channels[channel].irq);
1300
mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode);
1301
translation = read_byte(ebda_seg, &EbdaData->ata.devices[device].translation);
1303
options = (translation==ATA_TRANSLATION_NONE?0:1<<3); // chs translation
1304
options |= (1<<4); // lba translation
1305
options |= (mode==ATA_MODE_PIO32?1:0<<7);
1306
options |= (translation==ATA_TRANSLATION_LBA?1:0<<9);
1307
options |= (translation==ATA_TRANSLATION_RECHS?3:0<<9);
1309
write_word(ebda_seg, &EbdaData->ata.dpte.iobase1, iobase1);
1310
write_word(ebda_seg, &EbdaData->ata.dpte.iobase2, iobase2);
1311
//write_byte(ebda_seg, &EbdaData->ata.dpte.prefix, (0xe | /*(device % 2))<<4*/ );
1312
write_byte(ebda_seg, &EbdaData->ata.dpte.unused, 0xcb );
1313
write_byte(ebda_seg, &EbdaData->ata.dpte.irq, irq );
1314
write_byte(ebda_seg, &EbdaData->ata.dpte.blkcount, 1 );
1315
write_byte(ebda_seg, &EbdaData->ata.dpte.dma, 0 );
1316
write_byte(ebda_seg, &EbdaData->ata.dpte.pio, 0 );
1317
write_word(ebda_seg, &EbdaData->ata.dpte.options, options);
1318
write_word(ebda_seg, &EbdaData->ata.dpte.reserved, 0);
1319
write_byte(ebda_seg, &EbdaData->ata.dpte.revision, 0x11);
1322
for (i=0; i<15; i++)
1323
checksum+=read_byte(ebda_seg, (&EbdaData->ata.dpte) + i);
1325
checksum = -checksum;
1326
write_byte(ebda_seg, &EbdaData->ata.dpte.checksum, checksum);
1332
Bit8u channel, iface, checksum, i;
1335
channel = device / 2;
1336
iface = read_byte(ebda_seg, &EbdaData->ata.channels[channel].iface);
1337
iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1);
1339
write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x42);
1340
write_word(DS, SI+(Bit16u)&Int13DPT->key, 0xbedd);
1341
write_byte(DS, SI+(Bit16u)&Int13DPT->dpi_length, 0x24);
1342
write_byte(DS, SI+(Bit16u)&Int13DPT->reserved1, 0);
1343
write_word(DS, SI+(Bit16u)&Int13DPT->reserved2, 0);
1345
if (iface==ATA_IFACE_ISA) {
1346
write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[0], 'I');
1347
write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[1], 'S');
1348
write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[2], 'A');
1349
write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[3], 0);
1354
write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[0], 'A');
1355
write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[1], 'T');
1356
write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[2], 'A');
1357
write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[3], 0);
1359
if (iface==ATA_IFACE_ISA) {
1360
write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[0], iobase1);
1361
write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[2], 0);
1362
write_dword(DS, SI+(Bit16u)&Int13DPT->iface_path[4], 0L);
1367
//write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[0], device%2);
1368
write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[1], 0);
1369
write_word(DS, SI+(Bit16u)&Int13DPT->device_path[2], 0);
1370
write_dword(DS, SI+(Bit16u)&Int13DPT->device_path[4], 0L);
1373
for (i=30; i<64; i++) checksum+=read_byte(DS, SI + i);
1374
checksum = -checksum;
1375
write_byte(DS, SI+(Bit16u)&Int13DPT->checksum, checksum);
1378
goto ahci_int13_success;
1380
case 0x4e: // // IBM/MS set hardware configuration
1381
// DMA, prefetch, PIO maximum not supported
1388
goto ahci_int13_success;
1391
goto ahci_int13_fail;
1395
case 0x09: /* initialize drive parameters */
1396
case 0x0c: /* seek to specified cylinder */
1397
case 0x0d: /* alternate disk reset */
1398
case 0x11: /* recalibrate */
1399
case 0x14: /* controller internal diagnostic */
1400
BX_INFO("ahci_int13: function %02xh unimplemented, returns success\n", GET_AH());
1401
goto ahci_int13_success;
1404
case 0x0a: /* read disk sectors with ECC */
1405
case 0x0b: /* write disk sectors with ECC */
1406
case 0x18: // set media type for format
1407
case 0x50: // IBM/MS send packet command
1409
BX_INFO("ahci_int13: function %02xh unsupported, returns fail\n", GET_AH());
1410
goto ahci_int13_fail;
1415
SET_AH(0x01); // defaults to invalid function in AH or invalid parameter
1416
ahci_int13_fail_noah:
1417
SET_DISK_RET_STATUS(GET_AH());
1418
ahci_int13_fail_nostatus:
1419
SET_CF(); // error occurred
1423
SET_AH(0x00); // no error
1424
ahci_int13_success_noah:
1425
SET_DISK_RET_STATUS(0x00);
1426
CLEAR_CF(); // no error
1430
#undef SET_DISK_RET_STATUS
1433
* Assembler part of the int 13 handler.
1437
; Allocate space for an iret frame we have to use
1438
; to call the old int 13 handler
1443
pusha ; Save 16bit values as arguments
1446
mov ax, #0 ; Allocate room for the return value on the stack
1452
cmp ax, #0x0 ; Check if the handler processed the request
1454
popa ; Restore the caller environment
1455
iret ; Call the old interrupt handler. Will not come back here.
1459
add sp, #6 ; Destroy the iret frame
1464
* Install the in13 interrupt handler
1465
* preserving the previous one.
1467
static void ahci_install_int_handler(SegAhci)
1473
VBOXAHCI_DEBUG("AHCI: Hooking int 13h vector\n");
1475
/* Read the old interrupt handler. */
1476
pfnInt13Old = read_word(0x0000, 0x0013*4);
1477
write_word(SegAhci, &AhciData->pfnInt13Old, pfnInt13Old);
1486
SET_INT_VECTOR(0x13, #0xF000, #ahci_int13_handler)
1494
* Allocates 1K from the base memory.
1496
static Bit16u ahci_mem_alloc()
1501
cBaseMem1K = read_byte(0x00, 0x0413);
1503
VBOXAHCI_DEBUG("AHCI: %x K of base memory available\n", cBaseMem1K);
1505
if (cBaseMem1K == 0)
777
DBG_AHCI("AHCI: Reached maximum device count, skipping\n");
782
* Allocates 1K of conventional memory.
784
static uint16_t ahci_mem_alloc(void)
786
uint16_t base_mem_kb;
789
base_mem_kb = read_word(0x00, 0x0413);
791
DBG_AHCI("AHCI: %dK of base mem\n", base_mem_kb);
793
if (base_mem_kb == 0)
1508
cBaseMem1K--; /* Allocate one block. */
1509
SegStart = (Bit16u)(((Bit32u)cBaseMem1K * 1024) >> 4); /* Calculate start segment. */
1511
write_byte(0x00, 0x0413, cBaseMem1K);
796
base_mem_kb--; /* Allocate one block. */
797
ahci_seg = (((uint32_t)base_mem_kb * 1024) >> 4); /* Calculate start segment. */
799
write_word(0x00, 0x0413, base_mem_kb);
1517
* Initializes the SATA controller and detects attached devices.
805
* Initializes the AHCI HBA and detects attached devices.
1519
static int ahci_ctrl_init(u16IoBase)
807
static int ahci_hba_init(uint16_t io_base)
813
bio_dsk_t __far *bios_dsk;
1527
817
ebda_seg = read_word(0x0040, 0x000E);
818
bios_dsk = ebda_seg :> &EbdaData->bdisk;
1529
VBOXAHCI_READ_REG(u16IoBase, AHCI_REG_VS, val);
1530
VBOXAHCI_DEBUG("AHCI: Controller has version: 0x%x (major) 0x%x (minor)\n",
1531
ahci_ctrl_extract_bits(val, 0xffff0000, 16),
1532
ahci_ctrl_extract_bits(val, 0x0000ffff, 0));
820
AHCI_READ_REG(io_base, AHCI_REG_VS, val);
821
DBG_AHCI("AHCI: Controller version: 0x%x (major) 0x%x (minor)\n",
822
ahci_ctrl_extract_bits(val, 0xffff0000, 16),
823
ahci_ctrl_extract_bits(val, 0x0000ffff, 0));
1534
825
/* Allocate 1K of base memory. */
1535
SegAhci = ahci_mem_alloc();
826
ahci_seg = ahci_mem_alloc();
1538
VBOXAHCI_DEBUG("AHCI: Could not allocate 1K of memory, can't boot from controller\n");
829
DBG_AHCI("AHCI: Could not allocate 1K of memory, can't boot from controller\n");
1542
write_word(ebda_seg, &EbdaData->SegAhci, SegAhci);
1543
write_byte(SegAhci, &AhciData->port, 0xff);
1544
write_word(SegAhci, &AhciData->iobase, u16IoBase);
1545
write_byte(SegAhci, &AhciData->cHardDisksOld, read_byte(0x40, 0x75));
832
DBG_AHCI("AHCI: ahci_seg=%04x, size=%04x, pointer at EBDA:%04x (EBDA size=%04x)\n",
833
ahci_seg, sizeof(ahci_t), (uint16_t)&EbdaData->bdisk.ahci_seg, sizeof(ebda_data_t));
835
bios_dsk->ahci_seg = ahci_seg;
836
bios_dsk->ahci_devcnt = 0;
838
ahci = ahci_seg :> 0;
839
ahci->cur_port = 0xff;
840
ahci->iobase = io_base;
842
/* Physical address of memory used for throwing away ATAPI data when reading 512-byte
843
* blocks from 2048-byte CD sectors.
845
ahci->sink_buf_phys = 0xCC000; //@todo: find some better place!
1547
847
/* Reset the controller. */
1548
ahci_ctrl_set_bits(u16IoBase, AHCI_REG_GHC, AHCI_GHC_HR);
848
ahci_ctrl_set_bits(io_base, AHCI_REG_GHC, AHCI_GHC_HR);
1551
VBOXAHCI_READ_REG(u16IoBase, AHCI_REG_GHC, val);
851
AHCI_READ_REG(io_base, AHCI_REG_GHC, val);
1552
852
} while (val & AHCI_GHC_HR != 0);
1554
VBOXAHCI_READ_REG(u16IoBase, AHCI_REG_CAP, val);
854
AHCI_READ_REG(io_base, AHCI_REG_CAP, val);
1555
855
cPorts = ahci_ctrl_extract_bits(val, 0x1f, 0) + 1; /* Extract number of ports.*/
1557
VBOXAHCI_DEBUG("AHCI: Controller has %u ports\n", cPorts);
857
DBG_AHCI("AHCI: HBA has %u ports\n", cPorts);
1559
859
/* Go through the ports. */
1563
if (ahci_ctrl_is_bit_set(u16IoBase, AHCI_REG_PI, RT_BIT_32(i)) != 0)
863
if (ahci_ctrl_is_bit_set(io_base, AHCI_REG_PI, RT_BIT_32(i)) != 0)
1565
VBOXAHCI_DEBUG("AHCI: Port %u is present\n", i);
1566
ahci_port_detect_device(SegAhci, u16IoBase, i);
865
DBG_AHCI("AHCI: Port %u is present\n", i);
866
ahci_port_detect_device(ahci_seg :> 0, i);
1568
868
if (cPorts == 0)