Revision e8b54394

b/hw/ide.c
372 372
#define SENSE_ILLEGAL_REQUEST 5
373 373
#define SENSE_UNIT_ATTENTION  6
374 374

  
375
#define SMART_READ_DATA       0xd0
376
#define SMART_READ_THRESH     0xd1
377
#define SMART_ATTR_AUTOSAVE   0xd2
378
#define SMART_SAVE_ATTR       0xd3
379
#define SMART_EXECUTE_OFFLINE 0xd4
380
#define SMART_READ_LOG        0xd5
381
#define SMART_WRITE_LOG       0xd6
382
#define SMART_ENABLE          0xd8
383
#define SMART_DISABLE         0xd9
384
#define SMART_STATUS          0xda
385

  
386
static int smart_attributes[][5] = {
387
    /* id,  flags, val, wrst, thrsh */
388
    { 0x01, 0x03, 0x64, 0x64, 0x06}, /* raw read */
389
    { 0x03, 0x03, 0x64, 0x64, 0x46}, /* spin up */
390
    { 0x04, 0x02, 0x64, 0x64, 0x14}, /* start stop count */
391
    { 0x05, 0x03, 0x64, 0x64, 0x36}, /* remapped sectors */
392
    { 0x00, 0x00, 0x00, 0x00, 0x00}
393
};
394

  
395

  
396

  
375 397
struct IDEState;
376 398

  
377 399
typedef void EndTransferFunc(struct IDEState *);
......
444 466
    int media_changed;
445 467
    /* for pmac */
446 468
    int is_read;
469
    /* SMART */
470
    uint8_t smart_enabled;
471
    uint8_t smart_autosave;
472
    int smart_errors;
473
    uint8_t smart_selftest_count;
474
    uint8_t *smart_selftest_data;
475

  
447 476
} IDEState;
448 477

  
449 478
/* XXX: DVDs that could fit on a CD will be reported as a CD */
......
594 623
    put_le16(p + 68, 120);
595 624
    put_le16(p + 80, 0xf0); /* ata3 -> ata6 supported */
596 625
    put_le16(p + 81, 0x16); /* conforms to ata5 */
597
    put_le16(p + 82, (1 << 14));
626
    /* 14=NOP supported, 0=SMART supported */
627
    put_le16(p + 82, (1 << 14) | 1);
598 628
    /* 13=flush_cache_ext,12=flush_cache,10=lba48 */
599 629
    put_le16(p + 83, (1 << 14) | (1 << 13) | (1 <<12) | (1 << 10));
600
    put_le16(p + 84, (1 << 14));
601
    put_le16(p + 85, (1 << 14));
630
    /* 14=set to 1, 1=SMART self test, 0=SMART error logging */
631
    put_le16(p + 84, (1 << 14) | 0);
632
    /* 14 = NOP supported, 0=SMART feature set enabled */
633
    put_le16(p + 85, (1 << 14) | 1);
602 634
    /* 13=flush_cache_ext,12=flush_cache,10=lba48 */
603 635
    put_le16(p + 86, (1 << 14) | (1 << 13) | (1 <<12) | (1 << 10));
604
    put_le16(p + 87, (1 << 14));
636
    /* 14=set to 1, 1=smart self test, 0=smart error logging */
637
    put_le16(p + 87, (1 << 14) | 0);
605 638
    put_le16(p + 88, 0x3f | (1 << 13)); /* udma5 set and supported */
606 639
    put_le16(p + 93, 1 | (1 << 14) | 0x2000);
607 640
    put_le16(p + 100, s->nb_sectors);
......
2567 2600
            s->status = READY_STAT | SEEK_STAT;
2568 2601
            ide_set_irq(s);
2569 2602
            break;
2603

  
2604
	case WIN_SMART:
2605
	    if (s->is_cdrom)
2606
		goto abort_cmd;
2607
	    if (s->hcyl != 0xc2 || s->lcyl != 0x4f)
2608
		goto abort_cmd;
2609
	    if (!s->smart_enabled && s->feature != SMART_ENABLE)
