~ubuntu-branches/ubuntu/saucy/bochs/saucy-proposed

« back to all changes in this revision

Viewing changes to bios/rombios.c

  • Committer: Bazaar Package Importer
  • Author(s): David Futcher
  • Date: 2009-04-30 07:46:11 UTC
  • mfrom: (1.1.11 upstream) (4.1.7 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090430074611-6dih80a5mk2uvxhk
Tags: 2.3.7+20090416-1ubuntu1
* Merge from debian unstable (LP: #370427), remaining changes:
  - debian/patches/12_no-ssp.patch: Build bios with -fno-stack-protector
  - Add Replaces/Conflicts for bochsbios-qemu (<< 2.3.6-2)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/////////////////////////////////////////////////////////////////////////
2
 
// $Id: rombios.c,v 1.209 2008/06/02 20:08:10 sshwarts Exp $
 
2
// $Id: rombios.c,v 1.230 2009/04/10 16:36:34 vruppert Exp $
3
3
/////////////////////////////////////////////////////////////////////////
4
4
//
5
5
//  Copyright (C) 2002  MandrakeSoft S.A.
620
620
  Bit16u ticks_low;
621
621
  Bit16u ticks_high;
622
622
  Bit8u  midnight_flag;
623
 
  } bios_data_t;
 
623
} bios_data_t;
624
624
 
625
625
#define BiosData ((bios_data_t  *) 0)
626
626
 
629
629
    Bit16u heads;      // # heads
630
630
    Bit16u cylinders;  // # cylinders
631
631
    Bit16u spt;        // # sectors / track
632
 
    } chs_t;
 
632
  } chs_t;
633
633
 
634
634
  // DPTE definition
635
635
  typedef struct {
645
645
    Bit16u reserved;
646
646
    Bit8u  revision;
647
647
    Bit8u  checksum;
648
 
    } dpte_t;
 
648
  } dpte_t;
649
649
 
650
650
  typedef struct {
651
651
    Bit8u  iface;        // ISA or PCI
652
652
    Bit16u iobase1;      // IO Base 1
653
653
    Bit16u iobase2;      // IO Base 2
654
654
    Bit8u  irq;          // IRQ
655
 
    } ata_channel_t;
 
655
  } ata_channel_t;
656
656
 
657
657
  typedef struct {
658
658
    Bit8u  type;         // Detected type of ata (ata/atapi/none/unknown)
668
668
 
669
669
    Bit32u sectors_low;  // Total sectors count
670
670
    Bit32u sectors_high;
671
 
    } ata_device_t;
 
671
  } ata_device_t;
672
672
 
673
673
  typedef struct {
674
674
    // ATA channels info
689
689
    // Count of transferred sectors and bytes
690
690
    Bit16u trsfsectors;
691
691
    Bit32u trsfbytes;
692
 
 
693
 
    } ata_t;
 
692
  } ata_t;
694
693
 
695
694
#if BX_ELTORITO_BOOT
696
695
  // ElTorito Device Emulation data
707
706
 
708
707
    // Virtual device
709
708
    chs_t  vdevice;
710
 
    } cdemu_t;
 
709
  } cdemu_t;
711
710
#endif // BX_ELTORITO_BOOT
712
711
 
713
712
  // for access to EBDA area
732
731
    // El Torito Emulation data
733
732
    cdemu_t cdemu;
734
733
#endif // BX_ELTORITO_BOOT
735
 
 
736
 
    } ebda_data_t;
 
734
  } ebda_data_t;
737
735
 
738
736
  #define EbdaData ((ebda_data_t *) 0)
739
737
 
746
744
    Bit16u segment;
747
745
    Bit32u lba1;
748
746
    Bit32u lba2;
749
 
    } int13ext_t;
 
747
  } int13ext_t;
750
748
 
751
749
  #define Int13Ext ((int13ext_t *) 0)
752
750
 
772
770
    Bit8u   device_path[8];
773
771
    Bit8u   reserved3;
774
772
    Bit8u   checksum;
775
 
    } dpt_t;
 
773
  } dpt_t;
776
774
 
777
775
  #define Int13DPT ((dpt_t *) 0)
778
776
 
783
781
    struct {
784
782
      Bit16u di, si, bp, sp;
785
783
      Bit16u bx, dx, cx, ax;
786
 
      } r16;
 
784
    } r16;
787
785
    struct {
788
786
      Bit16u filler[4];
789
787
      Bit8u  bl, bh, dl, dh, cl, ch, al, ah;
790
 
      } r8;
791
 
    } u;
792
 
  } pusha_regs_t;
 
788
    } r8;
 
789
  } u;
 
790
} pusha_regs_t;
793
791
 
794
792
typedef struct {
795
793
 union {
796
794
  struct {
797
795
    Bit32u edi, esi, ebp, esp;
798
796
    Bit32u ebx, edx, ecx, eax;
799
 
    } r32;
 
797
  } r32;
800
798
  struct {
801
799
    Bit16u di, filler1, si, filler2, bp, filler3, sp, filler4;
802
800
    Bit16u bx, filler5, dx, filler6, cx, filler7, ax, filler8;
803
 
    } r16;
 
801
  } r16;
804
802
  struct {
805
803
    Bit32u filler[4];
806
804
    Bit8u  bl, bh;
811
809
    Bit16u filler3;
812
810
    Bit8u  al, ah;
813
811
    Bit16u filler4;
814
 
    } r8;
815
 
  } u;
 
812
  } r8;
 
813
 } u;
816
814
} pushad_regs_t;
817
815
 
818
816
typedef struct {
819
817
  union {
820
818
    struct {
821
819
      Bit16u flags;
822
 
      } r16;
 
820
    } r16;
823
821
    struct {
824
822
      Bit8u  flagsl;
825
823
      Bit8u  flagsh;
826
 
      } r8;
827
 
    } u;
828
 
  } flags_t;
 
824
    } r8;
 
825
  } u;
 
826
} flags_t;
829
827
 
830
828
#define SetCF(x)   x.u.r8.flagsl |= 0x01
831
829
#define SetZF(x)   x.u.r8.flagsl |= 0x40
837
835
  Bit16u ip;
838
836
  Bit16u cs;
839
837
  flags_t flags;
840
 
  } iret_addr_t;
 
838
} iret_addr_t;
841
839
 
842
840
typedef struct {
843
841
  Bit16u type;
845
843
  Bit32u vector;
846
844
  Bit32u description;
847
845
  Bit32u reserved;
848
 
  } ipl_entry_t;
849
 
 
 
846
} ipl_entry_t;
850
847
 
851
848
 
852
849
static Bit8u          inb();
940
937
 
941
938
#endif // BX_ELTORITO_BOOT
942
939
 
943
 
static char bios_cvs_version_string[] = "$Revision: 1.209 $ $Date: 2008/06/02 20:08:10 $";
 
940
static char bios_cvs_version_string[] = "$Revision: 1.230 $ $Date: 2009/04/10 16:36:34 $";
944
941
 
945
942
#define BIOS_COPYRIGHT_STRING "(c) 2002 MandrakeSoft S.A. Written by Kevin Lawton & the Bochs team."
946
943
 
1118
1115
      {   none,   none,   none,   none, none },
1119
1116
      {   none,   none,   none,   none, none },
1120
1117
      { 0x565c, 0x567c,   none,   none, none }, /* \| */
1121
 
      { 0x5700, 0x5700,   none,   none, none }, /* F11 */
1122
 
      { 0x5800, 0x5800,   none,   none, none }  /* F12 */
 
1118
      { 0x8500, 0x8700, 0x8900, 0x8b00, none }, /* F11 */
 
1119
      { 0x8600, 0x8800, 0x8a00, 0x8c00, none }, /* F12 */
1123
1120
      };
1124
1121
 
1125
1122
  Bit8u
1647
1644
    if ( c == '%' ) {
1648
1645
      in_format = 1;
1649
1646
      format_width = 0;
1650
 
      }
 
1647
    }
1651
1648
    else if (in_format) {
1652
1649
      if ( (c>='0') && (c<='9') ) {
1653
1650
        format_width = (format_width * 10) + (c - '0');
1654
 
        }
 
1651
      }
1655
1652
      else {
1656
1653
        arg_ptr++; // increment to next arg
1657
1654
        arg = read_word(arg_seg, arg_ptr);
1665
1662
          for (i=format_width-1; i>=0; i--) {
1666
1663
            nibble = (arg >> (4 * i)) & 0x000f;
1667
1664
            send (action, (nibble<=9)? (nibble+'0') : (nibble-10+hexadd));
1668
 
            }
1669
1665
          }
 
1666
        }
1670
1667
        else if (c == 'u') {
1671
1668
          put_uint(action, arg, format_width, 0);
1672
 
          }
 
1669
        }
1673
1670
        else if (c == 'l') {
1674
1671
          s++;
1675
1672
          c = read_byte(get_CS(), s); /* is it ld,lx,lu? */
1680
1677
              put_luint(action, 0L-(((Bit32u) hibyte << 16) | arg), format_width-1, 1);
1681
1678
            else
1682
1679
              put_luint(action, ((Bit32u) hibyte << 16) | arg, format_width, 0);
1683
 
           }
 
1680
          }
1684
1681
          else if (c == 'u') {
1685
1682
            put_luint(action, ((Bit32u) hibyte << 16) | arg, format_width, 0);
1686
 
           }
 
1683
          }
1687
1684
          else if (c == 'x' || c == 'X')
1688
 
           {
 
1685
          {
1689
1686
            if (format_width == 0)
1690
1687
              format_width = 8;
1691
1688
            if (c == 'x')
1695
1692
            for (i=format_width-1; i>=0; i--) {
1696
1693
              nibble = ((((Bit32u) hibyte <<16) | arg) >> (4 * i)) & 0x000f;
1697
1694
              send (action, (nibble<=9)? (nibble+'0') : (nibble-10+hexadd));
1698
 
              }
1699
 
           }
 
1695
            }
1700
1696
          }
 
1697
        }
1701
1698
        else if (c == 'd') {
1702
1699
          if (arg & 0x8000)
1703
1700
            put_int(action, -arg, format_width - 1, 1);
1704
1701
          else
1705
1702
            put_int(action, arg, format_width, 0);
1706
 
          }
 
1703
        }
1707
1704
        else if (c == 's') {
1708
1705
          put_str(action, get_CS(), arg);
1709
 
          }
 
1706
        }
1710
1707
        else if (c == 'S') {
1711
1708
          hibyte = arg;
1712
1709
          arg_ptr++;
1713
1710
          arg = read_word(arg_seg, arg_ptr);
1714
1711
          put_str(action, hibyte, arg);
1715
 
          }
 
1712
        }
1716
1713
        else if (c == 'c') {
1717
1714
          send(action, arg);
1718
 
          }
 
1715
        }
1719
1716
        else
1720
1717
          BX_PANIC("bios_printf: unknown format\n");
1721
1718
          in_format = 0;
1722
 
        }
1723
1719
      }
 
1720
    }
1724
1721
    else {
1725
1722
      send(action, c);
1726
 
      }
 
1723
    }
1727
1724
    s ++;
1728
 
    }
 
1725
  }
1729
1726
 
1730
1727
  if (action & BIOS_PRINTF_HALT) {
1731
1728
    // freeze in a busy loop.
1735
1732
    hlt
1736
1733
    jmp halt2_loop
1737
1734
ASM_END
1738
 
    }
 
1735
  }
1739
1736
}
1740
1737
 
1741
1738
//--------------------------------------------------------------------------
1760
1757
        if (inb(0x64) & 0x01) {
1761
1758
            inb(0x60);
1762
1759
            max = 0x2000;
1763
 
            }
1764
1760
        }
 
1761
    }
1765
1762
 
1766
1763
    // Due to timer issues, and if the IPS setting is > 15000000,
1767
1764
    // the incoming keys might not be flushed here. That will
1917
1914
  BX_PANIC("Unimplemented shutdown status: %02x\n",(Bit8u)status);
1918
1915
}
1919
1916
 
 
1917
void s3_resume_panic()
 
1918
{
 
1919
  BX_PANIC("Returned from s3_resume.\n");
 
1920
}
 
1921
 
1920
1922
//--------------------------------------------------------------------------
1921
1923
// print_bios_banner
1922
1924
//   displays a the bios version
2030
2032
  if (check_for_keystroke())
2031
2033
  {
2032
2034
    scan_code = get_keystroke();
2033
 
    if (scan_code == 0x58) /* F12 */
 
2035
    if (scan_code == 0x86) /* F12 */
2034
2036
    {
2035
2037
      while (check_for_keystroke())
2036
2038
        get_keystroke();
2077
2079
          write_word(IPL_SEG, IPL_BOOTFIRST_OFFSET, scan_code);
2078
2080
        }
2079
2081
      }
2080
 
    printf("\n");
 
2082
 
 
2083
      printf("\n");
2081
2084
    }
2082
2085
  }
2083
2086
}
2198
2201
  outb(0xfedc, 0x00);
2199
2202
}
2200
2203
 
 
2204
int
 
2205
s3_resume()
 
2206
{
 
2207
    Bit32u s3_wakeup_vector;
 
2208
    Bit8u s3_resume_flag;
 
2209
 
 
2210
    s3_resume_flag = read_byte(0x40, 0xb0);
 
2211
    s3_wakeup_vector = read_dword(0x40, 0xb2);
 
2212
 
 
2213
    BX_INFO("S3 resume called %x 0x%lx\n", s3_resume_flag, s3_wakeup_vector);
 
2214
    if (s3_resume_flag != 0xFE || !s3_wakeup_vector)
 
2215
            return 0;
 
2216
 
 
2217
    write_byte(0x40, 0xb0, 0);
 
2218
 
 
2219
    /* setup wakeup vector */
 
2220
    write_word(0x40, 0xb6, (s3_wakeup_vector & 0xF)); /* IP */
 
2221
    write_word(0x40, 0xb8, (s3_wakeup_vector >> 4)); /* CS */
 
2222
 
 
2223
    BX_INFO("S3 resume jump to %x:%x\n", (s3_wakeup_vector >> 4),
 
2224
                    (s3_wakeup_vector & 0xF));
 
2225
ASM_START
 
2226
    jmpf [0x04b6]
 
2227
ASM_END
 
2228
    return 1;
 
2229
}
 
2230
 
2201
2231
#if BX_USE_ATADRV
2202
2232
 
2203
2233
// ---------------------------------------------------------------------------
2355
2385
    write_word(ebda_seg,&EbdaData->ata.channels[channel].iobase1,0x0);
2356
2386
    write_word(ebda_seg,&EbdaData->ata.channels[channel].iobase2,0x0);
2357
2387
    write_byte(ebda_seg,&EbdaData->ata.channels[channel].irq,0);
2358
 
    }
 
2388
  }
2359
2389
 
2360
2390
  // Devices info init.
2361
2391
  for (device=0; device<BX_MAX_ATA_DEVICES; device++) {
2375
2405
 
2376
2406
    write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low,0L);
2377
2407
    write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_high,0L);
2378
 
    }
 
2408
  }
2379
2409
 
2380
 
  // hdidmap  and cdidmap init.
 
2410
  // hdidmap and cdidmap init.
2381
2411
  for (device=0; device<BX_MAX_ATA_DEVICES; device++) {
2382
2412
    write_byte(ebda_seg,&EbdaData->ata.hdidmap[device],BX_MAX_ATA_DEVICES);
2383
2413
    write_byte(ebda_seg,&EbdaData->ata.cdidmap[device],BX_MAX_ATA_DEVICES);
2384
 
    }
 
2414
  }
2385
2415
 
2386
2416
  write_byte(ebda_seg,&EbdaData->ata.hdcount,0);
2387
2417
  write_byte(ebda_seg,&EbdaData->ata.cdcount,0);
2593
2623
        case ATA_TRANSLATION_RECHS:
2594
2624
          BX_INFO("r-echs");
2595
2625
          break;
2596
 
        }
 
2626
      }
 
2627
 
2597
2628
      switch (translation) {
2598
2629
        case ATA_TRANSLATION_NONE:
2599
2630
          break;
2614
2645
            if(cylinders>61439) cylinders=61439;
2615
2646
            heads=15;
2616
2647
            cylinders = (Bit16u)((Bit32u)(cylinders)*16/15);
2617
 
            }
 
2648
          }
2618
2649
          // then go through the large bitshift process
2619
2650
        case ATA_TRANSLATION_LARGE:
2620
2651
          while(cylinders > 1024) {
2625
2656
            if (heads > 127) break;
2626
2657
          }
2627
2658
          break;
2628
 
        }
 
2659
      }
 
2660
 
2629
2661
      // clip to 1024 cylinders in lchs
2630
2662
      if (cylinders > 1024) cylinders=1024;
2631
2663
      BX_INFO(" LCHS=%d/%d/%d\n", cylinders, heads, spt);
2637
2669
      // fill hdidmap
2638
2670
      write_byte(ebda_seg,&EbdaData->ata.hdidmap[hdcount], device);
2639
2671
      hdcount++;
2640
 
      }
 
2672
    }
2641
2673
 
2642
2674
    // Now we send a IDENTIFY command to ATAPI device
2643
2675
    if(type == ATA_TYPE_ATAPI) {
2665
2697
      // fill cdidmap
2666
2698
      write_byte(ebda_seg,&EbdaData->ata.cdidmap[cdcount], device);
2667
2699
      cdcount++;
2668
 
      }
 
2700
    }
2669
2701
 
2670
 
      {
 
2702
    {
2671
2703
      Bit32u sizeinmb;
2672
2704
      Bit16u ataversion;
2673
2705
      Bit8u  c, i, version, model[41];
2682
2714
          for(version=15;version>0;version--) {
2683
2715
            if((ataversion&(1<<version))!=0)
2684
2716
            break;
2685
 
            }
 
2717
          }
2686
2718
 
2687
2719
          // Read model name
2688
 
          for(i=0;i<20;i++){
 
2720
          for(i=0;i<20;i++) {
2689
2721
            write_byte(get_SS(),model+(i*2),read_byte(get_SS(),buffer+(i*2)+54+1));
2690
2722
            write_byte(get_SS(),model+(i*2)+1,read_byte(get_SS(),buffer+(i*2)+54));
2691
 
            }
 
2723
          }
2692
2724
 
2693
2725
          // Reformat
2694
2726
          write_byte(get_SS(),model+40,0x00);
2696
2728
            if(read_byte(get_SS(),model+i)==0x20)
2697
2729
              write_byte(get_SS(),model+i,0x00);
2698
2730
            else break;
 
2731
          }
 
2732
          if (i>36) {
 
2733
            write_byte(get_SS(),model+36,0x00);
 
2734
            for(i=35;i>32;i--){
 
2735
              write_byte(get_SS(),model+i,0x2E);
2699
2736
            }
 
2737
          }
2700
2738
          break;
2701
 
        }
 
2739
      }
2702
2740
 
2703
2741
      switch (type) {
2704
2742
        case ATA_TYPE_ATA:
2705
2743
          printf("ata%d %s: ",channel,slave?" slave":"master");
2706
 
          i=0; while(c=read_byte(get_SS(),model+i++)) printf("%c",c);
2707
 
          if (sizeinmb < (1UL<<16))
 
2744
          i=0;
 
2745
          while(c=read_byte(get_SS(),model+i++))
 
2746
            printf("%c",c);
 
2747
          if (sizeinmb < (1UL<<16))
2708
2748
            printf(" ATA-%d Hard-Disk (%4u MBytes)\n", version, (Bit16u)sizeinmb);
2709
 
          else
 
2749
          else
2710
2750
            printf(" ATA-%d Hard-Disk (%4u GBytes)\n", version, (Bit16u)(sizeinmb>>10));
2711
2751
          break;
2712
2752
        case ATA_TYPE_ATAPI:
2720
2760
        case ATA_TYPE_UNKNOWN:
2721
2761
          printf("ata%d %s: Unknown device\n",channel,slave?" slave":"master");
2722
2762
          break;
2723
 
        }
2724
2763
      }
2725
2764
    }
 
2765
  }
2726
2766
 
2727
2767
  // Store the devices counts
2728
2768
  write_byte(ebda_seg,&EbdaData->ata.hdcount, hdcount);
2852
2892
      command |= 0x04;
2853
2893
      count &= (1UL << 8) - 1;
2854
2894
      lba_low &= (1UL << 24) - 1;
2855
 
      }
 
2895
    }
2856
2896
    sector = (Bit16u) (lba_low & 0x000000ffL);
2857
2897
    cylinder = (Bit16u) ((lba_low>>8) & 0x0000ffffL);
2858
2898
    head = ((Bit16u) ((lba_low>>24) & 0x0000000fL)) | ATA_CB_DH_LBA;
2872
2912
  if (status & ATA_CB_STAT_ERR) {
2873
2913
    BX_DEBUG_ATA("ata_cmd_data_in : read error\n");
2874
2914
    return 2;
2875
 
    } else if ( !(status & ATA_CB_STAT_DRQ) ) {
 
2915
  } else if ( !(status & ATA_CB_STAT_DRQ) ) {
2876
2916
    BX_DEBUG_ATA("ata_cmd_data_in : DRQ not set (status %02x)\n", (unsigned) status);
2877
2917
    return 3;
2878
2918
  }
2934
2974
          != ATA_CB_STAT_RDY ) {
2935
2975
        BX_DEBUG_ATA("ata_cmd_data_in : no sectors left (status %02x)\n", (unsigned) status);
2936
2976
        return 4;
2937
 
        }
 
2977
      }
2938
2978
      break;
2939
 
      }
 
2979
    }
2940
2980
    else {
2941
2981
      if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
2942
2982
          != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) {
3003
3043
      command |= 0x04;
3004
3044
      count &= (1UL << 8) - 1;
3005
3045
      lba_low &= (1UL << 24) - 1;
3006
 
      }
 
3046
    }
3007
3047
    sector = (Bit16u) (lba_low & 0x000000ffL);
3008
3048
    cylinder = (Bit16u) ((lba_low>>8) & 0x0000ffffL);
3009
3049
    head = ((Bit16u) ((lba_low>>24) & 0x0000000fL)) | ATA_CB_DH_LBA;
3023
3063
  if (status & ATA_CB_STAT_ERR) {
3024
3064
    BX_DEBUG_ATA("ata_cmd_data_out : read error\n");
3025
3065
    return 2;
3026
 
    } else if ( !(status & ATA_CB_STAT_DRQ) ) {
 
3066
  } else if ( !(status & ATA_CB_STAT_DRQ) ) {
3027
3067
    BX_DEBUG_ATA("ata_cmd_data_out : DRQ not set (status %02x)\n", (unsigned) status);
3028
3068
    return 3;
3029
 
    }
 
3069
  }
3030
3070
 
3031
3071
  // FIXME : move seg/off translation here
3032
3072
 
3086
3126
          != ATA_CB_STAT_RDY ) {
3087
3127
        BX_DEBUG_ATA("ata_cmd_data_out : no sectors left (status %02x)\n", (unsigned) status);
3088
3128
        return 6;
3089
 
        }
 
3129
      }
3090
3130
      break;
3091
 
      }
 
3131
    }
3092
3132
    else {
3093
3133
      if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
3094
3134
          != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) {
3132
3172
  if (inout == ATA_DATA_OUT) {
3133
3173
    BX_INFO("ata_cmd_packet: DATA_OUT not supported yet\n");
3134
3174
    return 1;
3135
 
    }
 
3175
  }
3136
3176
 
3137
3177
  // The header length must be even
3138
3178
  if (header & 1) {
3139
3179
    BX_DEBUG_ATA("ata_cmd_packet : header must be even (%04x)\n",header);
3140
3180
    return 1;
3141
 
    }
 
3181
  }
3142
3182
 
3143
3183
  iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1);
3144
3184
  iobase2 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase2);
3172
3212
  if (status & ATA_CB_STAT_ERR) {
3173
3213
    BX_DEBUG_ATA("ata_cmd_packet : error, status is %02x\n",status);
3174
3214
    return 3;
3175
 
    } else if ( !(status & ATA_CB_STAT_DRQ) ) {
 
3215
  } else if ( !(status & ATA_CB_STAT_DRQ) ) {
3176
3216
    BX_DEBUG_ATA("ata_cmd_packet : DRQ not set (status %02x)\n", (unsigned) status);
3177
3217
    return 4;
3178
 
    }
 
3218
  }
3179
3219
 
3180
3220
  // Normalize address
3181
3221
  cmdseg += (cmdoff / 16);
3205
3245
  if (inout == ATA_DATA_NO) {
3206
3246
    await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
3207
3247
    status = inb(iobase1 + ATA_CB_STAT);
3208
 
    }
 
3248
  }
3209
3249
  else {
3210
 
        Bit16u loops = 0;
3211
 
        Bit8u sc;
3212
 
  while (1) {
 
3250
    Bit16u loops = 0;
 
3251
    Bit8u sc;
 
3252
 
 
3253
    while (1) {
3213
3254
 
3214
3255
      if (loops == 0) {//first time through
3215
3256
        status = inb(iobase2 + ATA_CB_ASTAT);
3243
3284
         lbefore=lcount;
3244
3285
         header-=lcount;
3245
3286
         lcount=0;
3246
 
         }
 
3287
      }
3247
3288
      else {
3248
3289
        lbefore=header;
3249
3290
        header=0;
3250
3291
        lcount-=lbefore;
3251
 
        }
 
3292
      }
3252
3293
 
3253
3294
      if(lcount>length) {
3254
3295
        lafter=lcount-length;
3255
3296
        lcount=length;
3256
3297
        length=0;
3257
 
        }
 
3298
      }
3258
3299
      else {
3259
3300
        lafter=0;
3260
3301
        length-=lcount;
3261
 
        }
 
3302
      }
3262
3303
 
3263
3304
      // Save byte count
3264
3305
      count = lcount;
3277
3318
        lcount+=1;
3278
3319
        if ((lafter > 0) && (lafter & 0x01)) {
3279
3320
          lafter-=1;
3280
 
          }
3281
3321
        }
 
3322
      }
3282
3323
 
3283
3324
      if (lmode == ATA_MODE_PIO32) {
3284
3325
        lcount>>=2; lbefore>>=2; lafter>>=2;
3285
 
        }
 
3326
      }
3286
3327
      else {
3287
3328
        lcount>>=1; lbefore>>=1; lafter>>=1;
3288
 
        }
 
3329
      }
3289
3330
 
3290
3331
       ;  // FIXME bcc bug
3291
3332
 
3365
3406
      // Save transferred bytes count
3366
3407
      transfer += count;
3367
3408
      write_dword(ebda_seg, &EbdaData->ata.trsfbytes,transfer);
3368
 
      }
3369
3409
    }
 
3410
  }
3370
3411
 
3371
3412
  // Final check, device must be ready
3372
3413
  if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
