Subversion Repositories pentevo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
716 lvd 1
#include "std.h"
2
 
3
#include "emul.h"
4
#include "vars.h"
5
 
6
#include "util.h"
7
 
8
//#define DUMP_HDD_IO 1
9
 
10
const int MAX_DEVICES = MAX_PHYS_HD_DRIVES+2*MAX_PHYS_CD_DRIVES;
11
 
12
PHYS_DEVICE phys[MAX_DEVICES];
13
int n_phys = 0;
14
 
15
/*
16
// this function is untested
17
void ATA_DEVICE::exec_mode_select()
18
{
19
   intrq = 1;
20
   command_ok();
21
 
22
   struct {
23
      SCSI_PASS_THROUGH_DIRECT p;
24
      unsigned char sense[0x40];
25
   } srb = { 0 }, dst;
26
 
27
   srb.p.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
28
   *(CDB*)&srb.p.Cdb = cdb;
29
   srb.p.CdbLength = sizeof(CDB);
30
   srb.p.DataIn = SCSI_IOCTL_DATA_OUT;
31
   srb.p.TimeOutValue = 10;
32
   srb.p.DataBuffer = transbf;
33
   srb.p.DataTransferLength = transcount;
34
   srb.p.SenseInfoLength = sizeof(srb.sense);
35
   srb.p.SenseInfoOffset = sizeof(SCSI_PASS_THROUGH_DIRECT);
36
 
37
   DWORD outsize;
38
   int r = DeviceIoControl(hDevice, IOCTL_SCSI_PASS_THROUGH_DIRECT,
39
                           &srb.p, sizeof(srb.p),
40
                           &dst, sizeof(dst),
41
                           &outsize, 0);
42
 
43
   if (!r) return;
44
   if (senselen = dst.p.SenseInfoLength) memcpy(sense, dst.sense, senselen);
45
   return;
46
}
47
*/
48
 
49
void init_hdd_cd()
50
{
51
   memset(&phys, 0, sizeof phys);
52
   if (conf.ide_skip_real)
53
       return;
54
 
55
   n_phys = 0;
56
   n_phys = ATA_PASSER::identify(phys + n_phys, MAX_DEVICES - n_phys);
57
   n_phys += ATAPI_PASSER::identify(phys + n_phys, MAX_DEVICES - n_phys);
58
 
59
   if (!n_phys)
60
       errmsg("HDD/CD emulator can't access physical drives");
61
}
62
 
63
void delstr_spaces(char *dst, char *src)
64
{
65
   for (; *src; src++)
66
      if (*src != ' ') *dst++ = *src;
67
   *dst = 0;
68
}
69
 
70
unsigned find_hdd_device(char *name)
71
{
72
   char s2[512];
73
   delstr_spaces(s2, name);
74
//   if(temp.win9x)
75
   for (int drive = 0; drive < n_phys; drive++)
76
   {
77
      char s1[512];
78
      delstr_spaces(s1, phys[drive].viewname);
79
      if (!stricmp(s1,s2))
80
          return drive;
81
   }
82
   return -1;
83
}
84
 
85
void ATA_DEVICE::configure(IDE_CONFIG *cfg)
86
{
87
   atapi_p.close(); ata_p.close();
88
 
89
   c = cfg->c, h = cfg->h, s = cfg->s, lba = cfg->lba; readonly = cfg->readonly;
90
 
91
   memset(&reg, 0, sizeof(reg)); // Очищаем регистры
92
   command_ok(); // Сбрасываем состояние и позицию передачи данных
93
 
94
   phys_dev = -1;
95
   if (!*cfg->image)
96
       return;
97
 
98
   PHYS_DEVICE filedev, *dev;
99
   phys_dev = find_hdd_device(cfg->image);
100
   if (phys_dev == -1)
101
   {
102
      if (cfg->image[0] == '<')
103
      {
104
          errmsg("no physical device %s", cfg->image);
105
          *cfg->image = 0;
106
          return;
107
      }
108
      strcpy(filedev.filename, cfg->image);
109
      filedev.type = cfg->cd ? ATA_FILECD : ATA_FILEHDD;
110
      dev = &filedev;
111
   }
112
   else
113
   {
114
      dev = &phys[phys_dev];
115
      if (dev->type == ATA_NTHDD)
116
      {
117
         // read geometry from id sector
118
         c = *(unsigned short*)(phys[phys_dev].idsector+2);
119
         h = *(unsigned short*)(phys[phys_dev].idsector+6);
120
         s = *(unsigned short*)(phys[phys_dev].idsector+12);
121
         lba = *(unsigned*)(phys[phys_dev].idsector+0x78); // lba28
122
         if(*((u16*)(phys[phys_dev].idsector+83*2)) & (1<<10))
123
         {
124
             lba = *(u64*)(phys[phys_dev].idsector+100*2); // lba48
125
         }
126
         if (!lba)
127
             lba = c*h*s;
128
      }
129
   }
130
   DWORD errcode;
131
   if (dev->type == ATA_NTHDD || dev->type == ATA_FILEHDD)
132
   {
133
       dev->usage = ATA_OP_USE;
134
       errcode = ata_p.open(dev);
135
       atapi = 0;
136
   }
137
 
138
   if (dev->type == ATA_SPTI_CD || dev->type == ATA_ASPI_CD || dev->type == ATA_FILECD)
139
   {
140
       dev->usage = ATA_OP_USE;
141
       errcode = atapi_p.open(dev);
142
       atapi = 1;
143
   }
144
 
145
   if (errcode == NO_ERROR)
146
       return;
147
   errmsg("failed to open %s", cfg->image);
148
   err_win32(errcode);
149
   *cfg->image = 0;
150
}
151
 
152
void ATA_PORT::reset()
153
{
154
   dev[0].reset(ATA_DEVICE::RESET_HARD);
155
   dev[1].reset(ATA_DEVICE::RESET_HARD);
156
}
157
 
158
unsigned char ATA_PORT::read(unsigned n_reg)
159
{
160
   u8 val1 = dev[0].read(n_reg);
161
   u8 val2 = dev[1].read(n_reg);
162
 
163
   unsigned devs = 0;
164
   devs |= (dev[0].loaded() ? 1 : 0);
165
   devs |= (dev[1].loaded() ? 2 : 0);
166
 
167
   u8 val = 0xFF;
168
   switch(devs)
169
   {
170
   case 1: val = val1; break;
171
   case 2: val = val2; break;
172
   case 3: val = dev[0].selected() ? val1 : val2; break;
173
   }
174
 
175
#ifdef DUMP_HDD_IO
176
   printf("R%X:%02X ", n_reg, val);
177
#endif
178
   return val;
179
}
180
 
181
unsigned ATA_PORT::read_data()
182
{
183
#ifdef DUMP_HDD_IO
184
   unsigned val = dev[0].read_data() & dev[1].read_data();
185
   printf("r%04X ", val & 0xFFFF);
186
   return val;
187
#endif
188
   return dev[0].read_data() & dev[1].read_data();
189
}
190
 
191
void ATA_PORT::write(unsigned n_reg, unsigned char data)
192
{
193
#ifdef DUMP_HDD_IO
194
   printf("R%X=%02X ", n_reg, data);
195
#endif
196
   dev[0].write(n_reg, data);
197
   dev[1].write(n_reg, data);
198
}
199
 
200
void ATA_PORT::write_data(unsigned data)
201
{
202
#ifdef DUMP_HDD_IO
203
   printf("w%04X ", data & 0xFFFF);
204
#endif
205
   dev[0].write_data(data);
206
   dev[1].write_data(data);
207
}
208
 
209
unsigned char ATA_PORT::read_intrq()
210
{
211
#ifdef DUMP_HDD_IO
212
unsigned char i = dev[0].read_intrq() & dev[1].read_intrq(); printf("i%d ", !!i); return i;
213
#endif
214
   return dev[0].read_intrq() & dev[1].read_intrq();
215
}
216
 
217
void ATA_DEVICE::reset_signature(RESET_TYPE mode)
218
{
219
   reg.count = reg.sec = 1;
220
   reg.err = 1;
221
   reg.cyl = atapi ? 0xEB14 : 0;
222
   reg.devhead |= 0x50;
223
   reg.devhead &= (atapi && mode == RESET_SOFT) ? 0x10 : 0;
224
   reg.status = (mode == RESET_SOFT || !atapi) ? STATUS_DRDY | STATUS_DSC : 0;
225
}
226
 
227
void ATA_DEVICE::reset(RESET_TYPE mode)
228
{
229
   reg.control = 0; // clear SRST
230
   intrq = 0;
231
   regs_sel = 0;
232
 
233
   command_ok();
234
   reset_signature(mode);
235
}
236
 
237
void ATA_DEVICE::command_ok()
238
{
239
   state = S_IDLE;
240
   transptr = -1;
241
   reg.err = 0;
242
   reg.status = STATUS_DRDY | STATUS_DSC;
243
}
244
 
245
unsigned char ATA_DEVICE::read_intrq()
246
{
247
   if (!loaded() || ((reg.devhead ^ device_id) & 0x10) || (reg.control & CONTROL_nIEN)) return 0xFF;
248
   return intrq? 0xFF : 0x00;
249
}
250
 
251
unsigned char ATA_DEVICE::read(unsigned n_reg)
252
{
253
   if (!loaded())
254
       return 0xFF;
255
 
256
/*
257
   if ((reg.devhead ^ device_id) & 0x10)
258
   {
259
       return 0xFF;
260
   }
261
*/
262
 
263
   if (n_reg == 7)
264
       intrq = 0;
265
   if (n_reg == 8)
266
       n_reg = 7; // read alt.status -> read status
267
 
268
   if ((n_reg == 7) && ((reg.devhead ^ device_id) & 0x10))
269
   {
270
       return 0;
271
   }
272
 
273
   if (n_reg == 7 || (reg.status & STATUS_BSY))
274
   {
275
//         printf("state=%d\n",state); //Alone Coder
276
           return reg.status;
277
   } // BSY=1 or read status
278
   // BSY = 0
279
   //// if (reg.status & STATUS_DRQ) return 0xFF;    // DRQ.  ATA-5: registers should not be queried while DRQ=1, but programs do this!
280
 
281
   update_regs();
282
   // DRQ = 0
283
   unsigned sel = regs_sel;
284
   if(lba > 0xFFFFFFFULL)
285
   { // lba48
286
       sel ^= (reg.control & CONTROL_HOB) ? 1 : 0;
287
   }
288
 
289
   return *regs_r[sel][n_reg];
290
}
291
 
292
unsigned ATA_DEVICE::read_data()
293
{
294
   if (!loaded())
295
       return 0xFFFFFFFF;
296
   if ((reg.devhead ^ device_id) & 0x10)
297
       return 0xFFFFFFFF;
298
   if (/* (reg.status & (STATUS_DRQ | STATUS_BSY)) != STATUS_DRQ ||*/ transptr >= transcount)
299
       return 0xFFFFFFFF;
300
 
301
   // DRQ=1, BSY=0, data present
302
   unsigned result = *(unsigned*)(transbf + transptr*2);
303
   transptr++;
304
//   printf(__FUNCTION__" data=0x%04X\n", result & 0xFFFF);
305
 
306
   if (transptr < transcount)
307
       return result;
308
   // look to state, prepare next block
309
   if (state == S_READ_ID || state == S_READ_ATAPI)
310
       command_ok();
311
   if (state == S_READ_SECTORS)
312
   {
313
//       __debugbreak();
314
//       printf("dev=%d, cnt=%d\n", device_id, reg.count);
315
       if(!--reg.count)
316
           command_ok();
317
       else
318
       {
319
           next_sector();
320
           read_sectors();
321
       }
322
   }
323
 
324
   return result;
325
}
326
 
327
char ATA_DEVICE::exec_ata_cmd(unsigned char cmd)
328
{
329
//   printf(__FUNCTION__" cmd=%02X\n", cmd);
330
   // EXECUTE DEVICE DIAGNOSTIC for both ATA and ATAPI
331
   if (cmd == 0x90)
332
   {
333
       reset_signature(RESET_SOFT);
334
       return 1;
335
   }
336
 
337
   if (atapi)
338
       return 0;
339
 
340
   // INITIALIZE DEVICE PARAMETERS
341
   if (cmd == 0x91)
342
   {
343
     // pos = (reg.cyl * h + (reg.devhead & 0x0F)) * s + reg.sec - 1;
344
     h = (reg.devhead & 0xF) + 1;
345
     s = reg.count;
346
     if(s == 0)
347
     {
348
          reg.status = STATUS_DRDY | STATUS_DF | STATUS_DSC | STATUS_ERR;
349
          return 1;
350
     }
351
 
352
     c = lba / s / h;
353
 
354
     reg.status = STATUS_DRDY | STATUS_DSC;
355
     return 1;
356
   }
357
 
358
   if ((cmd & 0xFE) == 0x20) // ATA-3 (mandatory), read sectors (20-w-retr/21-wo-retr)
359
   { // cmd #21 obsolette, rqd for is-dos
360
//       printf(__FUNCTION__" sec_cnt=%d\n", reg.count);
361
//       __debugbreak();
362
       read_sectors();
363
       return 1;
364
   }
365
 
366
   if ((cmd == 0x24) && (lba > 0xFFFFFFFULL)) // ATA-6 read sectors ext (lba48)
367
   {
368
       read_sectors();
369
       return 1;
370
   }
371
 
372
 
373
   if((cmd & 0xFE) == 0x40) // ATA-3 (mandatory),  verify sectors
374
   { //rqd for is-dos
375
       verify_sectors();
376
       return 1;
377
   }
378
 
379
   if ((cmd == 0x42) && (lba > 0xFFFFFFFULL)) // ATA-6 verify sectors ext (lba48)
380
   {
381
       verify_sectors();
382
       return 1;
383
   }
384
 
385
   if ((cmd & 0xFE) == 0x30 && !readonly) // ATA-3 (mandatory), write sectors (30-w-retr,31-wo-retr)
386
   {
387
      if (seek())
388
      {
389
          state = S_WRITE_SECTORS;
390
          reg.status = STATUS_DRQ | STATUS_DSC;
391
          transptr = 0;
392
          transcount = 0x100;
393
      }
394
      return 1;
395
   }
396
 
397
   if ((cmd == 0x34) && (lba > 0xFFFFFFFULL) && !readonly) // ATA-6 write sectors ext (lba48)
398
   {
399
      if (seek())
400
      {
401
          state = S_WRITE_SECTORS;
402
          reg.status = STATUS_DRQ | STATUS_DSC;
403
          transptr = 0;
404
          transcount = 0x100;
405
      }
406
      return 1;
407
   }
408
 
409
   if(cmd == 0x50) // format track (данная реализация - ничего не делает)
410
   {
411
      reg.sec = 1;
412
      if (seek())
413
      {
414
          state = S_FORMAT_TRACK;
415
          reg.status = STATUS_DRQ | STATUS_DSC;
416
          transptr = 0;
417
          transcount = 0x100;
418
      }
419
      return 1;
420
   }
421
 
422
   if (cmd == 0xEC)
423
   {
424
       prepare_id();
425
       return 1;
426
   }
427
 
428
   if (cmd == 0xE7)
429
   { // FLUSH CACHE
430
      if (ata_p.flush())
431
      {
432
          command_ok();
433
          intrq = 1;
434
      }
435
      else
436
          reg.status = STATUS_DRDY | STATUS_DF | STATUS_DSC | STATUS_ERR; // 0x71
437
      return 1;
438
   }
439
 
440
   if (cmd == 0x10)
441
   {
442
      recalibrate();
443
      command_ok();
444
      intrq = 1;
445
      return 1;
446
   }
447
 
448
   if (cmd == 0x70)
449
   { // seek
450
      if (!seek())
451
          return 1;
452
      command_ok();
453
      intrq = 1;
454
      return 1;
455
   }
456
 
457
   printf("*** unknown ata cmd %02X ***\n", cmd);
458
 
459
   return 0;
460
}
461
 
462
char ATA_DEVICE::exec_atapi_cmd(unsigned char cmd)
463
{
464
   if (!atapi)
465
       return 0;
466
 
467
   // soft reset
468
   if (cmd == 0x08)
469
   {
470
       reset(RESET_SOFT);
471
       return 1;
472
   }
473
   if (cmd == 0xA1) // IDENTIFY PACKET DEVICE
474
   {
475
       prepare_id();
476
       return 1;
477
   }
478
 
479
   if (cmd == 0xA0)
480
   { // packet
481
      state = S_RECV_PACKET;
482
      reg.status = STATUS_DRQ;
483
      reg.intreason = INT_COD;
484
      transptr = 0;
485
      transcount = 6;
486
      return 1;
487
   }
488
 
489
   if (cmd == 0xEC)
490
   {
491
       reg.count = 1;
492
       reg.sec = 1;
493
       reg.cyl = 0xEB14;
494
 
495
       reg.status = STATUS_DSC | STATUS_DRDY | STATUS_ERR;
496
       reg.err = ERR_ABRT;
497
       state = S_IDLE;
498
       intrq = 1;
499
       return 1;
500
   }
501
 
502
   printf("*** unknown atapi cmd %02X ***\n", cmd);
503
   // "command aborted" with ATAPI signature
504
   reg.count = 1;
505
   reg.sec = 1;
506
   reg.cyl = 0xEB14;
507
   return 0;
508
}
509
 
510
void ATA_DEVICE::write(unsigned n_reg, unsigned char data)
511
{
512
//   printf("dev=%d, reg=%d, data=%02X\n", device_id, n_reg, data);
513
   if (!loaded())
514
       return;
515
 
516
   reg.control &= ~CONTROL_HOB;
517
 
518
   if (n_reg == 1)
519
   {
520
       reg.feat = data;
521
       return;
522
   }
523
 
524
   if (n_reg != 7) // Не регистр команд
525
   {
526
      *regs_w[regs_sel][n_reg] = data;
527
      regs_sel ^= (lba > 0xFFFFFFFULL) ? 1 : 0;
528
 
529
      update_cur();
530
 
531
      if (reg.control & CONTROL_SRST)
532
      {
533
//          printf("dev=%d, reset\n", device_id);
534
          reset(RESET_SRST);
535
      }
536
      return;
537
   }
538
 
539
   // execute command!
540
   if (((reg.devhead ^ device_id) & 0x10) && data != 0x90)
541
       return;
542
   if (!(reg.status & STATUS_DRDY) && !atapi)
543
   {
544
       printf("warning: hdd not ready cmd = %02X (ignored)\n", data);
545
       return;
546
   }
547
 
548
   reg.err = 0; intrq = 0;
549
 
550
//{printf(" [");for (int q=1;q<9;q++) printf("-%02X",regs[q]);printf("]\n");}
551
   if (exec_atapi_cmd(data))
552
       return;
553
   if (exec_ata_cmd(data))
554
       return;
555
   reg.status = STATUS_DSC | STATUS_DRDY | STATUS_ERR;
556
   reg.err = ERR_ABRT;
557
   state = S_IDLE; intrq = 1;
558
}
559
 