2610
		goto abort_cmd;
2611
	    switch (s->feature) {
2612
	    case SMART_DISABLE:
2613
		s->smart_enabled = 0;
2614
		s->status = READY_STAT | SEEK_STAT;
2615
		ide_set_irq(s);
2616
		break;
2617
	    case SMART_ENABLE:
2618
		s->smart_enabled = 1;
2619
		s->status = READY_STAT | SEEK_STAT;
2620
		ide_set_irq(s);
2621
		break;
2622
	    case SMART_ATTR_AUTOSAVE:
2623
		switch (s->sector) {
2624
		case 0x00:
2625
		    s->smart_autosave = 0;
2626
		    break;
2627
		case 0xf1:
2628
		    s->smart_autosave = 1;
2629
		    break;
2630
		default:
2631
		    goto abort_cmd;
2632
		}
2633
		s->status = READY_STAT | SEEK_STAT;
2634
		ide_set_irq(s);
2635
		break;
2636
	    case SMART_STATUS:
2637
		if (!s->smart_errors) {
2638
		    s->hcyl = 0xc2;
2639
		    s->lcyl = 0x4f;
2640
		} else {
2641
		    s->hcyl = 0x2c;
2642
		    s->lcyl = 0xf4;
2643
		}
2644
		s->status = READY_STAT | SEEK_STAT;
2645
		ide_set_irq(s);
2646
		break;
2647
	    case SMART_READ_THRESH:
2648
		memset(s->io_buffer, 0, 0x200);
2649
		s->io_buffer[0] = 0x01; /* smart struct version */
2650
		for (n=0; n<30; n++) {
2651
		    if (smart_attributes[n][0] == 0)
2652
			break;
2653
		    s->io_buffer[2+0+(n*12)] = smart_attributes[n][0];
2654
		    s->io_buffer[2+1+(n*12)] = smart_attributes[n][4];
2655
		}
2656
		for (n=0; n<511; n++) /* checksum */
2657
		    s->io_buffer[511] += s->io_buffer[n];
2658
		s->io_buffer[511] = 0x100 - s->io_buffer[511];
2659
		s->status = READY_STAT | SEEK_STAT;
2660
		ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);
2661
		ide_set_irq(s);
2662
		break;
2663
	    case SMART_READ_DATA:
2664
		memset(s->io_buffer, 0, 0x200);
2665
		s->io_buffer[0] = 0x01; /* smart struct version */
2666
		for (n=0; n<30; n++) {
2667
		    if (smart_attributes[n][0] == 0)
2668
			break;
2669
		    s->io_buffer[2+0+(n*12)] = smart_attributes[n][0];
2670
		    s->io_buffer[2+1+(n*12)] = smart_attributes[n][1];
2671
		    s->io_buffer[2+3+(n*12)] = smart_attributes[n][2];
2672
		    s->io_buffer[2+4+(n*12)] = smart_attributes[n][3];
2673
		}
2674
		s->io_buffer[362] = 0x02 | (s->smart_autosave?0x80:0x00);
2675
		if (s->smart_selftest_count == 0) {
2676
		    s->io_buffer[363] = 0;
2677
		} else {
2678
		    s->io_buffer[363] = 
2679
			s->smart_selftest_data[3 + 
2680
					       (s->smart_selftest_count - 1) * 
2681
					       24];
2682
		}
2683
		s->io_buffer[364] = 0x20; 
2684
		s->io_buffer[365] = 0x01; 
2685
		/* offline data collection capacity: execute + self-test*/
2686
		s->io_buffer[367] = (1<<4 | 1<<3 | 1); 
2687
		s->io_buffer[368] = 0x03; /* smart capability (1) */
2688
		s->io_buffer[369] = 0x00; /* smart capability (2) */
2689
		s->io_buffer[370] = 0x01; /* error logging supported */
2690
		s->io_buffer[372] = 0x02; /* minutes for poll short test */
2691
		s->io_buffer[373] = 0x36; /* minutes for poll ext test */