3373
3414
         != ATA_CB_STAT_RDY ) {
3374
3415
    BX_DEBUG_ATA("ata_cmd_packet : not ready (status %02x)\n", (unsigned) status);
3375
3416
    return 4;
3376
 
    }
 
3417
  }
3377
3418
 
3378
3419
  // Enable interrupts
3379
3420
  outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15);
3561
3602
  // Find out the first cdrom
3562
3603
  for (device=0; device<BX_MAX_ATA_DEVICES;device++) {
3563
3604
    if (atapi_is_cdrom(device)) break;
3564
 
    }
 
3605
  }
 
3606
 
 
3607
  // if not found
 
3608
  if(device >= BX_MAX_ATA_DEVICES) return 2;
3565
3609
 
3566
3610
  if(error = atapi_is_ready(device) != 0)
3567
3611
    BX_INFO("ata_is_ready returned %d\n",error);
3568
3612
 
3569
 
  // if not found
3570
 
  if(device >= BX_MAX_ATA_DEVICES) return 2;
3571
 
 
3572
3613
  // Read the Boot Record Volume Descriptor
3573
3614
  memsetb(get_SS(),atacmd,0,12);
3574
3615
  atacmd[0]=0x28;                      // READ command
3582
3623
    return 3;
3583
3624
 
3584
3625
  // Validity checks
3585
 
  if(buffer[0]!=0)return 4;
 
3626
  if(buffer[0]!=0) return 4;
3586
3627
  for(i=0;i<5;i++){
3587
 
    if(buffer[1+i]!=read_byte(0xf000,&isotag[i]))return 5;
3588
 
   }
 
3628
    if(buffer[1+i]!=read_byte(0xf000,&isotag[i])) return 5;
 
3629
  }
3589
3630
  for(i=0;i<23;i++)
3590
 
    if(buffer[7+i]!=read_byte(0xf000,&eltorito[i]))return 6;
 
3631
    if(buffer[7+i]!=read_byte(0xf000,&eltorito[i])) return 6;
3591
3632
 
3592
3633
  // ok, now we calculate the Boot catalog address
3593
3634
  lba=buffer[0x4A]*0x1000000+buffer[0x49]*0x10000+buffer[0x48]*0x100+buffer[0x47];
3618
3659
    // FIXME ElTorito Hardcoded. cdrom is hardcoded as device 0xE0.
3619
3660
    // Win2000 cd boot needs to know it booted from cd
3620
3661
    write_byte(ebda_seg,&EbdaData->cdemu.emulated_drive,0xE0);
3621
 
    }
 
3662
  }
3622
3663
  else if(buffer[0x21]<4)
3623
3664
    write_byte(ebda_seg,&EbdaData->cdemu.emulated_drive,0x00);
3624
3665
  else
3682
3723
      write_byte(0x40,0x10,read_byte(0x40,0x10)|0x41);
3683
3724
    else
3684
3725
      write_byte(ebda_seg, &EbdaData->ata.hdcount, read_byte(ebda_seg, &EbdaData->ata.hdcount) + 1);
3685
 
   }
3686
 
 
 
3726
  }
3687
3727
 
3688
3728
  // everything is ok, so from now on, the emulation is active
3689
3729
  if(read_byte(ebda_seg,&EbdaData->cdemu.media)!=0)
3698
3738
// ---------------------------------------------------------------------------
3699
3739
#endif // BX_ELTORITO_BOOT
3700
3740
 
3701
 
  void
3702
 
int14_function(regs, ds, iret_addr)
 
3741
void int14_function(regs, ds, iret_addr)
3703
3742
  pusha_regs_t regs; // regs pushed from PUSHA instruction
3704
3743
  Bit16u ds; // previous DS:, DS set to 0x0000 by asm wrapper
3705
3744
  iret_addr_t  iret_addr; // CS,IP,Flags pushed from original INT call
3706
3745
{
3707
3746
  Bit16u addr,timer,val16;
3708
 
  Bit8u timeout;
 
3747
  Bit8u counter;
3709
3748
 
3710
3749
  ASM_START
3711
3750
  sti
3712
3751
  ASM_END
3713
3752
 
3714
3753
  addr = read_word(0x0040, (regs.u.r16.dx << 1));
3715
 
  timeout = read_byte(0x0040, 0x007C + regs.u.r16.dx);
 
3754
  counter = read_byte(0x0040, 0x007C + regs.u.r16.dx);
3716
3755
  if ((regs.u.r16.dx < 4) && (addr > 0)) {
3717
3756
    switch (regs.u.r8.ah) {
3718
3757
      case 0:
3732
3771
        break;
3733
3772
      case 1:
3734
3773
        timer = read_word(0x0040, 0x006C);
3735
 
        while (((inb(addr+5) & 0x60) != 0x60) && (timeout)) {
 
3774
        while (((inb(addr+5) & 0x60) != 0x60) && (counter)) {
3736
3775
          val16 = read_word(0x0040, 0x006C);
3737
3776
          if (val16 != timer) {
3738
3777
            timer = val16;
3739
 
            timeout--;
3740
 
            }
 
3778
            counter--;
3741
3779
          }
3742
 
        if (timeout) outb(addr, regs.u.r8.al);
3743
 
        regs.u.r8.ah = inb(addr+5);
3744
 
        if (!timeout) regs.u.r8.ah |= 0x80;
 
3780
        }
 
3781
        if (counter > 0) {
 
3782
          outb(addr, regs.u.r8.al);
 
3783
          regs.u.r8.ah = inb(addr+5);
 
3784
        } else {
 
3785
          regs.u.r8.ah = 0x80;
 
3786
        }
3745
3787
        ClearCF(iret_addr.flags);
3746
3788
        break;
3747
3789
      case 2:
3748
3790
        timer = read_word(0x0040, 0x006C);
3749
 
        while (((inb(addr+5) & 0x01) == 0) && (timeout)) {
 
3791
        while (((inb(addr+5) & 0x01) == 0) && (counter)) {
3750
3792
          val16 = read_word(0x0040, 0x006C);
3751
3793
          if (val16 != timer) {
3752
3794
            timer = val16;
3753
 
            timeout--;
3754
 
            }
 
3795
            counter--;
3755
3796
          }
3756
 
        if (timeout) {
3757
 
          regs.u.r8.ah = 0;
 
3797
        }
 
3798
        if (counter > 0) {
 
3799
          regs.u.r8.ah = inb(addr+5);
3758
3800
          regs.u.r8.al = inb(addr);
3759
3801
        } else {
3760
 
          regs.u.r8.ah = inb(addr+5);
3761
 
          }
 
3802
          regs.u.r8.ah = 0x80;
 
3803
        }
3762
3804
        ClearCF(iret_addr.flags);
3763
3805
        break;
3764
3806
      case 3:
3771
3813
      }
3772
3814
  } else {
3773
3815
    SetCF(iret_addr.flags); // Unsupported
3774
 
    }
 
3816
  }
3775
3817
}
3776
3818
 
3777
3819
  void
4127
4169
                  CLEAR_CF();
4128
4170
                  regs.u.r8.ah = 0;
4129
4171
                  return;
4130
 
                  }
4131
4172
                }
 
4173
              }
4132
4174
 
4133
4175
              // error
4134
4176
              SET_CF();
4144
4186
                SET_CF();  // error
4145
4187
                regs.u.r8.ah = 5; // no far call installed
4146
4188
                return;
4147
 
                }
 
4189
              }
4148
4190
              inhibit_mouse_int_and_events(); // disable IRQ12 and packets
4149
4191
              ret = send_to_mouse_ctrl(0xF4); // enable mouse command
4150
4192
              if (ret == 0) {
4154
4196
                  CLEAR_CF();
4155
4197
                  regs.u.r8.ah = 0;
4156
4198
                  return;
4157
 
                  }
4158
4199
                }
 
4200
              }
4159
4201
              SET_CF();
4160
4202
              regs.u.r8.ah = ret;
4161
4203
              return;
4165
4207
              SET_CF();  // error
4166
4208
              regs.u.r8.ah = 1; // invalid subfunction
4167
4209
              return;
4168
 
            }
 
4210
          }
4169
4211
          break;
4170
4212
 
4171
4213
        case 1: // Reset Mouse
4207
4249
                  regs.u.r8.bl = mouse_data1;
4208
4250
                  regs.u.r8.bh = mouse_data2;
4209
4251
                  return;
4210
 
                  }
4211
4252
                }
4212
4253
              }
4213
4254
            }
 
4255
          }
4214
4256
 
4215
4257
          // error
4216
4258
          SET_CF();
4311
4353
                  BX_PANIC("Mouse status returned %02x (should be ack)\n", (unsigned)mouse_data1);
4312
4354
                if (ret == 0) {
4313
4355
                  ret = get_mouse_data(&mouse_data1);
4314
 
                  if ( ret == 0 ) {
 
4356
                  if (ret == 0) {
4315
4357
                    ret = get_mouse_data(&mouse_data2);
4316
 
                    if ( ret == 0 ) {
 
4358
                    if (ret == 0) {
4317
4359
                      ret = get_mouse_data(&mouse_data3);
4318
 
                      if ( ret == 0 ) {
 
4360
                      if (ret == 0) {
4319
4361
                        CLEAR_CF();
4320
4362
                        regs.u.r8.ah = 0;
4321
4363
                        regs.u.r8.bl = mouse_data1;
4323
4365
                        regs.u.r8.dl = mouse_data3;
4324
4366
                        set_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable
4325
4367
                        return;
4326
 
                        }
4327
4368
                      }
4328
4369
                    }
4329
4370
                  }
4330
4371
                }
 
4372
              }
4331
4373
 
4332
4374
              // error
4333
4375
              SET_CF();
4360
4402
 
4361
4403
            default:
4362
4404
              BX_PANIC("INT 15h C2 AL=6, BH=%02x\n", (unsigned) regs.u.r8.bh);
4363
 
            }
 
4405
          }
4364
4406
          break;
4365
4407
 
4366
4408
        case 7: // Set Mouse Handler Address
4375
4417
            if ( (mouse_flags_2 & 0x80) != 0 ) {
4376
4418
              mouse_flags_2 &= ~0x80;
4377
4419
              inhibit_mouse_int_and_events(); // disable IRQ12 and packets
4378
 
              }
4379
4420
            }
 
4421
          }
4380
4422
          else {
4381
4423
            /* install handler */
4382
4424
            mouse_flags_2 |= 0x80;
4383
 
            }
 
4425
          }
4384
4426
          write_byte(ebda_seg, 0x0027, mouse_flags_2);
4385
4427
          CLEAR_CF();
4386
4428
          regs.u.r8.ah = 0;
4390
4432
BX_DEBUG_INT15("case default:\n");
4391
4433
          regs.u.r8.ah = 1; // invalid function
4392
4434
          SET_CF();
4393
 
        }
 
4435
      }
4394
4436
      break;
4395
4437
 
4396
4438
    default:
4399
4441
      SET_CF();
4400
4442
      regs.u.r8.ah = UNSUPPORTED_FUNCTION;
4401
4443
      break;
4402
 
    }
 
4444
  }
4403
4445
}
4404
4446
#endif // BX_USE_PS2_MOUSE
4405
4447
 
4406
4448
 
4407
 
void set_e820_range(ES, DI, start, end, type)
 
4449
void set_e820_range(ES, DI, start, end, extra_start, extra_end, type)
4408
4450
     Bit16u ES;
4409
4451
     Bit16u DI;
4410
4452
     Bit32u start;
4411
4453
     Bit32u end;
 
4454
     Bit8u extra_start;
 
4455
     Bit8u extra_end;
4412
4456
     Bit16u type;
