?? ide.c
字號:
ide_set_sector(s, sector_num); s->nsector -= n; if (dma_buf_rw(bm, 1) == 0) goto eot; } /* end of transfer ? */ if (s->nsector == 0) { s->status = READY_STAT | SEEK_STAT; ide_set_irq(s); eot: bm->status &= ~BM_STATUS_DMAING; bm->status |= BM_STATUS_INT; bm->dma_cb = NULL; bm->ide_if = NULL; bm->aiocb = NULL; return; } /* launch next transfer */ n = s->nsector; if (n > MAX_MULT_SECTORS) n = MAX_MULT_SECTORS; s->io_buffer_index = 0; s->io_buffer_size = n * 512;#ifdef DEBUG_AIO printf("aio_read: sector_num=%lld n=%d\n", sector_num, n);#endif bm->aiocb = bdrv_aio_read(s->bs, sector_num, s->io_buffer, n, ide_read_dma_cb, bm);}static void ide_sector_read_dma(IDEState *s){ s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT; s->io_buffer_index = 0; s->io_buffer_size = 0; ide_dma_start(s, ide_read_dma_cb);}static void ide_sector_write_timer_cb(void *opaque){ IDEState *s = opaque; ide_set_irq(s);}static void ide_sector_write(IDEState *s){ int64_t sector_num; int ret, n, n1; s->status = READY_STAT | SEEK_STAT; sector_num = ide_get_sector(s);#if defined(DEBUG_IDE) printf("write sector=%Ld\n", sector_num);#endif n = s->nsector; if (n > s->req_nb_sectors) n = s->req_nb_sectors; ret = bdrv_write(s->bs, sector_num, s->io_buffer, n); s->nsector -= n; if (s->nsector == 0) { /* no more sectors to write */ ide_transfer_stop(s); } else { n1 = s->nsector; if (n1 > s->req_nb_sectors) n1 = s->req_nb_sectors; ide_transfer_start(s, s->io_buffer, 512 * n1, ide_sector_write); } ide_set_sector(s, sector_num + n);#ifdef TARGET_I386 if (win2k_install_hack && ((++s->irq_count % 16) == 0)) { /* It seems there is a bug in the Windows 2000 installer HDD IDE driver which fills the disk with empty logs when the IDE write IRQ comes too early. This hack tries to correct that at the expense of slower write performances. Use this option _only_ to install Windows 2000. You must disable it for normal use. */ qemu_mod_timer(s->sector_write_timer, qemu_get_clock(vm_clock) + (ticks_per_sec / 1000)); } else #endif { ide_set_irq(s); }}/* XXX: handle errors */static void ide_write_dma_cb(void *opaque, int ret){ BMDMAState *bm = opaque; IDEState *s = bm->ide_if; int n; int64_t sector_num; n = s->io_buffer_size >> 9; sector_num = ide_get_sector(s); if (n > 0) { sector_num += n; ide_set_sector(s, sector_num); s->nsector -= n; } /* end of transfer ? */ if (s->nsector == 0) { s->status = READY_STAT | SEEK_STAT; ide_set_irq(s); eot: bm->status &= ~BM_STATUS_DMAING; bm->status |= BM_STATUS_INT; bm->dma_cb = NULL; bm->ide_if = NULL; bm->aiocb = NULL; return; } /* launch next transfer */ n = s->nsector; if (n > MAX_MULT_SECTORS) n = MAX_MULT_SECTORS; s->io_buffer_index = 0; s->io_buffer_size = n * 512; if (dma_buf_rw(bm, 0) == 0) goto eot;#ifdef DEBUG_AIO printf("aio_write: sector_num=%lld n=%d\n", sector_num, n);#endif bm->aiocb = bdrv_aio_write(s->bs, sector_num, s->io_buffer, n, ide_write_dma_cb, bm);}static void ide_sector_write_dma(IDEState *s){ s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT; s->io_buffer_index = 0; s->io_buffer_size = 0; ide_dma_start(s, ide_write_dma_cb);}static void ide_atapi_cmd_ok(IDEState *s){ s->error = 0; s->status = READY_STAT; s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; ide_set_irq(s);}static void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc){#ifdef DEBUG_IDE_ATAPI printf("atapi_cmd_error: sense=0x%x asc=0x%x\n", sense_key, asc);#endif s->error = sense_key << 4; s->status = READY_STAT | ERR_STAT; s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; s->sense_key = sense_key; s->asc = asc; ide_set_irq(s);}static inline void cpu_to_ube16(uint8_t *buf, int val){ buf[0] = val >> 8; buf[1] = val;}static inline void cpu_to_ube32(uint8_t *buf, unsigned int val){ buf[0] = val >> 24; buf[1] = val >> 16; buf[2] = val >> 8; buf[3] = val;}static inline int ube16_to_cpu(const uint8_t *buf){ return (buf[0] << 8) | buf[1];}static inline int ube32_to_cpu(const uint8_t *buf){ return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];}static void lba_to_msf(uint8_t *buf, int lba){ lba += 150; buf[0] = (lba / 75) / 60; buf[1] = (lba / 75) % 60; buf[2] = lba % 75;}static void cd_data_to_raw(uint8_t *buf, int lba){ /* sync bytes */ buf[0] = 0x00; memset(buf + 1, 0xff, 10); buf[11] = 0x00; buf += 12; /* MSF */ lba_to_msf(buf, lba); buf[3] = 0x01; /* mode 1 data */ buf += 4; /* data */ buf += 2048; /* XXX: ECC not computed */ memset(buf, 0, 288);}static int cd_read_sector(BlockDriverState *bs, int lba, uint8_t *buf, int sector_size){ int ret; switch(sector_size) { case 2048: ret = bdrv_read(bs, (int64_t)lba << 2, buf, 4); break; case 2352: ret = bdrv_read(bs, (int64_t)lba << 2, buf + 16, 4); if (ret < 0) return ret; cd_data_to_raw(buf, lba); break; default: ret = -EIO; break; } return ret;}static void ide_atapi_io_error(IDEState *s, int ret){ /* XXX: handle more errors */ if (ret == -ENOMEDIUM) { ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); } else { ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR); }}/* The whole ATAPI transfer logic is handled in this function */static void ide_atapi_cmd_reply_end(IDEState *s){ int byte_count_limit, size, ret;#ifdef DEBUG_IDE_ATAPI printf("reply: tx_size=%d elem_tx_size=%d index=%d\n", s->packet_transfer_size, s->elementary_transfer_size, s->io_buffer_index);#endif if (s->packet_transfer_size <= 0) { /* end of transfer */ ide_transfer_stop(s); s->status = READY_STAT; s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; ide_set_irq(s);#ifdef DEBUG_IDE_ATAPI printf("status=0x%x\n", s->status);#endif } else { /* see if a new sector must be read */ if (s->lba != -1 && s->io_buffer_index >= s->cd_sector_size) { ret = cd_read_sector(s->bs, s->lba, s->io_buffer, s->cd_sector_size); if (ret < 0) { ide_transfer_stop(s); ide_atapi_io_error(s, ret); return; } s->lba++; s->io_buffer_index = 0; } if (s->elementary_transfer_size > 0) { /* there are some data left to transmit in this elementary transfer */ size = s->cd_sector_size - s->io_buffer_index; if (size > s->elementary_transfer_size) size = s->elementary_transfer_size; ide_transfer_start(s, s->io_buffer + s->io_buffer_index, size, ide_atapi_cmd_reply_end); s->packet_transfer_size -= size; s->elementary_transfer_size -= size; s->io_buffer_index += size; } else { /* a new transfer is needed */ s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO; byte_count_limit = s->lcyl | (s->hcyl << 8);#ifdef DEBUG_IDE_ATAPI printf("byte_count_limit=%d\n", byte_count_limit);#endif if (byte_count_limit == 0xffff) byte_count_limit--; size = s->packet_transfer_size; if (size > byte_count_limit) { /* byte count limit must be even if this case */ if (byte_count_limit & 1) byte_count_limit--; size = byte_count_limit; } s->lcyl = size; s->hcyl = size >> 8; s->elementary_transfer_size = size; /* we cannot transmit more than one sector at a time */ if (s->lba != -1) { if (size > (s->cd_sector_size - s->io_buffer_index)) size = (s->cd_sector_size - s->io_buffer_index); } ide_transfer_start(s, s->io_buffer + s->io_buffer_index, size, ide_atapi_cmd_reply_end); s->packet_transfer_size -= size; s->elementary_transfer_size -= size; s->io_buffer_index += size; ide_set_irq(s);#ifdef DEBUG_IDE_ATAPI printf("status=0x%x\n", s->status);#endif } }}/* send a reply of 'size' bytes in s->io_buffer to an ATAPI command */static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size){ if (size > max_size) size = max_size; s->lba = -1; /* no sector read */ s->packet_transfer_size = size; s->io_buffer_size = size; /* dma: send the reply data as one chunk */ s->elementary_transfer_size = 0; s->io_buffer_index = 0; if (s->atapi_dma) { s->status = READY_STAT | DRQ_STAT; ide_dma_start(s, ide_atapi_cmd_read_dma_cb); } else { s->status = READY_STAT; ide_atapi_cmd_reply_end(s); }}/* start a CD-CDROM read command */static void ide_atapi_cmd_read_pio(IDEState *s, int lba, int nb_sectors, int sector_size){ s->lba = lba; s->packet_transfer_size = nb_sectors * sector_size; s->elementary_transfer_size = 0; s->io_buffer_index = sector_size; s->cd_sector_size = sector_size; s->status = READY_STAT; ide_atapi_cmd_reply_end(s);}/* ATAPI DMA support *//* XXX: handle read errors */static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret){ BMDMAState *bm = opaque; IDEState *s = bm->ide_if; int data_offset, n; if (ret < 0) { ide_atapi_io_error(s, ret); goto eot; } if (s->io_buffer_size > 0) { /* * For a cdrom read sector command (s->lba != -1), * adjust the lba for the next s->io_buffer_size chunk * and dma the current chunk. * For a command != read (s->lba == -1), just transfer * the reply data. */ if (s->lba != -1) { if (s->cd_sector_size == 2352) { n = 1; cd_data_to_raw(s->io_buffer, s->lba); } else { n = s->io_buffer_size >> 11; } s->lba += n; } s->packet_transfer_size -= s->io_buffer_size; if (dma_buf_rw(bm, 1) == 0) goto eot; } if (s->packet_transfer_size <= 0) { s->status = READY_STAT; s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; ide_set_irq(s); eot: bm->status &= ~BM_STATUS_DMAING; bm->status |= BM_STATUS_INT; bm->dma_cb = NULL; bm->ide_if = NULL; bm->aiocb = NULL; return; } s->io_buffer_index = 0; if (s->cd_sector_size == 2352) { n = 1; s->io_buffer_size = s->cd_sector_size; data_offset = 16; } else {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -