fix: PACKET command hangs in Virtualbox when try to write readonly drive.
fix: possible null pointer dereference in pcache_commit_all.
chore: attach cdrom into QEMU's IDE bus.
-d cpu_reset \
-d trace:ide_dma_cb \
-drive id=disk,file="machine/disk0.vdi",if=none \
+ -drive id=cdrom,file="$(BUILD_DIR)/$(OS_ISO)",readonly=on,if=none,format=raw \
-device ahci,id=ahci \
-device ide-hd,drive=disk,bus=ahci.0 \
+ -device ide-cd,drive=cdrom,bus=ahci.1 \
-monitor telnet::$(QEMU_MON_PORT),server,nowait &
\ No newline at end of file
port_regs[HBA_RPxCMD] |= HBA_PxCMD_ST;
if (!ahci_init_device(port)) {
- kprintf(KERROR "fail to init device");
+ kprintf(KERROR "init fail: 0x%x@p%d\n", port->regs[HBA_RPxSIG], i);
+ continue;
}
block_mount_disk(port->device);
* SATA AHCI HBA Spec, Section 5.3.7
* SCSI Command Reference Manual, Section 3.26
*/
- struct scsi_cdb16* cdb16 = (struct scsi_cdb16*)cmd_table->atapi_cmd;
sata_create_fis(cmd_fis, ATA_PACKET, 512 << 8, 0);
- scsi_create_packet16(cdb16, SCSI_READ_CAPACITY_16, 0, 512);
- cdb16->misc1 = 0x10; // service action
+ // for dev use 12 bytes cdb, READ_CAPACITY must use the 10 bytes variation.
+ if (port->device->cbd_size == 12) {
+ struct scsi_cdb12* cdb12 = (struct scsi_cdb12*)cmd_table->atapi_cmd;
+ // ugly tricks to construct 10 byte cdb from 12 byte cdb
+ scsi_create_packet12(cdb12, SCSI_READ_CAPACITY_10, 0, 512 << 8);
+ } else {
+ struct scsi_cdb16* cdb16 = (struct scsi_cdb16*)cmd_table->atapi_cmd;
+ scsi_create_packet16(cdb16, SCSI_READ_CAPACITY_16, 0, 512);
+ cdb16->misc1 = 0x10; // service action
+ }
+
cmd_header->transferred_size = 0;
cmd_header->options |= HBA_CMDH_ATAPI;
sata_read_error(struct hba_port* port)
{
uint32_t tfd = port->regs[HBA_RPxTFD];
- port->device->last_error = (tfd >> 8) & 0xff;
- port->device->last_status = tfd & 0xff;
+ port->device->last_result.sense_key = (tfd & 0xf000) >> 12;
+ port->device->last_result.error = (tfd & 0x0f00) >> 8;
+ port->device->last_result.status = tfd & 0x00ff;
}
int
void
scsi_parse_capacity(struct hba_device* device, uint32_t* parameter)
{
- device->max_lba = SCSI_FLIP(*(parameter + 1));
- device->block_size = SCSI_FLIP(*(parameter + 2));
+ if (device->cbd_size == SCSI_CDB16) {
+ device->max_lba =
+ SCSI_FLIP(*(parameter + 1)) | (SCSI_FLIP(*parameter) << 32);
+ device->block_size = SCSI_FLIP(*(parameter + 2));
+ } else {
+ // for READ_CAPACITY(10)
+ device->max_lba = SCSI_FLIP(*(parameter));
+ device->block_size = SCSI_FLIP(*(parameter + 1));
+ }
}
int
while (retries < MAX_RETRY) {
port->regs[HBA_RPxCI] = bitmask;
- wait_until(!(port->regs[HBA_RPxCI] & bitmask));
+ wait_until_expire(!(port->regs[HBA_RPxCI] & bitmask), 1000000);
if ((port->regs[HBA_RPxTFD] & HBA_PxTFD_ERR)) {
// 有错误
#define HBA_PxINTR_DMA (1 << 2)
#define HBA_PxINTR_DHR (1)
#define HBA_PxINTR_DPS (1 << 5)
+#define HBA_PxINTR_TFEE (1 << 30)
+#define HBA_PxINTR_IFE (1 << 27)
#define HBA_PxTFD_ERR (1)
#define HBA_PxTFD_BSY (1 << 7)
#define HBA_PxTFD_DRQ (1 << 3)
uint32_t block_size;
uint64_t wwn;
uint8_t cbd_size;
- uint8_t last_error;
- uint8_t last_status;
+ struct
+ {
+ uint8_t sense_key;
+ uint8_t error;
+ uint8_t status;
+ uint8_t reserve;
+ } last_result;
uint32_t alignment_offset;
uint32_t block_per_sec;
uint32_t capabilities;
#define SCSI_WRITE_BLOCKS_16 0x8a
#define SCSI_WRITE_BLOCKS_12 0xaa
+#define SCSI_CDB16 16
+#define SCSI_CDB12 12
+
struct scsi_cdb12
{
uint8_t opcode;
void
pcache_commit_all(struct v_inode* inode)
{
+ if (!inode->pg_cache) {
+ return;
+ }
+
struct pcache* cache = inode->pg_cache;
struct pcache_pg *pos, *n;
@sleep 1
run: $(BUILD_DIR)/$(OS_ISO)
- @qemu-system-i386 -cdrom $(BUILD_DIR)/$(OS_ISO) $(QEMU_OPTIONS)
+ @qemu-system-i386 $(QEMU_OPTIONS)
@sleep 1
@telnet 127.0.0.1 $(QEMU_MON_PORT)
debug-qemu: all-debug
@i686-elf-objcopy --only-keep-debug $(BIN_DIR)/$(OS_BIN) $(BUILD_DIR)/kernel.dbg
- @qemu-system-i386 -cdrom $(BUILD_DIR)/$(OS_ISO) $(QEMU_OPTIONS)
+ @qemu-system-i386 $(QEMU_OPTIONS)
@sleep 1
@$(QEMU_MON_TERM) -- telnet 127.0.0.1 $(QEMU_MON_PORT)
@gdb -s $(BUILD_DIR)/kernel.dbg -ex "target remote localhost:1234"
debug-qemu-vscode: all-debug
@i686-elf-objcopy --only-keep-debug $(BIN_DIR)/$(OS_BIN) $(BUILD_DIR)/kernel.dbg
- @qemu-system-i386 -cdrom $(BUILD_DIR)/$(OS_ISO) $(QEMU_OPTIONS)
+ @qemu-system-i386 $(QEMU_OPTIONS)
@sleep 0.5
@telnet 127.0.0.1 $(QEMU_MON_PORT)