560
void ATA_DEVICE::write_data(unsigned data)
561
{
562
   if (!loaded()) return;
563
   if ((reg.devhead ^ device_id) & 0x10)
564
       return;
565
   if (/* (reg.status & (STATUS_DRQ | STATUS_BSY)) != STATUS_DRQ ||*/ transptr >= transcount)
566
       return;
567
   *(unsigned short*)(transbf + transptr*2) = (unsigned short)data; transptr++;
568
   if (transptr < transcount)
569
       return;
570
   // look to state, prepare next block
571
   if (state == S_WRITE_SECTORS)
572
   {
573
       write_sectors();
574
       return;
575
   }
576
 
577
   if (state == S_FORMAT_TRACK)
578
   {
579
       format_track();
580
       return;
581
   }
582
 
583
   if (state == S_RECV_PACKET)
584
   {
585
       handle_atapi_packet();
586
       return;
587
   }
588
/*   if (state == S_MODE_SELECT) { exec_mode_select(); return; } */
589
}
590
 
591
char ATA_DEVICE::seek()
592
{
593
   u64 pos;
594
   if (reg.devhead & 0x40)
595
   {
596
      pos = lba_cur;
597
      if (lba_cur >= lba)
598
      {
599
//          printf("seek error: lba %I64u:%I64u\n", lba, pos);
600
 
601
          seek_err:
602
          reg.status = STATUS_DRDY | STATUS_DF | STATUS_ERR;
603
          reg.err = ERR_IDNF | ERR_ABRT;
604
          intrq = 1;
605
          return 0;
606
      }
607
//      printf("lba %I64u:%I64u\n", lba, pos);
608
   }
609
   else
610
   {
611
      if (c_cur >= c || h_cur >= h || s_cur > s || s_cur == 0)
612
      {
613
//          printf("seek error: chs %4d/%02d/%02d\n", c_cur,  h_cur, s_cur);
614
          goto seek_err;
615
      }
616
      pos = (c_cur * h + h_cur) * s + s_cur - 1;
617
//      printf("chs %4d/%02d/%02d: %I64u\n", c_cur,  h_cur, s_cur, pos);
618
   }
619
//printf("[seek %I64u]", pos << 9);
620
   if (!ata_p.seek(pos))
621
   {
622
      reg.status = STATUS_DRDY | STATUS_DF | STATUS_ERR;
623
      reg.err = ERR_IDNF | ERR_ABRT;
624
      intrq = 1;
625
      return 0;
626
   }
627
   return 1;
628
}
629
 
630
void ATA_DEVICE::format_track()
631
{
632
   intrq = 1;
633
   if(!seek())
634
       return;
635
 
636
   command_ok();
637
   return;
638
}
639
 
640
void ATA_DEVICE::write_sectors()
641
{
642
   intrq = 1;
643
//printf(" [write] ");
644
   if(!seek())
645
       return;
646
 
647
   if (!ata_p.write_sector(transbf))
648
   {
649
      reg.status = STATUS_DRDY | STATUS_DSC | STATUS_ERR;
650
      reg.err = ERR_UNC;
651
      state = S_IDLE;
652
      return;
653
   }
654
 
655
   if (!--reg.count)
656
   {
657
       command_ok();
658
       return;
659
   }
660
   next_sector();
661
 
662
   transptr = 0, transcount = 0x100;
663
   state = S_WRITE_SECTORS;
664
   reg.err = 0;
665
   reg.status = STATUS_DRQ | STATUS_DSC;
666
}
667
 
