|
|
1.1 root 1: /*
2: Hatari - ide.c
3:
4: This file is distributed under the GNU Public License, version 2 or at
5: your option any later version. Read the file gpl.txt for details.
6:
7: This is where we intercept read/writes to/from the IDE controller hardware.
8: */
1.1.1.2 ! root 9:
! 10: #include <SDL_endian.h>
! 11: #include <errno.h>
! 12:
! 13: #include <sys/types.h>
! 14: #include <sys/stat.h>
! 15: #include <unistd.h>
1.1 root 16:
17: #include "main.h"
1.1.1.2 ! root 18: #include "config.h"
1.1 root 19: #include "configuration.h"
1.1.1.2 ! root 20: #include "debugui.h"
! 21: #include "file.h"
1.1 root 22: #include "ide.h"
23: #include "m68000.h"
1.1.1.2 ! root 24: #include "mfp.h"
1.1 root 25: #include "stMemory.h"
26: #include "sysdeps.h"
27:
1.1.1.2 ! root 28: #if HAVE_MALLOC_H
! 29: # include <malloc.h>
! 30: #endif
! 31:
! 32:
! 33: struct IDEState;
! 34:
1.1 root 35:
36: #define IDE_DEBUG 0
37:
38: #if IDE_DEBUG
39: #define Dprintf(a) printf a
40: #else
41: #define Dprintf(a)
42: #endif
43:
1.1.1.2 ! root 44: static struct IDEState *opaque_ide_if;
! 45:
! 46: static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val);
! 47: static uint32_t ide_ioport_read(void *opaque, uint32_t addr1);
! 48: static uint32_t ide_status_read(void *opaque, uint32_t addr);
! 49: static void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val);
! 50: static void ide_data_writew(void *opaque, uint32_t addr, uint32_t val);
! 51: static uint32_t ide_data_readw(void *opaque, uint32_t addr);
! 52: static void ide_data_writel(void *opaque, uint32_t addr, uint32_t val);
! 53: static uint32_t ide_data_readl(void *opaque, uint32_t addr);
! 54:
! 55:
! 56: /**
! 57: * Convert Falcon IDE registers to "normal" IDE register numbers.
! 58: * (taken from Aranym - cheers!)
! 59: */
! 60: static uint32_t fcha2io(uint32_t address)
! 61: {
! 62: switch (address)
! 63: {
! 64: case 0xf00000:
! 65: return 0x00;
! 66: case 0xf00005:
! 67: return 0x01;
! 68: case 0xf00009:
! 69: return 0x02;
! 70: case 0xf0000d:
! 71: return 0x03;
! 72: case 0xf00011:
! 73: return 0x04;
! 74: case 0xf00015:
! 75: return 0x05;
! 76: case 0xf00019:
! 77: return 0x06;
! 78: case 0xf0001d:
! 79: return 0x07;
! 80: case 0xf00039:
! 81: return 0x16;
! 82: default:
! 83: return 0xffffffff;
! 84: }
! 85: }
! 86:
1.1 root 87:
88: /**
89: * Handle byte read access from IDE IO memory.
90: */
91: uae_u32 Ide_Mem_bget(uaecptr addr)
92: {
1.1.1.2 ! root 93: int ideport;
! 94: uint8_t retval;
! 95:
1.1 root 96: Dprintf(("IdeMem_bget($%x)\n", addr));
97:
98: addr &= 0x00ffffff; /* Use a 24 bit address */
99:
100: if (addr >= 0xf00040 || !ConfigureParams.HardDisk.bUseIdeHardDiskImage)
101: {
102: /* invalid memory addressing --> bus error */
103: M68000_BusError(addr, 1);
104: return -1;
105: }
106:
1.1.1.2 ! root 107: ideport = fcha2io(addr);
! 108:
! 109: switch (ideport)
! 110: {
! 111: case 1 ... 7:
! 112: retval = ide_ioport_read(opaque_ide_if, ideport);
! 113: break;
! 114: case 8:
! 115: case 22:
! 116: retval = ide_status_read(opaque_ide_if, 0);
! 117: if ((retval & 1))
! 118: DebugUI();
! 119: break;
! 120: default:
! 121: retval = 0xFF;
! 122: break;
! 123: }
! 124:
! 125: return retval;
1.1 root 126: }
127:
128:
129: /**
130: * Handle word read access from IDE IO memory.
131: */
132: uae_u32 Ide_Mem_wget(uaecptr addr)
133: {
1.1.1.2 ! root 134: uint16_t retval;
1.1 root 135:
136: addr &= 0x00ffffff; /* Use a 24 bit address */
137:
138: if (addr >= 0xf00040 || !ConfigureParams.HardDisk.bUseIdeHardDiskImage)
139: {
140: /* invalid memory addressing --> bus error */
141: M68000_BusError(addr, 1);
1.1.1.2 ! root 142: if (ConfigureParams.HardDisk.bUseIdeHardDiskImage)
! 143: fprintf(stderr, "Illegal IDE IO memory access: IdeMem_wget($%x)\n", addr);
1.1 root 144: return -1;
145: }
146:
1.1.1.2 ! root 147: if (addr == 0xf00000)
! 148: {
! 149: retval = ide_data_readw(opaque_ide_if, 0);
! 150: }
! 151: else
! 152: {
! 153: retval = 0xFFFF;
! 154: }
! 155:
! 156: Dprintf(("IdeMem_wget($%x) = $%04x\n", addr, retval));
! 157:
! 158:
! 159: return retval;
1.1 root 160: }
161:
162:
163: /**
164: * Handle long-word read access from IDE IO memory.
165: */
166: uae_u32 Ide_Mem_lget(uaecptr addr)
167: {
1.1.1.2 ! root 168: uint32_t retval;
1.1 root 169:
170: addr &= 0x00ffffff; /* Use a 24 bit address */
171:
172: if (addr >= 0xf00040 || !ConfigureParams.HardDisk.bUseIdeHardDiskImage)
173: {
174: /* invalid memory addressing --> bus error */
175: M68000_BusError(addr, 1);
1.1.1.2 ! root 176: if (ConfigureParams.HardDisk.bUseIdeHardDiskImage)
! 177: fprintf(stderr, "Illegal IDE IO memory access: IdeMem_lget($%x)\n", addr);
1.1 root 178: return -1;
179: }
180:
1.1.1.2 ! root 181: if (addr == 0xf00000)
! 182: {
! 183: retval = ide_data_readl(opaque_ide_if, 0);
! 184: }
! 185: else
! 186: {
! 187: retval = 0xFFFFFFFF;
! 188: }
! 189:
! 190: /* word swap for long access to data register */
! 191: retval = ((retval >> 16) & 0x0000ffff) | ((retval & 0x0000ffff) << 16);
! 192:
! 193: Dprintf(("IdeMem_lget($%x) = $%08x\n", addr, retval));
! 194:
! 195: return retval;
1.1 root 196: }
197:
198:
199: /**
200: * Handle byte write access to IDE IO memory.
201: */
202: void Ide_Mem_bput(uaecptr addr, uae_u32 val)
203: {
1.1.1.2 ! root 204: int ideport;
1.1 root 205:
206: addr &= 0x00ffffff; /* Use a 24 bit address */
1.1.1.2 ! root 207: val &= 0x0ff;
! 208:
! 209: Dprintf(("IdeMem_bput($%x, $%x)\n", addr, val));
1.1 root 210:
211: if (addr >= 0xf00040 || !ConfigureParams.HardDisk.bUseIdeHardDiskImage)
212: {
213: /* invalid memory addressing --> bus error */
214: M68000_BusError(addr, 0);
215: //fprintf(stderr, "Illegal IDE IO memory access: IdeMem_bput($%x)\n", addr);
216: return;
217: }
218:
1.1.1.2 ! root 219: ideport = fcha2io(addr);
! 220:
! 221: switch (ideport)
! 222: {
! 223: case 1 ... 7:
! 224: ide_ioport_write(opaque_ide_if, ideport, val);
! 225: break;
! 226: case 8:
! 227: case 22:
! 228: ide_cmd_write(opaque_ide_if, 0, val);
! 229: break;
! 230: default:
! 231: break;
! 232: }
1.1 root 233: }
234:
235:
236: /**
237: * Handle word write access to IDE IO memory.
238: */
239: void Ide_Mem_wput(uaecptr addr, uae_u32 val)
240: {
241: addr &= 0x00ffffff; /* Use a 24 bit address */
1.1.1.2 ! root 242: val &= 0x0ffff;
! 243:
! 244: Dprintf(("IdeMem_wput($%x, $%x)\n", addr, val));
1.1 root 245:
246: if (addr >= 0xf00040 || !ConfigureParams.HardDisk.bUseIdeHardDiskImage)
247: {
248: /* invalid memory addressing --> bus error */
249: M68000_BusError(addr, 0);
250: //fprintf(stderr, "Illegal IDE IO memory access: IdeMem_wput($%x)\n", addr);
251: return;
252: }
253:
1.1.1.2 ! root 254: if (addr == 0xf00000)
! 255: {
! 256: ide_data_writew(opaque_ide_if, 0, val);
! 257: }
1.1 root 258: }
259:
260:
261: /**
262: * Handle long-word write access to IDE IO memory.
263: */
264: void Ide_Mem_lput(uaecptr addr, uae_u32 val)
265: {
266: addr &= 0x00ffffff; /* Use a 24 bit address */
267:
1.1.1.2 ! root 268: Dprintf(("IdeMem_lput($%x, $%x)\n", addr, val));
! 269:
1.1 root 270: if (addr >= 0xf00040 || !ConfigureParams.HardDisk.bUseIdeHardDiskImage)
271: {
272: /* invalid memory addressing --> bus error */
273: M68000_BusError(addr, 0);
274: //fprintf(stderr, "Illegal IDE IO memory access: IdeMem_lput($%x)\n", addr);
275: return;
276: }
277:
1.1.1.2 ! root 278: /* word swap for long access to data register */
! 279: val = ((val >> 16) & 0x0000ffff) | ((val & 0x0000ffff) << 16);
! 280:
! 281: if (addr == 0xf00000)
! 282: {
! 283: ide_data_writel(opaque_ide_if, 0, val);
! 284: }
! 285: }
! 286:
! 287:
! 288: /*----------------------------------------------------------------------------*/
! 289:
! 290:
! 291: /*
! 292: * QEMU IDE disk and CD-ROM Emulator
! 293: *
! 294: * Copyright (c) 2003 Fabrice Bellard
! 295: * Copyright (c) 2006 Openedhand Ltd.
! 296: *
! 297: * Permission is hereby granted, free of charge, to any person obtaining a copy
! 298: * of this software and associated documentation files (the "Software"), to deal
! 299: * in the Software without restriction, including without limitation the rights
! 300: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
! 301: * copies of the Software, and to permit persons to whom the Software is
! 302: * furnished to do so, subject to the following conditions:
! 303: *
! 304: * The above copyright notice and this permission notice shall be included in
! 305: * all copies or substantial portions of the Software.
! 306: *
! 307: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
! 308: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
! 309: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
! 310: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
! 311: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
! 312: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
! 313: * THE SOFTWARE.
! 314: */
! 315:
! 316: #define FW_VERSION "1.0"
! 317:
! 318:
! 319: #define BDRV_TYPE_HD 0
! 320: #define BDRV_TYPE_CDROM 1
! 321: #define BDRV_TYPE_FLOPPY 2
! 322: #define BIOS_ATA_TRANSLATION_AUTO 0
! 323: #define BIOS_ATA_TRANSLATION_NONE 1
! 324: #define BIOS_ATA_TRANSLATION_LBA 2
! 325: #define BIOS_ATA_TRANSLATION_LARGE 3
! 326: #define BIOS_ATA_TRANSLATION_RECHS 4
! 327:
! 328: #ifndef ENOMEDIUM // It's not defined on Mac OS X for example
! 329: #define ENOMEDIUM ENODEV
! 330: #endif
! 331:
! 332:
! 333: typedef struct BlockDriverState BlockDriverState;
! 334:
! 335: struct BlockDriverState {
! 336: int64_t total_sectors; /* if we are reading a disk image, give its
! 337: size in sectors */
! 338: int read_only; /* if true, the media is read only */
! 339: int removable; /* if true, the media can be removed */
! 340: int locked; /* if true, the media cannot temporarily be ejected */
! 341: int sg; /* if true, the device is a /dev/sg* */
! 342: /* event callback when inserting/removing */
! 343: void (*change_cb)(void *opaque);
! 344: void *change_opaque;
! 345:
! 346: FILE *fhndl;
! 347: void *opaque;
! 348:
! 349: char filename[1024];
! 350: char backing_file[1024]; /* if non zero, the image is a diff of
! 351: this file image */
! 352: int media_changed;
! 353:
! 354: /* I/O stats (display with "info blockstats"). */
! 355: uint64_t rd_bytes;
! 356: uint64_t wr_bytes;
! 357: uint64_t rd_ops;
! 358: uint64_t wr_ops;
! 359:
! 360: /* NOTE: the following infos are only hints for real hardware
! 361: drivers. They are not used by the block driver */
! 362: int cyls, heads, secs, translation;
! 363: int type;
! 364: };
! 365:
! 366:
! 367: static inline void cpu_to_be16wu(uint16_t *p, uint16_t v)
! 368: {
! 369: uint8_t *p1 = (uint8_t *)p;
! 370:
! 371: p1[0] = v >> 8;
! 372: p1[1] = v;
! 373: }
! 374:
! 375:
! 376: #if defined(WIN32)
! 377:
! 378: #include <windows.h>
! 379:
! 380: static void *qemu_memalign(size_t alignment, size_t size)
! 381: {
! 382: return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
! 383: }
! 384:
! 385: static void qemu_free(void *ptr)
! 386: {
! 387: VirtualFree(ptr, 0, MEM_RELEASE);
! 388: }
! 389:
! 390: #else
! 391:
! 392: static void *qemu_memalign(size_t alignment, size_t size)
! 393: {
! 394: #if HAVE_POSIX_MEMALIGN
! 395: int ret;
! 396: void *ptr;
! 397: ret = posix_memalign(&ptr, alignment, size);
! 398: if (ret != 0)
! 399: return NULL;
! 400: return ptr;
! 401: #elif HAVE_MEMALIGN
! 402: return memalign(alignment, size);
! 403: #else
! 404: return valloc(size);
! 405: #endif
! 406: }
! 407:
! 408: #define qemu_free free
! 409:
! 410: #endif
! 411:
! 412:
! 413: #define le32_to_cpu SDL_SwapLE32
! 414: #define le16_to_cpu SDL_SwapLE16
! 415: #define cpu_to_le32 SDL_SwapLE32
! 416: #define cpu_to_le16 SDL_SwapLE16
! 417:
! 418:
! 419: #define MIN(a, b) (((a) < (b)) ? (a) : (b))
! 420:
! 421: #define SECTOR_BITS 9
! 422: #define SECTOR_SIZE (1 << SECTOR_BITS)
! 423:
! 424:
! 425: /**
! 426: * return 0 as number of sectors if no device present or error
! 427: */
! 428: static void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr)
! 429: {
! 430: int64_t length;
! 431: length = File_Length(bs->filename);
! 432:
! 433: if (length < 0)
! 434: length = 0;
! 435: else
! 436: length = length >> SECTOR_BITS;
! 437: *nb_sectors_ptr = length;
! 438: }
! 439:
! 440: static void bdrv_get_geometry_hint(BlockDriverState *bs,
! 441: int *pcyls, int *pheads, int *psecs)
! 442: {
! 443: *pcyls = bs->cyls;
! 444: *pheads = bs->heads;
! 445: *psecs = bs->secs;
! 446: }
! 447:
! 448: static void bdrv_set_translation_hint(BlockDriverState *bs, int translation)
! 449: {
! 450: bs->translation = translation;
! 451: }
! 452:
! 453: static void bdrv_set_geometry_hint(BlockDriverState *bs,
! 454: int cyls, int heads, int secs)
! 455: {
! 456: bs->cyls = cyls;
! 457: bs->heads = heads;
! 458: bs->secs = secs;
! 459: }
! 460:
! 461: static int bdrv_get_type_hint(BlockDriverState *bs)
! 462: {
! 463: return bs->type;
! 464: }
! 465:
! 466: static int bdrv_get_translation_hint(BlockDriverState *bs)
! 467: {
! 468: return bs->translation;
! 469: }
! 470:
! 471: /* XXX: no longer used */
! 472: static void bdrv_set_change_cb(BlockDriverState *bs,
! 473: void (*change_cb)(void *opaque), void *opaque)
! 474: {
! 475: bs->change_cb = change_cb;
! 476: bs->change_opaque = opaque;
! 477: }
! 478:
! 479:
! 480: /**
! 481: * Return TRUE if the media is present
! 482: */
! 483: static int bdrv_is_inserted(BlockDriverState *bs)
! 484: {
! 485: return (bs->fhndl != NULL);
! 486: }
! 487:
! 488:
! 489: static int bdrv_is_locked(BlockDriverState *bs)
! 490: {
! 491: return bs->locked;
! 492: }
! 493:
! 494: /**
! 495: * Lock or unlock the media (if it is locked, the user won't be able
! 496: * to eject it manually).
! 497: */
! 498: static void bdrv_set_locked(BlockDriverState *bs, int locked)
! 499: {
! 500: bs->locked = locked;
! 501: }
! 502:
! 503:
! 504: /* return < 0 if error. See bdrv_write() for the return codes */
! 505: static int bdrv_read(BlockDriverState *bs, int64_t sector_num,
! 506: uint8_t *buf, int nb_sectors)
! 507: {
! 508: if (!bs->fhndl)
! 509: return -ENOMEDIUM;
! 510:
! 511: int ret, len;
! 512: len = nb_sectors * 512;
! 513:
! 514: fseek(bs->fhndl, sector_num*512, SEEK_SET);
! 515: ret = fread(buf, 1, len, bs->fhndl);
! 516: if (ret != len)
! 517: {
! 518: fprintf(stderr,"Error during read!\n");
! 519: return -EINVAL;
! 520: }
! 521: else
! 522: {
! 523: bs->rd_bytes += (unsigned) len;
! 524: bs->rd_ops ++;
! 525: return 0;
! 526: }
! 527: }
! 528:
! 529:
! 530: /* Return < 0 if error. Important errors are:
! 531: -EIO generic I/O error (may happen for all errors)
! 532: -ENOMEDIUM No media inserted.
! 533: -EINVAL Invalid sector number or nb_sectors
! 534: -EACCES Trying to write a read-only device
! 535: */
! 536: static int bdrv_write(BlockDriverState *bs, int64_t sector_num,
! 537: const uint8_t *buf, int nb_sectors)
! 538: {
! 539: if (!bs->fhndl)
! 540: return -ENOMEDIUM;
! 541: if (bs->read_only)
! 542: return -EACCES;
! 543:
! 544: int ret, len;
! 545: len = nb_sectors * 512;
! 546:
! 547: fseek(bs->fhndl, sector_num*512, SEEK_SET);
! 548: ret = fwrite(buf, 1, len, bs->fhndl);
! 549: if (ret != len)
! 550: {
! 551: fprintf(stderr,"Error during bdrv_write\n");
! 552: return -EIO;
! 553: }
! 554: else
! 555: {
! 556: bs->wr_bytes += (unsigned) len;
! 557: bs->wr_ops ++;
! 558: return 0;
! 559: }
! 560: }
! 561:
! 562:
! 563: static int bdrv_open(BlockDriverState *bs, const char *filename, int flags)
! 564: {
! 565: fprintf(stderr,"Opening %s\n", filename);
! 566:
! 567: strncpy(bs->filename, filename, sizeof(bs->filename));
! 568:
! 569: bs->read_only = 0;
! 570:
! 571: bs->fhndl = fopen(filename, "rb+");
! 572:
! 573: if (!bs->fhndl) {
! 574: /* Maybe the file is read-only? */
! 575: bs->fhndl = fopen(filename, "rb");
! 576: if (!bs->fhndl)
! 577: perror("bdrv_open");
! 578: bs->read_only = 1;
! 579: }
! 580:
! 581: /* call the change callback */
! 582: bs->media_changed = 1;
! 583: if (bs->change_cb)
! 584: bs->change_cb(bs->change_opaque);
! 585:
! 586: return 0;
! 587: }
! 588:
! 589: static void bdrv_flush(BlockDriverState *bs)
! 590: {
! 591: fflush(bs->fhndl);
! 592: }
! 593:
! 594: static void bdrv_close(BlockDriverState *bs)
! 595: {
! 596: fclose(bs->fhndl);
! 597: bs->fhndl = NULL;
! 598: }
! 599:
! 600: /**
! 601: * If eject_flag is TRUE, eject the media. Otherwise, close the tray
! 602: */
! 603: static void bdrv_eject(BlockDriverState *bs, int eject_flag)
! 604: {
! 605: if (eject_flag)
! 606: bdrv_close(bs);
! 607: }
! 608:
! 609:
! 610: /* debug IDE devices */
! 611: // #define DEBUG_IDE
! 612: // #define DEBUG_IDE_ATAPI
! 613:
! 614: // #define USE_DMA_CDROM
! 615:
! 616: /* Bits of HD_STATUS */
! 617: #define ERR_STAT 0x01
! 618: #define INDEX_STAT 0x02
! 619: #define ECC_STAT 0x04 /* Corrected error */
! 620: #define DRQ_STAT 0x08
! 621: #define SEEK_STAT 0x10
! 622: #define SRV_STAT 0x10
! 623: #define WRERR_STAT 0x20
! 624: #define READY_STAT 0x40
! 625: #define BUSY_STAT 0x80
! 626:
! 627: /* Bits for HD_ERROR */
! 628: #define MARK_ERR 0x01 /* Bad address mark */
! 629: #define TRK0_ERR 0x02 /* couldn't find track 0 */
! 630: #define ABRT_ERR 0x04 /* Command aborted */
! 631: #define MCR_ERR 0x08 /* media change request */
! 632: #define ID_ERR 0x10 /* ID field not found */
! 633: #define MC_ERR 0x20 /* media changed */
! 634: #define ECC_ERR 0x40 /* Uncorrectable ECC error */
! 635: #define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */
! 636: #define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */
! 637:
! 638: /* Bits of HD_NSECTOR */
! 639: #define CD 0x01
! 640: #define IO 0x02
! 641: #define REL 0x04
! 642: #define TAG_MASK 0xf8
! 643:
! 644: #define IDE_CMD_RESET 0x04
! 645: #define IDE_CMD_DISABLE_IRQ 0x02
! 646:
! 647: /* ATA/ATAPI Commands pre T13 Spec */
! 648: #define WIN_NOP 0x00
! 649: /*
! 650: * 0x01->0x02 Reserved
! 651: */
! 652: #define CFA_REQ_EXT_ERROR_CODE 0x03 /* CFA Request Extended Error Code */
! 653: /*
! 654: * 0x04->0x07 Reserved
! 655: */
! 656: #define WIN_SRST 0x08 /* ATAPI soft reset command */
! 657: #define WIN_DEVICE_RESET 0x08
! 658: /*
! 659: * 0x09->0x0F Reserved
! 660: */
! 661: #define WIN_RECAL 0x10
! 662: #define WIN_RESTORE WIN_RECAL
! 663: /*
! 664: * 0x10->0x1F Reserved
! 665: */
! 666: #define WIN_READ 0x20 /* 28-Bit */
! 667: #define WIN_READ_ONCE 0x21 /* 28-Bit without retries */
! 668: #define WIN_READ_LONG 0x22 /* 28-Bit */
! 669: #define WIN_READ_LONG_ONCE 0x23 /* 28-Bit without retries */
! 670: #define WIN_READ_EXT 0x24 /* 48-Bit */
! 671: #define WIN_READDMA_EXT 0x25 /* 48-Bit */
! 672: #define WIN_READDMA_QUEUED_EXT 0x26 /* 48-Bit */
! 673: #define WIN_READ_NATIVE_MAX_EXT 0x27 /* 48-Bit */
! 674: /*
! 675: * 0x28
! 676: */
! 677: #define WIN_MULTREAD_EXT 0x29 /* 48-Bit */
! 678: /*
! 679: * 0x2A->0x2F Reserved
! 680: */
! 681: #define WIN_WRITE 0x30 /* 28-Bit */
! 682: #define WIN_WRITE_ONCE 0x31 /* 28-Bit without retries */
! 683: #define WIN_WRITE_LONG 0x32 /* 28-Bit */
! 684: #define WIN_WRITE_LONG_ONCE 0x33 /* 28-Bit without retries */
! 685: #define WIN_WRITE_EXT 0x34 /* 48-Bit */
! 686: #define WIN_WRITEDMA_EXT 0x35 /* 48-Bit */
! 687: #define WIN_WRITEDMA_QUEUED_EXT 0x36 /* 48-Bit */
! 688: #define WIN_SET_MAX_EXT 0x37 /* 48-Bit */
! 689: #define CFA_WRITE_SECT_WO_ERASE 0x38 /* CFA Write Sectors without erase */
! 690: #define WIN_MULTWRITE_EXT 0x39 /* 48-Bit */
! 691: /*
! 692: * 0x3A->0x3B Reserved
! 693: */
! 694: #define WIN_WRITE_VERIFY 0x3C /* 28-Bit */
! 695: /*
! 696: * 0x3D->0x3F Reserved
! 697: */
! 698: #define WIN_VERIFY 0x40 /* 28-Bit - Read Verify Sectors */
! 699: #define WIN_VERIFY_ONCE 0x41 /* 28-Bit - without retries */
! 700: #define WIN_VERIFY_EXT 0x42 /* 48-Bit */
! 701: /*
! 702: * 0x43->0x4F Reserved
! 703: */
! 704: #define WIN_FORMAT 0x50
! 705: /*
! 706: * 0x51->0x5F Reserved
! 707: */
! 708: #define WIN_INIT 0x60
! 709: /*
! 710: * 0x61->0x5F Reserved
! 711: */
! 712: #define WIN_SEEK 0x70 /* 0x70-0x7F Reserved */
! 713: #define CFA_TRANSLATE_SECTOR 0x87 /* CFA Translate Sector */
! 714: #define WIN_DIAGNOSE 0x90
! 715: #define WIN_SPECIFY 0x91 /* set drive geometry translation */
! 716: #define WIN_DOWNLOAD_MICROCODE 0x92
! 717: #define WIN_STANDBYNOW2 0x94
! 718: #define CFA_IDLEIMMEDIATE 0x95 /* force drive to become "ready" */
! 719: #define WIN_STANDBY2 0x96
! 720: #define WIN_SETIDLE2 0x97
! 721: #define WIN_CHECKPOWERMODE2 0x98
! 722: #define WIN_SLEEPNOW2 0x99
! 723: /*
! 724: * 0x9A VENDOR
! 725: */
! 726: #define WIN_PACKETCMD 0xA0 /* Send a packet command. */
! 727: #define WIN_PIDENTIFY 0xA1 /* identify ATAPI device */
! 728: #define WIN_QUEUED_SERVICE 0xA2
! 729: #define WIN_SMART 0xB0 /* self-monitoring and reporting */
! 730: #define CFA_ACCESS_METADATA_STORAGE 0xB8
! 731: #define CFA_ERASE_SECTORS 0xC0 /* microdrives implement as NOP */
! 732: #define WIN_MULTREAD 0xC4 /* read sectors using multiple mode*/
! 733: #define WIN_MULTWRITE 0xC5 /* write sectors using multiple mode */
! 734: #define WIN_SETMULT 0xC6 /* enable/disable multiple mode */
! 735: #define WIN_READDMA_QUEUED 0xC7 /* read sectors using Queued DMA transfers */
! 736: #define WIN_READDMA 0xC8 /* read sectors using DMA transfers */
! 737: #define WIN_READDMA_ONCE 0xC9 /* 28-Bit - without retries */
! 738: #define WIN_WRITEDMA 0xCA /* write sectors using DMA transfers */
! 739: #define WIN_WRITEDMA_ONCE 0xCB /* 28-Bit - without retries */
! 740: #define WIN_WRITEDMA_QUEUED 0xCC /* write sectors using Queued DMA transfers */
! 741: #define CFA_WRITE_MULTI_WO_ERASE 0xCD /* CFA Write multiple without erase */
! 742: #define WIN_GETMEDIASTATUS 0xDA
! 743: #define WIN_ACKMEDIACHANGE 0xDB /* ATA-1, ATA-2 vendor */
! 744: #define WIN_POSTBOOT 0xDC
! 745: #define WIN_PREBOOT 0xDD
! 746: #define WIN_DOORLOCK 0xDE /* lock door on removable drives */
! 747: #define WIN_DOORUNLOCK 0xDF /* unlock door on removable drives */
! 748: #define WIN_STANDBYNOW1 0xE0
! 749: #define WIN_IDLEIMMEDIATE 0xE1 /* force drive to become "ready" */
! 750: #define WIN_STANDBY 0xE2 /* Set device in Standby Mode */
! 751: #define WIN_SETIDLE1 0xE3
! 752: #define WIN_READ_BUFFER 0xE4 /* force read only 1 sector */
! 753: #define WIN_CHECKPOWERMODE1 0xE5
! 754: #define WIN_SLEEPNOW1 0xE6
! 755: #define WIN_FLUSH_CACHE 0xE7
! 756: #define WIN_WRITE_BUFFER 0xE8 /* force write only 1 sector */
! 757: #define WIN_WRITE_SAME 0xE9 /* read ata-2 to use */
! 758: /* SET_FEATURES 0x22 or 0xDD */
! 759: #define WIN_FLUSH_CACHE_EXT 0xEA /* 48-Bit */
! 760: #define WIN_IDENTIFY 0xEC /* ask drive to identify itself */
! 761: #define WIN_MEDIAEJECT 0xED
! 762: #define WIN_IDENTIFY_DMA 0xEE /* same as WIN_IDENTIFY, but DMA */
! 763: #define WIN_SETFEATURES 0xEF /* set special drive features */
! 764: #define EXABYTE_ENABLE_NEST 0xF0
! 765: #define IBM_SENSE_CONDITION 0xF0 /* measure disk temperature */
! 766: #define WIN_SECURITY_SET_PASS 0xF1
! 767: #define WIN_SECURITY_UNLOCK 0xF2
! 768: #define WIN_SECURITY_ERASE_PREPARE 0xF3
! 769: #define WIN_SECURITY_ERASE_UNIT 0xF4
! 770: #define WIN_SECURITY_FREEZE_LOCK 0xF5
! 771: #define CFA_WEAR_LEVEL 0xF5 /* microdrives implement as NOP */
! 772: #define WIN_SECURITY_DISABLE 0xF6
! 773: #define WIN_READ_NATIVE_MAX 0xF8 /* return the native maximum address */
! 774: #define WIN_SET_MAX 0xF9
! 775: #define DISABLE_SEAGATE 0xFB
! 776:
! 777: /* set to 1 set disable mult support */
! 778: #define MAX_MULT_SECTORS 16
! 779:
! 780: /* ATAPI defines */
! 781:
! 782: #define ATAPI_PACKET_SIZE 12
! 783:
! 784: /* The generic packet command opcodes for CD/DVD Logical Units,
! 785: * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
! 786: #define GPCMD_BLANK 0xa1
! 787: #define GPCMD_CLOSE_TRACK 0x5b
! 788: #define GPCMD_FLUSH_CACHE 0x35
! 789: #define GPCMD_FORMAT_UNIT 0x04
! 790: #define GPCMD_GET_CONFIGURATION 0x46
! 791: #define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a
! 792: #define GPCMD_GET_PERFORMANCE 0xac
! 793: #define GPCMD_INQUIRY 0x12
! 794: #define GPCMD_LOAD_UNLOAD 0xa6
! 795: #define GPCMD_MECHANISM_STATUS 0xbd
! 796: #define GPCMD_MODE_SELECT_10 0x55
! 797: #define GPCMD_MODE_SENSE_10 0x5a
! 798: #define GPCMD_PAUSE_RESUME 0x4b
! 799: #define GPCMD_PLAY_AUDIO_10 0x45
! 800: #define GPCMD_PLAY_AUDIO_MSF 0x47
! 801: #define GPCMD_PLAY_AUDIO_TI 0x48
! 802: #define GPCMD_PLAY_CD 0xbc
! 803: #define GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e
! 804: #define GPCMD_READ_10 0x28
! 805: #define GPCMD_READ_12 0xa8
! 806: #define GPCMD_READ_CDVD_CAPACITY 0x25
! 807: #define GPCMD_READ_CD 0xbe
! 808: #define GPCMD_READ_CD_MSF 0xb9
! 809: #define GPCMD_READ_DISC_INFO 0x51
! 810: #define GPCMD_READ_DVD_STRUCTURE 0xad
! 811: #define GPCMD_READ_FORMAT_CAPACITIES 0x23
! 812: #define GPCMD_READ_HEADER 0x44
! 813: #define GPCMD_READ_TRACK_RZONE_INFO 0x52
! 814: #define GPCMD_READ_SUBCHANNEL 0x42
! 815: #define GPCMD_READ_TOC_PMA_ATIP 0x43
! 816: #define GPCMD_REPAIR_RZONE_TRACK 0x58
! 817: #define GPCMD_REPORT_KEY 0xa4
! 818: #define GPCMD_REQUEST_SENSE 0x03
! 819: #define GPCMD_RESERVE_RZONE_TRACK 0x53
! 820: #define GPCMD_SCAN 0xba
! 821: #define GPCMD_SEEK 0x2b
! 822: #define GPCMD_SEND_DVD_STRUCTURE 0xad
! 823: #define GPCMD_SEND_EVENT 0xa2
! 824: #define GPCMD_SEND_KEY 0xa3
! 825: #define GPCMD_SEND_OPC 0x54
! 826: #define GPCMD_SET_READ_AHEAD 0xa7
! 827: #define GPCMD_SET_STREAMING 0xb6
! 828: #define GPCMD_START_STOP_UNIT 0x1b
! 829: #define GPCMD_STOP_PLAY_SCAN 0x4e
! 830: #define GPCMD_TEST_UNIT_READY 0x00
! 831: #define GPCMD_VERIFY_10 0x2f
! 832: #define GPCMD_WRITE_10 0x2a
! 833: #define GPCMD_WRITE_AND_VERIFY_10 0x2e
! 834: /* This is listed as optional in ATAPI 2.6, but is (curiously)
! 835: * missing from Mt. Fuji, Table 57. It _is_ mentioned in Mt. Fuji
! 836: * Table 377 as an MMC command for SCSi devices though... Most ATAPI
! 837: * drives support it. */
! 838: #define GPCMD_SET_SPEED 0xbb
! 839: /* This seems to be a SCSI specific CD-ROM opcode
! 840: * to play data at track/index */
! 841: #define GPCMD_PLAYAUDIO_TI 0x48
! 842: /*
! 843: * From MS Media Status Notification Support Specification. For
! 844: * older drives only.
! 845: */
! 846: #define GPCMD_GET_MEDIA_STATUS 0xda
! 847: #define GPCMD_MODE_SENSE_6 0x1a
! 848:
! 849: /* Mode page codes for mode sense/set */
! 850: #define GPMODE_R_W_ERROR_PAGE 0x01
! 851: #define GPMODE_WRITE_PARMS_PAGE 0x05
! 852: #define GPMODE_AUDIO_CTL_PAGE 0x0e
! 853: #define GPMODE_POWER_PAGE 0x1a
! 854: #define GPMODE_FAULT_FAIL_PAGE 0x1c
! 855: #define GPMODE_TO_PROTECT_PAGE 0x1d
! 856: #define GPMODE_CAPABILITIES_PAGE 0x2a
! 857: #define GPMODE_ALL_PAGES 0x3f
! 858: /* Not in Mt. Fuji, but in ATAPI 2.6 -- depricated now in favor
! 859: * of MODE_SENSE_POWER_PAGE */
! 860: #define GPMODE_CDROM_PAGE 0x0d
! 861:
! 862: #define ATAPI_INT_REASON_CD 0x01 /* 0 = data transfer */
! 863: #define ATAPI_INT_REASON_IO 0x02 /* 1 = transfer to the host */
! 864: #define ATAPI_INT_REASON_REL 0x04
! 865: #define ATAPI_INT_REASON_TAG 0xf8
! 866:
! 867: /* same constants as bochs */
! 868: #define ASC_ILLEGAL_OPCODE 0x20
! 869: #define ASC_LOGICAL_BLOCK_OOR 0x21
! 870: #define ASC_INV_FIELD_IN_CMD_PACKET 0x24
! 871: #define ASC_MEDIUM_NOT_PRESENT 0x3a
! 872: #define ASC_SAVING_PARAMETERS_NOT_SUPPORTED 0x39
! 873:
! 874: #define SENSE_NONE 0
! 875: #define SENSE_NOT_READY 2
! 876: #define SENSE_ILLEGAL_REQUEST 5
! 877: #define SENSE_UNIT_ATTENTION 6
! 878:
! 879: typedef void EndTransferFunc(struct IDEState *);
! 880:
! 881: /* NOTE: IDEState represents in fact one drive */
! 882: typedef struct IDEState
! 883: {
! 884: /* ide config */
! 885: int is_cdrom;
! 886: int cylinders, heads, sectors;
! 887: int64_t nb_sectors;
! 888: int mult_sectors;
! 889: int identify_set;
! 890: uint16_t identify_data[256];
! 891: int drive_serial;
! 892: /* ide regs */
! 893: uint8_t feature;
! 894: uint8_t error;
! 895: uint32_t nsector;
! 896: uint8_t sector;
! 897: uint8_t lcyl;
! 898: uint8_t hcyl;
! 899: /* other part of tf for lba48 support */
! 900: uint8_t hob_feature;
! 901: uint8_t hob_nsector;
! 902: uint8_t hob_sector;
! 903: uint8_t hob_lcyl;
! 904: uint8_t hob_hcyl;
! 905:
! 906: uint8_t select;
! 907: uint8_t status;
! 908:
! 909: /* 0x3f6 command, only meaningful for drive 0 */
! 910: uint8_t cmd;
! 911: /* set for lba48 access */
! 912: uint8_t lba48;
! 913: /* depends on bit 4 in select, only meaningful for drive 0 */
! 914: struct IDEState *cur_drive;
! 915: BlockDriverState *bs;
! 916: /* ATAPI specific */
! 917: uint8_t sense_key;
! 918: uint8_t asc;
! 919: int packet_transfer_size;
! 920: int elementary_transfer_size;
! 921: int io_buffer_index;
! 922: int lba;
! 923: int cd_sector_size;
! 924: /* ATA DMA state */
! 925: int io_buffer_size;
! 926: /* PIO transfer handling */
! 927: int req_nb_sectors; /* number of sectors per interrupt */
! 928: EndTransferFunc *end_transfer_func;
! 929: uint8_t *data_ptr;
! 930: uint8_t *data_end;
! 931: uint8_t *io_buffer;
! 932: int media_changed;
! 933: } IDEState;
! 934:
! 935:
! 936: static void padstr(char *str, const char *src, int len)
! 937: {
! 938: int i, v;
! 939: for (i = 0; i < len; i++)
! 940: {
! 941: if (*src)
! 942: v = *src++;
! 943: else
! 944: v = ' ';
! 945: str[i^1] = v;
! 946: }
! 947: }
! 948:
! 949: static void padstr8(uint8_t *buf, int buf_size, const char *src)
! 950: {
! 951: int i;
! 952: for (i = 0; i < buf_size; i++)
! 953: {
! 954: if (*src)
! 955: buf[i] = *src++;
! 956: else
! 957: buf[i] = ' ';
! 958: }
! 959: }
! 960:
! 961: static void put_le16(uint16_t *p, unsigned int v)
! 962: {
! 963: *p = SDL_SwapLE16(v);
! 964: }
! 965:
! 966: static void ide_identify(IDEState *s)
! 967: {
! 968: uint16_t *p;
! 969: unsigned int oldsize;
! 970: char buf[20];
! 971:
! 972: if (s->identify_set)
! 973: {
! 974: memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data));
! 975: return;
! 976: }
! 977:
! 978: memset(s->io_buffer, 0, 512);
! 979: p = (uint16_t *)s->io_buffer;
! 980: put_le16(p + 0, 0x0040);
! 981: put_le16(p + 1, s->cylinders);
! 982: put_le16(p + 3, s->heads);
! 983: put_le16(p + 4, 512 * s->sectors); /* XXX: retired, remove ? */
! 984: put_le16(p + 5, 512); /* XXX: retired, remove ? */
! 985: put_le16(p + 6, s->sectors);
! 986: snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);
! 987: padstr((char *)(p + 10), buf, 20); /* serial number */
! 988: put_le16(p + 20, 3); /* XXX: retired, remove ? */
! 989: put_le16(p + 21, 512); /* cache size in sectors */
! 990: put_le16(p + 22, 4); /* ecc bytes */
! 991: padstr((char *)(p + 23), FW_VERSION, 8); /* firmware version */
! 992: padstr((char *)(p + 27), "Hatari IDE disk", 40); /* model */
! 993: #if MAX_MULT_SECTORS > 1
! 994: put_le16(p + 47, 0x8000 | MAX_MULT_SECTORS);
! 995: #endif
! 996: put_le16(p + 48, 1); /* dword I/O */
! 997: put_le16(p + 49, (1 << 11) | (1 << 9) | (1 << 8)); /* DMA and LBA supported */
! 998: put_le16(p + 51, 0x200); /* PIO transfer cycle */
! 999: put_le16(p + 52, 0x200); /* DMA transfer cycle */
! 1000: put_le16(p + 53, 1 | (1 << 1) | (1 << 2)); /* words 54-58,64-70,88 are valid */
! 1001: put_le16(p + 54, s->cylinders);
! 1002: put_le16(p + 55, s->heads);
! 1003: put_le16(p + 56, s->sectors);
! 1004: oldsize = s->cylinders * s->heads * s->sectors;
! 1005: put_le16(p + 57, oldsize);
! 1006: put_le16(p + 58, oldsize >> 16);
! 1007: if (s->mult_sectors)
! 1008: put_le16(p + 59, 0x100 | s->mult_sectors);
! 1009: put_le16(p + 60, s->nb_sectors);
! 1010: put_le16(p + 61, s->nb_sectors >> 16);
! 1011: put_le16(p + 63, 0x07); /* mdma0-2 supported */
! 1012: put_le16(p + 65, 120);
! 1013: put_le16(p + 66, 120);
! 1014: put_le16(p + 67, 120);
! 1015: put_le16(p + 68, 120);
! 1016: put_le16(p + 80, 0xf0); /* ata3 -> ata6 supported */
! 1017: put_le16(p + 81, 0x16); /* conforms to ata5 */
! 1018: put_le16(p + 82, (1 << 14));
! 1019: /* 13=flush_cache_ext,12=flush_cache,10=lba48 */
! 1020: put_le16(p + 83, (1 << 14) | (1 << 13) | (1 <<12) | (1 << 10));
! 1021: put_le16(p + 84, (1 << 14));
! 1022: put_le16(p + 85, (1 << 14));
! 1023: /* 13=flush_cache_ext,12=flush_cache,10=lba48 */
! 1024: put_le16(p + 86, (1 << 14) | (1 << 13) | (1 <<12) | (1 << 10));
! 1025: put_le16(p + 87, (1 << 14));
! 1026: put_le16(p + 88, 0x3f | (1 << 13)); /* udma5 set and supported */
! 1027: put_le16(p + 93, 1 | (1 << 14) | 0x2000);
! 1028: put_le16(p + 100, s->nb_sectors);
! 1029: put_le16(p + 101, s->nb_sectors >> 16);
! 1030: put_le16(p + 102, s->nb_sectors >> 32);
! 1031: put_le16(p + 103, s->nb_sectors >> 48);
! 1032:
! 1033: memcpy(s->identify_data, p, sizeof(s->identify_data));
! 1034: s->identify_set = 1;
! 1035: }
! 1036:
! 1037: static void ide_atapi_identify(IDEState *s)
! 1038: {
! 1039: uint16_t *p;
! 1040: char buf[20];
! 1041:
! 1042: if (s->identify_set)
! 1043: {
! 1044: memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data));
! 1045: return;
! 1046: }
! 1047:
! 1048: memset(s->io_buffer, 0, 512);
! 1049: p = (uint16_t *)s->io_buffer;
! 1050: /* Removable CDROM, 50us response, 12 byte packets */
! 1051: put_le16(p + 0, (2 << 14) | (5 << 8) | (1 << 7) | (2 << 5) | (0 << 0));
! 1052: snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);
! 1053: padstr((char *)(p + 10), buf, 20); /* serial number */
! 1054: put_le16(p + 20, 3); /* buffer type */
! 1055: put_le16(p + 21, 512); /* cache size in sectors */
! 1056: put_le16(p + 22, 4); /* ecc bytes */
! 1057: padstr((char *)(p + 23), FW_VERSION, 8); /* firmware version */
! 1058: padstr((char *)(p + 27), "Hatari CD-ROM", 40); /* model */
! 1059: put_le16(p + 48, 1); /* dword I/O (XXX: should not be set on CDROM) */
! 1060: #ifdef USE_DMA_CDROM
! 1061: put_le16(p + 49, 1 << 9 | 1 << 8); /* DMA and LBA supported */
! 1062: put_le16(p + 53, 7); /* words 64-70, 54-58, 88 valid */
! 1063: put_le16(p + 63, 7); /* mdma0-2 supported */
! 1064: put_le16(p + 64, 0x3f); /* PIO modes supported */
! 1065: #else
! 1066: put_le16(p + 49, 1 << 9); /* LBA supported, no DMA */
! 1067: put_le16(p + 53, 3); /* words 64-70, 54-58 valid */
! 1068: put_le16(p + 63, 0x103); /* DMA modes XXX: may be incorrect */
! 1069: put_le16(p + 64, 1); /* PIO modes */
! 1070: #endif
! 1071: put_le16(p + 65, 0xb4); /* minimum DMA multiword tx cycle time */
! 1072: put_le16(p + 66, 0xb4); /* recommended DMA multiword tx cycle time */
! 1073: put_le16(p + 67, 0x12c); /* minimum PIO cycle time without flow control */
! 1074: put_le16(p + 68, 0xb4); /* minimum PIO cycle time with IORDY flow control */
! 1075:
! 1076: put_le16(p + 71, 30); /* in ns */
! 1077: put_le16(p + 72, 30); /* in ns */
! 1078:
! 1079: put_le16(p + 80, 0x1e); /* support up to ATA/ATAPI-4 */
! 1080: #ifdef USE_DMA_CDROM
! 1081: put_le16(p + 88, 0x3f | (1 << 13)); /* udma5 set and supported */
! 1082: #endif
! 1083: memcpy(s->identify_data, p, sizeof(s->identify_data));
! 1084: s->identify_set = 1;
! 1085: }
! 1086:
! 1087:
! 1088: static void ide_set_signature(IDEState *s)
! 1089: {
! 1090: s->select &= 0xf0; /* clear head */
! 1091: /* put signature */
! 1092: s->nsector = 1;
! 1093: s->sector = 1;
! 1094: if (s->is_cdrom)
! 1095: {
! 1096: s->lcyl = 0x14;
! 1097: s->hcyl = 0xeb;
! 1098: }
! 1099: else if (s->bs)
! 1100: {
! 1101: s->lcyl = 0;
! 1102: s->hcyl = 0;
! 1103: }
! 1104: else
! 1105: {
! 1106: s->lcyl = 0xff;
! 1107: s->hcyl = 0xff;
! 1108: }
! 1109: }
! 1110:
! 1111: static inline void ide_abort_command(IDEState *s)
! 1112: {
! 1113: s->status = READY_STAT | ERR_STAT;
! 1114: s->error = ABRT_ERR;
! 1115: }
! 1116:
! 1117: static inline void ide_set_irq(IDEState *s)
! 1118: {
! 1119: if (!(s->cmd & IDE_CMD_DISABLE_IRQ))
! 1120: {
! 1121: /* raise IRQ */
! 1122: MFP_InputOnChannel(MFP_FDCHDC_BIT, MFP_IERB, &MFP_IPRB);
! 1123: MFP_GPIP &= ~0x20;
! 1124: }
! 1125: }
! 1126:
! 1127: /* prepare data transfer and tell what to do after */
! 1128: static void ide_transfer_start(IDEState *s, uint8_t *buf, int size,
! 1129: EndTransferFunc *end_transfer_func)
! 1130: {
! 1131: s->end_transfer_func = end_transfer_func;
! 1132: s->data_ptr = buf;
! 1133: s->data_end = buf + size;
! 1134: if (!(s->status & ERR_STAT))
! 1135: s->status |= DRQ_STAT;
! 1136: }
! 1137:
! 1138: static void ide_transfer_stop(IDEState *s)
! 1139: {
! 1140: s->end_transfer_func = ide_transfer_stop;
! 1141: s->data_ptr = s->io_buffer;
! 1142: s->data_end = s->io_buffer;
! 1143: s->status &= ~DRQ_STAT;
! 1144: }
! 1145:
! 1146: static int64_t ide_get_sector(IDEState *s)
! 1147: {
! 1148: int64_t sector_num;
! 1149: if (s->select & 0x40)
! 1150: {
! 1151: /* lba */
! 1152: if (!s->lba48)
! 1153: {
! 1154: sector_num = ((s->select & 0x0f) << 24) | (s->hcyl << 16) |
! 1155: (s->lcyl << 8) | s->sector;
! 1156: }
! 1157: else
! 1158: {
! 1159: sector_num = ((int64_t)s->hob_hcyl << 40) |
! 1160: ((int64_t) s->hob_lcyl << 32) |
! 1161: ((int64_t) s->hob_sector << 24) |
! 1162: ((int64_t) s->hcyl << 16) |
! 1163: ((int64_t) s->lcyl << 8) | s->sector;
! 1164: }
! 1165: }
! 1166: else
! 1167: {
! 1168: sector_num = ((s->hcyl << 8) | s->lcyl) * s->heads * s->sectors +
! 1169: (s->select & 0x0f) * s->sectors + (s->sector - 1);
! 1170: }
! 1171: return sector_num;
! 1172: }
! 1173:
! 1174: static void ide_set_sector(IDEState *s, int64_t sector_num)
! 1175: {
! 1176: unsigned int cyl, r;
! 1177: if (s->select & 0x40)
! 1178: {
! 1179: if (!s->lba48)
! 1180: {
! 1181: s->select = (s->select & 0xf0) | (sector_num >> 24);
! 1182: s->hcyl = (sector_num >> 16);
! 1183: s->lcyl = (sector_num >> 8);
! 1184: s->sector = (sector_num);
! 1185: }
! 1186: else
! 1187: {
! 1188: s->sector = sector_num;
! 1189: s->lcyl = sector_num >> 8;
! 1190: s->hcyl = sector_num >> 16;
! 1191: s->hob_sector = sector_num >> 24;
! 1192: s->hob_lcyl = sector_num >> 32;
! 1193: s->hob_hcyl = sector_num >> 40;
! 1194: }
! 1195: }
! 1196: else
! 1197: {
! 1198: cyl = sector_num / (s->heads * s->sectors);
! 1199: r = sector_num % (s->heads * s->sectors);
! 1200: s->hcyl = cyl >> 8;
! 1201: s->lcyl = cyl;
! 1202: s->select = (s->select & 0xf0) | ((r / s->sectors) & 0x0f);
! 1203: s->sector = (r % s->sectors) + 1;
! 1204: }
! 1205: }
! 1206:
! 1207: static void ide_sector_read(IDEState *s)
! 1208: {
! 1209: int64_t sector_num;
! 1210: int ret, n;
! 1211:
! 1212: s->status = READY_STAT | SEEK_STAT;
! 1213: s->error = 0; /* not needed by IDE spec, but needed by Windows */
! 1214: sector_num = ide_get_sector(s);
! 1215: n = s->nsector;
! 1216: if (n == 0)
! 1217: {
! 1218: /* no more sector to read from disk */
! 1219: ide_transfer_stop(s);
! 1220: }
! 1221: else
! 1222: {
! 1223: #if defined(DEBUG_IDE)
! 1224: printf("read sector=%Ld\n", sector_num);
! 1225: #endif
! 1226: if (n > s->req_nb_sectors)
! 1227: n = s->req_nb_sectors;
! 1228: ret = bdrv_read(s->bs, sector_num, s->io_buffer, n);
! 1229: ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_read);
! 1230: ide_set_irq(s);
! 1231: ide_set_sector(s, sector_num + n);
! 1232: s->nsector -= n;
! 1233: }
! 1234: }
! 1235:
! 1236:
! 1237: static void ide_sector_write(IDEState *s)
! 1238: {
! 1239: int64_t sector_num;
! 1240: int ret, n, n1;
! 1241:
! 1242: s->status = READY_STAT | SEEK_STAT;
! 1243: sector_num = ide_get_sector(s);
! 1244: #if defined(DEBUG_IDE)
! 1245: printf("write sector=%Ld\n", sector_num);
! 1246: #endif
! 1247: n = s->nsector;
! 1248: if (n > s->req_nb_sectors)
! 1249: n = s->req_nb_sectors;
! 1250: ret = bdrv_write(s->bs, sector_num, s->io_buffer, n);
! 1251: s->nsector -= n;
! 1252: if (s->nsector == 0)
! 1253: {
! 1254: /* no more sectors to write */
! 1255: ide_transfer_stop(s);
! 1256: }
! 1257: else
! 1258: {
! 1259: n1 = s->nsector;
! 1260: if (n1 > s->req_nb_sectors)
! 1261: n1 = s->req_nb_sectors;
! 1262: ide_transfer_start(s, s->io_buffer, 512 * n1, ide_sector_write);
! 1263: }
! 1264: ide_set_sector(s, sector_num + n);
! 1265:
! 1266: ide_set_irq(s);
! 1267: }
! 1268:
! 1269:
! 1270: static void ide_atapi_cmd_ok(IDEState *s)
! 1271: {
! 1272: s->error = 0;
! 1273: s->status = READY_STAT;
! 1274: s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
! 1275: ide_set_irq(s);
! 1276: }
! 1277:
! 1278: static void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc)
! 1279: {
! 1280: #ifdef DEBUG_IDE_ATAPI
! 1281: printf("atapi_cmd_error: sense=0x%x asc=0x%x\n", sense_key, asc);
! 1282: #endif
! 1283: s->error = sense_key << 4;
! 1284: s->status = READY_STAT | ERR_STAT;
! 1285: s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
! 1286: s->sense_key = sense_key;
! 1287: s->asc = asc;
! 1288: ide_set_irq(s);
! 1289: }
! 1290:
! 1291: static inline void cpu_to_ube16(uint8_t *buf, int val)
! 1292: {
! 1293: buf[0] = val >> 8;
! 1294: buf[1] = val;
! 1295: }
! 1296:
! 1297: static inline void cpu_to_ube32(uint8_t *buf, unsigned int val)
! 1298: {
! 1299: buf[0] = val >> 24;
! 1300: buf[1] = val >> 16;
! 1301: buf[2] = val >> 8;
! 1302: buf[3] = val;
! 1303: }
! 1304:
! 1305: static inline int ube16_to_cpu(const uint8_t *buf)
! 1306: {
! 1307: return (buf[0] << 8) | buf[1];
! 1308: }
! 1309:
! 1310: static inline int ube32_to_cpu(const uint8_t *buf)
! 1311: {
! 1312: return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
! 1313: }
! 1314:
! 1315: static void lba_to_msf(uint8_t *buf, int lba)
! 1316: {
! 1317: lba += 150;
! 1318: buf[0] = (lba / 75) / 60;
! 1319: buf[1] = (lba / 75) % 60;
! 1320: buf[2] = lba % 75;
! 1321: }
! 1322:
! 1323: static void cd_data_to_raw(uint8_t *buf, int lba)
! 1324: {
! 1325: /* sync bytes */
! 1326: buf[0] = 0x00;
! 1327: memset(buf + 1, 0xff, 10);
! 1328: buf[11] = 0x00;
! 1329: buf += 12;
! 1330: /* MSF */
! 1331: lba_to_msf(buf, lba);
! 1332: buf[3] = 0x01; /* mode 1 data */
! 1333: buf += 4;
! 1334: /* data */
! 1335: buf += 2048;
! 1336: /* XXX: ECC not computed */
! 1337: memset(buf, 0, 288);
! 1338: }
! 1339:
! 1340: static int cd_read_sector(BlockDriverState *bs, int lba, uint8_t *buf,
! 1341: int sector_size)
! 1342: {
! 1343: int ret;
! 1344:
! 1345: switch (sector_size)
! 1346: {
! 1347: case 2048:
! 1348: ret = bdrv_read(bs, (int64_t)lba << 2, buf, 4);
! 1349: break;
! 1350: case 2352:
! 1351: ret = bdrv_read(bs, (int64_t)lba << 2, buf + 16, 4);
! 1352: if (ret < 0)
! 1353: return ret;
! 1354: cd_data_to_raw(buf, lba);
! 1355: break;
! 1356: default:
! 1357: ret = -EIO;
! 1358: break;
! 1359: }
! 1360: return ret;
! 1361: }
! 1362:
! 1363: static void ide_atapi_io_error(IDEState *s, int ret)
! 1364: {
! 1365: /* XXX: handle more errors */
! 1366: if (ret == -ENOMEDIUM)
! 1367: {
! 1368: ide_atapi_cmd_error(s, SENSE_NOT_READY,
! 1369: ASC_MEDIUM_NOT_PRESENT);
! 1370: }
! 1371: else
! 1372: {
! 1373: ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
! 1374: ASC_LOGICAL_BLOCK_OOR);
! 1375: }
! 1376: }
! 1377:
! 1378: /* The whole ATAPI transfer logic is handled in this function */
! 1379: static void ide_atapi_cmd_reply_end(IDEState *s)
! 1380: {
! 1381: int byte_count_limit, size, ret;
! 1382: #ifdef DEBUG_IDE_ATAPI
! 1383: printf("reply: tx_size=%d elem_tx_size=%d index=%d\n",
! 1384: s->packet_transfer_size,
! 1385: s->elementary_transfer_size,
! 1386: s->io_buffer_index);
! 1387: #endif
! 1388: if (s->packet_transfer_size <= 0)
! 1389: {
! 1390: /* end of transfer */
! 1391: ide_transfer_stop(s);
! 1392: s->status = READY_STAT;
! 1393: s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
! 1394: ide_set_irq(s);
! 1395: #ifdef DEBUG_IDE_ATAPI
! 1396: printf("status=0x%x\n", s->status);
! 1397: #endif
! 1398: }
! 1399: else
! 1400: {
! 1401: /* see if a new sector must be read */
! 1402: if (s->lba != -1 && s->io_buffer_index >= s->cd_sector_size)
! 1403: {
! 1404: ret = cd_read_sector(s->bs, s->lba, s->io_buffer, s->cd_sector_size);
! 1405: if (ret < 0)
! 1406: {
! 1407: ide_transfer_stop(s);
! 1408: ide_atapi_io_error(s, ret);
! 1409: return;
! 1410: }
! 1411: s->lba++;
! 1412: s->io_buffer_index = 0;
! 1413: }
! 1414: if (s->elementary_transfer_size > 0)
! 1415: {
! 1416: /* there are some data left to transmit in this elementary
! 1417: transfer */
! 1418: size = s->cd_sector_size - s->io_buffer_index;
! 1419: if (size > s->elementary_transfer_size)
! 1420: size = s->elementary_transfer_size;
! 1421: ide_transfer_start(s, s->io_buffer + s->io_buffer_index,
! 1422: size, ide_atapi_cmd_reply_end);
! 1423: s->packet_transfer_size -= size;
! 1424: s->elementary_transfer_size -= size;
! 1425: s->io_buffer_index += size;
! 1426: }
! 1427: else
! 1428: {
! 1429: /* a new transfer is needed */
! 1430: s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO;
! 1431: byte_count_limit = s->lcyl | (s->hcyl << 8);
! 1432: #ifdef DEBUG_IDE_ATAPI
! 1433: printf("byte_count_limit=%d\n", byte_count_limit);
! 1434: #endif
! 1435: if (byte_count_limit == 0xffff)
! 1436: byte_count_limit--;
! 1437: size = s->packet_transfer_size;
! 1438: if (size > byte_count_limit)
! 1439: {
! 1440: /* byte count limit must be even if this case */
! 1441: if (byte_count_limit & 1)
! 1442: byte_count_limit--;
! 1443: size = byte_count_limit;
! 1444: }
! 1445: s->lcyl = size;
! 1446: s->hcyl = size >> 8;
! 1447: s->elementary_transfer_size = size;
! 1448: /* we cannot transmit more than one sector at a time */
! 1449: if (s->lba != -1)
! 1450: {
! 1451: if (size > (s->cd_sector_size - s->io_buffer_index))
! 1452: size = (s->cd_sector_size - s->io_buffer_index);
! 1453: }
! 1454: ide_transfer_start(s, s->io_buffer + s->io_buffer_index,
! 1455: size, ide_atapi_cmd_reply_end);
! 1456: s->packet_transfer_size -= size;
! 1457: s->elementary_transfer_size -= size;
! 1458: s->io_buffer_index += size;
! 1459: ide_set_irq(s);
! 1460: #ifdef DEBUG_IDE_ATAPI
! 1461: printf("status=0x%x\n", s->status);
! 1462: #endif
! 1463: }
! 1464: }
! 1465: }
! 1466:
! 1467: /* send a reply of 'size' bytes in s->io_buffer to an ATAPI command */
! 1468: static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size)
! 1469: {
! 1470: if (size > max_size)
! 1471: size = max_size;
! 1472: s->lba = -1; /* no sector read */
! 1473: s->packet_transfer_size = size;
! 1474: s->io_buffer_size = size; /* dma: send the reply data as one chunk */
! 1475: s->elementary_transfer_size = 0;
! 1476: s->io_buffer_index = 0;
! 1477:
! 1478: s->status = READY_STAT;
! 1479: ide_atapi_cmd_reply_end(s);
! 1480: }
! 1481:
! 1482: /* start a CD-CDROM read command */
! 1483: static void ide_atapi_cmd_read(IDEState *s, int lba, int nb_sectors,
! 1484: int sector_size)
! 1485: {
! 1486: #ifdef DEBUG_IDE_ATAPI
! 1487: printf("read pio: LBA=%d nb_sectors=%d\n", lba, nb_sectors);
! 1488: #endif
! 1489: s->lba = lba;
! 1490: s->packet_transfer_size = nb_sectors * sector_size;
! 1491: s->elementary_transfer_size = 0;
! 1492: s->io_buffer_index = sector_size;
! 1493: s->cd_sector_size = sector_size;
! 1494:
! 1495: s->status = READY_STAT;
! 1496: ide_atapi_cmd_reply_end(s);
! 1497: }
! 1498:
! 1499:
! 1500: static void ide_atapi_cmd(IDEState *s)
! 1501: {
! 1502: const uint8_t *packet;
! 1503: uint8_t *buf;
! 1504: int max_len;
! 1505:
! 1506: packet = s->io_buffer;
! 1507: buf = s->io_buffer;
! 1508: #ifdef DEBUG_IDE_ATAPI
! 1509: {
! 1510: int i;
! 1511: printf("ATAPI limit=0x%x packet:", s->lcyl | (s->hcyl << 8));
! 1512: for (i = 0; i < ATAPI_PACKET_SIZE; i++)
! 1513: {
! 1514: printf(" %02x", packet[i]);
! 1515: }
! 1516: printf("\n");
! 1517: }
! 1518: #endif
! 1519: switch (s->io_buffer[0])
! 1520: {
! 1521: case GPCMD_TEST_UNIT_READY:
! 1522: if (bdrv_is_inserted(s->bs))
! 1523: {
! 1524: ide_atapi_cmd_ok(s);
! 1525: }
! 1526: else
! 1527: {
! 1528: ide_atapi_cmd_error(s, SENSE_NOT_READY,
! 1529: ASC_MEDIUM_NOT_PRESENT);
! 1530: }
! 1531: break;
! 1532: case GPCMD_MODE_SENSE_6:
! 1533: case GPCMD_MODE_SENSE_10:
! 1534: {
! 1535: int action, code;
! 1536: if (packet[0] == GPCMD_MODE_SENSE_10)
! 1537: max_len = ube16_to_cpu(packet + 7);
! 1538: else
! 1539: max_len = packet[4];
! 1540: action = packet[2] >> 6;
! 1541: code = packet[2] & 0x3f;
! 1542: switch (action)
! 1543: {
! 1544: case 0: /* current values */
! 1545: switch (code)
! 1546: {
! 1547: case 0x01: /* error recovery */
! 1548: cpu_to_ube16(&buf[0], 16 + 6);
! 1549: buf[2] = 0x70;
! 1550: buf[3] = 0;
! 1551: buf[4] = 0;
! 1552: buf[5] = 0;
! 1553: buf[6] = 0;
! 1554: buf[7] = 0;
! 1555:
! 1556: buf[8] = 0x01;
! 1557: buf[9] = 0x06;
! 1558: buf[10] = 0x00;
! 1559: buf[11] = 0x05;
! 1560: buf[12] = 0x00;
! 1561: buf[13] = 0x00;
! 1562: buf[14] = 0x00;
! 1563: buf[15] = 0x00;
! 1564: ide_atapi_cmd_reply(s, 16, max_len);
! 1565: break;
! 1566: case 0x2a:
! 1567: cpu_to_ube16(&buf[0], 28 + 6);
! 1568: buf[2] = 0x70;
! 1569: buf[3] = 0;
! 1570: buf[4] = 0;
! 1571: buf[5] = 0;
! 1572: buf[6] = 0;
! 1573: buf[7] = 0;
! 1574:
! 1575: buf[8] = 0x2a;
! 1576: buf[9] = 0x12;
! 1577: buf[10] = 0x00;
! 1578: buf[11] = 0x00;
! 1579:
! 1580: buf[12] = 0x70;
! 1581: buf[13] = 3 << 5;
! 1582: buf[14] = (1 << 0) | (1 << 3) | (1 << 5);
! 1583: if (bdrv_is_locked(s->bs))
! 1584: buf[6] |= 1 << 1;
! 1585: buf[15] = 0x00;
! 1586: cpu_to_ube16(&buf[16], 706);
! 1587: buf[18] = 0;
! 1588: buf[19] = 2;
! 1589: cpu_to_ube16(&buf[20], 512);
! 1590: cpu_to_ube16(&buf[22], 706);
! 1591: buf[24] = 0;
! 1592: buf[25] = 0;
! 1593: buf[26] = 0;
! 1594: buf[27] = 0;
! 1595: ide_atapi_cmd_reply(s, 28, max_len);
! 1596: break;
! 1597: default:
! 1598: goto error_cmd;
! 1599: }
! 1600: break;
! 1601: case 1: /* changeable values */
! 1602: goto error_cmd;
! 1603: case 2: /* default values */
! 1604: goto error_cmd;
! 1605: default:
! 1606: case 3: /* saved values */
! 1607: ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
! 1608: ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
! 1609: break;
! 1610: }
! 1611: }
! 1612: break;
! 1613: case GPCMD_REQUEST_SENSE:
! 1614: max_len = packet[4];
! 1615: memset(buf, 0, 18);
! 1616: buf[0] = 0x70 | (1 << 7);
! 1617: buf[2] = s->sense_key;
! 1618: buf[7] = 10;
! 1619: buf[12] = s->asc;
! 1620: ide_atapi_cmd_reply(s, 18, max_len);
! 1621: break;
! 1622: case GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
! 1623: if (bdrv_is_inserted(s->bs))
! 1624: {
! 1625: bdrv_set_locked(s->bs, packet[4] & 1);
! 1626: ide_atapi_cmd_ok(s);
! 1627: }
! 1628: else
! 1629: {
! 1630: ide_atapi_cmd_error(s, SENSE_NOT_READY,
! 1631: ASC_MEDIUM_NOT_PRESENT);
! 1632: }
! 1633: break;
! 1634: case GPCMD_READ_10:
! 1635: case GPCMD_READ_12:
! 1636: {
! 1637: int nb_sectors, lba;
! 1638:
! 1639: if (packet[0] == GPCMD_READ_10)
! 1640: nb_sectors = ube16_to_cpu(packet + 7);
! 1641: else
! 1642: nb_sectors = ube32_to_cpu(packet + 6);
! 1643: lba = ube32_to_cpu(packet + 2);
! 1644: if (nb_sectors == 0)
! 1645: {
! 1646: ide_atapi_cmd_ok(s);
! 1647: break;
! 1648: }
! 1649: ide_atapi_cmd_read(s, lba, nb_sectors, 2048);
! 1650: }
! 1651: break;
! 1652: case GPCMD_READ_CD:
! 1653: {
! 1654: int nb_sectors, lba, transfer_request;
! 1655:
! 1656: nb_sectors = (packet[6] << 16) | (packet[7] << 8) | packet[8];
! 1657: lba = ube32_to_cpu(packet + 2);
! 1658: if (nb_sectors == 0)
! 1659: {
! 1660: ide_atapi_cmd_ok(s);
! 1661: break;
! 1662: }
! 1663: transfer_request = packet[9];
! 1664: switch (transfer_request & 0xf8)
! 1665: {
! 1666: case 0x00:
! 1667: /* nothing */
! 1668: ide_atapi_cmd_ok(s);
! 1669: break;
! 1670: case 0x10:
! 1671: /* normal read */
! 1672: ide_atapi_cmd_read(s, lba, nb_sectors, 2048);
! 1673: break;
! 1674: case 0xf8:
! 1675: /* read all data */
! 1676: ide_atapi_cmd_read(s, lba, nb_sectors, 2352);
! 1677: break;
! 1678: default:
! 1679: ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
! 1680: ASC_INV_FIELD_IN_CMD_PACKET);
! 1681: break;
! 1682: }
! 1683: }
! 1684: break;
! 1685: case GPCMD_SEEK:
! 1686: {
! 1687: unsigned int lba;
! 1688: uint64_t total_sectors;
! 1689:
! 1690: bdrv_get_geometry(s->bs, &total_sectors);
! 1691: total_sectors >>= 2;
! 1692: if (total_sectors == 0)
! 1693: {
! 1694: ide_atapi_cmd_error(s, SENSE_NOT_READY,
! 1695: ASC_MEDIUM_NOT_PRESENT);
! 1696: break;
! 1697: }
! 1698: lba = ube32_to_cpu(packet + 2);
! 1699: if (lba >= total_sectors)
! 1700: {
! 1701: ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
! 1702: ASC_LOGICAL_BLOCK_OOR);
! 1703: break;
! 1704: }
! 1705: ide_atapi_cmd_ok(s);
! 1706: }
! 1707: break;
! 1708: case GPCMD_START_STOP_UNIT:
! 1709: {
! 1710: int start, eject;
! 1711: start = packet[4] & 1;
! 1712: eject = (packet[4] >> 1) & 1;
! 1713:
! 1714: if (eject && !start)
! 1715: {
! 1716: /* eject the disk */
! 1717: bdrv_eject(s->bs, 1);
! 1718: }
! 1719: else if (eject && start)
! 1720: {
! 1721: /* close the tray */
! 1722: bdrv_eject(s->bs, 0);
! 1723: }
! 1724: ide_atapi_cmd_ok(s);
! 1725: }
! 1726: break;
! 1727: case GPCMD_MECHANISM_STATUS:
! 1728: {
! 1729: max_len = ube16_to_cpu(packet + 8);
! 1730: cpu_to_ube16(buf, 0);
! 1731: /* no current LBA */
! 1732: buf[2] = 0;
! 1733: buf[3] = 0;
! 1734: buf[4] = 0;
! 1735: buf[5] = 1;
! 1736: cpu_to_ube16(buf + 6, 0);
! 1737: ide_atapi_cmd_reply(s, 8, max_len);
! 1738: }
! 1739: break;
! 1740: case GPCMD_READ_TOC_PMA_ATIP:
! 1741: {
! 1742: int format, msf, start_track, len;
! 1743: uint64_t total_sectors;
! 1744:
! 1745: bdrv_get_geometry(s->bs, &total_sectors);
! 1746: total_sectors >>= 2;
! 1747: if (total_sectors == 0)
! 1748: {
! 1749: ide_atapi_cmd_error(s, SENSE_NOT_READY,
! 1750: ASC_MEDIUM_NOT_PRESENT);
! 1751: break;
! 1752: }
! 1753: max_len = ube16_to_cpu(packet + 7);
! 1754: format = packet[9] >> 6;
! 1755: msf = (packet[1] >> 1) & 1;
! 1756: start_track = packet[6];
! 1757: switch (format)
! 1758: {
! 1759: case 0:
! 1760: fprintf(stderr,"FIXME: cdrom_read_toc");
! 1761: len=-1;
! 1762: //len = cdrom_read_toc(total_sectors, buf, msf, start_track);
! 1763: if (len < 0)
! 1764: goto error_cmd;
! 1765: ide_atapi_cmd_reply(s, len, max_len);
! 1766: break;
! 1767: case 1:
! 1768: /* multi session : only a single session defined */
! 1769: memset(buf, 0, 12);
! 1770: buf[1] = 0x0a;
! 1771: buf[2] = 0x01;
! 1772: buf[3] = 0x01;
! 1773: ide_atapi_cmd_reply(s, 12, max_len);
! 1774: break;
! 1775: case 2:
! 1776: fprintf(stderr,"FIXME: cdrom_read_toc_raw");
! 1777: len=-1;
! 1778: //len = cdrom_read_toc_raw(total_sectors, buf, msf, start_track);
! 1779: if (len < 0)
! 1780: goto error_cmd;
! 1781: ide_atapi_cmd_reply(s, len, max_len);
! 1782: break;
! 1783: default:
! 1784: error_cmd:
! 1785: ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
! 1786: ASC_INV_FIELD_IN_CMD_PACKET);
! 1787: break;
! 1788: }
! 1789: }
! 1790: break;
! 1791: case GPCMD_READ_CDVD_CAPACITY:
! 1792: {
! 1793: uint64_t total_sectors;
! 1794:
! 1795: bdrv_get_geometry(s->bs, &total_sectors);
! 1796: total_sectors >>= 2;
! 1797: if (total_sectors == 0)
! 1798: {
! 1799: ide_atapi_cmd_error(s, SENSE_NOT_READY,
! 1800: ASC_MEDIUM_NOT_PRESENT);
! 1801: break;
! 1802: }
! 1803: /* NOTE: it is really the number of sectors minus 1 */
! 1804: cpu_to_ube32(buf, total_sectors - 1);
! 1805: cpu_to_ube32(buf + 4, 2048);
! 1806: ide_atapi_cmd_reply(s, 8, 8);
! 1807: }
! 1808: break;
! 1809: case GPCMD_READ_DVD_STRUCTURE:
! 1810: {
! 1811: int media = packet[1];
! 1812: int layer = packet[6];
! 1813: int format = packet[2];
! 1814: uint64_t total_sectors;
! 1815:
! 1816: if (media != 0 || layer != 0)
! 1817: {
! 1818: ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
! 1819: ASC_INV_FIELD_IN_CMD_PACKET);
! 1820: }
! 1821:
! 1822: switch (format)
! 1823: {
! 1824: case 0:
! 1825: bdrv_get_geometry(s->bs, &total_sectors);
! 1826: total_sectors >>= 2;
! 1827: if (total_sectors == 0)
! 1828: {
! 1829: ide_atapi_cmd_error(s, SENSE_NOT_READY,
! 1830: ASC_MEDIUM_NOT_PRESENT);
! 1831: break;
! 1832: }
! 1833:
! 1834: memset(buf, 0, 2052);
! 1835:
! 1836: buf[4] = 1; // DVD-ROM, part version 1
! 1837: buf[5] = 0xf; // 120mm disc, maximum rate unspecified
! 1838: buf[6] = 0; // one layer, embossed data
! 1839: buf[7] = 0;
! 1840:
! 1841: cpu_to_ube32(buf + 8, 0);
! 1842: cpu_to_ube32(buf + 12, total_sectors - 1);
! 1843: cpu_to_ube32(buf + 16, total_sectors - 1);
! 1844:
! 1845: cpu_to_be16wu((uint16_t *)buf, 2048 + 4);
! 1846:
! 1847: ide_atapi_cmd_reply(s, 2048 + 3, 2048 + 4);
! 1848: break;
! 1849:
! 1850: default:
! 1851: ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
! 1852: ASC_INV_FIELD_IN_CMD_PACKET);
! 1853: break;
! 1854: }
! 1855: }
! 1856: break;
! 1857: case GPCMD_SET_SPEED:
! 1858: ide_atapi_cmd_ok(s);
! 1859: break;
! 1860: case GPCMD_INQUIRY:
! 1861: max_len = packet[4];
! 1862: buf[0] = 0x05; /* CD-ROM */
! 1863: buf[1] = 0x80; /* removable */
! 1864: buf[2] = 0x00; /* ISO */
! 1865: buf[3] = 0x21; /* ATAPI-2 (XXX: put ATAPI-4 ?) */
! 1866: buf[4] = 31; /* additional length */
! 1867: buf[5] = 0; /* reserved */
! 1868: buf[6] = 0; /* reserved */
! 1869: buf[7] = 0; /* reserved */
! 1870: padstr8(buf + 8, 8, "QEMU");
! 1871: padstr8(buf + 16, 16, "QEMU CD-ROM");
! 1872: padstr8(buf + 32, 4, FW_VERSION);
! 1873: ide_atapi_cmd_reply(s, 36, max_len);
! 1874: break;
! 1875: case GPCMD_GET_CONFIGURATION:
! 1876: {
! 1877: uint64_t total_sectors;
! 1878:
! 1879: /* only feature 0 is supported */
! 1880: if (packet[2] != 0 || packet[3] != 0)
! 1881: {
! 1882: ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
! 1883: ASC_INV_FIELD_IN_CMD_PACKET);
! 1884: break;
! 1885: }
! 1886: memset(buf, 0, 32);
! 1887: bdrv_get_geometry(s->bs, &total_sectors);
! 1888: buf[3] = 16;
! 1889: buf[7] = total_sectors <= 1433600 ? 0x08 : 0x10; /* current profile */
! 1890: buf[10] = 0x10 | 0x1;
! 1891: buf[11] = 0x08; /* size of profile list */
! 1892: buf[13] = 0x10; /* DVD-ROM profile */
! 1893: buf[14] = buf[7] == 0x10; /* (in)active */
! 1894: buf[17] = 0x08; /* CD-ROM profile */
! 1895: buf[18] = buf[7] == 0x08; /* (in)active */
! 1896: ide_atapi_cmd_reply(s, 32, 32);
! 1897: break;
! 1898: }
! 1899: default:
! 1900: ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
! 1901: ASC_ILLEGAL_OPCODE);
! 1902: break;
! 1903: }
! 1904: }
! 1905:
! 1906:
! 1907: /* called when the inserted state of the media has changed */
! 1908: static void cdrom_change_cb(void *opaque)
! 1909: {
! 1910: IDEState *s = opaque;
! 1911: uint64_t nb_sectors;
! 1912:
! 1913: /* XXX: send interrupt too */
! 1914: bdrv_get_geometry(s->bs, &nb_sectors);
! 1915: s->nb_sectors = nb_sectors;
! 1916: }
! 1917:
! 1918: static void ide_cmd_lba48_transform(IDEState *s, int lba48)
! 1919: {
! 1920: s->lba48 = lba48;
! 1921:
! 1922: /* handle the 'magic' 0 nsector count conversion here. to avoid
! 1923: * fiddling with the rest of the read logic, we just store the
! 1924: * full sector count in ->nsector and ignore ->hob_nsector from now
! 1925: */
! 1926: if (!s->lba48)
! 1927: {
! 1928: if (!s->nsector)
! 1929: s->nsector = 256;
! 1930: }
! 1931: else
! 1932: {
! 1933: if (!s->nsector && !s->hob_nsector)
! 1934: s->nsector = 65536;
! 1935: else
! 1936: {
! 1937: int lo = s->nsector;
! 1938: int hi = s->hob_nsector;
! 1939:
! 1940: s->nsector = (hi << 8) | lo;
! 1941: }
! 1942: }
! 1943: }
! 1944:
! 1945: static void ide_clear_hob(IDEState *ide_if)
! 1946: {
! 1947: /* any write clears HOB high bit of device control register */
! 1948: ide_if[0].select &= ~(1 << 7);
! 1949: ide_if[1].select &= ~(1 << 7);
! 1950: }
! 1951:
! 1952: static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
! 1953: {
! 1954: IDEState *ide_if = opaque;
! 1955: IDEState *s;
! 1956: int unit, n;
! 1957: int lba48 = 0;
! 1958:
! 1959: #ifdef DEBUG_IDE
! 1960: printf("IDE: write addr=0x%x val=0x%02x\n", addr, val);
! 1961: #endif
! 1962:
! 1963: addr &= 7;
! 1964: switch (addr)
! 1965: {
! 1966: case 0:
! 1967: break;
! 1968: case 1:
! 1969: ide_clear_hob(ide_if);
! 1970: /* NOTE: data is written to the two drives */
! 1971: ide_if[0].hob_feature = ide_if[0].feature;
! 1972: ide_if[1].hob_feature = ide_if[1].feature;
! 1973: ide_if[0].feature = val;
! 1974: ide_if[1].feature = val;
! 1975: break;
! 1976: case 2:
! 1977: ide_clear_hob(ide_if);
! 1978: ide_if[0].hob_nsector = ide_if[0].nsector;
! 1979: ide_if[1].hob_nsector = ide_if[1].nsector;
! 1980: ide_if[0].nsector = val;
! 1981: ide_if[1].nsector = val;
! 1982: break;
! 1983: case 3:
! 1984: ide_clear_hob(ide_if);
! 1985: ide_if[0].hob_sector = ide_if[0].sector;
! 1986: ide_if[1].hob_sector = ide_if[1].sector;
! 1987: ide_if[0].sector = val;
! 1988: ide_if[1].sector = val;
! 1989: break;
! 1990: case 4:
! 1991: ide_clear_hob(ide_if);
! 1992: ide_if[0].hob_lcyl = ide_if[0].lcyl;
! 1993: ide_if[1].hob_lcyl = ide_if[1].lcyl;
! 1994: ide_if[0].lcyl = val;
! 1995: ide_if[1].lcyl = val;
! 1996: break;
! 1997: case 5:
! 1998: ide_clear_hob(ide_if);
! 1999: ide_if[0].hob_hcyl = ide_if[0].hcyl;
! 2000: ide_if[1].hob_hcyl = ide_if[1].hcyl;
! 2001: ide_if[0].hcyl = val;
! 2002: ide_if[1].hcyl = val;
! 2003: break;
! 2004: case 6:
! 2005: /* FIXME: HOB readback uses bit 7 */
! 2006: ide_if[0].select = (val & ~0x10) | 0xa0;
! 2007: ide_if[1].select = (val | 0x10) | 0xa0;
! 2008: /* select drive */
! 2009: unit = (val >> 4) & 1;
! 2010: s = ide_if + unit;
! 2011: ide_if->cur_drive = s;
! 2012: break;
! 2013: default:
! 2014: case 7:
! 2015: /* command */
! 2016: #if defined(DEBUG_IDE)
! 2017: printf("ide: CMD=%02x\n", val);
! 2018: #endif
! 2019: s = ide_if->cur_drive;
! 2020: /* ignore commands to non existant slave */
! 2021: if (s != ide_if && !s->bs)
! 2022: {
! 2023: fprintf(stderr,"CMD to non-existant slave!\n");
! 2024: break;
! 2025: }
! 2026:
! 2027: switch (val)
! 2028: {
! 2029: case WIN_IDENTIFY:
! 2030: if (s->bs && !s->is_cdrom)
! 2031: {
! 2032: ide_identify(s);
! 2033: s->status = READY_STAT | SEEK_STAT;
! 2034: ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop);
! 2035: }
! 2036: else
! 2037: {
! 2038: if (s->is_cdrom)
! 2039: {
! 2040: ide_set_signature(s);
! 2041: }
! 2042: ide_abort_command(s);
! 2043: }
! 2044: ide_set_irq(s);
! 2045: break;
! 2046: case WIN_SPECIFY:
! 2047: case WIN_RECAL:
! 2048: s->error = 0;
! 2049: s->status = READY_STAT | SEEK_STAT;
! 2050: ide_set_irq(s);
! 2051: break;
! 2052: case WIN_SETMULT:
! 2053: if ((s->nsector & 0xff) != 0 &&
! 2054: ((s->nsector & 0xff) > MAX_MULT_SECTORS ||
! 2055: (s->nsector & (s->nsector - 1)) != 0))
! 2056: {
! 2057: ide_abort_command(s);
! 2058: }
! 2059: else
! 2060: {
! 2061: s->mult_sectors = s->nsector & 0xff;
! 2062: s->status = READY_STAT;
! 2063: }
! 2064: ide_set_irq(s);
! 2065: break;
! 2066: case WIN_VERIFY_EXT:
! 2067: lba48 = 1;
! 2068: case WIN_VERIFY:
! 2069: case WIN_VERIFY_ONCE:
! 2070: /* do sector number check ? */
! 2071: ide_cmd_lba48_transform(s, lba48);
! 2072: s->status = READY_STAT;
! 2073: ide_set_irq(s);
! 2074: break;
! 2075: case WIN_READ_EXT:
! 2076: lba48 = 1;
! 2077: case WIN_READ:
! 2078: case WIN_READ_ONCE:
! 2079: if (!s->bs)
! 2080: goto abort_cmd;
! 2081: ide_cmd_lba48_transform(s, lba48);
! 2082: s->req_nb_sectors = 1;
! 2083: ide_sector_read(s);
! 2084: break;
! 2085: case WIN_WRITE_EXT:
! 2086: lba48 = 1;
! 2087: case WIN_WRITE:
! 2088: case WIN_WRITE_ONCE:
! 2089: case CFA_WRITE_SECT_WO_ERASE:
! 2090: case WIN_WRITE_VERIFY:
! 2091: ide_cmd_lba48_transform(s, lba48);
! 2092: s->error = 0;
! 2093: s->status = SEEK_STAT | READY_STAT;
! 2094: s->req_nb_sectors = 1;
! 2095: ide_transfer_start(s, s->io_buffer, 512, ide_sector_write);
! 2096: s->media_changed = 1;
! 2097: break;
! 2098: case WIN_MULTREAD_EXT:
! 2099: lba48 = 1;
! 2100: case WIN_MULTREAD:
! 2101: if (!s->mult_sectors)
! 2102: goto abort_cmd;
! 2103: ide_cmd_lba48_transform(s, lba48);
! 2104: s->req_nb_sectors = s->mult_sectors;
! 2105: ide_sector_read(s);
! 2106: break;
! 2107: case WIN_MULTWRITE_EXT:
! 2108: lba48 = 1;
! 2109: case WIN_MULTWRITE:
! 2110: case CFA_WRITE_MULTI_WO_ERASE:
! 2111: if (!s->mult_sectors)
! 2112: goto abort_cmd;
! 2113: ide_cmd_lba48_transform(s, lba48);
! 2114: s->error = 0;
! 2115: s->status = SEEK_STAT | READY_STAT;
! 2116: s->req_nb_sectors = s->mult_sectors;
! 2117: n = s->nsector;
! 2118: if (n > s->req_nb_sectors)
! 2119: n = s->req_nb_sectors;
! 2120: ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_write);
! 2121: s->media_changed = 1;
! 2122: break;
! 2123: case WIN_READDMA_EXT:
! 2124: lba48 = 1;
! 2125: case WIN_READDMA:
! 2126: case WIN_READDMA_ONCE:
! 2127: if (!s->bs)
! 2128: goto abort_cmd;
! 2129: ide_cmd_lba48_transform(s, lba48);
! 2130: // ide_sector_read_dma(s);
! 2131: fprintf(stderr, "IDE: DMA read not supported!\n");
! 2132: break;
! 2133: case WIN_WRITEDMA_EXT:
! 2134: lba48 = 1;
! 2135: case WIN_WRITEDMA:
! 2136: case WIN_WRITEDMA_ONCE:
! 2137: if (!s->bs)
! 2138: goto abort_cmd;
! 2139: ide_cmd_lba48_transform(s, lba48);
! 2140: // ide_sector_write_dma(s);
! 2141: fprintf(stderr, "IDE: DMA write not supported!\n");
! 2142: s->media_changed = 1;
! 2143: break;
! 2144: case WIN_READ_NATIVE_MAX_EXT:
! 2145: lba48 = 1;
! 2146: case WIN_READ_NATIVE_MAX:
! 2147: ide_cmd_lba48_transform(s, lba48);
! 2148: ide_set_sector(s, s->nb_sectors - 1);
! 2149: s->status = READY_STAT;
! 2150: ide_set_irq(s);
! 2151: break;
! 2152: case WIN_CHECKPOWERMODE1:
! 2153: case WIN_CHECKPOWERMODE2:
! 2154: s->nsector = 0xff; /* device active or idle */
! 2155: s->status = READY_STAT;
! 2156: ide_set_irq(s);
! 2157: break;
! 2158: case WIN_SETFEATURES:
! 2159: if (!s->bs)
! 2160: goto abort_cmd;
! 2161: /* XXX: valid for CDROM ? */
! 2162: switch (s->feature)
! 2163: {
! 2164: case 0xcc: /* reverting to power-on defaults enable */
! 2165: case 0x66: /* reverting to power-on defaults disable */
! 2166: case 0x02: /* write cache enable */
! 2167: case 0x82: /* write cache disable */
! 2168: case 0xaa: /* read look-ahead enable */
! 2169: case 0x55: /* read look-ahead disable */
! 2170: case 0x05: /* set advanced power management mode */
! 2171: case 0x85: /* disable advanced power management mode */
! 2172: case 0x69: /* NOP */
! 2173: case 0x67: /* NOP */
! 2174: case 0x96: /* NOP */
! 2175: case 0x9a: /* NOP */
! 2176: case 0x42: /* enable Automatic Acoustic Mode */
! 2177: case 0xc2: /* disable Automatic Acoustic Mode */
! 2178: s->status = READY_STAT | SEEK_STAT;
! 2179: ide_set_irq(s);
! 2180: break;
! 2181: case 0x03: /* set transfer mode */
! 2182: {
! 2183: uint8_t val = s->nsector & 0x07;
! 2184:
! 2185: switch (s->nsector >> 3)
! 2186: {
! 2187: case 0x00: /* pio default */
! 2188: case 0x01: /* pio mode */
! 2189: put_le16(s->identify_data + 63,0x07);
! 2190: put_le16(s->identify_data + 88,0x3f);
! 2191: break;
! 2192: case 0x04: /* mdma mode */
! 2193: put_le16(s->identify_data + 63,0x07 | (1 << (val + 8)));
! 2194: put_le16(s->identify_data + 88,0x3f);
! 2195: break;
! 2196: case 0x08: /* udma mode */
! 2197: put_le16(s->identify_data + 63,0x07);
! 2198: put_le16(s->identify_data + 88,0x3f | (1 << (val + 8)));
! 2199: break;
! 2200: default:
! 2201: goto abort_cmd;
! 2202: }
! 2203: s->status = READY_STAT | SEEK_STAT;
! 2204: ide_set_irq(s);
! 2205: break;
! 2206: }
! 2207: default:
! 2208: goto abort_cmd;
! 2209: }
! 2210: break;
! 2211: case WIN_FLUSH_CACHE:
! 2212: case WIN_FLUSH_CACHE_EXT:
! 2213: if (s->bs)
! 2214: bdrv_flush(s->bs);
! 2215: s->status = READY_STAT;
! 2216: ide_set_irq(s);
! 2217: break;
! 2218: case WIN_STANDBY:
! 2219: case WIN_STANDBY2:
! 2220: case WIN_STANDBYNOW1:
! 2221: case WIN_STANDBYNOW2:
! 2222: case WIN_IDLEIMMEDIATE:
! 2223: case CFA_IDLEIMMEDIATE:
! 2224: case WIN_SETIDLE1:
! 2225: case WIN_SETIDLE2:
! 2226: case WIN_SLEEPNOW1:
! 2227: case WIN_SLEEPNOW2:
! 2228: s->status = READY_STAT;
! 2229: ide_set_irq(s);
! 2230: break;
! 2231: /* ATAPI commands */
! 2232: case WIN_PIDENTIFY:
! 2233: if (s->is_cdrom)
! 2234: {
! 2235: ide_atapi_identify(s);
! 2236: s->status = READY_STAT | SEEK_STAT;
! 2237: ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop);
! 2238: }
! 2239: else
! 2240: {
! 2241: ide_abort_command(s);
! 2242: }
! 2243: ide_set_irq(s);
! 2244: break;
! 2245: case WIN_DIAGNOSE:
! 2246: ide_set_signature(s);
! 2247: s->status = 0x00; /* NOTE: READY is _not_ set */
! 2248: s->error = 0x01;
! 2249: ide_set_irq(s);
! 2250: break;
! 2251: case WIN_SRST:
! 2252: if (!s->is_cdrom)
! 2253: goto abort_cmd;
! 2254: ide_set_signature(s);
! 2255: s->status = 0x00; /* NOTE: READY is _not_ set */
! 2256: s->error = 0x01;
! 2257: break;
! 2258: case WIN_PACKETCMD:
! 2259: if (!s->is_cdrom)
! 2260: goto abort_cmd;
! 2261: /* overlapping commands not supported */
! 2262: if (s->feature & 0x02)
! 2263: goto abort_cmd;
! 2264: s->status = READY_STAT;
! 2265: // s->atapi_dma = s->feature & 1;
! 2266: s->nsector = 1;
! 2267: ide_transfer_start(s, s->io_buffer, ATAPI_PACKET_SIZE,
! 2268: ide_atapi_cmd);
! 2269: break;
! 2270: default:
! 2271: abort_cmd:
! 2272: ide_abort_command(s);
! 2273: ide_set_irq(s);
! 2274: break;
! 2275: }
! 2276: }
! 2277: }
! 2278:
! 2279: static uint32_t ide_ioport_read(void *opaque, uint32_t addr1)
! 2280: {
! 2281: IDEState *ide_if = opaque;
! 2282: IDEState *s = ide_if->cur_drive;
! 2283: uint32_t addr;
! 2284: int ret, hob;
! 2285:
! 2286: addr = addr1 & 7;
! 2287: /* FIXME: HOB readback uses bit 7, but it's always set right now */
! 2288: //hob = s->select & (1 << 7);
! 2289: hob = 0;
! 2290: switch (addr)
! 2291: {
! 2292: case 0:
! 2293: ret = 0xff;
! 2294: break;
! 2295: case 1:
! 2296: if (!ide_if[0].bs && !ide_if[1].bs)
! 2297: ret = 0;
! 2298: else if (!hob)
! 2299: ret = s->error;
! 2300: else
! 2301: ret = s->hob_feature;
! 2302: break;
! 2303: case 2:
! 2304: if (!ide_if[0].bs && !ide_if[1].bs)
! 2305: ret = 0;
! 2306: else if (!hob)
! 2307: ret = s->nsector & 0xff;
! 2308: else
! 2309: ret = s->hob_nsector;
! 2310: break;
! 2311: case 3:
! 2312: if (!ide_if[0].bs && !ide_if[1].bs)
! 2313: ret = 0;
! 2314: else if (!hob)
! 2315: ret = s->sector;
! 2316: else
! 2317: ret = s->hob_sector;
! 2318: break;
! 2319: case 4:
! 2320: if (!ide_if[0].bs && !ide_if[1].bs)
! 2321: ret = 0;
! 2322: else if (!hob)
! 2323: ret = s->lcyl;
! 2324: else
! 2325: ret = s->hob_lcyl;
! 2326: break;
! 2327: case 5:
! 2328: if (!ide_if[0].bs && !ide_if[1].bs)
! 2329: ret = 0;
! 2330: else if (!hob)
! 2331: ret = s->hcyl;
! 2332: else
! 2333: ret = s->hob_hcyl;
! 2334: break;
! 2335: case 6:
! 2336: if (!ide_if[0].bs && !ide_if[1].bs)
! 2337: ret = 0;
! 2338: else
! 2339: ret = s->select;
! 2340: break;
! 2341: default:
! 2342: case 7:
! 2343: if ((!ide_if[0].bs && !ide_if[1].bs) ||
! 2344: (s != ide_if && !s->bs))
! 2345: ret = 0;
! 2346: else
! 2347: ret = s->status;
! 2348: /* Lower IRQ */
! 2349: MFP_GPIP |= 0x20;
! 2350: break;
! 2351: }
! 2352: #ifdef DEBUG_IDE
! 2353: printf("ide: read addr=0x%x val=%02x\n", addr1, ret);
! 2354: #endif
! 2355: return ret;
! 2356: }
! 2357:
! 2358: static uint32_t ide_status_read(void *opaque, uint32_t addr)
! 2359: {
! 2360: IDEState *ide_if = opaque;
! 2361: IDEState *s = ide_if->cur_drive;
! 2362: int ret;
! 2363:
! 2364: if ((!ide_if[0].bs && !ide_if[1].bs) ||
! 2365: (s != ide_if && !s->bs))
! 2366: ret = 0;
! 2367: else
! 2368: ret = s->status;
! 2369: #ifdef DEBUG_IDE
! 2370: printf("ide: read status addr=0x%x val=%02x\n", addr, ret);
! 2371: #endif
! 2372: return ret;
! 2373: }
! 2374:
! 2375: static void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val)
! 2376: {
! 2377: IDEState *ide_if = opaque;
! 2378: IDEState *s;
! 2379: int i;
! 2380:
! 2381: #ifdef DEBUG_IDE
! 2382: printf("ide: write control addr=0x%x val=%02x\n", addr, val);
! 2383: #endif
! 2384: /* common for both drives */
! 2385: if (!(ide_if[0].cmd & IDE_CMD_RESET) &&
! 2386: (val & IDE_CMD_RESET))
! 2387: {
! 2388: /* reset low to high */
! 2389: for (i = 0;i < 2; i++)
! 2390: {
! 2391: s = &ide_if[i];
! 2392: s->status = BUSY_STAT | SEEK_STAT;
! 2393: s->error = 0x01;
! 2394: }
! 2395: }
! 2396: else if ((ide_if[0].cmd & IDE_CMD_RESET) &&
! 2397: !(val & IDE_CMD_RESET))
! 2398: {
! 2399: /* high to low */
! 2400: for (i = 0;i < 2; i++)
! 2401: {
! 2402: s = &ide_if[i];
! 2403: if (s->is_cdrom)
! 2404: s->status = 0x00; /* NOTE: READY is _not_ set */
! 2405: else
! 2406: s->status = READY_STAT | SEEK_STAT;
! 2407: ide_set_signature(s);
! 2408: }
! 2409: }
! 2410:
! 2411: ide_if[0].cmd = val;
! 2412: ide_if[1].cmd = val;
! 2413: }
! 2414:
! 2415: static void ide_data_writew(void *opaque, uint32_t addr, uint32_t val)
! 2416: {
! 2417: IDEState *s = ((IDEState *)opaque)->cur_drive;
! 2418: uint8_t *p;
! 2419:
! 2420: p = s->data_ptr;
! 2421: *(uint16_t *)p = le16_to_cpu(val);
! 2422: p += 2;
! 2423: s->data_ptr = p;
! 2424: if (p >= s->data_end)
! 2425: s->end_transfer_func(s);
! 2426: }
! 2427:
! 2428: static uint32_t ide_data_readw(void *opaque, uint32_t addr)
! 2429: {
! 2430: IDEState *s = ((IDEState *)opaque)->cur_drive;
! 2431: uint8_t *p;
! 2432: int ret;
! 2433: p = s->data_ptr;
! 2434: ret = cpu_to_le16(*(uint16_t *)p);
! 2435: p += 2;
! 2436: s->data_ptr = p;
! 2437: if (p >= s->data_end)
! 2438: s->end_transfer_func(s);
! 2439: return ret;
! 2440: }
! 2441:
! 2442: static void ide_data_writel(void *opaque, uint32_t addr, uint32_t val)
! 2443: {
! 2444: IDEState *s = ((IDEState *)opaque)->cur_drive;
! 2445: uint8_t *p;
! 2446:
! 2447: p = s->data_ptr;
! 2448: *(uint32_t *)p = le32_to_cpu(val);
! 2449: p += 4;
! 2450: s->data_ptr = p;
! 2451: if (p >= s->data_end)
! 2452: s->end_transfer_func(s);
! 2453: }
! 2454:
! 2455: static uint32_t ide_data_readl(void *opaque, uint32_t addr)
! 2456: {
! 2457: IDEState *s = ((IDEState *)opaque)->cur_drive;
! 2458: uint8_t *p;
! 2459: int ret;
! 2460:
! 2461: p = s->data_ptr;
! 2462: ret = cpu_to_le32(*(uint32_t *)p);
! 2463: p += 4;
! 2464: s->data_ptr = p;
! 2465: if (p >= s->data_end)
! 2466: s->end_transfer_func(s);
! 2467: return ret;
! 2468: }
! 2469:
! 2470: static void ide_dummy_transfer_stop(IDEState *s)
! 2471: {
! 2472: s->data_ptr = s->io_buffer;
! 2473: s->data_end = s->io_buffer;
! 2474: s->io_buffer[0] = 0xff;
! 2475: s->io_buffer[1] = 0xff;
! 2476: s->io_buffer[2] = 0xff;
! 2477: s->io_buffer[3] = 0xff;
! 2478: }
! 2479:
! 2480: static void ide_reset(IDEState *s)
! 2481: {
! 2482: s->mult_sectors = MAX_MULT_SECTORS;
! 2483: s->cur_drive = s;
! 2484: s->select = 0xa0;
! 2485: s->status = READY_STAT | SEEK_STAT;
! 2486:
! 2487: ide_set_signature(s);
! 2488: /* init the transfer handler so that 0xffff is returned on data
! 2489: accesses */
! 2490: s->end_transfer_func = ide_dummy_transfer_stop;
! 2491: ide_dummy_transfer_stop(s);
! 2492: s->media_changed = 0;
! 2493: }
! 2494:
! 2495: struct partition
! 2496: {
! 2497: uint8_t boot_ind; /* 0x80 - active */
! 2498: uint8_t head; /* starting head */
! 2499: uint8_t sector; /* starting sector */
! 2500: uint8_t cyl; /* starting cylinder */
! 2501: uint8_t sys_ind; /* What partition type */
! 2502: uint8_t end_head; /* end head */
! 2503: uint8_t end_sector; /* end sector */
! 2504: uint8_t end_cyl; /* end cylinder */
! 2505: uint32_t start_sect; /* starting sector counting from 0 */
! 2506: uint32_t nr_sects; /* nr of sectors in partition */
! 2507: } __attribute__((packed));
! 2508:
! 2509: /* try to guess the disk logical geometry from the MSDOS partition table. Return 0 if OK, -1 if could not guess */
! 2510: static int guess_disk_lchs(IDEState *s,
! 2511: int *pcylinders, int *pheads, int *psectors)
! 2512: {
! 2513: uint8_t *buf;
! 2514: int ret, i, heads, sectors, cylinders;
! 2515: struct partition *p;
! 2516: uint32_t nr_sects;
! 2517:
! 2518: buf = qemu_memalign(512, 512);
! 2519: if (buf == NULL)
! 2520: return -1;
! 2521: ret = bdrv_read(s->bs, 0, buf, 1);
! 2522: if (ret < 0)
! 2523: {
! 2524: qemu_free(buf);
! 2525: return -1;
! 2526: }
! 2527: /* test msdos magic */
! 2528: if (buf[510] != 0x55 || buf[511] != 0xaa)
! 2529: {
! 2530: qemu_free(buf);
! 2531: return -1;
! 2532: }
! 2533: for (i = 0; i < 4; i++)
! 2534: {
! 2535: p = ((struct partition *)(buf + 0x1be)) + i;
! 2536: nr_sects = le32_to_cpu(p->nr_sects);
! 2537: if (nr_sects && p->end_head)
! 2538: {
! 2539: /* We make the assumption that the partition terminates on
! 2540: a cylinder boundary */
! 2541: heads = p->end_head + 1;
! 2542: sectors = p->end_sector & 63;
! 2543: if (sectors == 0)
! 2544: continue;
! 2545: cylinders = s->nb_sectors / (heads * sectors);
! 2546: if (cylinders < 1 || cylinders > 16383)
! 2547: continue;
! 2548: *pheads = heads;
! 2549: *psectors = sectors;
! 2550: *pcylinders = cylinders;
! 2551: #if 0
! 2552: printf("guessed geometry: LCHS=%d %d %d\n",
! 2553: cylinders, heads, sectors);
! 2554: #endif
! 2555: qemu_free(buf);
! 2556: return 0;
! 2557: }
! 2558: }
! 2559: qemu_free(buf);
! 2560: return -1;
! 2561: }
! 2562:
! 2563: static void ide_init2(IDEState *ide_state, BlockDriverState *hd0,
! 2564: BlockDriverState *hd1)
! 2565: {
! 2566: IDEState *s;
! 2567: static int drive_serial = 1;
! 2568: int i, cylinders, heads, secs, translation, lba_detected = 0;
! 2569: uint64_t nb_sectors;
! 2570:
! 2571: for (i = 0; i < 2; i++)
! 2572: {
! 2573: s = ide_state + i;
! 2574: s->io_buffer = qemu_memalign(512, MAX_MULT_SECTORS*512 + 4);
! 2575: if (i == 0)
! 2576: s->bs = hd0;
! 2577: else
! 2578: s->bs = hd1;
! 2579: if (s->bs)
! 2580: {
! 2581: bdrv_get_geometry(s->bs, &nb_sectors);
! 2582: s->nb_sectors = nb_sectors;
! 2583: /* if a geometry hint is available, use it */
! 2584: bdrv_get_geometry_hint(s->bs, &cylinders, &heads, &secs);
! 2585: translation = bdrv_get_translation_hint(s->bs);
! 2586: if (cylinders != 0)
! 2587: {
! 2588: s->cylinders = cylinders;
! 2589: s->heads = heads;
! 2590: s->sectors = secs;
! 2591: }
! 2592: else
! 2593: {
! 2594: if (guess_disk_lchs(s, &cylinders, &heads, &secs) == 0)
! 2595: {
! 2596: if (heads > 16)
! 2597: {
! 2598: /* if heads > 16, it means that a BIOS LBA
! 2599: translation was active, so the default
! 2600: hardware geometry is OK */
! 2601: lba_detected = 1;
! 2602: goto default_geometry;
! 2603: }
! 2604: else
! 2605: {
! 2606: s->cylinders = cylinders;
! 2607: s->heads = heads;
! 2608: s->sectors = secs;
! 2609: /* disable any translation to be in sync with
! 2610: the logical geometry */
! 2611: if (translation == BIOS_ATA_TRANSLATION_AUTO)
! 2612: {
! 2613: bdrv_set_translation_hint(s->bs,
! 2614: BIOS_ATA_TRANSLATION_NONE);
! 2615: }
! 2616: }
! 2617: }
! 2618: else
! 2619: {
! 2620: default_geometry:
! 2621: /* if no geometry, use a standard physical disk geometry */
! 2622: cylinders = nb_sectors / (16 * 63);
! 2623: if (cylinders > 16383)
! 2624: cylinders = 16383;
! 2625: else if (cylinders < 2)
! 2626: cylinders = 2;
! 2627: s->cylinders = cylinders;
! 2628: s->heads = 16;
! 2629: s->sectors = 63;
! 2630: if ((lba_detected == 1) && (translation == BIOS_ATA_TRANSLATION_AUTO))
! 2631: {
! 2632: if ((s->cylinders * s->heads) <= 131072)
! 2633: {
! 2634: bdrv_set_translation_hint(s->bs,
! 2635: BIOS_ATA_TRANSLATION_LARGE);
! 2636: }
! 2637: else
! 2638: {
! 2639: bdrv_set_translation_hint(s->bs,
! 2640: BIOS_ATA_TRANSLATION_LBA);
! 2641: }
! 2642: }
! 2643: }
! 2644: bdrv_set_geometry_hint(s->bs, s->cylinders, s->heads, s->sectors);
! 2645: }
! 2646: if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM)
! 2647: {
! 2648: s->is_cdrom = 1;
! 2649: bdrv_set_change_cb(s->bs, cdrom_change_cb, s);
! 2650: }
! 2651: }
! 2652: s->drive_serial = drive_serial++;
! 2653:
! 2654: ide_reset(s);
! 2655: }
! 2656: }
! 2657:
! 2658:
! 2659: /*----------------------------------------------------------------------------*/
! 2660:
! 2661:
! 2662: static BlockDriverState *hd_table[2];
! 2663:
! 2664:
! 2665: /**
! 2666: * Initialize the IDE subsystem
! 2667: */
! 2668: void Ide_Init(void)
! 2669: {
! 2670: if (!ConfigureParams.HardDisk.bUseIdeHardDiskImage)
! 2671: return;
! 2672:
! 2673: opaque_ide_if = malloc(sizeof(IDEState) * 2);
! 2674: hd_table[0] = malloc(sizeof(BlockDriverState));
! 2675: hd_table[1] = malloc(sizeof(BlockDriverState));
! 2676:
! 2677: if (!opaque_ide_if || !hd_table[0] || !hd_table[1])
! 2678: {
! 2679: perror("Ide_Init");
! 2680: return;
! 2681: }
! 2682:
! 2683: memset(opaque_ide_if, 0, sizeof(IDEState) * 2);
! 2684:
! 2685: memset(hd_table[0], 0, sizeof(BlockDriverState));
! 2686: memset(hd_table[1], 0, sizeof(BlockDriverState));
! 2687:
! 2688: bdrv_open(hd_table[0], ConfigureParams.HardDisk.szIdeHardDiskImage, 0);
! 2689:
! 2690: ide_init2(&opaque_ide_if[0], hd_table[0], NULL /*hd_table[1]*/);
! 2691: }
! 2692:
! 2693:
! 2694: /**
! 2695: * Free resources from the IDE subsystem
! 2696: */
! 2697: void Ide_UnInit(void)
! 2698: {
! 2699: int i;
! 2700:
! 2701: for (i = 0; i < 2; i++)
! 2702: {
! 2703: if (hd_table[i])
! 2704: {
! 2705: if (bdrv_is_inserted(hd_table[i]))
! 2706: {
! 2707: bdrv_close(hd_table[i]);
! 2708: }
! 2709: free(hd_table[i]);
! 2710: hd_table[i] = NULL;
! 2711: }
! 2712: }
! 2713:
! 2714: if (opaque_ide_if)
! 2715: free(opaque_ide_if);
! 2716: opaque_ide_if = NULL;
1.1 root 2717: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.