4413
4457
{
4414
4458
    write_word(ES, DI, start);
4415
4459
    write_word(ES, DI+2, start >> 16);
4416
 
    write_word(ES, DI+4, 0x00);
 
4460
    write_word(ES, DI+4, extra_start);
4417
4461
    write_word(ES, DI+6, 0x00);
4418
4462
 
4419
4463
    end -= start;
 
4464
    extra_end -= extra_start;
4420
4465
    write_word(ES, DI+8, end);
4421
4466
    write_word(ES, DI+10, end >> 16);
4422
 
    write_word(ES, DI+12, 0x0000);
 
4467
    write_word(ES, DI+12, extra_end);
4423
4468
    write_word(ES, DI+14, 0x0000);
4424
4469
 
4425
4470
    write_word(ES, DI+16, type);
4432
4477
  Bit16u ES, DS, FLAGS;
4433
4478
{
4434
4479
  Bit32u  extended_memory_size=0; // 64bits long
 
4480
  Bit32u  extra_lowbits_memory_size=0;
4435
4481
  Bit16u  CX,DX;
 
4482
  Bit8u   extra_highbits_memory_size=0;
4436
4483
 
4437
4484
BX_DEBUG_INT15("int15 AX=%04x\n",regs.u.r16.ax);
4438
4485
 
4482
4529
      break;
4483
4530
 
4484
4531
    case 0xe8:
4485
 
        switch(regs.u.r8.al)
4486
 
        {
 
4532
        switch(regs.u.r8.al) {
4487
4533
         case 0x20: // coded by osmaker aka K.J.
4488
4534
            if(regs.u.r32.edx == 0x534D4150)
4489
4535
            {
4506
4552
                    extended_memory_size += (1L * 1024 * 1024);
4507
4553
                }
4508
4554
 
 
4555
                extra_lowbits_memory_size = inb_cmos(0x5c);
 
4556
                extra_lowbits_memory_size <<= 8;
 
4557
                extra_lowbits_memory_size |= inb_cmos(0x5b);
 
4558
                extra_lowbits_memory_size *= 64;
 
4559
                extra_lowbits_memory_size *= 1024;
 
4560
                extra_highbits_memory_size = inb_cmos(0x5d);
 
4561
 
4509
4562
                switch(regs.u.r16.bx)
4510
4563
                {
4511
4564
                    case 0:
4512
4565
                        set_e820_range(ES, regs.u.r16.di,
4513
 
                                       0x0000000L, 0x0009fc00L, 1);
 
4566
                                       0x0000000L, 0x0009f000L, 0, 0, 1);
4514
4567
                        regs.u.r32.ebx = 1;
4515
 
                        regs.u.r32.eax = 0x534D4150;
4516
 
                        regs.u.r32.ecx = 0x14;
4517
 
                        CLEAR_CF();
4518
 
                        return;
4519
4568
                        break;
4520
4569
                    case 1:
4521
4570
                        set_e820_range(ES, regs.u.r16.di,
4522
 
                                       0x0009fc00L, 0x000a0000L, 2);
 
4571
                                       0x0009f000L, 0x000a0000L, 0, 0, 2);
4523
4572
                        regs.u.r32.ebx = 2;
4524
 
                        regs.u.r32.eax = 0x534D4150;
4525
 
                        regs.u.r32.ecx = 0x14;
4526
 
                        CLEAR_CF();
4527
 
                        return;
4528
4573
                        break;
4529
4574
                    case 2:
4530
4575
                        set_e820_range(ES, regs.u.r16.di,
4531
 
                                       0x000e8000L, 0x00100000L, 2);
 
4576
                                       0x000e8000L, 0x00100000L, 0, 0, 2);
4532
4577
                        regs.u.r32.ebx = 3;
4533
 
                        regs.u.r32.eax = 0x534D4150;
4534
 
                        regs.u.r32.ecx = 0x14;
4535
 
                        CLEAR_CF();
4536
 
                        return;
4537
4578
                        break;
4538
4579
                    case 3:
4539
4580
#if BX_ROMBIOS32
4540
4581
                        set_e820_range(ES, regs.u.r16.di,
4541
4582
                                       0x00100000L,
4542
 
                                       extended_memory_size - ACPI_DATA_SIZE, 1);
 
4583
                                       extended_memory_size - ACPI_DATA_SIZE, 0, 0, 1);
4543
4584
                        regs.u.r32.ebx = 4;
4544
4585
#else
4545
4586
                        set_e820_range(ES, regs.u.r16.di,
4546
4587
                                       0x00100000L,
4547
 
                                       extended_memory_size, 1);
 
4588
                                       extended_memory_size, 0, 0, 1);
4548
4589
                        regs.u.r32.ebx = 5;
4549
4590
#endif
4550
 
                        regs.u.r32.eax = 0x534D4150;
4551
 
                        regs.u.r32.ecx = 0x14;
4552
 
                        CLEAR_CF();
4553
 
                        return;
4554
4591
                        break;
4555
4592
                    case 4:
4556
4593
                        set_e820_range(ES, regs.u.r16.di,
4557
4594
                                       extended_memory_size - ACPI_DATA_SIZE,
4558
 
                                       extended_memory_size, 3); // ACPI RAM
 
4595
                                       extended_memory_size, 0, 0, 3); // ACPI RAM
4559
4596
                        regs.u.r32.ebx = 5;
4560
 
                        regs.u.r32.eax = 0x534D4150;
4561
 
                        regs.u.r32.ecx = 0x14;
4562
 
                        CLEAR_CF();
4563
 
                        return;
4564
4597
                        break;
4565
4598
                    case 5:
4566
4599
                        /* 256KB BIOS area at the end of 4 GB */
4567
4600
                        set_e820_range(ES, regs.u.r16.di,
4568
 
                                       0xfffc0000L, 0x00000000L, 2);
 
4601
                                       0xfffc0000L, 0x00000000L, 0, 0, 2);
 
4602
                        if (extra_highbits_memory_size || extra_lowbits_memory_size)
 
4603
                            regs.u.r32.ebx = 6;
 
4604
                        else
 
4605
                            regs.u.r32.ebx = 0;
 
4606
                        break;
 
4607
                    case 6:
 
4608
                        /* Maping of memory above 4 GB */
 
4609
                        set_e820_range(ES, regs.u.r16.di, 0x00000000L,
 
4610
                            extra_lowbits_memory_size, 1, extra_highbits_memory_size
 
4611
                                       + 1, 1);
4569
4612
                        regs.u.r32.ebx = 0;
4570
 
                        regs.u.r32.eax = 0x534D4150;
4571
 
                        regs.u.r32.ecx = 0x14;
4572
 
                        CLEAR_CF();
4573
 
                        return;
 
4613
                        break;
4574
4614
                    default:  /* AX=E820, DX=534D4150, BX unrecognized */
4575
4615
                        goto int15_unimplemented;
4576
4616
                        break;
4577
4617
                }
 
4618
                regs.u.r32.eax = 0x534D4150;
 
4619
                regs.u.r32.ecx = 0x14;
 
4620
                CLEAR_CF();
4578
4621
            } else {
4579
4622
              // if DX != 0x534D4150)
4580
4623
              goto int15_unimplemented;
4660
4703
 
4661
4704
      if ( !dequeue_key(&scan_code, &ascii_code, 1) ) {
4662
4705
        BX_PANIC("KBD: int16h: out of keyboard input\n");
4663
 
        }
 
4706
      }
4664
4707
      if (scan_code !=0 && ascii_code == 0xF0) ascii_code = 0;
4665
4708
      else if (ascii_code == 0xE0) ascii_code = 0;
4666
4709
      AX = (scan_code << 8) | ascii_code;
4670
4713
      if ( !dequeue_key(&scan_code, &ascii_code, 0) ) {
4671
4714
        SET_ZF();
4672
4715
        return;
4673
 
        }
 
4716
      }
4674
4717
      if (scan_code !=0 && ascii_code == 0xF0) ascii_code = 0;
4675
4718
      else if (ascii_code == 0xE0) ascii_code = 0;
4676
4719
      AX = (scan_code << 8) | ascii_code;
4685
4728
    case 0x05: /* store key-stroke into buffer */
4686
4729
      if ( !enqueue_key(GET_CH(), GET_CL()) ) {
4687
4730
        SET_AL(1);
4688
 
        }
 
4731
      }
4689
4732
      else {
4690
4733
        SET_AL(0);
4691
 
        }
 
4734
      }
4692
4735
      break;
4693
4736
 
4694
4737
    case 0x09: /* GET KEYBOARD FUNCTIONALITY */
4731
4774
 
4732
4775
      if ( !dequeue_key(&scan_code, &ascii_code, 1) ) {
4733
4776
        BX_PANIC("KBD: int16h: out of keyboard input\n");
4734
 
        }
 
4777
      }
4735
4778
      if (scan_code !=0 && ascii_code == 0xF0) ascii_code = 0;
4736
4779
      AX = (scan_code << 8) | ascii_code;
4737
4780
      break;
4740
4783
      if ( !dequeue_key(&scan_code, &ascii_code, 0) ) {
4741
4784
        SET_ZF();
4742
4785
        return;
4743
 
        }
 
4786
      }
4744
4787
      if (scan_code !=0 && ascii_code == 0xF0) ascii_code = 0;
4745
4788
      AX = (scan_code << 8) | ascii_code;
4746
4789
      CLEAR_ZF();
4769
4812
 
4770
4813
    default:
4771
4814
      BX_INFO("KBD: unsupported int 16h function %02x\n", GET_AH());
4772
 
    }
 
4815
  }
4773
4816
}
4774
4817
 
4775
4818
  unsigned int
4805
4848
      if (buffer_head >= buffer_end)
4806
4849
        buffer_head = buffer_start;
4807
4850
      write_word(0x0040, 0x001a, buffer_head);
4808
 
      }
 
4851
    }
4809
4852
    return(1);
4810
 
    }
 
4853
  }
4811
4854
  else {
4812
4855
    return(0);
4813
 
    }
 
4856
  }
4814
4857
}
4815
4858
 
4816
4859
static char panic_msg_keyb_buffer_full[] = "%s: keyboard input buffer full\n";
4879
4922
  Bit8u response;
4880
4923
  Bit16u ss;
4881
4924
 
4882
 
  while ( (inb(0x64) & 0x21) != 0x21 ) {
4883
 
    }
 
4925
  while ((inb(0x64) & 0x21) != 0x21) { }
4884
4926
 
4885
4927
  response = inb(0x60);
4886
4928
 
4918
4960
  if (scancode == 0) {
4919
4961
    BX_INFO("KBD: int09 handler: AL=0\n");
4920
4962
    return;
4921
 
    }
 
4963
  }
4922
4964
 
4923
4965
 
4924
4966
  shift_flags = read_byte(0x0040, 0x17);
5109
5151
 
5110
5152
  if (buffer_tail == buffer_head) {
5111
5153
    return(0);
5112
 
    }
 
5154
  }
5113
5155
 
5114
 
   write_byte(0x0040, temp_tail, ascii_code);
5115
 
   write_byte(0x0040, temp_tail+1, scan_code);
5116
 
   write_word(0x0040, 0x001C, buffer_tail);
5117
 
   return(1);
 
5156
  write_byte(0x0040, temp_tail, ascii_code);
 
5157
  write_byte(0x0040, temp_tail+1, scan_code);
 
5158
  write_word(0x0040, 0x001C, buffer_tail);
 
5159
  return(1);
5118
5160
}
5119
5161
 
5120
 
 
5121
5162
  void
5122
5163
int74_function(make_farcall, Z, Y, X, status)
5123
5164
  Bit16u make_farcall, Z, Y, X, status;
5130
5171
  make_farcall = 0;
5131
5172
 
5132
5173
  in_byte = inb(0x64);
5133
 
  if ( (in_byte & 0x21) != 0x21 ) {
 
5174
  if ((in_byte & 0x21) != 0x21) {
5134
5175
    return;
5135
 
    }
 
5176
  }
 
5177
 
5136
5178
  in_byte = inb(0x60);
5137
5179
BX_DEBUG_INT74("int74: read byte %02x\n", in_byte);
5138
5180
 
5139
5181
  mouse_flags_1 = read_byte(ebda_seg, 0x0026);
5140
5182
  mouse_flags_2 = read_byte(ebda_seg, 0x0027);
5141
5183
 
5142
 
  if ( (mouse_flags_2 & 0x80) != 0x80 ) {
 
5184
  if ((mouse_flags_2 & 0x80) != 0x80) {
5143
5185
      return;
5144
5186
  }
5145
5187
 
5160
5202
    }
5161
5203
  else {
5162
5204
    mouse_flags_1++;
5163
 
    }
 
5205
  }
5164
5206
  write_byte(ebda_seg, 0x0026, mouse_flags_1);
5165
5207
}
5166
5208
 
5188
5230
  if ( (GET_ELDL() < 0x80) || (GET_ELDL() >= 0x80 + BX_MAX_ATA_DEVICES) ) {
5189
5231
    BX_INFO("int13_harddisk: function %02x, ELDL out of range %02x\n", GET_AH(), GET_ELDL());
5190
5232
    goto int13_fail;
5191
 
    }
 
5233
  }
5192
5234
 
5193
5235
  // Get the ata channel
5194
5236
  device=read_byte(ebda_seg,&EbdaData->ata.hdidmap[GET_ELDL()-0x80]);
5197
5239
  if (device >= BX_MAX_ATA_DEVICES) {
5198
5240
    BX_INFO("int13_harddisk: function %02x, unmapped device for ELDL=%02x\n", GET_AH(), GET_ELDL());
5199
5241
    goto int13_fail;
5200
 
    }
 
5242
  }
5201
5243
 
5202
5244
  switch (GET_AH()) {
5203
5245
 
5238
5280
      nlspt = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.spt);
5239
5281
 
5240
5282
      // sanity check on cyl heads, sec
5241
 
      if( (cylinder >= nlc) || (head >= nlh) || (sector > nlspt )) {
 
5283
      if( (cylinder >= nlc) || (head >= nlh) || (sector > nlspt) ) {
5242
5284
        BX_INFO("int13_harddisk: function %02x, parameters out of range %04x/%04x/%04x!\n", GET_AH(), cylinder, head, sector);
5243
5285
        goto int13_fail;
5244
 
        }
 
5286
      }
5245
5287
 
5246
5288
      // FIXME verify
5247
 
      if ( GET_AH() == 0x04 ) goto int13_success;
 
5289
      if (GET_AH() == 0x04) goto int13_success;
5248
5290
 
5249
5291
      nph   = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.heads);
5250
5292
      npspt = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.spt);
5254
5296
        lba_low = ((((Bit32u)cylinder * (Bit32u)nlh) + (Bit32u)head) * (Bit32u)nlspt) + (Bit32u)sector - 1;
5255
5297
        lba_high = 0;
5256
5298
        sector = 0; // this forces the command to be lba
5257
 
        }
 
5299
      }
5258
5300
 
5259
 
      if ( GET_AH() == 0x02 )
 
5301
      if (GET_AH() == 0x02)
5260
5302
        status=ata_cmd_data_in(device, ATA_CMD_READ_SECTORS, count, cylinder, head, sector, lba_low, lba_high, segment, offset);
5261
5303
      else
5262
5304
        status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, cylinder, head, sector, lba_low, lba_high, segment, offset);
5268
5310
        BX_INFO("int13_harddisk: function %02x, error %02x !\n",GET_AH(),status);
5269
5311
        SET_AH(0x0c);
