Annotation of hatari/src/ide.c, revision 1.1.1.2

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.