668
void ATA_DEVICE::read_sectors()
669
{
670
//   __debugbreak();
671
   intrq = 1;
672
   if (!seek())
673
      return;
674
 
675
   if (!ata_p.read_sector(transbf))
676
   {
677
      reg.status = STATUS_DRDY | STATUS_DSC | STATUS_ERR;
678
      reg.err = ERR_UNC | ERR_IDNF;
679
      state = S_IDLE;
680
      return;
681
   }
682
   transptr = 0;
683
   transcount = 0x100;
684
   state = S_READ_SECTORS;
685
   reg.err = 0;
686
   reg.status = STATUS_DRDY | STATUS_DRQ | STATUS_DSC;
687
 
688
/*
689
   if(reg.devhead & 0x40)
690
       printf("dev=%d lba=%d\n", device_id, *(unsigned*)(regs+3) & 0x0FFFFFFF);
691
   else
692
       printf("dev=%d c/h/s=%d/%d/%d\n", device_id, reg.cyl, (reg.devhead & 0xF), reg.sec);
693
*/
694
}
695
 
696
void ATA_DEVICE::verify_sectors()
697
{
698
   intrq = 1;
699
//   __debugbreak();
700
 
701
   do
702
   {
703
       --n_cur;
704
/*
705
       if(reg.devhead & 0x40)
706
           printf("lba=%d\n", *(unsigned*)(regs+3) & 0x0FFFFFFF);
707
       else
708
           printf("c/h/s=%d/%d/%d\n", reg.cyl, (reg.devhead & 0xF), reg.sec);
709
*/
710
       if (!seek())
711
           return;
712
/*
713
       u8 Buf[512];
714
       if (!ata_p.read_sector(Buf))
715
       {
716
          reg.status = STATUS_DRDY | STATUS_DF | STATUS_CORR | STATUS_DSC | STATUS_ERR;
717
          reg.err = ERR_UNC | ERR_IDNF | ERR_ABRT | ERR_AMNF;
718
          state = S_IDLE;
719
          return;
720
       }
721
*/
722
       if(n_cur)
723
           next_sector();
724
   }while(n_cur);
725
   command_ok();
726
}
727
 
728
void ATA_DEVICE::next_sector()
729
{
730
   if (reg.devhead & 0x40)
731
   { // LBA
732
      lba_cur++;
733
      return;
734
   }
735
   // need to recalc CHS for every sector, coz ATA registers
736
   // should contain current position on failure
737
   if (s_cur < s)
738
   {
739
       s_cur++;
740
       return;
741
   }
742
   s_cur = 1;
743
 
744
   if (++h_cur < h)
745
   {
746
       return;
747
   }
748
   h_cur = 0;
749
   c_cur++;
750
}
751
 
752
void ATA_DEVICE::recalibrate()
753
{
754
   lba_cur = 0;
755
   c_cur = 0;
756
   h_cur = 0;
757
   s_cur = 1;
758
 
759
   reg.cyl = 0;
760
   reg.devhead &= 0xF0;
761
 
762
   if (reg.devhead & 0x40) // LBA
763
   {
764
      reg.sec = 0;
765
      return;
766
   }
767
 
768
   reg.sec = 1;
769
}
770
 
771
#define TOC_DATA_TRACK          0x04
772
 
773
// [vv] Работа с файлом - образом диска напрямую
774
void ATA_DEVICE::handle_atapi_packet_emulate()
775
{
776
//    printf("%s\n", __FUNCTION__);
777
    memcpy(&atapi_p.cdb, transbf, 12);
778
 
779
    switch(atapi_p.cdb.CDB12.OperationCode)
780
    {
781
    case SCSIOP_TEST_UNIT_READY:; // 6
782
          command_ok();
783
          return;
784
 
785
    case SCSIOP_READ:; // 10
786
    {
787
      unsigned cnt = (u32(atapi_p.cdb.CDB10.TransferBlocksMsb) << 8) | atapi_p.cdb.CDB10.TransferBlocksLsb;
788
      unsigned pos = (u32(atapi_p.cdb.CDB10.LogicalBlockByte0) << 24) |
789
                     (u32(atapi_p.cdb.CDB10.LogicalBlockByte1) << 16) |
790
                     (u32(atapi_p.cdb.CDB10.LogicalBlockByte2) << 8) |
791
                     atapi_p.cdb.CDB10.LogicalBlockByte3;
792
 
793
      if(cnt * 2048 > sizeof(transbf))
794
      {
795
          reg.status = STATUS_DRDY | STATUS_DSC | STATUS_ERR;
796
          reg.err = ERR_UNC | ERR_IDNF;
797
          state = S_IDLE;
798
          return;
799
      }
800
 
801
      for(unsigned i = 0; i < cnt; i++, pos++)
802
      {
803
          if (!atapi_p.seek(pos))
804
          {
805
             reg.status = STATUS_DRDY | STATUS_DSC | STATUS_ERR;
806
             reg.err = ERR_UNC | ERR_IDNF;
807
             state = S_IDLE;
808
             return;
809
          }
810
 
811
          if (!atapi_p.read_sector(transbf + i * 2048))
812
          {
813
             reg.status = STATUS_DRDY | STATUS_DSC | STATUS_ERR;
814
             reg.err = ERR_UNC | ERR_IDNF;
815
             state = S_IDLE;
816
             return;
817
          }
818
      }
819
      intrq = 1;
820
      reg.atapi_count = cnt * 2048;
821
      reg.intreason = INT_IO;
822
      reg.status = STATUS_DRQ;
823
      transcount = (cnt * 2048)/2;
824
      transptr = 0;
825
      state = S_READ_ATAPI;
826
      return;
827
    }
828
 
829
    case SCSIOP_READ_TOC:; // 10
830
    {
831
      u8 TOC_DATA[] =
832
      {
833
        0, 4+8*2 - 2, 1, 0xAA,
834
        0, TOC_DATA_TRACK, 1, 0, 0, 0, 0, 0,
835
        0, TOC_DATA_TRACK, 0xAA, 0, 0, 0, 0, 0,
836
      };
837
      unsigned len = sizeof(TOC_DATA);
838
      memcpy(transbf, TOC_DATA, len);
839
      reg.atapi_count = len;
840
      reg.intreason = INT_IO;
841
      reg.status = STATUS_DRQ;
842
      transcount = (len + 1)/2;
843
      transptr = 0;
844
      state = S_READ_ATAPI;
845
      return;
846
    }
847
    case SCSIOP_START_STOP_UNIT:; // 10
848
          command_ok();
849
          return;
850
 
851
    case SCSIOP_SET_CD_SPEED:; // 12
852
          command_ok();
853
          return;
854
    }
855
 
856
    printf("*** unknown scsi cmd %02X ***\n", atapi_p.cdb.CDB12.OperationCode);
857
 
858
    reg.err = 0;
859
    state = S_IDLE;
860
    reg.status = STATUS_DSC | STATUS_ERR | STATUS_DRDY;
861
}
862
 