5270
5312
        goto int13_fail_noah;
5271
 
        }
 
5313
      }
5272
5314
 
5273
5315
      goto int13_success;
5274
5316
      break;
5287
5329
      nlspt = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.spt);
5288
5330
      count = read_byte(ebda_seg, &EbdaData->ata.hdcount);
5289
5331
 
5290
 
      nlc = nlc - 2; /* 0 based , last sector not used */
 
5332
      nlc = nlc - 2; /* 0 based, last sector not used */
5291
5333
      SET_AL(0);
5292
5334
      SET_CH(nlc & 0xff);
5293
5335
      SET_CL(((nlc >> 2) & 0xc0) | (nlspt & 0x3f));
5304
5346
 
5305
5347
      // Read the status from controller
5306
5348
      status = inb(read_word(ebda_seg, &EbdaData->ata.channels[device/2].iobase1) + ATA_CB_STAT);
5307
 
      if ( (status & ( ATA_CB_STAT_BSY | ATA_CB_STAT_RDY )) == ATA_CB_STAT_RDY ) {
 
5349
      if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY)) == ATA_CB_STAT_RDY ) {
5308
5350
        goto int13_success;
5309
 
        }
 
5351
      }
5310
5352
      else {
5311
5353
        SET_AH(0xAA);
5312
5354
        goto int13_fail_noah;
5313
 
        }
 
5355
      }
5314
5356
      break;
5315
5357
 
5316
5358
    case 0x15: /* read disk drive size */
5350
5392
      if (lba_high > read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_high) ) {
5351
5393
        BX_INFO("int13_harddisk: function %02x. LBA out of range\n",GET_AH());
5352
5394
        goto int13_fail;
5353
 
        }
 
5395
      }
5354
5396
 
5355
5397
      // Get 32 lsb lba and check
5356
5398
      lba_low=read_dword(DS, SI+(Bit16u)&Int13Ext->lba1);
5358
5400
          && lba_low >= read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_low) ) {
5359
5401
        BX_INFO("int13_harddisk: function %02x. LBA out of range\n",GET_AH());
5360
5402
        goto int13_fail;
5361
 
        }
 
5403
      }
5362
5404
 
5363
5405
      // If verify or seek
5364
5406
      if (( GET_AH() == 0x44 ) || ( GET_AH() == 0x47 ))
5365
5407
        goto int13_success;
5366
5408
 
5367
5409
      // Execute the command
5368
 
      if ( GET_AH() == 0x42 )
 
5410
      if (GET_AH() == 0x42)
5369
5411
        status=ata_cmd_data_in(device, ATA_CMD_READ_SECTORS, count, 0, 0, 0, lba_low, lba_high, segment, offset);
5370
5412
      else
5371
5413
        status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, 0, 0, 0, lba_low, lba_high, segment, offset);
5377
5419
        BX_INFO("int13_harddisk: function %02x, error %02x !\n",GET_AH(),status);
5378
5420
        SET_AH(0x0c);
5379
5421
        goto int13_fail_noah;
5380
 
        }
 
5422
      }
5381
5423
 
5382
5424
      goto int13_success;
5383
5425
      break;
5426
5468
        write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count1, lba_low);
5427
5469
        write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, lba_high);
5428
5470
        write_word(DS, SI+(Bit16u)&Int13DPT->blksize, blksize);
5429
 
        }
 
5471
      }
5430
5472
 
5431
5473
      // EDD 2.x
5432
5474
      if(size >= 0x1e) {
5471
5513
        for (i=0; i<15; i++) checksum+=read_byte(ebda_seg, ((Bit8u*)(&EbdaData->ata.dpte)) + i);
5472
5514
        checksum = ~checksum;
5473
5515
        write_byte(ebda_seg, &EbdaData->ata.dpte.checksum, checksum);
5474
 
        }
 
5516
      }
5475
5517
 
5476
5518
      // EDD 3.x
5477
5519
      if(size >= 0x42) {
5493
5535
          write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[1], 'S');
5494
5536
          write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[2], 'A');
5495
5537
          write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[3], 0);
5496
 
          }
 
5538
        }
5497
5539
        else {
5498
5540
          // FIXME PCI
5499
 
          }
 
5541
        }
5500
5542
        write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[0], 'A');
5501
5543
        write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[1], 'T');
5502
5544
        write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[2], 'A');
5506
5548
          write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[0], iobase1);
5507
5549
          write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[2], 0);
5508
5550
          write_dword(DS, SI+(Bit16u)&Int13DPT->iface_path[4], 0L);
5509
 
          }
 
5551
        }
5510
5552
        else {
5511
5553
          // FIXME PCI
5512
 
          }
 
5554
        }
5513
5555
        write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[0], device%2);
5514
5556
        write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[1], 0);
5515
5557
        write_word(DS, SI+(Bit16u)&Int13DPT->device_path[2], 0);
5519
5561
        for (i=30; i<64; i++) checksum+=read_byte(DS, SI + i);
5520
5562
        checksum = ~checksum;
5521
5563
        write_byte(DS, SI+(Bit16u)&Int13DPT->checksum, checksum);
5522
 
        }
 
5564
      }
5523
5565
 
5524
5566
      goto int13_success;
5525
5567
      break;
5533
5575
        case 0x06:
5534
5576
          goto int13_success;
5535
5577
          break;
5536
 
        default :
 
5578
        default:
5537
5579
          goto int13_fail;
5538
 
        }
 
5580
      }
5539
5581
      break;
5540
5582
 
5541
5583
    case 0x09: /* initialize drive parameters */
5555
5597
      BX_INFO("int13_harddisk: function %02xh unsupported, returns fail\n", GET_AH());
5556
5598
      goto int13_fail;
5557
5599
      break;
5558
 
    }
 
5600
  }
5559
5601
 
5560
5602
int13_fail:
5561
 
    SET_AH(0x01); // defaults to invalid function in AH or invalid parameter
 
5603
  SET_AH(0x01); // defaults to invalid function in AH or invalid parameter
5562
5604
int13_fail_noah:
5563
 
    SET_DISK_RET_STATUS(GET_AH());
 
5605
  SET_DISK_RET_STATUS(GET_AH());
5564
5606
int13_fail_nostatus:
5565
 
    SET_CF();     // error occurred
5566
 
    return;
 
5607
  SET_CF();     // error occurred
 
5608
  return;
5567
5609
 
5568
5610
int13_success:
5569
 
    SET_AH(0x00); // no error
 
5611
  SET_AH(0x00); // no error
5570
5612
int13_success_noah:
5571
 
    SET_DISK_RET_STATUS(0x00);
5572
 
    CLEAR_CF();   // no error
5573
 
    return;
 
5613
  SET_DISK_RET_STATUS(0x00);
 
5614
  CLEAR_CF();   // no error
5574
5615
}
5575
5616
 
5576
5617
// ---------------------------------------------------------------------------
5595
5636
  if( (GET_ELDL() < 0xE0) || (GET_ELDL() >= 0xE0+BX_MAX_ATA_DEVICES) ) {
5596
5637
    BX_INFO("int13_cdrom: function %02x, ELDL out of range %02x\n", GET_AH(), GET_ELDL());
5597
5638
    goto int13_fail;
5598
 
    }
 
5639
  }
5599
5640
 
5600
5641
  // Get the ata channel
5601
5642
  device=read_byte(ebda_seg,&EbdaData->ata.cdidmap[GET_ELDL()-0xE0]);
5604
5645
  if (device >= BX_MAX_ATA_DEVICES) {
5605
5646
    BX_INFO("int13_cdrom: function %02x, unmapped device for ELDL=%02x\n", GET_AH(), GET_ELDL());
5606
5647
    goto int13_fail;
5607
 
    }
 
5648
  }
5608
5649
 
5609
5650
  switch (GET_AH()) {
5610
5651
 
5663
5704
      if (lba != 0L) {
5664
5705
        BX_PANIC("int13_cdrom: function %02x. Can't use 64bits lba\n",GET_AH());
5665
5706
        goto int13_fail;
5666
 
        }
 
5707
      }
5667
5708
 
5668
5709
      // Get 32 bits lba
5669
5710
      lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba1);
5670
5711
 
5671
5712
      // If verify or seek
5672
 
      if (( GET_AH() == 0x44 ) || ( GET_AH() == 0x47 ))
 
5713
      if ((GET_AH() == 0x44) || (GET_AH() == 0x47))
5673
5714
        goto int13_success;
5674
5715
 
5675
5716
      memsetb(get_SS(),atacmd,0,12);
5689
5730
        BX_INFO("int13_cdrom: function %02x, status %02x !\n",GET_AH(),status);
5690
5731
        SET_AH(0x0c);
5691
5732
        goto int13_fail_noah;
5692
 
        }
 
5733
      }
5693
5734
 
5694
5735
      goto int13_success;
5695
5736
      break;
5705
5746
            SET_AH(0xb4);
5706
5747
            SET_AL(1);
5707
5748
            goto int13_fail_noah;
5708
 
            }
 
5749
          }
5709
5750
          write_byte(ebda_seg, &EbdaData->ata.devices[device].lock, ++locks);
5710
5751
          SET_AL(1);
5711
5752
          break;
5714
5755
            SET_AH(0xb0);
5715
5756
            SET_AL(0);
5716
5757
            goto int13_fail_noah;
5717
 
            }
 
5758
          }
5718
5759
          write_byte(ebda_seg, &EbdaData->ata.devices[device].lock, --locks);
5719
5760
          SET_AL(locks==0?0:1);
5720
5761
          break;
5721
5762
        case 2 :  // status
5722
5763
          SET_AL(locks==0?0:1);
5723
5764
          break;
5724
 
        }
 
5765
      }
 
5766
 
5725
5767
      goto int13_success;
5726
5768
      break;
5727
5769
 
5731
5773
      if (locks != 0) {
5732
5774
        SET_AH(0xb1); // media locked
5733
5775
        goto int13_fail_noah;
5734
 
        }
 
5776
      }
5735
5777
      // FIXME should handle 0x31 no media in device
5736
5778
      // FIXME should handle 0xb5 valid request failed
5737
5779
 
5778
5820
        write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count1, 0xffffffff);  // FIXME should be Bit64
5779
5821
        write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, 0xffffffff);
5780
5822
        write_word(DS, SI+(Bit16u)&Int13DPT->blksize, blksize);
5781
 
        }
 
5823
      }
5782
5824
 
5783
5825
      // EDD 2.x
5784
5826
      if(size >= 0x1e) {
5819
5861
        for (i=0; i<15; i++) checksum+=read_byte(ebda_seg, ((Bit8u*)(&EbdaData->ata.dpte)) + i);
5820
5862
        checksum = ~checksum;
5821
5863
        write_byte(ebda_seg, &EbdaData->ata.dpte.checksum, checksum);
5822
 
        }
 
5864
      }
5823
5865
 
5824
5866
      // EDD 3.x
5825
5867
      if(size >= 0x42) {
5841
5883
          write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[1], 'S');
5842
5884
          write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[2], 'A');
5843
5885
          write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[3], 0);
5844
 
          }
 
5886
        }
5845
5887
        else {
5846
5888
          // FIXME PCI
5847
 
          }
 
5889
        }
5848
5890
        write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[0], 'A');
5849
5891
        write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[1], 'T');
5850
5892
        write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[2], 'A');
5854
5896
          write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[0], iobase1);
5855
5897
          write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[2], 0);
5856
5898
          write_dword(DS, SI+(Bit16u)&Int13DPT->iface_path[4], 0L);
5857
 
          }
 
5899
        }
5858
5900
        else {
5859
5901
          // FIXME PCI
5860
 
          }
 
5902
        }
5861
5903
        write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[0], device%2);
5862
5904
        write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[1], 0);
5863
5905
        write_word(DS, SI+(Bit16u)&Int13DPT->device_path[2], 0);
5867
5909
        for (i=30; i<64; i++) checksum+=read_byte(DS, SI + i);
5868
5910
        checksum = ~checksum;
5869
5911
        write_byte(DS, SI+(Bit16u)&Int13DPT->checksum, checksum);
5870
 
        }
 
5912
      }
5871
5913
 
5872
5914
      goto int13_success;
5873
5915
      break;
5887
5929
        case 0x06:
5888
5930
          goto int13_success;
5889
5931
          break;
5890
 
        default :
 
5932
        default:
5891
5933
          goto int13_fail;
5892
 
        }
 
5934
      }
5893
5935
      break;
5894
5936
 
5895
5937
    // all those functions return unimplemented
5904
5946
      BX_INFO("int13_cdrom: unsupported AH=%02x\n", GET_AH());
5905
5947
      goto int13_fail;
5906
5948
      break;
5907
 
    }
 
5949
  }
5908
5950
 
5909
5951
int13_fail:
5910
 
    SET_AH(0x01); // defaults to invalid function in AH or invalid parameter
 
5952
  SET_AH(0x01); // defaults to invalid function in AH or invalid parameter
5911
5953
int13_fail_noah:
5912
 
    SET_DISK_RET_STATUS(GET_AH());
 
5954
  SET_DISK_RET_STATUS(GET_AH());
5913
5955
int13_fail_nostatus:
5914
 
    SET_CF();     // error occurred
5915
 
    return;
 
5956
  SET_CF();     // error occurred
 
5957
  return;
5916
5958
 
5917
5959
int13_success:
5918
 
    SET_AH(0x00); // no error
 
5960
  SET_AH(0x00); // no error
5919
5961
int13_success_noah:
5920
 
    SET_DISK_RET_STATUS(0x00);
