static int atapi_update_req_len(struct ide_internal * ide, struct ide_channel * channel, uint_t xfer_len) {
struct ide_drive * drive = get_selected_drive(channel);
- // PrintDebug("Updating request length (pre=%d)\n", drive->req_len);
+ //PrintDebug("\tUpdating request length (pre=%d)\n", drive->req_len);
if (drive->req_len == 0) {
PrintError("ATAPI Error: request of length 0\n");
}
// if the device can't return as much as the OS requested
+ // this is actually a decrement of the req_len by the amount requested by the OS
if (drive->req_len > xfer_len) {
drive->req_len = xfer_len;
}
- // PrintDebug("Updating request length (post=%d)\n", drive->req_len);
+ // PrintDebug("\tUpdating request length (post=%d)\n", drive->req_len);
return 0;
}
drive->irq_flags.c_d = 0;
channel->status.busy = 0;
- channel->status.data_req = 1;
channel->status.error = 0;
+ if (drive->transfer_length > 0) {
+ channel->status.data_req = 1;
+ }
+
ide_raise_irq(ide, channel);
}
static int atapi_read_chunk(struct ide_internal * ide, struct ide_channel * channel) {
struct ide_drive * drive = get_selected_drive(channel);
- int ret = drive->ops->read(drive->data_buf, drive->current_lba * ATAPI_BLOCK_SIZE, ATAPI_BLOCK_SIZE,
-drive->private_data);
+ int ret = drive->ops->read(drive->data_buf,
+ drive->current_lba * ATAPI_BLOCK_SIZE,
+ ATAPI_BLOCK_SIZE, drive->private_data);
if (ret == -1) {
PrintError("IDE: Error reading CD block (LBA=%p)\n", (void *)(addr_t)(drive->current_lba));
case 0x28: // read(10)
case 0xa8: // read(12)
- // Update lba address to point to next block
+ // Update lba address to point to next block
drive->current_lba++;
// read the next block
uint32_t lba = be_to_le_32(cmd->lba);
uint16_t xfer_len = be_to_le_16(cmd->xfer_len);
- PrintDebug("READ10: XferLen=%d\n", xfer_len);
+ PrintDebug("READ10: XferLen=%d ; LBA=%x \n", xfer_len, lba );
/* Check if cd is ready
* if not: atapi_cmd_error(... ATAPI_SEN_NOT_RDY, ASC_MEDIA_NOT_PRESENT)
return 0;
}
- if (lba + xfer_len > drive->ops->get_capacity(drive->private_data)) {
+ if ((lba + xfer_len) > (drive->ops->get_capacity(drive->private_data) / ATAPI_BLOCK_SIZE)) {
PrintError("IDE: xfer len exceeded capacity (lba=%d) (xfer_len=%d) (ReadEnd=%d) (capacity=%d)\n",
lba, xfer_len, lba + xfer_len,
(uint32_t)drive->ops->get_capacity(drive->private_data));
return 0;
}
- // PrintDebug("Reading %d blocks from LBA 0x%x\n", xfer_len, lba);
-
+ // PrintDebug("Reading %d blocks from LBA 0x%x\n", xfer_len, lba);
drive->current_lba = lba;
// Update the request length value in the cylinder registers
struct atapi_rd_capacity_resp * resp = (struct atapi_rd_capacity_resp *)(drive->data_buf);
uint32_t capacity = drive->ops->get_capacity(drive->private_data);
- resp->lba = le_to_be_32(capacity);
+ resp->lba = le_to_be_32((capacity / ATAPI_BLOCK_SIZE) - 1);
resp->block_len = le_to_be_32(ATAPI_BLOCK_SIZE);
atapi_setup_cmd_resp(ide, channel, sizeof(struct atapi_rd_capacity_resp));
xfer_len = alloc_len;
}
+ V3_Print("ATAPI Get config: xfer_len=%d\b", xfer_len);
+
atapi_setup_cmd_resp(ide, channel, xfer_len);
return 0;
err = (struct atapi_error_recovery *)(drive->data_buf +
sizeof(struct atapi_mode_sense_hdr));
+
memcpy(err, &(drive->cd_state.err_recovery), sizeof(struct atapi_error_recovery));
resp_len += sizeof(struct atapi_error_recovery);
+ PrintError("mode sense (error recovery) resp_len=%d\n", resp_len);
+
+
hdr->mode_data_len = le_to_be_16(resp_len - 2);
break;
}
case 0x2a: { // CDROM caps and mech. status
+
+ uint8_t * buf = drive->data_buf;
+
+
+
+ PrintError("mode sense (caps/mechs v2) resp_len=%d\n", resp_len);
+
+ *((uint16_t *)buf) = le_to_be_16(28 + 6);
+ buf[2] = 0x70;
+ buf[3] = 0;
+ buf[4] = 0;
+ buf[5] = 0;
+ buf[6] = 0;
+ buf[7] = 0;
+
+ buf[8] = 0x2a;
+ buf[9] = 0x12;
+ buf[10] = 0x00;
+ buf[11] = 0x00;
+
+ /* Claim PLAY_AUDIO capability (0x01) since some Linux
+ code checks for this to automount media. */
+ buf[12] = 0x71;
+ buf[13] = 3 << 5;
+ buf[14] = (1 << 0) | (1 << 3) | (1 << 5);
+
+ buf[6] |= 1 << 1;
+ buf[15] = 0x00;
+ *((uint16_t *)&(buf[16])) = le_to_be_16(706);
+ buf[18] = 0;
+ buf[19] = 2;
+ *((uint16_t *)&(buf[20])) = le_to_be_16(512);
+ *((uint16_t *)&(buf[22])) = le_to_be_16(706);
+ buf[24] = 0;
+ buf[25] = 0;
+ buf[26] = 0;
+ buf[27] = 0;
+
+ resp_len = 28;
+
+#if 0
struct atapi_cdrom_caps * caps = NULL;
caps = (struct atapi_cdrom_caps *)(drive->data_buf + sizeof(struct atapi_mode_sense_hdr));
+
+
memset(caps, 0, sizeof(struct atapi_cdrom_caps));
resp_len += sizeof(struct atapi_cdrom_caps);
hdr->mode_data_len = le_to_be_16(resp_len - 2);
+
+ PrintError("mode sense (caps/mechs v2) resp_len=%d\n", resp_len);
+
caps->page_code = 0x2a;
caps->page_len = 0x12;
caps->mode2_form1 = 1;
caps->lun_buf_size = le_to_be_16(512);
caps->obsolete2 = le_to_be_16(0x2c2);
+#endif
+
break;
}
case 0x0d:
// We do this after error checking, because its only valid if everything worked
- memset(hdr, 0, sizeof(struct atapi_mode_sense_hdr));
- hdr->media_type_code = 0x70;
+ // memset(hdr, 0, sizeof(struct atapi_mode_sense_hdr));
+ // hdr->media_type_code = 0x70;
PrintDebug("resp_len=%d\n", resp_len);
}
+
static int atapi_inquiry(struct ide_internal * ide, struct ide_channel * channel) {
struct ide_drive * drive = get_selected_drive(channel);
struct atapi_inquiry_cmd * inquiry_cmd = (struct atapi_inquiry_cmd *)(drive->data_buf);
}
+static int atapi_mech_status(struct ide_internal * ide, struct ide_channel * channel) {
+ struct ide_drive * drive = get_selected_drive(channel);
+ struct atapi_mech_status_cmd * status_cmd = (struct atapi_mech_status_cmd *)(drive->data_buf);
+ uint16_t alloc_len = be_to_le_16(status_cmd->alloc_len);
+ struct atapi_mech_status_resp * resp = (struct atapi_mech_status_resp *)(drive->data_buf);
+ int xfer_len = sizeof(struct atapi_mech_status_resp);
+
+ memset(resp, 0, sizeof(struct atapi_mech_status_resp));
+
+ resp->lba = le_to_be_32(1);
+ resp->slot_table_len = le_to_be_16(0);
+
+ if (alloc_len < xfer_len) {
+ xfer_len = alloc_len;
+ }
+
+ atapi_setup_cmd_resp(ide, channel, xfer_len);
+
+ return 0;
+}
+
+
static int atapi_cmd_is_data_op(uint8_t cmd) {
switch (cmd) {
case 0x28: // read (10)
*/
break;
case 0x03: // request sense
+ PrintError("IDE: Requesting Sense (0x3)\n");
atapi_req_sense(ide, channel);
break;
}
break;
+ case 0xbd: // mechanism status
+ if (atapi_mech_status(ide, channel) == -1) {
+ PrintError("IDE: error in ATAPI Mechanism status query (%x)\n", cmd);
+ return -1;
+ }
+ break;
+
+
case 0xa8: // read(12)
case 0x1b: // start/stop drive
- case 0xbd: // mechanism status
case 0xbe: // read cd
drive_id->dword_io = 1;
// enable DMA access
+ /* Disabled until command packet DMA is fixed */
drive_id->dma_enable = 1;
// enable LBA access
drive_id->rw_multiples = 0x80ff;
// words 64-70, 54-58 valid
- drive_id->field_valid = 0x0007; // DMA + pkg cmd valid
+ /* Disabled until command packet DMA is fixed */
+ drive_id->field_valid = 0x0007; // DMA + pkg cmd valid
// copied from CFA540A
- drive_id->buf[63] = 0x0103; // variable (DMA stuff)
- //drive_id->buf[63] = 0x0000; // variable (DMA stuff)
-
- // drive_id->buf[64] = 0x0001; // PIO
+ /* Disabled until command packet DMA is fixed */
+ drive_id->buf[63] = 0x0103; // variable (DMA stuff)
+
+
+ /* uncommented to disable dma(?) */
+ // drive_id->buf[64] = 0x0001; // PIO
+
+
drive_id->buf[65] = 0x00b4;
drive_id->buf[66] = 0x00b4;
drive_id->buf[67] = 0x012c;
// drive_id->buf[80] = 0x1e; // supports up to ATA/ATAPI-4
drive_id->major_rev_num = 0x0040; // supports up to ATA/ATAPI-6
+ /* Disabled until command packet DMA is fixed */
drive_id->dma_ultra = 0x2020; // Ultra_DMA_Mode_5_Selected | Ultra_DMA_Mode_5_Supported;
}