- #include "std.h" 
-   
- #include "emul.h" 
- #include "vars.h" 
-   
- #include "util.h" 
-   
- //#define DUMP_HDD_IO 1 
-   
- const unsigned MAX_DEVICES = MAX_PHYS_HD_DRIVES+2*MAX_PHYS_CD_DRIVES; 
-   
- PHYS_DEVICE phys[MAX_DEVICES]; 
- unsigned n_phys = 0; 
-   
- /* 
- // this function is untested 
- void ATA_DEVICE::exec_mode_select() 
- { 
-    intrq = 1; 
-    command_ok(); 
-   
-    struct { 
-       SCSI_PASS_THROUGH_DIRECT p; 
-       unsigned char sense[0x40]; 
-    } srb = { 0 }, dst; 
-   
-    srb.p.Length = sizeof(SCSI_PASS_THROUGH_DIRECT); 
-    *(CDB*)&srb.p.Cdb = cdb; 
-    srb.p.CdbLength = sizeof(CDB); 
-    srb.p.DataIn = SCSI_IOCTL_DATA_OUT; 
-    srb.p.TimeOutValue = 10; 
-    srb.p.DataBuffer = transbf; 
-    srb.p.DataTransferLength = transcount; 
-    srb.p.SenseInfoLength = sizeof(srb.sense); 
-    srb.p.SenseInfoOffset = sizeof(SCSI_PASS_THROUGH_DIRECT); 
-   
-    DWORD outsize; 
-    int r = DeviceIoControl(hDevice, IOCTL_SCSI_PASS_THROUGH_DIRECT, 
-                            &srb.p, sizeof(srb.p), 
-                            &dst, sizeof(dst), 
-                            &outsize, 0); 
-   
-    if (!r) return; 
-    if (senselen = dst.p.SenseInfoLength) memcpy(sense, dst.sense, senselen); 
-    return; 
- } 
- */ 
-   
- void init_hdd_cd() 
- { 
-    memset(&phys, 0, sizeof phys); 
-    if (conf.ide_skip_real) 
-        return; 
-   
-    n_phys = 0; 
-    n_phys = ATA_PASSER::identify(phys + n_phys, MAX_DEVICES - n_phys); 
-    n_phys += ATAPI_PASSER::identify(phys + n_phys, MAX_DEVICES - n_phys); 
-   
-    if (!n_phys) 
-        errmsg("HDD/CD emulator can't access physical drives"); 
- } 
-   
- static void delstr_spaces(char *dst, char *src) 
- { 
-    for (; *src; src++) 
-       if (*src != ' ') *dst++ = *src; 
-    *dst = 0; 
- } 
-   
- unsigned find_hdd_device(char *name) 
- { 
-    char s2[512]; 
-    delstr_spaces(s2, name); 
- //   if(temp.win9x) 
-    for (unsigned drive = 0; drive < n_phys; drive++) 
-    { 
-       char s1[512]; 
-       delstr_spaces(s1, phys[drive].viewname); 
-       if (!stricmp(s1,s2)) 
-           return drive; 
-    } 
-    return -1U; 
- } 
-   
- void ATA_DEVICE::configure(IDE_CONFIG *cfg) 
- { 
-    atapi_p.close(); ata_p.close(); 
-   
-    c = cfg->c; h = cfg->h; s = cfg->s; lba = cfg->lba; readonly = cfg->readonly; 
-   
-    memset(®, 0, sizeof(reg)); // ╬ўш∙рхь ЁхушёЄЁ√ 
-    command_ok(); // ╤сЁрё√трхь ёюёЄю эшх ш яючшЎш■ яхЁхфрўш фрээ√ї 
-   
-    phys_dev = -1U; 
-    if (!*cfg->image) 
-        return; 
-   
-    PHYS_DEVICE filedev, *dev; 
-    phys_dev = find_hdd_device(cfg->image); 
-    if (phys_dev == -1U) 
-    { 
-       if (cfg->image[0] == '<') 
-       { 
-           errmsg("no physical device %s", cfg->image); 
-           *cfg->image = 0; 
-           return; 
-       } 
-       strcpy(filedev.filename, cfg->image); 
-       filedev.type = cfg->cd ? ATA_FILECD : ATA_FILEHDD; 
-       dev = &filedev; 
-    } 
-    else 
-    { 
-       dev = &phys[phys_dev]; 
-       if (dev->type == ATA_NTHDD) 
-       { 
-          // read geometry from id sector 
-          c = *(unsigned short*)(phys[phys_dev].idsector+2); 
-          h = *(unsigned short*)(phys[phys_dev].idsector+6); 
-          s = *(unsigned short*)(phys[phys_dev].idsector+12); 
-          lba = *(unsigned*)(phys[phys_dev].idsector+0x78); // lba28 
-          if(*((u16*)(phys[phys_dev].idsector+83*2)) & (1<<10)) 
-          { 
-              lba = *(u64*)(phys[phys_dev].idsector+100*2); // lba48 
-          } 
-          if (!lba) 
-              lba = c*h*s; 
-       } 
-    } 
-    DWORD errcode = ERROR_DEVICE_NOT_AVAILABLE; 
-    if (dev->type == ATA_NTHDD || dev->type == ATA_FILEHDD) 
-    { 
-        dev->usage = ATA_OP_USE; 
-        errcode = ata_p.open(dev); 
-        atapi = 0; 
-    } 
-   
-    if (dev->type == ATA_SPTI_CD || dev->type == ATA_ASPI_CD || dev->type == ATA_FILECD) 
-    { 
-        dev->usage = ATA_OP_USE; 
-        errcode = atapi_p.open(dev); 
-        atapi = 1; 
-    } 
-   
-    if (errcode == NO_ERROR) 
-        return; 
-    errmsg("failed to open %s", cfg->image); 
-    err_win32(errcode); 
-    *cfg->image = 0; 
- } 
-   
- void ATA_PORT::reset() 
- { 
-    dev[0].reset(ATA_DEVICE::RESET_HARD); 
-    dev[1].reset(ATA_DEVICE::RESET_HARD); 
- } 
-   
- unsigned char ATA_PORT::read(unsigned n_reg) 
- { 
-    u8 val1 = dev[0].read(n_reg); 
-    u8 val2 = dev[1].read(n_reg); 
-   
-    unsigned devs = 0; 
-    devs |= (dev[0].loaded() ? 1 : 0); 
-    devs |= (dev[1].loaded() ? 2 : 0); 
-   
-    u8 val = 0xFF; 
-    switch(devs) 
-    { 
-    case 1: val = val1; break; 
-    case 2: val = val2; break; 
-    case 3: val = dev[0].selected() ? val1 : val2; break; 
-    } 
-   
- #ifdef DUMP_HDD_IO 
-    printf("R%X:%02X ", n_reg, val); 
- #endif 
-    return val; 
- } 
-   
- unsigned ATA_PORT::read_data() 
- { 
- #ifdef DUMP_HDD_IO 
-    unsigned val = dev[0].read_data() & dev[1].read_data(); 
-    printf("r%04X ", val & 0xFFFF); 
-    return val; 
- #endif 
-    return dev[0].read_data() & dev[1].read_data(); 
- } 
-   
- void ATA_PORT::write(unsigned n_reg, unsigned char data) 
- { 
- #ifdef DUMP_HDD_IO 
-    printf("R%X=%02X ", n_reg, data); 
- #endif 
-    dev[0].write(n_reg, data); 
-    dev[1].write(n_reg, data); 
- } 
-   
- void ATA_PORT::write_data(unsigned data) 
- { 
- #ifdef DUMP_HDD_IO 
-    printf("w%04X ", data & 0xFFFF); 
- #endif 
-    dev[0].write_data(data); 
-    dev[1].write_data(data); 
- } 
-   
- unsigned char ATA_PORT::read_intrq() 
- { 
- #ifdef DUMP_HDD_IO 
- unsigned char i = dev[0].read_intrq() & dev[1].read_intrq(); printf("i%d ", !!i); return i; 
- #endif 
-    return dev[0].read_intrq() & dev[1].read_intrq(); 
- } 
-   
- void ATA_DEVICE::reset_signature(RESET_TYPE mode) 
- { 
-    reg.count = reg.sec = 1; 
-    reg.err = 1; 
-    reg.cyl = atapi ? 0xEB14 : 0; 
-    reg.devhead |= 0x50; 
-    reg.devhead &= (atapi && mode == RESET_SOFT) ? 0x10 : 0; 
-    reg.status = (mode == RESET_SOFT || !atapi) ? STATUS_DRDY | STATUS_DSC : 0; 
- } 
-   
- void ATA_DEVICE::reset(RESET_TYPE mode) 
- { 
-    reg.control = 0; // clear SRST 
-    intrq = 0; 
-    regs_sel = 0; 
-   
-    command_ok(); 
-    reset_signature(mode); 
- } 
-   
- void ATA_DEVICE::command_ok() 
- { 
-    state = S_IDLE; 
-    transptr = -1U; 
-    reg.err = 0; 
-    reg.status = STATUS_DRDY | STATUS_DSC; 
- } 
-   
- unsigned char ATA_DEVICE::read_intrq() 
- { 
-    if (!loaded() || ((reg.devhead ^ device_id) & 0x10) || (reg.control & CONTROL_nIEN)) return 0xFF; 
-    return intrq? 0xFF : 0x00; 
- } 
-   
- unsigned char ATA_DEVICE::read(unsigned n_reg) 
- { 
-    if (!loaded()) 
-        return 0xFF; 
-   
- /* 
-    if ((reg.devhead ^ device_id) & 0x10) 
-    { 
-        return 0xFF; 
-    } 
- */ 
-   
-    if (n_reg == 7) 
-        intrq = 0; 
-    if (n_reg == 8) 
-        n_reg = 7; // read alt.status -> read status 
-   
-    if ((n_reg == 7) && ((reg.devhead ^ device_id) & 0x10)) 
-    { 
-        return 0; 
-    } 
-   
-    if (n_reg == 7 || (reg.status & STATUS_BSY)) 
-    { 
- //         printf("state=%d\n",state); //Alone Coder 
-            return reg.status; 
-    } // BSY=1 or read status 
-    // BSY = 0 
-    //// if (reg.status & STATUS_DRQ) return 0xFF;    // DRQ.  ATA-5: registers should not be queried while DRQ=1, but programs do this! 
-   
-    update_regs(); 
-    // DRQ = 0 
-    unsigned sel = regs_sel; 
-    if(lba > 0xFFFFFFFULL) 
-    { // lba48 
-        sel ^= (reg.control & CONTROL_HOB) ? 1 : 0; 
-    } 
-   
-    return *regs_r[sel][n_reg]; 
- } 
-   
- unsigned ATA_DEVICE::read_data() 
- { 
-    if (!loaded()) 
-        return 0xFFFFFFFF; 
-    if ((reg.devhead ^ device_id) & 0x10) 
-        return 0xFFFFFFFF; 
-    if (/* (reg.status & (STATUS_DRQ | STATUS_BSY)) != STATUS_DRQ ||*/ transptr >= transcount) 
-        return 0xFFFFFFFF; 
-   
-    // DRQ=1, BSY=0, data present 
-    unsigned result = *(unsigned*)(transbf + transptr*2); 
-    transptr++; 
- //   printf(__FUNCTION__" data=0x%04X\n", result & 0xFFFF); 
-   
-    if (transptr < transcount) 
-        return result; 
-    // look to state, prepare next block 
-    if (state == S_READ_ID || state == S_READ_ATAPI) 
-        command_ok(); 
-    if (state == S_READ_SECTORS) 
-    { 
- //       __debugbreak(); 
- //       printf("dev=%d, cnt=%d\n", device_id, reg.count); 
-        if(!--reg.count) 
-            command_ok(); 
-        else 
-        { 
-            next_sector(); 
-            read_sectors(); 
-        } 
-    } 
-   
-    return result; 
- } 
-   
- char ATA_DEVICE::exec_ata_cmd(unsigned char cmd) 
- { 
- //   printf(__FUNCTION__" cmd=%02X\n", cmd); 
-    // EXECUTE DEVICE DIAGNOSTIC for both ATA and ATAPI 
-    if (cmd == 0x90) 
-    { 
-        reset_signature(RESET_SOFT); 
-        return 1; 
-    } 
-   
-    if (atapi) 
-        return 0; 
-   
-    // INITIALIZE DEVICE PARAMETERS 
-    if (cmd == 0x91) 
-    { 
-      // pos = (reg.cyl * h + (reg.devhead & 0x0F)) * s + reg.sec - 1; 
-      h = (reg.devhead & 0xF) + 1; 
-      s = reg.count; 
-      if(s == 0) 
-      { 
-           reg.status = STATUS_DRDY | STATUS_DF | STATUS_DSC | STATUS_ERR; 
-           return 1; 
-      } 
-   
-      c = unsigned(lba / s / h); 
-   
-      reg.status = STATUS_DRDY | STATUS_DSC; 
-      return 1; 
-    } 
-   
-    if ((cmd & 0xFE) == 0x20) // ATA-3 (mandatory), read sectors (20-w-retr/21-wo-retr) 
-    { // cmd #21 obsolette, rqd for is-dos 
- //       printf(__FUNCTION__" sec_cnt=%d\n", reg.count); 
- //       __debugbreak(); 
-        read_sectors(); 
-        return 1; 
-    } 
-   
-    if ((cmd == 0x24) && (lba > 0xFFFFFFFULL)) // ATA-6 read sectors ext (lba48) 
-    { 
-        read_sectors(); 
-        return 1; 
-    } 
-   
-   
-    if((cmd & 0xFE) == 0x40) // ATA-3 (mandatory),  verify sectors 
-    { //rqd for is-dos 
-        verify_sectors(); 
-        return 1; 
-    } 
-   
-    if ((cmd == 0x42) && (lba > 0xFFFFFFFULL)) // ATA-6 verify sectors ext (lba48) 
-    { 
-        verify_sectors(); 
-        return 1; 
-    } 
-   
-    if ((cmd & 0xFE) == 0x30 && !readonly) // ATA-3 (mandatory), write sectors (30-w-retr,31-wo-retr) 
-    { 
-       if (seek()) 
-       { 
-           state = S_WRITE_SECTORS; 
-           reg.status = STATUS_DRQ | STATUS_DSC; 
-           transptr = 0; 
-           transcount = 0x100; 
-       } 
-       return 1; 
-    } 
-   
-    if ((cmd == 0x34) && (lba > 0xFFFFFFFULL) && !readonly) // ATA-6 write sectors ext (lba48) 
-    { 
-       if (seek()) 
-       { 
-           state = S_WRITE_SECTORS; 
-           reg.status = STATUS_DRQ | STATUS_DSC; 
-           transptr = 0; 
-           transcount = 0x100; 
-       } 
-       return 1; 
-    } 
-   
-    if(cmd == 0x50) // format track (фрээр  ЁхрышчрЎш  - эшўхую эх фхырхЄ) 
-    { 
-       reg.sec = 1; 
-       if (seek()) 
-       { 
-           state = S_FORMAT_TRACK; 
-           reg.status = STATUS_DRQ | STATUS_DSC; 
-           transptr = 0; 
-           transcount = 0x100; 
-       } 
-       return 1; 
-    } 
-   
-    if (cmd == 0xEC) 
-    { 
-        prepare_id(); 
-        return 1; 
-    } 
-   
-    if (cmd == 0xE7) 
-    { // FLUSH CACHE 
-       if (ata_p.flush()) 
-       { 
-           command_ok(); 
-           intrq = 1; 
-       } 
-       else 
-           reg.status = STATUS_DRDY | STATUS_DF | STATUS_DSC | STATUS_ERR; // 0x71 
-       return 1; 
-    } 
-   
-    if (cmd == 0x10) 
-    { 
-       recalibrate(); 
-       command_ok(); 
-       intrq = 1; 
-       return 1; 
-    } 
-   
-    if (cmd == 0x70) 
-    { // seek 
-       if (!seek()) 
-           return 1; 
-       command_ok(); 
-       intrq = 1; 
-       return 1; 
-    } 
-   
-    printf("*** unknown ata cmd %02X ***\n", cmd); 
-   
-    return 0; 
- } 
-   
- char ATA_DEVICE::exec_atapi_cmd(unsigned char cmd) 
- { 
-    if (!atapi) 
-        return 0; 
-   
-    // soft reset 
-    if (cmd == 0x08) 
-    { 
-        reset(RESET_SOFT); 
-        return 1; 
-    } 
-    if (cmd == 0xA1) // IDENTIFY PACKET DEVICE 
-    { 
-        prepare_id(); 
-        return 1; 
-    } 
-   
-    if (cmd == 0xA0) 
-    { // packet 
-       state = S_RECV_PACKET; 
-       reg.status = STATUS_DRQ; 
-       reg.intreason = INT_COD; 
-       transptr = 0; 
-       transcount = 6; 
-       return 1; 
-    } 
-   
-    if (cmd == 0xEC) 
-    { 
-        reg.count = 1; 
-        reg.sec = 1; 
-        reg.cyl = 0xEB14; 
-   
-        reg.status = STATUS_DSC | STATUS_DRDY | STATUS_ERR; 
-        reg.err = ERR_ABRT; 
-        state = S_IDLE; 
-        intrq = 1; 
-        return 1; 
-    } 
-   
-    printf("*** unknown atapi cmd %02X ***\n", cmd); 
-    // "command aborted" with ATAPI signature 
-    reg.count = 1; 
-    reg.sec = 1; 
-    reg.cyl = 0xEB14; 
-    return 0; 
- } 
-   
- void ATA_DEVICE::write(unsigned n_reg, unsigned char data) 
- { 
- //   printf("dev=%d, reg=%d, data=%02X\n", device_id, n_reg, data); 
-    if (!loaded()) 
-        return; 
-   
-    reg.control &= ~CONTROL_HOB; 
-   
-    if (n_reg == 1) 
-    { 
-        reg.feat = data; 
-        return; 
-    } 
-   
-    if (n_reg != 7) // ═х ЁхушёЄЁ ъюьрэф 
-    { 
-       *regs_w[regs_sel][n_reg] = data; 
-       regs_sel ^= (lba > 0xFFFFFFFULL) ? 1 : 0; 
-   
-       update_cur(); 
-   
-       if (reg.control & CONTROL_SRST) 
-       { 
- //          printf("dev=%d, reset\n", device_id); 
-           reset(RESET_SRST); 
-       } 
-       return; 
-    } 
-   
-    // execute command! 
-    if (((reg.devhead ^ device_id) & 0x10) && data != 0x90) 
-        return; 
-    if (!(reg.status & STATUS_DRDY) && !atapi) 
-    { 
-        printf("warning: hdd not ready cmd = %02X (ignored)\n", data); 
-        return; 
-    } 
-   
-    reg.err = 0; intrq = 0; 
-   
- //{printf(" [");for (int q=1;q<9;q++) printf("-%02X",regs[q]);printf("]\n");} 
-    if (exec_atapi_cmd(data)) 
-        return; 
-    if (exec_ata_cmd(data)) 
-        return; 
-    reg.status = STATUS_DSC | STATUS_DRDY | STATUS_ERR; 
-    reg.err = ERR_ABRT; 
-    state = S_IDLE; intrq = 1; 
- } 
-   
- void ATA_DEVICE::write_data(unsigned data) 
- { 
-    if (!loaded()) return; 
-    if ((reg.devhead ^ device_id) & 0x10) 
-        return; 
-    if (/* (reg.status & (STATUS_DRQ | STATUS_BSY)) != STATUS_DRQ ||*/ transptr >= transcount) 
-        return; 
-    *(unsigned short*)(transbf + transptr*2) = (unsigned short)data; transptr++; 
-    if (transptr < transcount) 
-        return; 
-    // look to state, prepare next block 
-    if (state == S_WRITE_SECTORS) 
-    { 
-        write_sectors(); 
-        return; 
-    } 
-   
-    if (state == S_FORMAT_TRACK) 
-    { 
-        format_track(); 
-        return; 
-    } 
-   
-    if (state == S_RECV_PACKET) 
-    { 
-        handle_atapi_packet(); 
-        return; 
-    } 
- /*   if (state == S_MODE_SELECT) { exec_mode_select(); return; } */ 
- } 
-   
- char ATA_DEVICE::seek() 
- { 
-    u64 pos; 
-    if (reg.devhead & 0x40) 
-    { 
-       pos = lba_cur; 
-       if (lba_cur >= lba) 
-       { 
- //          printf("seek error: lba %I64u:%I64u\n", lba, pos); 
-   
-           seek_err: 
-           reg.status = STATUS_DRDY | STATUS_DF | STATUS_ERR; 
-           reg.err = ERR_IDNF | ERR_ABRT; 
-           intrq = 1; 
-           return 0; 
-       } 
- //      printf("lba %I64u:%I64u\n", lba, pos); 
-    } 
-    else 
-    { 
-       if (c_cur >= c || h_cur >= h || s_cur > s || s_cur == 0) 
-       { 
- //          printf("seek error: chs %4d/%02d/%02d\n", c_cur,  h_cur, s_cur); 
-           goto seek_err; 
-       } 
-       pos = (c_cur * h + h_cur) * s + s_cur - 1; 
- //      printf("chs %4d/%02d/%02d: %I64u\n", c_cur,  h_cur, s_cur, pos); 
-    } 
- //printf("[seek %I64u]", pos << 9); 
-    if (!ata_p.seek(pos)) 
-    { 
-       reg.status = STATUS_DRDY | STATUS_DF | STATUS_ERR; 
-       reg.err = ERR_IDNF | ERR_ABRT; 
-       intrq = 1; 
-       return 0; 
-    } 
-    return 1; 
- } 
-   
- void ATA_DEVICE::format_track() 
- { 
-    intrq = 1; 
-    if(!seek()) 
-        return; 
-   
-    command_ok(); 
-    return; 
- } 
-   
- void ATA_DEVICE::write_sectors() 
- { 
-    intrq = 1; 
- //printf(" [write] "); 
-    if(!seek()) 
-        return; 
-   
-    if (!ata_p.write_sector(transbf)) 
-    { 
-       reg.status = STATUS_DRDY | STATUS_DSC | STATUS_ERR; 
-       reg.err = ERR_UNC; 
-       state = S_IDLE; 
-       return; 
-    } 
-   
-    if (!--reg.count) 
-    { 
-        command_ok(); 
-        return; 
-    } 
-    next_sector(); 
-   
-    transptr = 0; transcount = 0x100; 
-    state = S_WRITE_SECTORS; 
-    reg.err = 0; 
-    reg.status = STATUS_DRQ | STATUS_DSC; 
- } 
-   
- void ATA_DEVICE::read_sectors() 
- { 
- //   __debugbreak(); 
-    intrq = 1; 
-    if (!seek()) 
-       return; 
-   
-    if (!ata_p.read_sector(transbf)) 
-    { 
-       reg.status = STATUS_DRDY | STATUS_DSC | STATUS_ERR; 
-       reg.err = ERR_UNC | ERR_IDNF; 
-       state = S_IDLE; 
-       return; 
-    } 
-    transptr = 0; 
-    transcount = 0x100; 
-    state = S_READ_SECTORS; 
-    reg.err = 0; 
-    reg.status = STATUS_DRDY | STATUS_DRQ | STATUS_DSC; 
-   
- /* 
-    if(reg.devhead & 0x40) 
-        printf("dev=%d lba=%d\n", device_id, *(unsigned*)(regs+3) & 0x0FFFFFFF); 
-    else 
-        printf("dev=%d c/h/s=%d/%d/%d\n", device_id, reg.cyl, (reg.devhead & 0xF), reg.sec); 
- */ 
- } 
-   
- void ATA_DEVICE::verify_sectors() 
- { 
-    intrq = 1; 
- //   __debugbreak(); 
-   
-    do 
-    { 
-        --n_cur; 
- /* 
-        if(reg.devhead & 0x40) 
-            printf("lba=%d\n", *(unsigned*)(regs+3) & 0x0FFFFFFF); 
-        else 
-            printf("c/h/s=%d/%d/%d\n", reg.cyl, (reg.devhead & 0xF), reg.sec); 
- */ 
-        if (!seek()) 
-            return; 
- /* 
-        u8 Buf[512]; 
-        if (!ata_p.read_sector(Buf)) 
-        { 
-           reg.status = STATUS_DRDY | STATUS_DF | STATUS_CORR | STATUS_DSC | STATUS_ERR; 
-           reg.err = ERR_UNC | ERR_IDNF | ERR_ABRT | ERR_AMNF; 
-           state = S_IDLE; 
-           return; 
-        } 
- */ 
-        if(n_cur) 
-            next_sector(); 
-    }while(n_cur); 
-    command_ok(); 
- } 
-   
- void ATA_DEVICE::next_sector() 
- { 
-    if (reg.devhead & 0x40) 
-    { // LBA 
-       lba_cur++; 
-       return; 
-    } 
-    // need to recalc CHS for every sector, coz ATA registers 
-    // should contain current position on failure 
-    if (s_cur < s) 
-    { 
-        s_cur++; 
-        return; 
-    } 
-    s_cur = 1; 
-   
-    if (++h_cur < h) 
-    { 
-        return; 
-    } 
-    h_cur = 0; 
-    c_cur++; 
- } 
-   
- void ATA_DEVICE::recalibrate() 
- { 
-    lba_cur = 0; 
-    c_cur = 0; 
-    h_cur = 0; 
-    s_cur = 1; 
-   
-    reg.cyl = 0; 
-    reg.devhead &= 0xF0; 
-   
-    if (reg.devhead & 0x40) // LBA 
-    { 
-       reg.sec = 0; 
-       return; 
-    } 
-   
-    reg.sec = 1; 
- } 
-   
- #define TOC_DATA_TRACK          0x04 
-   
- // [vv] ╨рсюЄр ё Їрщыюь - юсЁрчюь фшёър эряЁ ьє■ 
- void ATA_DEVICE::handle_atapi_packet_emulate() 
- { 
- //    printf("%s\n", __FUNCTION__); 
-     memcpy(&atapi_p.cdb, transbf, 12); 
-   
-     switch(atapi_p.cdb.CDB12.OperationCode) 
-     { 
-     case SCSIOP_TEST_UNIT_READY:; // 6 
-           command_ok(); 
-           return; 
-   
-     case SCSIOP_READ:; // 10 
-     { 
-       unsigned cnt = (u32(atapi_p.cdb.CDB10.TransferBlocksMsb) << 8) | atapi_p.cdb.CDB10.TransferBlocksLsb; 
-       unsigned pos = (u32(atapi_p.cdb.CDB10.LogicalBlockByte0) << 24) | 
-                      (u32(atapi_p.cdb.CDB10.LogicalBlockByte1) << 16) | 
-                      (u32(atapi_p.cdb.CDB10.LogicalBlockByte2) << 8) | 
-                      atapi_p.cdb.CDB10.LogicalBlockByte3; 
-   
-       if(cnt * 2048 > sizeof(transbf)) 
-       { 
-           reg.status = STATUS_DRDY | STATUS_DSC | STATUS_ERR; 
-           reg.err = ERR_UNC | ERR_IDNF; 
-           state = S_IDLE; 
-           return; 
-       } 
-   
-       for(unsigned i = 0; i < cnt; i++, pos++) 
-       { 
-           if (!atapi_p.seek(pos)) 
-           { 
-              reg.status = STATUS_DRDY | STATUS_DSC | STATUS_ERR; 
-              reg.err = ERR_UNC | ERR_IDNF; 
-              state = S_IDLE; 
-              return; 
-           } 
-   
-           if (!atapi_p.read_sector(transbf + i * 2048)) 
-           { 
-              reg.status = STATUS_DRDY | STATUS_DSC | STATUS_ERR; 
-              reg.err = ERR_UNC | ERR_IDNF; 
-              state = S_IDLE; 
-              return; 
-           } 
-       } 
-       intrq = 1; 
-       reg.atapi_count = u16(cnt * 2048); 
-       reg.intreason = INT_IO; 
-       reg.status = STATUS_DRQ; 
-       transcount = (cnt * 2048)/2; 
-       transptr = 0; 
-       state = S_READ_ATAPI; 
-       return; 
-     } 
-   
-     case SCSIOP_READ_TOC:; // 10 
-     { 
-       static const u8 TOC_DATA[] = 
-       { 
-         0, 4+8*2 - 2, 1, 0xAA, 
-         0, TOC_DATA_TRACK, 1, 0, 0, 0, 0, 0, 
-         0, TOC_DATA_TRACK, 0xAA, 0, 0, 0, 0, 0, 
-       }; 
-       unsigned len = sizeof(TOC_DATA); 
-       memcpy(transbf, TOC_DATA, len); 
-       reg.atapi_count = u16(len); 
-       reg.intreason = INT_IO; 
-       reg.status = STATUS_DRQ; 
-       transcount = (len + 1)/2; 
-       transptr = 0; 
-       state = S_READ_ATAPI; 
-       return; 
-     } 
-     case SCSIOP_START_STOP_UNIT:; // 10 
-           command_ok(); 
-           return; 
-   
-     case SCSIOP_SET_CD_SPEED:; // 12 
-           command_ok(); 
-           return; 
-     } 
-   
-     printf("*** unknown scsi cmd %02X ***\n", atapi_p.cdb.CDB12.OperationCode); 
-   
-     reg.err = 0; 
-     state = S_IDLE; 
-     reg.status = STATUS_DSC | STATUS_ERR | STATUS_DRDY; 
- } 
-   
- void ATA_DEVICE::handle_atapi_packet() 
- { 
- #if defined(DUMP_HDD_IO) 
-    { 
-        printf(" [packet"); 
-        for (int i = 0; i < 12; i++) 
-            printf("-%02X", transbf[i]); 
-        printf("]\n"); 
-    } 
- #endif 
-    if(phys_dev == -1U) 
-        return handle_atapi_packet_emulate(); 
-   
-    memcpy(&atapi_p.cdb, transbf, 12); 
-   
-    intrq = 1; 
-   
-    if (atapi_p.cdb.MODE_SELECT10.OperationCode == 0x55) 
-    { // MODE SELECT requires additional data from host 
-   
-       state = S_MODE_SELECT; 
-       reg.status = STATUS_DRQ; 
-       reg.intreason = 0; 
-       transptr = 0; 
-       transcount = atapi_p.cdb.MODE_SELECT10.ParameterListLength[0]*0x100 + atapi_p.cdb.MODE_SELECT10.ParameterListLength[1]; 
-       return; 
-    } 
-   
-    if (atapi_p.cdb.CDB6READWRITE.OperationCode == 0x03 && atapi_p.senselen) 
-    { // REQ.SENSE - read cached 
-       memcpy(transbf, atapi_p.sense, atapi_p.senselen); 
-       atapi_p.passed_length = atapi_p.senselen; atapi_p.senselen = 0; // next time read from device 
-       goto ok; 
-    } 
-   
-    if (atapi_p.pass_through(transbf, sizeof transbf)) 
-    { 
-       if (atapi_p.senselen) 
-       { 
-           reg.err = u8(atapi_p.sense[2] << 4); 
-           goto err; 
-       } // err = sense key //win9x hangs on drq after atapi packet when emulator does goto err (see walkaround in SEND_ASPI_CMD) 
-     ok: 
-       if (!atapi_p.cdb.CDB6READWRITE.OperationCode) 
-           atapi_p.passed_length = 0; // bugfix in cdrom driver: TEST UNIT READY has no data 
-       if (!atapi_p.passed_length /* || atapi_p.passed_length == sizeof transbf */ ) 
-       { 
-           command_ok(); 
-           return; 
-       } 
-       reg.atapi_count = u16(atapi_p.passed_length); 
-       reg.intreason = INT_IO; 
-       reg.status = STATUS_DRQ; 
-       transcount = (atapi_p.passed_length+1)/2; 
-           //printf("transcount=%d\n",transcount); //32768 in win9x 
-       transptr = 0; 
-       state = S_READ_ATAPI; 
-    } 
-    else 
-    { // bus error 
-       reg.err = 0; 
-     err: 
-       state = S_IDLE; 
-       reg.status = STATUS_DSC | STATUS_ERR | STATUS_DRDY; 
-    } 
- } 
-   
- void ATA_DEVICE::prepare_id() 
- { 
-    if (phys_dev == -1U) 
-    { 
-       memset(transbf, 0, 512); 
-       make_ata_string(transbf+54, 20, "UNREAL SPECCY HARD DRIVE IMAGE"); 
-       make_ata_string(transbf+20, 10, "0000"); 
-       make_ata_string(transbf+46,  4, VERS_STRING); 
-       *(unsigned short*)transbf = 0x045A; 
-       ((unsigned short*)transbf)[1] = (unsigned short)c; 
-       ((unsigned short*)transbf)[3] = (unsigned short)h; 
-       ((unsigned short*)transbf)[6] = (unsigned short)s; 
-       *(unsigned*)(transbf+60*2) = (lba > 0xFFFFFFFULL) ? 0xFFFFFFF : unsigned(lba); // lba28 
-       ((unsigned short*)transbf)[20] = 3; // a dual ported multi-sector buffer capable of simultaneous transfers with a read caching capability 
-       ((unsigned short*)transbf)[21] = 512; // cache size=256k 
-       ((unsigned short*)transbf)[22] = 4; // ECC bytes 
-       ((unsigned short*)transbf)[49] = 0x200; // LBA supported 
-       ((unsigned short*)transbf)[80] = 0x3E; // support specifications up to ATA-5 
-       ((unsigned short*)transbf)[81] = 0x13; // ATA/ATAPI-5 T13 1321D revision 3 
-       ((unsigned short*)transbf)[82] = 0x60; // supported look-ahead and write cache 
-   
-       if(lba > 0xFFFFFFFULL) 
-       { 
-           ((unsigned short*)transbf)[83] = 0x400; // lba48 supported 
-           ((unsigned short*)transbf)[86] = 0x400; // lba48 supported 
-           *(u64*)(transbf+100*2) = lba; // lba48 
-       } 
-   
-       // make checksum 
-       transbf[510] = 0xA5; 
-       unsigned char cs = 0; 
-       for (unsigned i = 0; i < 511; i++) 
-           cs += transbf[i]; 
-       transbf[511] = 0-cs; 
-    } 
-    else 
-    { // copy as is... 
-       memcpy(transbf, phys[phys_dev].idsector, 512); 
-    } 
-   
-    state = S_READ_ID; 
-    transptr = 0; 
-    transcount = 0x100; 
-    intrq = 1; 
-    reg.status = STATUS_DRDY | STATUS_DRQ | STATUS_DSC; 
-    reg.err = 0; 
- } 
-   
- void ATA_DEVICE::update_regs() 
- { 
-    if(reg.devhead & 0x40) 
-    { // lba 
-        if(lba > 0xFFFFFFFULL) 
-        { // lba48 
-            reg.lba0 = lba_cur & 0xFF; 
-            reg.lba1 = (lba_cur >> 8) & 0xFF; 
-            reg.lba2 = (lba_cur >> 16) & 0xFF; 
-            reg.lba4 = (lba_cur >> 24) & 0xFF; 
-            reg.lba5 = (lba_cur >> 32) & 0xFF; 
-            reg.lba6 = (lba_cur >> 40) & 0xFF; 
-        } 
-        else 
-        { // lba28 
-            reg.lba0 = lba_cur & 0xFF; 
-            reg.lba1 = (lba_cur >> 8) & 0xFF; 
-            reg.lba2 = (lba_cur >> 16) & 0xFF; 
-            reg.lba3 &= ~0xF; 
-            reg.lba3 |= (lba_cur >> 24) & 0xF; 
-        } 
-    } 
-    else 
-    { // chs 
-        reg.cyl = u16(c_cur); 
-        reg.devhead &= ~0xF; 
-        reg.devhead |= h_cur & 0xF; 
-        reg.sec = u8(s_cur); 
-    } 
- } 
-   
- void ATA_DEVICE::update_cur() 
- { 
-    n_cur = reg.count; 
-    if(lba > 0xFFFFFFFULL) 
-    { // lba48 
-        lba_cur = reg.lba0 | (u64(reg.lba1) << 8) | (u64(reg.lba2) << 16) | (u64(reg.lba4) << 24) | (u64(reg.lba5) << 32) | (u64(reg.lba6) << 40); 
-        n_cur |= unsigned(reg.count1 << 8); 
-    } 
-    else 
-    { // lba28 
-        lba_cur = reg.lba0 | (u64(reg.lba1) << 8) | (u64(reg.lba2) << 16) | (u64(reg.lba3 & 0xF) << 24); 
-    } 
-   
-    c_cur = reg.cyl; 
-    h_cur = reg.devhead & 0xF; 
-    s_cur = reg.sec; 
- } 
-