5921
 
    CLEAR_CF();   // no error
5922
 
    return;
 
5962
  SET_DISK_RET_STATUS(0x00);
 
5963
  CLEAR_CF();   // no error
5923
5964
}
5924
5965
 
5925
5966
// ---------------------------------------------------------------------------
5969
6010
      if(GET_AL() == 0x00) {
5970
6011
        // FIXME ElTorito Various. Should be handled accordingly to spec
5971
6012
        write_byte(ebda_seg,&EbdaData->cdemu.active, 0x00); // bye bye
5972
 
        }
 
6013
      }
5973
6014
 
5974
6015
      goto int13_success;
5975
6016
      break;
5978
6019
      BX_INFO("int13_eltorito: unsupported AH=%02x\n", GET_AH());
5979
6020
      goto int13_fail;
5980
6021
      break;
5981
 
    }
 
6022
  }
5982
6023
 
5983
6024
int13_fail:
5984
 
    SET_AH(0x01); // defaults to invalid function in AH or invalid parameter
5985
 
    SET_DISK_RET_STATUS(GET_AH());
5986
 
    SET_CF();     // error occurred
5987
 
    return;
 
6025
  SET_AH(0x01); // defaults to invalid function in AH or invalid parameter
 
6026
  SET_DISK_RET_STATUS(GET_AH());
 
6027
  SET_CF();     // error occurred
 
6028
  return;
5988
6029
 
5989
6030
int13_success:
5990
 
    SET_AH(0x00); // no error
5991
 
    SET_DISK_RET_STATUS(0x00);
5992
 
    CLEAR_CF();   // no error
5993
 
    return;
 
6031
  SET_AH(0x00); // no error
 
6032
  SET_DISK_RET_STATUS(0x00);
 
6033
  CLEAR_CF();   // no error
5994
6034
}
5995
6035
 
5996
6036
// ---------------------------------------------------------------------------
6024
6064
  SET_DISK_RET_STATUS(0x00);
6025
6065
 
6026
6066
  /* basic checks : emulation should be active, dl should equal the emulated drive */
6027
 
  if( (read_byte(ebda_seg,&EbdaData->cdemu.active) ==0 )
6028
 
   || (read_byte(ebda_seg,&EbdaData->cdemu.emulated_drive ) != GET_DL())) {
 
6067
  if( (read_byte(ebda_seg,&EbdaData->cdemu.active) ==0) ||
 
6068
      (read_byte(ebda_seg,&EbdaData->cdemu.emulated_drive ) != GET_DL())) {
6029
6069
    BX_INFO("int13_cdemu: function %02x, emulation not active for DL= %02x\n", GET_AH(), GET_DL());
6030
6070
    goto int13_fail;
6031
 
    }
 
6071
  }
6032
6072
 
6033
6073
  switch (GET_AH()) {
6034
6074
 
6084
6124
       || (cylinder >= vcylinders)
6085
6125
       || (head     >= vheads)) {
6086
6126
        goto int13_fail;
6087
 
        }
 
6127
      }
6088
6128
 
6089
6129
      // After controls, verify do nothing
6090
6130
      if (GET_AH() == 0x04) goto int13_success;
6118
6158
        SET_AH(0x02);
6119
6159
        SET_AL(0);
6120
6160
        goto int13_fail_noah;
6121
 
        }
 
6161
      }
6122
6162
 
6123
6163
      goto int13_success;
6124
6164
      break;
6128
6168
      vcylinders=read_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders) - 1;
6129
6169
      vheads=read_word(ebda_seg,&EbdaData->cdemu.vdevice.heads) - 1;
6130
6170
 
6131
 
      SET_AL( 0x00 );
6132
 
      SET_BL( 0x00 );
6133
 
      SET_CH( vcylinders & 0xff );
6134
 
      SET_CL((( vcylinders >> 2) & 0xc0) | ( vspt  & 0x3f ));
6135
 
      SET_DH( vheads );
6136
 
      SET_DL( 0x02 );   // FIXME ElTorito Various. should send the real count of drives 1 or 2
 
6171
      SET_AL(0x00);
 
6172
      SET_BL(0x00);
 
6173
      SET_CH(vcylinders & 0xff);
 
6174
      SET_CL(((vcylinders >> 2) & 0xc0) | (vspt & 0x3f));
 
6175
      SET_DH(vheads);
 
6176
      SET_DL(0x02);   // FIXME ElTorito Various. should send the real count of drives 1 or 2
6137
6177
                        // FIXME ElTorito Harddisk. should send the HD count
6138
6178
 
6139
6179
      switch(read_byte(ebda_seg,&EbdaData->cdemu.media)) {
6140
6180
        case 0x01: SET_BL( 0x02 ); break;
6141
6181
        case 0x02: SET_BL( 0x04 ); break;
6142
6182
        case 0x03: SET_BL( 0x06 ); break;
6143
 
        }
 
6183
    }
6144
6184
 
6145
6185
ASM_START
6146
6186
      push bp
6179
6219
      BX_INFO("int13_cdemu function AH=%02x unsupported, returns fail\n", GET_AH());
6180
6220
      goto int13_fail;
6181
6221
      break;
6182
 
    }
 
6222
  }
6183
6223
 
6184
6224
int13_fail:
6185
 
    SET_AH(0x01); // defaults to invalid function in AH or invalid parameter
 
6225
  SET_AH(0x01); // defaults to invalid function in AH or invalid parameter
6186
6226
int13_fail_noah:
6187
 
    SET_DISK_RET_STATUS(GET_AH());
 
6227
  SET_DISK_RET_STATUS(GET_AH());
6188
6228
int13_fail_nostatus:
6189
 
    SET_CF();     // error occurred
6190
 
    return;
 
6229
  SET_CF();     // error occurred
 
6230
  return;
6191
6231
 
6192
6232
int13_success:
6193
 
    SET_AH(0x00); // no error
 
6233
  SET_AH(0x00); // no error
6194
6234
int13_success_noah:
6195
 
    SET_DISK_RET_STATUS(0x00);
6196
 
    CLEAR_CF();   // no error
6197
 
    return;
 
6235
  SET_DISK_RET_STATUS(0x00);
 
6236
  CLEAR_CF();   // no error
6198
6237
}
6199
6238
 
6200
6239
// ---------------------------------------------------------------------------
6290
6329
  drive_map = inb_cmos(0x12);
6291
6330
  drive_map = (((drive_map & 0xf0)==0) ? 0 : 1) |
6292
6331
              (((drive_map & 0x0f)==0) ? 0 : 2);
6293
 
  n_drives = (drive_map==0) ? 0 :
6294
 
    ((drive_map==3) ? 2 : 1);
 
6332
  n_drives = (drive_map==0) ? 0 : ((drive_map==3) ? 2 : 1);
6295
6333
 
6296
6334
  if (!(drive_map & (1<<(GET_ELDL()&0x7f)))) { /* allow 0, 1, or 2 disks */
6297
6335
    SET_AH(0x01);
6298
6336
    SET_DISK_RET_STATUS(0x01);
6299
6337
    SET_CF(); /* error occurred */
6300
6338
    return;
6301
 
    }
 
6339
  }
6302
6340
 
6303
6341
  switch (GET_AH()) {
6304
6342
 
6339
6377
      if (hd_cylinders > 1024) {
6340
6378
        if (hd_cylinders <= 2048) {
6341
6379
          cylinder <<= 1;
6342
 
          }
 
6380
        }
6343
6381
        else if (hd_cylinders <= 4096) {
6344
6382
          cylinder <<= 2;
6345
 
          }
 
6383
        }
6346
6384
        else if (hd_cylinders <= 8192) {
6347
6385
          cylinder <<= 3;
6348
 
          }
 
6386
        }
6349
6387
        else { // hd_cylinders <= 16384
6350
6388
          cylinder <<= 4;
6351
 
          }
 
6389
        }
6352
6390
 
6353
6391
        ax = head / hd_heads;
6354
6392
        cyl_mod = ax & 0xff;
6355
6393
        head    = ax >> 8;
6356
6394
        cylinder |= cyl_mod;
6357
 
        }
 
6395
      }
6358
6396
 
6359
6397
      if ( (cylinder >= hd_cylinders) ||
6360
6398
           (sector > hd_sectors) ||
6363
6401
        SET_DISK_RET_STATUS(1);
6364
6402
        SET_CF(); /* error occurred */
6365
6403
        return;
6366
 
        }
 
6404
      }
6367
6405
 
6368
6406
      if ( (num_sectors > 128) || (num_sectors == 0) )
6369
6407
        BX_PANIC("int13_harddisk: num_sectors out of range!\n");
6376
6414
        SET_DISK_RET_STATUS(0);
6377
6415
        CLEAR_CF();
6378
6416
        return;
6379
 
        }
 
6417
      }
6380
6418
 
6381
6419
      status = inb(0x1f7);
6382
6420
      if (status & 0x80) {
6383
6421
        BX_PANIC("hard drive BIOS:(read/verify) BUSY bit set\n");
6384
 
        }
 
6422
      }
6385
6423
      outb(0x01f2, num_sectors);
6386
6424
      /* activate LBA? (tomv) */
6387
6425
      if (hd_heads > 16) {
6388
6426
BX_DEBUG_INT13_HD("CHS: %x %x %x\n", cylinder, head, sector);
6389
6427
        outLBA(cylinder,hd_heads,head,hd_sectors,sector,drive);
6390
 
        }
 
6428
      }
6391
6429
      else {
6392
6430
        outb(0x01f3, sector);
6393
6431
        outb(0x01f4, cylinder & 0x00ff);
6394
6432
        outb(0x01f5, cylinder >> 8);
6395
6433
        outb(0x01f6, 0xa0 | ((drive & 0x01)<<4) | (head & 0x0f));
6396
 
        }
 
6434
      }
6397
6435
      outb(0x01f7, 0x20);
6398
6436
 
6399
6437
      while (1) {
6400
6438
        status = inb(0x1f7);
6401
 
        if ( !(status & 0x80) ) break;
6402
 
        }
 
6439
        if (!(status & 0x80)) break;
 
6440
      }
6403
6441
 
6404
6442
      if (status & 0x01) {
6405
6443
        BX_PANIC("hard drive BIOS:(read/verify) read error\n");
6406
 
      } else if ( !(status & 0x08) ) {
 
6444
      } else if (!(status & 0x08)) {
6407
6445
        BX_DEBUG_INT13_HD("status was %02x\n", (unsigned) status);
6408
6446
        BX_PANIC("hard drive BIOS:(read/verify) expected DRQ=1\n");
6409
6447
      }
6451
6489
        num_sectors--;
6452
6490
        if (num_sectors == 0) {
6453
6491
          status = inb(0x1f7);
6454
 
          if ( (status & 0xc9) != 0x40 )
 
6492
          if ((status & 0xc9) != 0x40)
6455
6493
            BX_PANIC("no sectors left to read/verify, status is %02x\n", (unsigned) status);
6456
6494
          break;
6457
 
          }
 
6495
        }
6458
6496
        else {
6459
6497
          status = inb(0x1f7);
6460
 
          if ( (status & 0xc9) != 0x48 )
 
6498
          if ((status & 0xc9) != 0x48)
6461
6499
            BX_PANIC("more sectors left to read/verify, status is %02x\n", (unsigned) status);
6462
6500
          continue;
6463
 
          }
6464
6501
        }
 
6502
      }
6465
6503
 
6466
6504
      SET_AH(0);
6467
6505
      SET_DISK_RET_STATUS(0);
6470
6508
      return;
6471
6509
      break;
6472
6510
 
6473
 
 
6474
6511
    case 0x03: /* write disk sectors */
6475
6512
BX_DEBUG_INT13_HD("int13_f03\n");
6476
6513
      drive = GET_ELDL ();
6485
6522
      if (hd_cylinders > 1024) {
6486
6523
        if (hd_cylinders <= 2048) {
6487
6524
          cylinder <<= 1;
6488
 
          }
 
6525
        }
6489
6526
        else if (hd_cylinders <= 4096) {
6490
6527
          cylinder <<= 2;
6491
 
          }
 
6528
        }
6492
6529
        else if (hd_cylinders <= 8192) {
6493
6530
          cylinder <<= 3;
6494
 
          }
 
6531
        }
6495
6532
        else { // hd_cylinders <= 16384
6496
6533
          cylinder <<= 4;
6497
 
          }
 
6534
        }
6498
6535
 
6499
6536
        ax = head / hd_heads;
6500
6537
        cyl_mod = ax & 0xff;
6501
6538
        head    = ax >> 8;
6502
6539
        cylinder |= cyl_mod;
6503
 
        }
 
6540
      }
6504
6541
 
6505
6542
      if ( (cylinder >= hd_cylinders) ||
6506
6543
           (sector > hd_sectors) ||
6507
6544
           (head >= hd_heads) ) {
6508
 
        SET_AH( 1);
 
6545
        SET_AH(1);
6509
6546
        SET_DISK_RET_STATUS(1);
6510
6547
        SET_CF(); /* error occurred */
6511
6548
        return;
6512
 
        }
 
6549
      }
6513
6550
 
6514
6551
      if ( (num_sectors > 128) || (num_sectors == 0) )
6515
6552
        BX_PANIC("int13_harddisk: num_sectors out of range!\n");
6520
6557
      status = inb(0x1f7);
6521
6558
      if (status & 0x80) {
6522
6559
        BX_PANIC("hard drive BIOS:(read) BUSY bit set\n");
6523
 
        }
 
6560
      }
6524
6561
// should check for Drive Ready Bit also in status reg
6525
6562
      outb(0x01f2, num_sectors);