863
void ATA_DEVICE::handle_atapi_packet()
864
{
865
#if defined(DUMP_HDD_IO)
866
   {
867
       printf(" [packet");
868
       for (int i = 0; i < 12; i++)
869
           printf("-%02X", transbf[i]);
870
       printf("]\n");
871
   }
872
#endif
873
   if(phys_dev == -1)
874
       return handle_atapi_packet_emulate();
875
 
876
   memcpy(&atapi_p.cdb, transbf, 12);
877
 
878
   intrq = 1;
879
 
880
   if (atapi_p.cdb.MODE_SELECT10.OperationCode == 0x55)
881
   { // MODE SELECT requires additional data from host
882
 
883
      state = S_MODE_SELECT;
884
      reg.status = STATUS_DRQ;
885
      reg.intreason = 0;
886
      transptr = 0;
887
      transcount = atapi_p.cdb.MODE_SELECT10.ParameterListLength[0]*0x100 + atapi_p.cdb.MODE_SELECT10.ParameterListLength[1];
888
      return;
889
   }
890
 
891
   if (atapi_p.cdb.CDB6READWRITE.OperationCode == 0x03 && atapi_p.senselen)
892
   { // REQ.SENSE - read cached
893
      memcpy(transbf, atapi_p.sense, atapi_p.senselen);
894
      atapi_p.passed_length = atapi_p.senselen; atapi_p.senselen = 0; // next time read from device
895
      goto ok;
896
   }
897
 
898
   if (atapi_p.pass_through(transbf, sizeof transbf))
899
   {
900
      if (atapi_p.senselen)
901
      {
902
          reg.err = atapi_p.sense[2] << 4;
903
          goto err;
904
      } // err = sense key //win9x hangs on drq after atapi packet when emulator does goto err (see walkaround in SEND_ASPI_CMD)
905
    ok:
906
      if (!atapi_p.cdb.CDB6READWRITE.OperationCode)
907
          atapi_p.passed_length = 0; // bugfix in cdrom driver: TEST UNIT READY has no data
908
      if (!atapi_p.passed_length /* || atapi_p.passed_length == sizeof transbf */ )
909
      {
910
          command_ok();
911
          return;
912
      }
913
      reg.atapi_count = atapi_p.passed_length;
914
      reg.intreason = INT_IO;
915
      reg.status = STATUS_DRQ;
916
      transcount = (atapi_p.passed_length+1)/2;
917
          //printf("transcount=%d\n",transcount); //32768 in win9x
918
      transptr = 0;
919
      state = S_READ_ATAPI;
920
   }
921
   else
922
   { // bus error
923
      reg.err = 0;
924
    err:
925
      state = S_IDLE;
926
      reg.status = STATUS_DSC | STATUS_ERR | STATUS_DRDY;
927
   }
928
}
929
 