2692
		s->io_buffer[374] = 0x01; /* minutes for poll conveyance */
2693

  
2694
		for (n=0; n<511; n++) 
2695
		    s->io_buffer[511] += s->io_buffer[n];
2696
		s->io_buffer[511] = 0x100 - s->io_buffer[511];
2697
		s->status = READY_STAT | SEEK_STAT;
2698
		ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);
2699
		ide_set_irq(s);
2700
		break;
2701
	    case SMART_READ_LOG:
2702
		switch (s->sector) {
2703
		case 0x01: /* summary smart error log */
2704
		    memset(s->io_buffer, 0, 0x200);
2705
		    s->io_buffer[0] = 0x01;
2706
		    s->io_buffer[1] = 0x00; /* no error entries */
2707
		    s->io_buffer[452] = s->smart_errors & 0xff;
2708
		    s->io_buffer[453] = (s->smart_errors & 0xff00) >> 8;
2709

  
2710
		    for (n=0; n<511; n++)
2711
			s->io_buffer[511] += s->io_buffer[n];
2712
		    s->io_buffer[511] = 0x100 - s->io_buffer[511];
2713
		    break;
2714
		case 0x06: /* smart self test log */
2715
		    memset(s->io_buffer, 0, 0x200);
2716
		    s->io_buffer[0] = 0x01; 
2717
		    if (s->smart_selftest_count == 0) {
2718
			s->io_buffer[508] = 0;
2719
		    } else {
2720
			s->io_buffer[508] = s->smart_selftest_count;
2721
			for (n=2; n<506; n++) 
2722
			    s->io_buffer[n] = s->smart_selftest_data[n];
2723
		    }		    
2724
		    for (n=0; n<511; n++)
2725
			s->io_buffer[511] += s->io_buffer[n];
2726
		    s->io_buffer[511] = 0x100 - s->io_buffer[511];
2727
		    break;
2728
		default:
2729
		    goto abort_cmd;
2730
		}
2731
		s->status = READY_STAT | SEEK_STAT;
2732
		ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);
2733
		ide_set_irq(s);
2734
		break;
2735
	    case SMART_EXECUTE_OFFLINE:
2736
		switch (s->sector) {
2737
		case 0: /* off-line routine */
2738
		case 1: /* short self test */
2739
		case 2: /* extended self test */
2740
		    s->smart_selftest_count++;
2741
		    if(s->smart_selftest_count > 21)
2742
			s->smart_selftest_count = 0;
2743
		    n = 2 + (s->smart_selftest_count - 1) * 24;
2744
		    s->smart_selftest_data[n] = s->sector;
2745
		    s->smart_selftest_data[n+1] = 0x00; /* OK and finished */
2746
		    s->smart_selftest_data[n+2] = 0x34; /* hour count lsb */
2747
		    s->smart_selftest_data[n+3] = 0x12; /* hour count msb */
2748
		    s->status = READY_STAT | SEEK_STAT;
2749
		    ide_set_irq(s);
2750
		    break;
2751
		default:
2752
		    goto abort_cmd;
2753
		}
2754
		break;
2755
	    default:
2756
		goto abort_cmd;
2757
	    }
2758
	    break;
2570 2759
        default:
2571 2760
        abort_cmd:
2572 2761
            ide_abort_command(s);
......
2828 3017
            s->heads = heads;
2829 3018
            s->sectors = secs;
2830 3019
            s->nb_sectors = nb_sectors;
2831

  
3020
	    /* The SMART values should be preserved across power cycles
3021
	       but they aren't.  */
3022
	    s->smart_enabled = 1;
3023
	    s->smart_autosave = 1;
3024
	    s->smart_errors = 0;
3025
	    s->smart_selftest_count = 0;
3026
	    s->smart_selftest_data = qemu_blockalign(s->bs, 512);
2832 3027
            if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
2833 3028
                s->is_cdrom = 1;
2834 3029
		bdrv_set_change_cb(s->bs, cdrom_change_cb, s);

Also available in: Unified diff