6526
6563
 
6528
6565
      if (hd_heads > 16) {
6529
6566
BX_DEBUG_INT13_HD("CHS (write): %x %x %x\n", cylinder, head, sector);
6530
6567
        outLBA(cylinder,hd_heads,head,hd_sectors,sector,GET_ELDL());
6531
 
        }
 
6568
      }
6532
6569
      else {
6533
6570
        outb(0x01f3, sector);
6534
6571
        outb(0x01f4, cylinder & 0x00ff);
6535
6572
        outb(0x01f5, cylinder >> 8);
6536
6573
        outb(0x01f6, 0xa0 | ((GET_ELDL() & 0x01)<<4) | (head & 0x0f));
6537
 
        }
 
6574
      }
6538
6575
      outb(0x01f7, 0x30);
6539
6576
 
6540
6577
      // wait for busy bit to turn off after seeking
6541
6578
      while (1) {
6542
6579
        status = inb(0x1f7);
6543
 
        if ( !(status & 0x80) ) break;
6544
 
        }
 
6580
        if (!(status & 0x80)) break;
 
6581
      }
6545
6582
 
6546
 
      if ( !(status & 0x08) ) {
 
6583
      if (!(status & 0x08)) {
6547
6584
        BX_DEBUG_INT13_HD("status was %02x\n", (unsigned) status);
6548
6585
        BX_PANIC("hard drive BIOS:(write) data-request bit not set\n");
6549
 
        }
 
6586
      }
6550
6587
 
6551
6588
      sector_count = 0;
6552
6589
      tempbx = BX;
6591
6628
        num_sectors--;
6592
6629
        if (num_sectors == 0) {
6593
6630
          status = inb(0x1f7);
6594
 
          if ( (status & 0xe9) != 0x40 )
 
6631
          if ((status & 0xe9) != 0x40)
6595
6632
            BX_PANIC("no sectors left to write, status is %02x\n", (unsigned) status);
6596
6633
          break;
6597
 
          }
 
6634
        }
6598
6635
        else {
6599
6636
          status = inb(0x1f7);
6600
 
          if ( (status & 0xc9) != 0x48 )
 
6637
          if ((status & 0xc9) != 0x48)
6601
6638
            BX_PANIC("more sectors left to write, status is %02x\n", (unsigned) status);
6602
6639
          continue;
6603
 
          }
6604
6640
        }
 
6641
      }
6605
6642
 
6606
6643
      SET_AH(0);
6607
6644
      SET_DISK_RET_STATUS(0);
6631
6668
      if (hd_cylinders <= 1024) {
6632
6669
        // hd_cylinders >>= 0;
6633
6670
        // hd_heads <<= 0;
6634
 
        }
 
6671
      }
6635
6672
      else if (hd_cylinders <= 2048) {
6636
6673
        hd_cylinders >>= 1;
6637
6674
        hd_heads <<= 1;
6638
 
        }
 
6675
      }
6639
6676
      else if (hd_cylinders <= 4096) {
6640
6677
        hd_cylinders >>= 2;
6641
6678
        hd_heads <<= 2;
6642
 
        }
 
6679
      }
6643
6680
      else if (hd_cylinders <= 8192) {
6644
6681
        hd_cylinders >>= 3;
6645
6682
        hd_heads <<= 3;
6646
 
        }
 
6683
      }
6647
6684
      else { // hd_cylinders <= 16384
6648
6685
        hd_cylinders >>= 4;
6649
6686
        hd_heads <<= 4;
6650
 
        }
 
6687
      }
6651
6688
 
6652
6689
      max_cylinder = hd_cylinders - 2; /* 0 based */
6653
6690
      SET_AL(0);
6705
6742
 
6706
6743
      // should look at 40:8E also???
6707
6744
      status = inb(0x01f7);
6708
 
      if ( (status & 0xc0) == 0x40 ) {
 
6745
      if ((status & 0xc0) == 0x40) {
6709
6746
        SET_AH(0);
6710
6747
        SET_DISK_RET_STATUS(0);
6711
6748
        CLEAR_CF(); // drive ready
6712
6749
        return;
6713
 
        }
 
6750
      }
6714
6751
      else {
6715
6752
        SET_AH(0xAA);
6716
6753
        SET_DISK_RET_STATUS(0xAA);
6717
6754
        SET_CF(); // not ready
6718
6755
        return;
6719
 
        }
 
6756
      }
6720
6757
      break;
6721
6758
 
6722
6759
    case 0x11: /* recalibrate */
6778
6815
      SET_DISK_RET_STATUS(1);
6779
6816
      SET_CF(); /* unsuccessful */
6780
6817
      return;
6781
 
      break;
6782
 
    }
 
6818
  }
6783
6819
}
6784
6820
 
6785
6821
static char panic_msg_reg12h[] = "HD%d cmos reg 12h not type F\n";
6847
6883
  // Wait for controller to come out of reset
6848
6884
  do {
6849
6885
    val8 = inb(0x3f4);
6850
 
  } while ( (val8 & 0xc0) != 0x80 );
 
6886
  } while ((val8 & 0xc0) != 0x80);
6851
6887
}
6852
6888
 
6853
6889
void floppy_prepare_controller(drive)
6932
6968
 
6933
6969
  if (floppy_drive_recal(drive) == 0) {
6934
6970
    return(0);
6935
 
    }
 
6971
  }
6936
6972
 
6937
6973
  // for now cheat and get drive type from CMOS,
6938
6974
  // assume media is same as drive type
6966
7002
  //    111 all other formats/drives
6967
7003
 
6968
7004
  drive_type = inb_cmos(0x10);
 
7005
 
6969
7006
  if (drive == 0)
6970
7007
    drive_type >>= 4;
6971
7008
  else
6972
7009
    drive_type &= 0x0f;
6973
 
  if ( drive_type == 1 ) {
 
7010
 
 
7011
  if (drive_type == 1) {
6974
7012
    // 360K 5.25" drive
6975
7013
    config_data = 0x00; // 0000 0000
6976
7014
    media_state = 0x25; // 0010 0101
6977
7015
    retval = 1;
6978
 
    }
6979
 
  else if ( drive_type == 2 ) {
 
7016
  }
 
7017
  else if (drive_type == 2) {
6980
7018
    // 1.2 MB 5.25" drive
6981
7019
    config_data = 0x00; // 0000 0000
6982
7020
    media_state = 0x25; // 0010 0101   // need double stepping??? (bit 5)
6983
7021
    retval = 1;
6984
 
    }
6985
 
  else if ( drive_type == 3 ) {
 
7022
  }
 
7023
  else if (drive_type == 3) {
6986
7024
    // 720K 3.5" drive
6987
7025
    config_data = 0x00; // 0000 0000 ???
6988
7026
    media_state = 0x17; // 0001 0111
6989
7027
    retval = 1;
6990
 
    }
6991
 
  else if ( drive_type == 4 ) {
 
7028
  }
 
7029
  else if (drive_type == 4) {
6992
7030
    // 1.44 MB 3.5" drive
6993
7031
    config_data = 0x00; // 0000 0000
6994
7032
    media_state = 0x17; // 0001 0111
6995
7033
    retval = 1;
6996
 
    }
6997
 
  else if ( drive_type == 5 ) {
 
7034
  }
 
7035
  else if (drive_type == 5) {
6998
7036
    // 2.88 MB 3.5" drive
6999
7037
    config_data = 0xCC; // 1100 1100
7000
7038
    media_state = 0xD7; // 1101 0111
7001
7039
    retval = 1;
7002
 
    }
7003
 
  //
 
7040
  }
7004
7041
  // Extended floppy size uses special cmos setting
7005
 
  else if ( drive_type == 6 ) {
 
7042
  else if (drive_type == 6) {
7006
7043
    // 160k 5.25" drive
7007
7044
    config_data = 0x00; // 0000 0000
7008
7045
    media_state = 0x27; // 0010 0111
7009
7046
    retval = 1;
7010
 
    }
7011
 
  else if ( drive_type == 7 ) {
 
7047
  }
 
7048
  else if (drive_type == 7) {
7012
7049
    // 180k 5.25" drive
7013
7050
    config_data = 0x00; // 0000 0000
7014
7051
    media_state = 0x27; // 0010 0111
7015
7052
    retval = 1;
7016
 
    }
7017
 
  else if ( drive_type == 8 ) {
 
7053
  }
 
7054
  else if (drive_type == 8) {
7018
7055
    // 320k 5.25" drive
7019
7056
    config_data = 0x00; // 0000 0000
7020
7057
    media_state = 0x27; // 0010 0111
7021
7058
    retval = 1;
7022
 
    }
7023
 
 
 
7059
  }
7024
7060
  else {
7025
7061
    // not recognized
7026
7062
    config_data = 0x00; // 0000 0000
7027
7063
    media_state = 0x00; // 0000 0000
7028
7064
    retval = 0;
7029
 
    }
 
7065
  }
7030
7066
 
7031
7067
  if (drive == 0)
7032
7068
    media_state_offset = 0x90;
7083
7119
  return(1);
7084
7120
}
7085
7121
 
7086
 
 
7087
 
 
7088
7122
  bx_bool
7089
7123
floppy_drive_exists(drive)
7090
7124
  Bit16u drive;
7649
7683
        SET_DL(num_floppies);
7650
7684
        SET_CF();
7651
7685
        return;
7652
 
        }
 
7686
      }
7653
7687
 
7654
7688
      drive_type = inb_cmos(0x10);
7655
7689
      num_floppies = 0;
7741
7775
        // set_diskette_ret_status here ???
7742
7776
        SET_CF();
7743
7777
        return;
7744
 
        }
 
7778
      }
7745
7779
      drive_type = inb_cmos(0x10);
7746
7780
 
7747
7781
      if (drive == 0)
7751
7785
      CLEAR_CF(); // successful, not present
7752
7786
      if (drive_type==0) {
7753
7787
        SET_AH(0); // drive not present
7754
 
        }
 
7788
      }
7755
7789
      else {
7756
7790
        SET_AH(1); // drive present, does not support change line
7757
 
        }
 
7791
      }
7758
7792
 
7759
7793
      return;
7760
7794
 
7766
7800
        set_diskette_ret_status(0x01);
7767
7801
        SET_CF();
7768
7802
        return;
7769
 
        }
 
7803
      }
7770
7804
 
7771
7805
      SET_AH(0x06); // change line not supported
7772
7806
      set_diskette_ret_status(0x06);
7791
7825
    default:
7792
7826
        BX_INFO("int13_diskette: unsupported AH=%02x\n", GET_AH());
7793
7827
 
7794
 
      // if ( (ah==0x20) || ((ah>=0x41) && (ah<=0x49)) || (ah==0x4e) ) {
 
7828
//    if ((ah==0x20) || ((ah>=0x41) && (ah<=0x49)) || (ah==0x4e)) {
7795
7829
        SET_AH(0x01); // ???
7796
7830
        set_diskette_ret_status(1);
7797
7831
        SET_CF();
7798
7832
        return;
7799
 
      //   }
 
7833
//    }
7800
7834
    }
7801
7835
}
7802
7836
#else  // #if BX_SUPPORT_FLOPPY
7806
7840
{
7807
7841
  Bit8u  val8;
7808
7842
 
7809
 
  switch ( GET_AH() ) {
 
7843
  switch (GET_AH()) {
7810
7844
 
7811
7845
    case 0x01: // Read Diskette Status
7812
7846
      CLEAR_CF();
7814
7848
      SET_AH(val8);
7815
7849
      if (val8) {
7816
7850
        SET_CF();
7817
 
        }
 
7851
      }
7818
7852
      return;
7819
7853
 
7820
7854
    default:
7858
7892
#if 0
7859
7893
  if (drive == 0) {
7860
7894
    DOR = 0x1c; // DOR: drive0 motor on, DMA&int enabled, normal op, drive select 0
7861
 
    }
 
7895
  }
7862
7896
  else {
7863
7897
    DOR = 0x2d; // DOR: drive1 motor on, DMA&int enabled, normal op, drive select 1
7864
 
    }
 
7898
  }
7865
7899
#endif
7866
7900
 
7867
 
  if ( (ctrl_info & 0x04) != 0x04 ) {
 
7901
  if ((ctrl_info & 0x04) != 0x04) {
7868
7902
    // Drive not determined means no drive exists, done.
7869
7903
    return;
7870
 
    }
 
7904
  }
7871
7905
 
7872
7906
#if 0
7873
7907
  // check Main Status Register for readiness
8073
8107
 
8074
8108
    bootdrv = (Bit8u)(status>>8);
8075
8109
    bootseg = read_word(ebda_seg,&EbdaData->cdemu.load_segment);
8076
 
    /* Canonicalize bootseg:bootip */
8077
 
    bootip = (bootseg & 0x0fff) << 4;
8078
 
    bootseg &= 0xf000;
 
8110
    bootip = 0;
8079
8111
    break;
8080
8112
#endif
8081
8113
 
8093
8125
  /* Jump to the boot vector */
8094
8126
ASM_START
8095
8127
    mov  bp, sp
 
8128
    push cs
 
8129
    push #int18_handler
8096
8130
    ;; Build an iret stack frame that will take us to the boot vector.
8097
8131
    ;; iret pops ip, then cs, then flags, so push them in the opposite order.
8098
8132
    pushf
8162
8196
      if (rtc_updating()) {
8163
8197
        SetCF(iret_addr.flags);
8164
8198
        break;
8165
 
        }
 
8199
      }
8166
8200
 