930
void ATA_DEVICE::prepare_id()
931
{
932
   if (phys_dev == -1)
933
   {
934
      memset(transbf, 0, 512);
935
      make_ata_string(transbf+54, 20, "UNREAL SPECCY HARD DRIVE IMAGE");
936
      make_ata_string(transbf+20, 10, "0000");
937
      make_ata_string(transbf+46,  4, VERS_STRING);
938
      *(unsigned short*)transbf = 0x045A;
939
      ((unsigned short*)transbf)[1] = (unsigned short)c;
940
      ((unsigned short*)transbf)[3] = (unsigned short)h;
941
      ((unsigned short*)transbf)[6] = (unsigned short)s;
942
      *(unsigned*)(transbf+60*2) = (lba > 0xFFFFFFFULL) ? 0xFFFFFFF : lba; // lba28
943
      ((unsigned short*)transbf)[20] = 3; // a dual ported multi-sector buffer capable of simultaneous transfers with a read caching capability
944
      ((unsigned short*)transbf)[21] = 512; // cache size=256k
945
      ((unsigned short*)transbf)[22] = 4; // ECC bytes
946
      ((unsigned short*)transbf)[49] = 0x200; // LBA supported
947
      ((unsigned short*)transbf)[80] = 0x3E; // support specifications up to ATA-5
948
      ((unsigned short*)transbf)[81] = 0x13; // ATA/ATAPI-5 T13 1321D revision 3
949
      ((unsigned short*)transbf)[82] = 0x60; // supported look-ahead and write cache
950
 
951
      if(lba > 0xFFFFFFFULL)
952
      {
953
          ((unsigned short*)transbf)[83] = 0x400; // lba48 supported
954
          ((unsigned short*)transbf)[86] = 0x400; // lba48 supported
955
          *(u64*)(transbf+100*2) = lba; // lba48
956
      }
957
 
958
      // make checksum
959
      transbf[510] = 0xA5;
960
      unsigned char cs = 0;
961
      for (unsigned i = 0; i < 511; i++)
962
          cs += transbf[i];
963
      transbf[511] = 0-cs;
964
   }
965
   else
966
   { // copy as is...
967
      memcpy(transbf, phys[phys_dev].idsector, 512);
968
   }
969
 
970
   state = S_READ_ID;
971
   transptr = 0;
972
   transcount = 0x100;
973
   intrq = 1;
974
   reg.status = STATUS_DRDY | STATUS_DRQ | STATUS_DSC;
975
   reg.err = 0;
976
}
977
 
978
void ATA_DEVICE::update_regs()
979
{
980
   if(reg.devhead & 0x40)
981
   { // lba
982
       if(lba > 0xFFFFFFFULL)
983
       { // lba48
984
           reg.lba0 = lba_cur & 0xFF;
985
           reg.lba1 = (lba_cur >> 8) & 0xFF;
986
           reg.lba2 = (lba_cur >> 16) & 0xFF;
987
           reg.lba4 = (lba_cur >> 24) & 0xFF;
988
           reg.lba5 = (lba_cur >> 32) & 0xFF;
989
           reg.lba6 = (lba_cur >> 40) & 0xFF;
990
       }
991
       else
992
       { // lba28
993
           reg.lba0 = lba_cur & 0xFF;
994
           reg.lba1 = (lba_cur >> 8) & 0xFF;
995
           reg.lba2 = (lba_cur >> 16) & 0xFF;
996
           reg.lba3 &= ~0xF;
997
           reg.lba3 |= (lba_cur >> 24) & 0xF;
998
       }
999
   }
1000
   else
1001
   { // chs
1002
       reg.cyl = c_cur;
1003
       reg.devhead &= ~0xF;
1004
       reg.devhead |= h_cur & 0xF;
1005
       reg.sec = s_cur;
1006
   }
1007
}
1008
 
1009
void ATA_DEVICE::update_cur()
1010
{
1011
   n_cur = reg.count;
1012
   if(lba > 0xFFFFFFFULL)
1013
   { // lba48
1014
       lba_cur = reg.lba0 | (u64(reg.lba1) << 8) | (u64(reg.lba2) << 16) | (u64(reg.lba4) << 24) | (u64(reg.lba5) << 32) | (u64(reg.lba6) << 40);
1015
       n_cur |= (reg.count1 << 8);
1016
   }
1017
   else
1018
   { // lba28
1019
       lba_cur = reg.lba0 | (u64(reg.lba1) << 8) | (u64(reg.lba2) << 16) | (u64(reg.lba3 & 0xF) << 24);
1020
   }
1021
 
1022
   c_cur = reg.cyl;
1023
   h_cur = reg.devhead & 0xF;
1024
   s_cur = reg.sec;
1025
}