8167
8201
      regs.u.r8.dh = inb_cmos(0x00); // Seconds
8168
8202
      regs.u.r8.cl = inb_cmos(0x02); // Minutes
8187
8221
      if (rtc_updating()) {
8188
8222
        init_rtc();
8189
8223
        // fall through as if an update were not in progress
8190
 
        }
 
8224
      }
8191
8225
      outb_cmos(0x00, regs.u.r8.dh); // Seconds
8192
8226
      outb_cmos(0x02, regs.u.r8.cl); // Minutes
8193
8227
      outb_cmos(0x04, regs.u.r8.ch); // Hours
8205
8239
      if (rtc_updating()) {
8206
8240
        SetCF(iret_addr.flags);
8207
8241
        break;
8208
 
        }
 
8242
      }
8209
8243
      regs.u.r8.cl = inb_cmos(0x09); // Year
8210
8244
      regs.u.r8.dh = inb_cmos(0x08); // Month
8211
8245
      regs.u.r8.dl = inb_cmos(0x07); // Day of Month
8258
8292
        // Alarm interrupt enabled already
8259
8293
        SetCF(iret_addr.flags); // Error: alarm in use
8260
8294
        break;
8261
 
        }
 
8295
      }
8262
8296
      if (rtc_updating()) {
8263
8297
        init_rtc();
8264
8298
        // fall through as if an update were not in progress
8265
 
        }
 
8299
      }
8266
8300
      outb_cmos(0x01, regs.u.r8.dh); // Seconds alarm
8267
8301
      outb_cmos(0x03, regs.u.r8.cl); // Minutes alarm
8268
8302
      outb_cmos(0x05, regs.u.r8.ch); // Hours alarm
8314
8348
 
8315
8349
    default:
8316
8350
      SetCF(iret_addr.flags); // Unsupported
8317
 
    }
 
8351
  }
8318
8352
}
8319
8353
 
8320
8354
  void
9053
9087
  mov   al, #0x20
9054
9088
  out   #0x20, al ;; master PIC EOI
9055
9089
 
 
9090
jmp_post_0x467:
9056
9091
  xor ax, ax
9057
9092
  mov ds, ax
9058
9093
 
9059
9094
  jmp far ptr [0x467]
9060
9095
 
 
9096
iret_post_0x467:
 
9097
  xor ax, ax
 
9098
  mov ds, ax
 
9099
 
 
9100
  mov sp, [0x467]
 
9101
  mov ss, [0x469]
 
9102
  iret
 
9103
 
 
9104
retf_post_0x467:
 
9105
  xor ax, ax
 
9106
  mov ds, ax
 
9107
 
 
9108
  mov sp, [0x467]
 
9109
  mov ss, [0x469]
 
9110
  retf
 
9111
 
 
9112
s3_post:
 
9113
  mov sp, #0xffe
 
9114
#if BX_ROMBIOS32
 
9115
  call rombios32_init
 
9116
#endif
 
9117
  call _s3_resume
 
9118
  mov bl, #0x00
 
9119
  and ax, ax
 
9120
  jz normal_post
 
9121
  call _s3_resume_panic
9061
9122
 
9062
9123
;--------------------
9063
9124
eoi_both_pics:
9728
9789
pcibios_init_iomem_bases:
9729
9790
  push bp
9730
9791
  mov  bp, sp
9731
 
  mov  eax, #0xe0000000 ;; base for memory init
 
9792
  mov  eax, #0xc0000000 ;; base for memory init
9732
9793
  push eax
9733
9794
  mov  ax, #0xc000 ;; base for i/o init
9734
9795
  push ax
9843
9904
  mov  dl, #0x00
9844
9905
  call pcibios_init_sel_reg
9845
9906
  mov  dx, #0x0cfc
9846
 
  in   eax, dx
9847
 
  cmp  eax, [si+12] ;; check irq router
 
9907
  in   ax, dx
 
9908
  cmp  ax, [si+12] ;; check irq router
9848
9909
  jne  pci_init_end
9849
9910
  mov  dl, [si+34]
9850
9911
  call pcibios_init_sel_reg
9972
10033
  mov gs, ax
9973
10034
  cld
9974
10035
 
9975
 
  ;; copy rombios32 code to ram (ram offset = 1MB)
9976
 
  mov esi, #0xfffe0000
9977
 
  mov edi, #0x00040000
9978
 
  mov ecx, #0x10000 / 4
9979
 
  rep
9980
 
    movsd
 
10036
  ;; init the stack pointer to point below EBDA
 
10037
  mov ax, [0x040e]
 
10038
  shl eax, #4
 
10039
  mov esp, #-0x10
 
10040
  add esp, eax
9981
10041
 
9982
 
  ;; init the stack pointer
9983
 
  mov esp, #0x00080000
 
10042
  ;; pass pointer to s3_resume_flag and s3_resume_vector to rombios32
 
10043
  push #0x04b0
 
10044
  push #0x04b2
9984
10045
 
9985
10046
  ;; call rombios32 code
9986
 
  mov eax, #0x00040000
 
10047
  mov eax, #0x000e0000
9987
10048
  call eax
9988
10049
 
9989
 
  ;; reset the memory (some boot loaders such as syslinux suppose
9990
 
  ;; that the memory is set to zero)
9991
 
  mov edi, #0x00040000
9992
 
  mov ecx, #0x40000 / 4
9993
 
  xor eax, eax
9994
 
  rep
9995
 
    stosd
9996
 
 
9997
10050
  ;; return to 16 bit protected mode first
9998
10051
  db 0xea
9999
10052
  dd rombios32_10
10103
10156
  ret
10104
10157
 
10105
10158
rom_checksum:
10106
 
  push ax
10107
 
  push bx
10108
 
  push cx
 
10159
  pusha
 
10160
  push ds
 
10161
 
10109
10162
  xor  ax, ax
10110
10163
  xor  bx, bx
10111
10164
  xor  cx, cx
 
10165
  xor  dx, dx
 
10166
 
10112
10167
  mov  ch, [2]
10113
10168
  shl  cx, #1
 
10169
 
 
10170
  jnc checksum_loop
 
10171
  xchg dx, cx
 
10172
  dec  cx
 
10173
 
10114
10174
checksum_loop:
10115
10175
  add  al, [bx]
10116
10176
  inc  bx
10117
10177
  loop checksum_loop
 
10178
 
 
10179
  test dx, dx
 
10180
  je checksum_out
 
10181
 
 
10182
  add  al, [bx]
 
10183
  mov  cx, dx
 
10184
  mov  dx, ds
 
10185
  add  dh, #0x10
 
10186
  mov  ds, dx
 
10187
  xor  dx, dx
 
10188
  xor  bx, bx
 
10189
 
 
10190
  jmp  checksum_loop
 
10191
 
 
10192
checksum_out:
10118
10193
  and  al, #0xff
10119
 
  pop  cx
10120
 
  pop  bx
10121
 
  pop  ax
 
10194
  pop  ds
 
10195
  popa
10122
10196
  ret
10123
10197
 
10124
10198
 
10194
10268
  mov  ax, 2[bx]
10195
10269
  cmp  ax, #0x506e
10196
10270
  jne  no_bev
 
10271
 
 
10272
  mov  ax, 0x16[bx] ;; 0x16 is the offset of Boot Connection Vector
 
10273
  cmp  ax, #0x0000
 
10274
  je   no_bcv
 
10275
 
 
10276
  ;; Option ROM has BCV. Run it now.
 
10277
  push cx       ;; Push seg
 
10278
  push ax       ;; Push offset
 
10279
 
 
10280
  ;; Point ES:DI at "$PnP", which tells the ROM that we are a PnP BIOS.
 
10281
  mov  bx, #0xf000
 
10282
  mov  es, bx
 
10283
  lea  di, pnp_string
 
10284
  /* jump to BCV function entry pointer */
 
10285
  mov  bp, sp   ;; Call ROM BCV routine using seg:off on stack
 
10286
  db   0xff     ;; call_far ss:[bp+0]
 
10287
  db   0x5e
 
10288
  db   0
 
10289
  cli           ;; In case expansion ROM BIOS turns IF on
 
10290
  add  sp, #2   ;; Pop offset value
 
10291
  pop  cx       ;; Pop seg value (restore CX)
 
10292
  jmp   no_bev
 
10293
 
 
10294
no_bcv:
10197
10295
  mov  ax, 0x1a[bx] ;; 0x1A is also the offset into the expansion header of...
10198
10296
  cmp  ax, #0x0000  ;; the Bootstrap Entry Vector, or zero if there is none.
10199
10297
  je   no_bev
10233
10331
  mov  ds, ax
10234
10332
  ret
10235
10333
 
10236
 
;; for 'C' strings and other data, insert them here with
10237
 
;; a the following hack:
10238
 
;; DATA_SEG_DEFS_HERE
10239
 
 
 
10334
post_init_pic:
 
10335
  mov al, #0x11 ; send initialisation commands
 
10336
  out 0x20, al
 
10337
  out 0xa0, al
 
10338
  mov al, #0x08
 
10339
  out 0x21, al
 
10340
  mov al, #0x70
 
10341
  out 0xa1, al
 
10342
  mov al, #0x04
 
10343
  out 0x21, al
 
10344
  mov al, #0x02
 
10345
  out 0xa1, al
 
10346
  mov al, #0x01
 
10347
  out 0x21, al
 
10348
  out 0xa1, al
 
10349
  mov  al, #0xb8
 
10350
  out  0x21, AL ;master pic: unmask IRQ 0, 1, 2, 6
 
10351
#if BX_USE_PS2_MOUSE
 
10352
  mov  al, #0x8f
 
10353
#else
 
10354
  mov  al, #0x9f
 
10355
#endif
 
10356
  out  0xa1, AL ;slave  pic: unmask IRQ 12, 13, 14
 
10357
  ret
10240
10358
 
10241
10359
;; the following area can be used to write dynamically generated tables
10242
10360
  .align 16
10291
10409
  cmp al, #0x05
10292
10410
  je  eoi_jmp_post
10293
10411
 
 
10412
  ;; 0x0A = jmp via [0x40:0x67] jump
 
10413
  cmp al, #0x0a
 
10414
  je  jmp_post_0x467
 
10415
 
 
10416
  ;; 0x0B = iret via [0x40:0x67]
 
10417
  cmp al, #0x0b
 
10418
  je  iret_post_0x467
 
10419
 
 
10420
  ;; 0x0C = retf via [0x40:0x67]
 
10421
  cmp al, #0x0c
 
10422
  je  retf_post_0x467
 
10423
 
10294
10424
  ;; Examine CMOS shutdown status.
10295
 
  ;;  0x01,0x02,0x03,0x04,0x06,0x07,0x08, 0x0a, 0x0b, 0x0c = Unimplemented shutdown status.
 
10425
  ;;  0x01,0x02,0x03,0x04,0x06,0x07,0x08 = Unimplemented shutdown status.
10296
10426
  push bx
10297
10427
  call _shutdown_status_panic
10298
10428
 
10320
10450
  mov  ds, ax
10321
10451
  mov  ss, ax
10322
10452
 
 
10453
  ;; Save shutdown status
 
10454
  mov 0x04b0, bl
 
10455
 
 
10456
  cmp bl, #0xfe
 
10457
  jz s3_post
 
10458
 
10323
10459
  ;; zero out BIOS data area (40:00..40:ff)
10324
10460
  mov  es, ax
10325
10461
  mov  cx, #0x0080 ;; 128 words
10486
10622
  SET_INT_VECTOR(0x10, #0xF000, #int10_handler)
10487
10623
 
10488
10624
  ;; PIC
10489
 
  mov al, #0x11 ; send initialisation commands
10490
 
  out 0x20, al
10491
 
  out 0xa0, al
10492
 
  mov al, #0x08
10493
 
  out 0x21, al
10494
 
  mov al, #0x70
10495
 
  out 0xa1, al
10496
 
  mov al, #0x04
10497
 
  out 0x21, al
10498
 
  mov al, #0x02
10499
 
  out 0xa1, al
10500
 
  mov al, #0x01
10501
 
  out 0x21, al
10502
 
  out 0xa1, al
10503
 
  mov  al, #0xb8
10504
 
  out  0x21, AL ;master pic: unmask IRQ 0, 1, 2, 6
10505
 
#if BX_USE_PS2_MOUSE
10506
 
  mov  al, #0x8f
10507
 
#else
10508
 
  mov  al, #0x9f
10509
 
#endif
10510
 
  out  0xa1, AL ;slave  pic: unmask IRQ 12, 13, 14
 
10625
  call post_init_pic
10511
10626
 
10512
10627
  mov  cx, #0xc000  ;; init vga bios
10513
10628
  mov  ax, #0xc780
10529
10644
  ;;
10530
10645
  call floppy_drive_post
10531
10646
 
10532
 
#if BX_USE_ATADRV
10533
 
 
10534
10647
  ;;
10535
10648
  ;; Hard Drive setup
10536
10649
  ;;
10537
10650
  call hard_drive_post
10538
10651
 
 
10652
#if BX_USE_ATADRV
 
10653
 
10539
10654
  ;;
10540
10655
  ;; ATA/ATAPI driver setup
10541
10656
  ;;
10542
10657
  call _ata_init
10543
10658
  call _ata_detect
10544
10659
  ;;
10545
 
#else // BX_USE_ATADRV
10546
 
 
10547
 
  ;;
10548
 
  ;; Hard Drive setup
10549
 
  ;;
10550
 
  call hard_drive_post
10551
10660
 
10552
10661
#endif // BX_USE_ATADRV
10553
10662