OpenCores
URL https://opencores.org/ocsvn/zet86/zet86/trunk

Subversion Repositories zet86

[/] [zet86/] [trunk/] [soc/] [bios/] [rombios.c] - Diff between revs 49 and 52

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 49 Rev 52
Line 419... Line 419...
.align 2
.align 2
lcmp_b_and_lt:
lcmp_b_and_lt:
    dec     bx
    dec     bx
    ret
    ret
 
 
 
lincl:
 
lincul:
 
    inc     word ptr [bx]
 
    je      LINC_HIGH_WORD
 
    ret
 
    .even
 
LINC_HIGH_WORD:
 
    inc     word ptr 2[bx]
 
    ret
 
 
  ASM_END
  ASM_END
 
 
// for access to RAM area which is used by interrupt vectors
// for access to RAM area which is used by interrupt vectors
// and BIOS Data Area
// and BIOS Data Area
 
 
Line 1012... Line 1022...
    jmp halt2_loop
    jmp halt2_loop
ASM_END
ASM_END
    }
    }
}
}
 
 
static char bios_svn_version_string[] = "$Revision: 1.13 $ $Date: 2009-03-05 00:26:53 $";
static char bios_svn_version_string[] = "$Version: 0.4.3 $ $Date: Tue, 10 Mar 2009 21:02:08 +0100 $";
 
 
 
#define BIOS_COPYRIGHT_STRING "(c) 2009 Zeus Gomez Marmolejo and (c) 2002 MandrakeSoft S.A."
 
 
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
// print_bios_banner
// print_bios_banner
//   displays a the bios version
//   displays a the bios version
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
Line 1040... Line 1052...
// drives (BCVs), only as bootable devices (BEVs).
// drives (BCVs), only as bootable devices (BEVs).
//
//
// http://www.phoenix.com/en/Customer+Services/White+Papers-Specs/pc+industry+specifications.htm
// http://www.phoenix.com/en/Customer+Services/White+Papers-Specs/pc+industry+specifications.htm
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
 
 
static char drivetypes[][20]={"", "Floppy flash image" };
static char drivetypes[][20]={"", "Floppy flash image", "Compact Flash" };
 
 
static void
static void
init_boot_vectors()
init_boot_vectors()
{
{
  ipl_entry_t e;
  ipl_entry_t e;
Line 1060... Line 1072...
  /* Floppy drive */
  /* Floppy drive */
  e.type = IPL_TYPE_FLOPPY; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0;
  e.type = IPL_TYPE_FLOPPY; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0;
  memcpyb(IPL_SEG, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e));
  memcpyb(IPL_SEG, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e));
  count++;
  count++;
 
 
 
  /* First HDD */
 
  e.type = IPL_TYPE_HARDDISK; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0;
 
  memcpyb(IPL_SEG, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e));
 
  count++;
 
 
  /* Remember how many devices we have */
  /* Remember how many devices we have */
  write_word(IPL_SEG, IPL_COUNT_OFFSET, count);
  write_word(IPL_SEG, IPL_COUNT_OFFSET, count);
  /* Not tried booting anything yet */
  /* Not tried booting anything yet */
  write_word(IPL_SEG, IPL_SEQUENCE_OFFSET, 0xffff);
  write_word(IPL_SEG, IPL_SEQUENCE_OFFSET, 0xffff);
}
}
Line 1499... Line 1516...
 
 
  void
  void
int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
  Bit16u DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
  Bit16u DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
{
{
 
  Bit8u    drive, num_sectors, sector, head, status;
 
  Bit8u    drive_map;
 
  Bit8u    n_drives;
 
  Bit16u   max_cylinder, cylinder;
 
  Bit16u   hd_cylinders;
 
  Bit8u    hd_heads, hd_sectors;
 
  Bit8u    sector_count;
 
  Bit16u   tempbx;
 
 
 
  Bit32u   log_sector;
 
 
  write_byte(0x0040, 0x008e, 0);  // clear completion flag
  write_byte(0x0040, 0x008e, 0);  // clear completion flag
 
 
 
  /* at this point, DL is >= 0x80 to be passed from the floppy int13h
 
     handler code */
 
  /* check how many disks first (cmos reg 0x12), return an error if
 
     drive not present */
 
  drive_map = 1;
 
  n_drives = 1;
 
 
 
  if (!(drive_map & (1<<(GET_ELDL()&0x7f)))) { /* allow 0, 1, or 2 disks */
 
    SET_AH(0x01);
 
    SET_DISK_RET_STATUS(0x01);
 
    SET_CF(); /* error occurred */
 
    return;
 
    }
 
 
  switch (GET_AH()) {
  switch (GET_AH()) {
 
 
 
    case 0x00: /* disk controller reset */
 
 
 
      SET_AH(0);
 
      SET_DISK_RET_STATUS(0);
 
      set_diskette_ret_status(0);
 
      set_diskette_current_cyl(0, 0); /* current cylinder, diskette 1 */
 
      set_diskette_current_cyl(1, 0); /* current cylinder, diskette 2 */
 
      CLEAR_CF(); /* successful */
 
      return;
 
      break;
 
 
 
    case 0x01: /* read disk status */
 
      status = read_byte(0x0040, 0x0074);
 
      SET_AH(status);
 
      SET_DISK_RET_STATUS(0);
 
      /* set CF if error status read */
 
      if (status) SET_CF();
 
      else        CLEAR_CF();
 
      return;
 
      break;
 
 
 
    case 0x04: // verify disk sectors
 
    case 0x02: // read disk sectors
 
      drive = GET_ELDL();
 
 
 
      // get_hd_geometry(drive, &hd_cylinders, &hd_heads, &hd_sectors);
 
      // fixed geometry:
 
      hd_cylinders = 993;
 
      hd_heads     = 16;
 
      hd_sectors   = 63;
 
 
 
      num_sectors = GET_AL();
 
      cylinder    = (GET_CL() & 0x00c0) << 2 | GET_CH();
 
      sector      = (GET_CL() & 0x3f);
 
      head        = GET_DH();
 
 
 
      if ( (cylinder >= hd_cylinders) ||
 
           (sector > hd_sectors) ||
 
           (head >= hd_heads) ) {
 
        SET_AH(1);
 
        SET_DISK_RET_STATUS(1);
 
        SET_CF(); /* error occurred */
 
        return;
 
        }
 
 
 
      if ( GET_AH() == 0x04 ) {
 
        SET_AH(0);
 
        SET_DISK_RET_STATUS(0);
 
        CLEAR_CF();
 
        return;
 
        }
 
 
 
      log_sector = ((Bit32u)cylinder) * ((Bit32u)hd_heads) * ((Bit32u)hd_sectors)
 
                 + ((Bit32u)head) * ((Bit32u)hd_sectors)
 
                 + ((Bit32u)sector) - 1;
 
 
 
      sector_count = 0;
 
      tempbx = BX;
 
 
 
ASM_START
 
  sti  ;; enable higher priority interrupts
 
ASM_END
 
 
 
      while (1) {
 
ASM_START
 
        ;; store temp bx in real DI register
 
        push bp
 
        mov  bp, sp
 
        mov  di, _int13_harddisk.tempbx + 2 [bp]
 
        pop  bp
 
 
 
        ;; adjust if there will be an overrun
 
        cmp   di, #0xfe00
 
        jbe   i13_f02_no_adjust
 
i13_f02_adjust:
 
        sub   di, #0x0200 ; sub 512 bytes from offset
 
        mov   ax, es
 
        add   ax, #0x0020 ; add 512 to segment
 
        mov   es, ax
 
 
 
i13_f02_no_adjust:
 
        ; timeout = TIMEOUT;
 
        mov   cx, #0xffff
 
 
 
        ; while((timeout > 0) && (!(CSR_ACE_STATUSL & ACE_STATUSL_CFCMDRDY))) timeout--;
 
        mov   dx, #0xe204
 
 
 
i13_f02_ace_statusl2:
 
        in    ax, dx
 
        and   ax, #0x100
 
        loopz i13_f02_ace_statusl2
 
 
 
        ; if(timeout == 0) return 0;
 
        cmp   cx, #0
 
        jnz   i13_f02_success2
 
ASM_END
 
        printf("i13_f02(1): Timeout\n");
 
ASM_START
 
        jmp   _int13_fail
 
 
 
i13_f02_success2:
 
        ; CSR_ACE_MLBAL = blocknr & 0x0000ffff;
 
        push  bp
 
        mov   bp, sp
 
        mov   ax, _int13_harddisk.log_sector + 2 [bp]
 
        mov   dx, #0xe210
 
        out   dx, ax
 
 
 
        ; CSR_ACE_MLBAH = (blocknr & 0x0fff0000) >> 16;
 
        mov   ax, _int13_harddisk.log_sector + 4 [bp]
 
        mov   dx, #0xe212
 
        out   dx, ax
 
        pop   bp
 
 
 
        ; CSR_ACE_SECCMD = ACE_SECCMD_READ|0x01;
 
        mov   ax, #0x0301
 
        mov   dx, #0xe214
 
        out   dx, ax
 
 
 
        ; CSR_ACE_CTLL |= ACE_CTLL_CFGRESET;
 
        mov   dx, #0xe218
 
        in    ax, dx
 
        or    ax, #0x0080
 
        out   dx, ax
 
 
 
        ; buffer_count = 16;
 
        mov   si, #16
 
 
 
        ; while(buffer_count > 0) {
 
i13_f02_cond_loop:
 
        cmp   si, #0
 
        jbe   i13_f02_exit_loop
 
 
 
        ; timeout = TIMEOUT;
 
        mov   cx, #0xffff
 
        mov   bx, #0x000f
 
 
 
        ; while((timeout > 0) && (!(CSR_ACE_STATUSL & ACE_STATUSL_DATARDY))) timeout--;
 
        mov   dx, #0xe204
 
i13_f02_ace_statusl3:
 
        in    ax, dx
 
        and   ax, #0x20
 
        loopz i13_f02_ace_statusl3
 
 
 
        ; if(timeout == 0) return 0;
 
        cmp   cx, #0
 
        jnz  i13_f02_success3
 
        dec   bx
 
        mov   cx, #0xffff
 
        jne   i13_f02_ace_statusl3
 
ASM_END
 
        printf("i13_f02(2): Timeout\n");
 
ASM_START
 
        jmp   _int13_fail
 
 
 
i13_f02_success3:
 
        ; for(i=0;i<16;i++) {
 
        mov   cx, #16
 
        ; *bufw = CSR_ACE_DATA;
 
        mov   dx, #0xe240
 
i13_f02_ace_data:
 
        in    ax, dx
 
        eseg
 
              mov   [di], ax
 
        ; bufw++;
 
        add   di, #2
 
        ; }
 
        loop  i13_f02_ace_data
 
 
 
        ; buffer_count--;
 
        dec   si
 
        jmp   i13_f02_cond_loop
 
 
 
        ; }
 
 
 
i13_f02_exit_loop:
 
        ; CSR_ACE_CTLL &= ~ACE_CTLL_CFGRESET;
 
        mov   dx, #0xe218
 
        in    ax, dx
 
        and   ax, #0xff7f
 
        out   dx, ax
 
 
 
i13_f02_done:
 
        ;; store real DI register back to temp bx
 
        push bp
 
        mov  bp, sp
 
        mov  _int13_harddisk.tempbx + 2 [bp], di
 
        pop  bp
 
ASM_END
 
 
 
        sector_count++;
 
        log_sector++;
 
        num_sectors--;
 
        if (num_sectors) continue;
 
        else break;
 
      }
 
 
 
      SET_AH(0);
 
      SET_DISK_RET_STATUS(0);
 
      SET_AL(sector_count);
 
      CLEAR_CF(); /* successful */
 
      return;
 
      break;
 
 
 
    case 0x03: /* write disk sectors */
 
      drive = GET_ELDL ();
 
 
 
      // get_hd_geometry(drive, &hd_cylinders, &hd_heads, &hd_sectors);
 
      // fixed geometry:
 
      hd_cylinders = 993;
 
      hd_heads     = 16;
 
      hd_sectors   = 63;
 
 
 
      num_sectors = GET_AL();
 
      cylinder    = GET_CH();
 
      cylinder    |= ( ((Bit16u) GET_CL()) << 2) & 0x300;
 
      sector      = (GET_CL() & 0x3f);
 
      head        = GET_DH();
 
 
 
      if ( (cylinder >= hd_cylinders) ||
 
           (sector > hd_sectors) ||
 
           (head >= hd_heads) ) {
 
        SET_AH( 1);
 
        SET_DISK_RET_STATUS(1);
 
        SET_CF(); /* error occurred */
 
        return;
 
        }
 
 
 
      log_sector = ((Bit32u)cylinder) * ((Bit32u)hd_heads) * ((Bit32u)hd_sectors)
 
                 + ((Bit32u)head) * ((Bit32u)hd_sectors)
 
                 + ((Bit32u)sector) - 1;
 
 
 
      sector_count = 0;
 
      tempbx = BX;
 
 
 
ASM_START
 
  sti  ;; enable higher priority interrupts
 
ASM_END
 
 
 
      while (1) {
 
ASM_START
 
        ;; store temp bx in real SI register
 
        push bp
 
        mov  bp, sp
 
        mov  si, _int13_harddisk.tempbx + 2 [bp]
 
        pop  bp
 
 
 
        ;; adjust if there will be an overrun
 
        cmp   si, #0xfe00
 
        jbe   i13_f03_no_adjust
 
i13_f03_adjust:
 
        sub   si, #0x0200 ; sub 512 bytes from offset
 
        mov   ax, es
 
        add   ax, #0x0020 ; add 512 to segment
 
        mov   es, ax
 
 
 
i13_f03_no_adjust:
 
        ; timeout = TIMEOUT;
 
        mov   cx, #0xffff
 
 
 
        ; while((timeout > 0) && (!(CSR_ACE_STATUSL & ACE_STATUSL_CFCMDRDY))) timeout--;
 
        mov   dx, #0xe204
 
 
 
i13_f03_ace_statusl2:
 
        in    ax, dx
 
        and   ax, #0x100
 
        loopz i13_f03_ace_statusl2
 
 
 
        ; if(timeout == 0) return 0;
 
        cmp   cx, #0
 
        jnz   i13_f03_success2
 
ASM_END
 
        printf("i13_f03(1): Timeout\n");
 
ASM_START
 
        jmp   _int13_fail
 
 
 
i13_f03_success2:
 
        ; CSR_ACE_MLBAL = blocknr & 0x0000ffff;
 
        push  bp
 
        mov   bp, sp
 
        mov   ax, _int13_harddisk.log_sector + 2 [bp]
 
        mov   dx, #0xe210
 
        out   dx, ax
 
 
 
        ; CSR_ACE_MLBAH = (blocknr & 0x0fff0000) >> 16;
 
        mov   ax, _int13_harddisk.log_sector + 4 [bp]
 
        mov   dx, #0xe212
 
        out   dx, ax
 
        pop   bp
 
 
 
        ; CSR_ACE_SECCMD = ACE_SECCMD_WRITE|0x01;
 
        mov   ax, #0x0401
 
        mov   dx, #0xe214
 
        out   dx, ax
 
 
 
        ; CSR_ACE_CTLL |= ACE_CTLL_CFGRESET;
 
        mov   dx, #0xe218
 
        in    ax, dx
 
        or    ax, #0x0080
 
        out   dx, ax
 
 
 
        ; buffer_count = 16;
 
        mov   di, #16
 
 
 
        ; while(buffer_count > 0) {
 
i13_f03_cond_loop:
 
        cmp   di, #0
 
        jbe   i13_f03_exit_loop
 
 
 
        ; timeout = TIMEOUT;
 
        mov   cx, #0xffff
 
        mov   bx, #0x000f
 
 
 
        ; while((timeout > 0) && (!(CSR_ACE_STATUSL & ACE_STATUSL_DATARDY))) timeout--;
 
        mov   dx, #0xe204
 
i13_f03_ace_statusl3:
 
        in    ax, dx
 
        and   ax, #0x20
 
        loopz i13_f03_ace_statusl3
 
 
 
        ; if(timeout == 0) return 0;
 
        cmp   cx, #0
 
        jnz   i13_f03_success3
 
        dec   bx
 
        mov   cx, #0xffff
 
        jne   i13_f03_ace_statusl3
 
ASM_END
 
        printf("i13_f03(2): Timeout\n");
 
ASM_START
 
        jmp   _int13_fail
 
 
 
i13_f03_success3:
 
        ; for(i=0;i<16;i++) {
 
        mov   cx, #16
 
        ; *bufw = CSR_ACE_DATA;
 
        mov   dx, #0xe240
 
i13_f03_ace_data:
 
        eseg
 
              mov   ax, [si]
 
        out   dx, ax
 
        ; bufw++;
 
        add   si, #2
 
        ; }
 
        loop  i13_f03_ace_data
 
 
 
        ; buffer_count--;
 
        dec   di
 
        jmp   i13_f03_cond_loop
 
 
 
        ; }
 
 
 
i13_f03_exit_loop:
 
        ; CSR_ACE_CTLL &= ~ACE_CTLL_CFGRESET;
 
        mov   dx, #0xe218
 
        in    ax, dx
 
        and   ax, #0xff7f
 
        out   dx, ax
 
 
 
i13_f03_done:
 
        ;; store real SI register back to temp bx
 
        push bp
 
        mov  bp, sp
 
        mov  _int13_harddisk.tempbx + 2 [bp], si
 
        pop  bp
 
ASM_END
 
 
 
        sector_count++;
 
        log_sector++;
 
        num_sectors--;
 
        if (num_sectors) continue;
 
        else break;
 
      }
 
 
 
      SET_AH(0);
 
      SET_DISK_RET_STATUS(0);
 
      SET_AL(sector_count);
 
      CLEAR_CF(); /* successful */
 
      return;
 
      break;
 
 
    case 0x08:
    case 0x08:
 
 
 
      drive = GET_ELDL ();
 
 
 
      // get_hd_geometry(drive, &hd_cylinders, &hd_heads, &hd_sectors);
 
      // fixed geometry:
 
      hd_cylinders = 993;
 
      hd_heads     = 16;
 
      hd_sectors   = 63;
 
 
 
      max_cylinder = hd_cylinders - 2; /* 0 based */
      SET_AL(0);
      SET_AL(0);
      SET_CH(0);
      SET_CH(max_cylinder & 0xff);
      SET_CL(0);
      SET_CL(((max_cylinder >> 2) & 0xc0) | (hd_sectors & 0x3f));
      SET_DH(0);
      SET_DH(hd_heads - 1);
      SET_DL(0); /* FIXME returns 0, 1, or n hard drives */
      SET_DL(n_drives); /* returns 0, 1, or 2 hard drives */
 
      SET_AH(0);
 
      SET_DISK_RET_STATUS(0);
 
      CLEAR_CF(); /* successful */
 
 
      // FIXME should set ES & DI
      return;
 
      break;
 
 
      goto int13_fail;
    case 0x09: /* initialize drive parameters */
 
    case 0x0c: /* seek to specified cylinder */
 
    case 0x0d: /* alternate disk reset */
 
    case 0x10: /* check drive ready */
 
    case 0x11: /* recalibrate */
 
      SET_AH(0);
 
      SET_DISK_RET_STATUS(0);
 
      CLEAR_CF(); /* successful */
 
      return;
 
      break;
 
 
 
    case 0x14: /* controller internal diagnostic */
 
      SET_AH(0);
 
      SET_DISK_RET_STATUS(0);
 
      CLEAR_CF(); /* successful */
 
      SET_AL(0);
 
      return;
 
      break;
 
 
 
    case 0x15: /* read disk drive size */
 
      drive = GET_ELDL();
 
      // get_hd_geometry(drive, &hd_cylinders, &hd_heads, &hd_sectors);
 
      // fixed geometry:
 
      hd_cylinders = 993;
 
      hd_heads     = 16;
 
      hd_sectors   = 63;
 
 
 
ASM_START
 
      push bp
 
      mov  bp, sp
 
      mov  al, _int13_harddisk.hd_heads + 2 [bp]
 
      mov  ah, _int13_harddisk.hd_sectors + 2 [bp]
 
      mul  al, ah ;; ax = heads * sectors
 
      mov  bx, _int13_harddisk.hd_cylinders + 2 [bp]
 
      dec  bx     ;; use (cylinders - 1) ???
 
      mul  ax, bx ;; dx:ax = (cylinders -1) * (heads * sectors)
 
      ;; now we need to move the 32bit result dx:ax to what the
 
      ;; BIOS wants which is cx:dx.
 
      ;; and then into CX:DX on the stack
 
      mov  _int13_harddisk.CX + 2 [bp], dx
 
      mov  _int13_harddisk.DX + 2 [bp], ax
 
      pop  bp
 
ASM_END
 
      SET_AH(3);  // hard disk accessible
 
      SET_DISK_RET_STATUS(0); // ??? should this be 0
 
      CLEAR_CF(); // successful
 
      return;
      break;
      break;
 
 
    default:
    default:
      BX_INFO("int13_harddisk: function %02xh unsupported, returns fail\n", GET_AH());
      BX_INFO("int13_harddisk: function %02xh unsupported, returns fail\n", GET_AH());
      goto int13_fail;
      goto int13_fail;
      break;
      break;
    }
    }
 
ASM_START
 
_int13_fail:
 
ASM_END
int13_fail:
int13_fail:
    SET_AH(0x01); // defaults to invalid function in AH or invalid parameter
    SET_AH(0x01); // defaults to invalid function in AH or invalid parameter
int13_fail_noah:
int13_fail_noah:
    SET_DISK_RET_STATUS(GET_AH());
    SET_DISK_RET_STATUS(GET_AH());
int13_fail_nostatus:
int13_fail_nostatus:
Line 1679... Line 2164...
  void
  void
set_diskette_current_cyl(drive, cyl)
set_diskette_current_cyl(drive, cyl)
  Bit8u drive;
  Bit8u drive;
  Bit8u cyl;
  Bit8u cyl;
{
{
/* TEMP HACK: FOR MSDOS */
/* TEMP HACK: FOR MSDOS
  if (drive > 1)
  if (drive > 1)
    drive = 1;
    drive = 1; */
  /*  BX_PANIC("set_diskette_current_cyl(): drive > 1\n"); */
  /*  BX_PANIC("set_diskette_current_cyl(): drive > 1\n"); */
  write_byte(0x0040, 0x0094+drive, cyl);
  write_byte(0x0040, 0x0094+drive, cyl);
}
}
 
 
void
void
Line 1723... Line 2208...
  bootdev = inb_cmos(0x3d);
  bootdev = inb_cmos(0x3d);
  bootdev |= ((inb_cmos(0x38) & 0xf0) << 4);
  bootdev |= ((inb_cmos(0x38) & 0xf0) << 4);
  bootdev >>= 4 * seq_nr;
  bootdev >>= 4 * seq_nr;
  bootdev &= 0xf;
  bootdev &= 0xf;
*/
*/
  bootdev = 0x1;
  bootdev = 0x2;  // 1: flopy disk, 2: hard disk
 
 
  /* Read user selected device */
  /* Read user selected device */
  bootfirst = read_word(IPL_SEG, IPL_BOOTFIRST_OFFSET);
  bootfirst = read_word(IPL_SEG, IPL_BOOTFIRST_OFFSET);
  if (bootfirst != 0xFFFF) {
  if (bootfirst != 0xFFFF) {
    bootdev = bootfirst;
    bootdev = bootfirst;
Line 1910... Line 2395...
  call  _int13_harddisk
  call  _int13_harddisk
;  pop   ax
;  pop   ax
;  shl   eax, #16
;  shl   eax, #16
 
 
int13_out:
int13_out:
 
;
 
; ZEUS HACK: put IF flag on.
 
;  Seems that MS-DOS does a 'cli' before calling this
 
;  but after int13 it doesn't set the interrupts back
 
;
 
  mov bp, sp
 
  mov ax, 24[bp]  ; FLAGS location
 
  or  ax, #0x0200 ; IF on
 
  mov 24[bp], ax
 
 
  pop ds
  pop ds
  pop es
  pop es
  ; popa ; we do this instead:
  ; popa ; we do this instead:
  pop di
  pop di
  pop si
  pop si
  pop bp
  pop bp
  add sp, #2
  add sp, #2
  pop bx
  pop bx
  pop dx
  pop dx
  pop cx
  pop cx
  pop ax
  pop ax
 
 
  iret
  iret
 
 
;----------
;----------
;- INT18h -
;- INT18h -
;----------
;----------
int18_handler: ;; Boot Failure recovery: try the next device.
int18_handler: ;; Boot Failure recovery: try the next device.
 
 
  ;; Reset SP and SS
  ;; Reset SP and SS
  mov  ax, #0xfffe
  mov  ax, #0xfffe
  mov  sp, ax
  mov  sp, ax
  xor  ax, ax
  xor  ax, ax
  mov  ss, ax
  mov  ss, ax
 
 
  ;; Get the boot sequence number out of the IPL memory
  ;; Get the boot sequence number out of the IPL memory
  mov  bx, #IPL_SEG
  mov  bx, #IPL_SEG
  mov  ds, bx                     ;; Set segment
  mov  ds, bx                     ;; Set segment
  mov  bx, IPL_SEQUENCE_OFFSET    ;; BX is now the sequence number
  mov  bx, IPL_SEQUENCE_OFFSET    ;; BX is now the sequence number
  inc  bx                         ;; ++
  inc  bx                         ;; ++
  mov  IPL_SEQUENCE_OFFSET, bx    ;; Write it back
  mov  IPL_SEQUENCE_OFFSET, bx    ;; Write it back
  mov  ds, ax                     ;; and reset the segment to zero.
  mov  ds, ax                     ;; and reset the segment to zero.
 
 
  ;; Carry on in the INT 19h handler, using the new sequence number
  ;; Carry on in the INT 19h handler, using the new sequence number
  push bx
  push bx
 
 
  jmp  int19_next_boot
  jmp  int19_next_boot
 
 
;----------
;----------
;- INT19h -
;- INT19h -
;----------
;----------
int19_relocated: ;; Boot function, relocated
int19_relocated: ;; Boot function, relocated
 
 
  ;; int19 was beginning to be really complex, so now it
  ;; int19 was beginning to be really complex, so now it
  ;; just calls a C function that does the work
  ;; just calls a C function that does the work
 
 
  push bp
  push bp
  mov  bp, sp
  mov  bp, sp
 
 
  ;; Reset SS and SP
  ;; Reset SS and SP
  mov  ax, #0xfffe
  mov  ax, #0xfffe
  mov  sp, ax
  mov  sp, ax
  xor  ax, ax
  xor  ax, ax
  mov  ss, ax
  mov  ss, ax
 
 
  ;; Start from the first boot device (0, in AX)
  ;; Start from the first boot device (0, in AX)
  mov  bx, #IPL_SEG
  mov  bx, #IPL_SEG
  mov  ds, bx                     ;; Set segment to write to the IPL memory
  mov  ds, bx                     ;; Set segment to write to the IPL memory
  mov  IPL_SEQUENCE_OFFSET, ax    ;; Save the sequence number
  mov  IPL_SEQUENCE_OFFSET, ax    ;; Save the sequence number
  mov  ds, ax                     ;; and reset the segment.
  mov  ds, ax                     ;; and reset the segment.
 
 
  push ax
  push ax
 
 
int19_next_boot:
int19_next_boot:
 
 
  ;; Call the C code for the next boot device
  ;; Call the C code for the next boot device
  call _int19_function
  call _int19_function
 
 
  ;; Boot failed: invoke the boot recovery function
  ;; Boot failed: invoke the boot recovery function
  int  #0x18
  int  #0x18
 
 
;----------
;----------
;- INT1Ch -
;- INT1Ch -
;----------
;----------
int1c_handler: ;; User Timer Tick
int1c_handler: ;; User Timer Tick
  iret
  iret
 
 
 
;--------------------
 
;- POST: HARD DRIVE -
 
;--------------------
 
; relocated here because the primary POST area isnt big enough.
 
hard_drive_post:
 
  // IRQ 14 = INT 76h
 
  // INT 76h calls INT 15h function ax=9100
 
 
 
  xor  ax, ax
 
  mov  ds, ax
 
  mov  0x0474, al /* hard disk status of last operation */
 
  mov  0x0477, al /* hard disk port offset (XT only ???) */
 
  mov  0x048c, al /* hard disk status register */
 
  mov  0x048d, al /* hard disk error register */
 
  mov  0x048e, al /* hard disk task complete flag */
 
  mov  al, #0x01
 
  mov  0x0475, al /* hard disk number attached */
 
  mov  al, #0xc0
 
  mov  0x0476, al /* hard disk control byte */
 
  SET_INT_VECTOR(0x13, #0xF000, #int13_handler)
 
  SET_INT_VECTOR(0x76, #0xF000, #int76_handler)
 
 
 
  ;; Initialize the sysace controller
 
  ; CSR_ACE_BUSMODE = ACE_BUSMODE_16BIT;
 
  mov  dx, #0xe200
 
  mov  ax, #0x0001
 
  out  dx, ax
 
 
 
  ; if(!(CSR_ACE_STATUSL & ACE_STATUSL_CFDETECT)) return 0;
 
  mov  dx, #0xe204
 
  in   ax,  dx
 
  and  ax, #0x0010
 
  jne  cf_detect
 
  hlt  ;; error
 
 
 
cf_detect:
 
  ; if((CSR_ACE_ERRORL != 0) || (CSR_ACE_ERRORH != 0)) return 0;
 
  mov  dx, #0xe208
 
  in   ax, dx
 
  cmp  ax, #0x0
 
jne  error_l
 
  mov  dx, #0xe20a
 
  in   ax, dx
 
  cmp  ax, #0x0
 
  je   lock_req
 
error_l:
 
  hlt
 
 
 
lock_req:
 
  ; CSR_ACE_CTLL |= ACE_CTLL_LOCKREQ;
 
  mov  dx, #0xe218
 
  in   ax, dx
 
  or   ax, #0x2
 
  out  dx, ax
 
 
 
  ; timeout = TIMEOUT;
 
  mov  cx, #0xffff
 
 
 
  ; while((timeout > 0) && (!(CSR_ACE_STATUSL & ACE_STATUSL_MPULOCK))) timeout--;
 
  mov  dx, #0xe204
 
ace_statusl:
 
  in   ax, dx
 
  and  ax, #0x2
 
  loopz ace_statusl
 
 
 
  ; if(timeout == 0) return 0;
 
  cmp  cx, #0x0
 
  jnz  success
 
  hlt  ;; error obtaining lock
 
 
;--------------------
success:
;- POST: EBDA segment
  ret
;--------------------
 
; relocated here because the primary POST area isnt big enough.
 
ebda_post:
;--------------------
  xor ax, ax            ; mov EBDA seg into 40E
;- POST: EBDA segment
  mov ds, ax
;--------------------
  mov word ptr [0x40E], #EBDA_SEG
; relocated here because the primary POST area isnt big enough.
  ret;;
ebda_post:
 
  xor ax, ax            ; mov EBDA seg into 40E
 
  mov ds, ax
 
  mov word ptr [0x40E], #EBDA_SEG
 
  ret;;
 
 
 
;--------------------
 
int76_handler:
 
  ;; record completion in BIOS task complete flag
 
  push  ax
 
  push  ds
 
  mov   ax, #0x0040
 
  mov   ds, ax
 
  mov   0x008E, #0xff
 
;  call  eoi_both_pics
 
  pop   ds
 
  pop   ax
 
  iret
 
 
rom_checksum:
 
 
rom_checksum:
  push ax
  push ax
  push bx
  push bx
  push cx
  push cx
  xor  ax, ax
  xor  ax, ax
  xor  bx, bx
  xor  bx, bx
  xor  cx, cx
  xor  cx, cx
  mov  ch, [2]
  mov  ch, [2]
  shl  cx, #1
  shl  cx, #1
checksum_loop:
checksum_loop:
  add  al, [bx]
  add  al, [bx]
  inc  bx
  inc  bx
  loop checksum_loop
  loop checksum_loop
  and  al, #0xff
  and  al, #0xff
  pop  cx
  pop  cx
  pop  bx
  pop  bx
  pop  ax
  pop  ax
  ret
  ret
 
 
 
 
;; We need a copy of this string, but we are not actually a PnP BIOS,
;; We need a copy of this string, but we are not actually a PnP BIOS,
;; so make sure it is *not* aligned, so OSes will not see it if they scan.
;; so make sure it is *not* aligned, so OSes will not see it if they scan.
.align 16
.align 16
  db 0
  db 0
pnp_string:
pnp_string:
  .ascii "$PnP"
  .ascii "$PnP"
 
 
 
 
rom_scan:
rom_scan:
  ;; Scan for existence of valid expansion ROMS.
  ;; Scan for existence of valid expansion ROMS.
  ;;   Video ROM:   from 0xC0000..0xC7FFF in 2k increments
  ;;   Video ROM:   from 0xC0000..0xC7FFF in 2k increments
  ;;   General ROM: from 0xC8000..0xDFFFF in 2k increments
  ;;   General ROM: from 0xC8000..0xDFFFF in 2k increments
  ;;   System  ROM: only 0xE0000
  ;;   System  ROM: only 0xE0000
  ;;
  ;;
  ;; Header:
  ;; Header:
  ;;   Offset    Value
  ;;   Offset    Value
  ;;   0         0x55
  ;;   0         0x55
  ;;   1         0xAA
  ;;   1         0xAA
  ;;   2         ROM length in 512-byte blocks
  ;;   2         ROM length in 512-byte blocks
  ;;   3         ROM initialization entry point (FAR CALL)
  ;;   3         ROM initialization entry point (FAR CALL)
 
 
rom_scan_loop:
rom_scan_loop:
  push ax       ;; Save AX
  push ax       ;; Save AX
  mov  ds, cx
  mov  ds, cx
  mov  ax, #0x0004 ;; start with increment of 4 (512-byte) blocks = 2k
  mov  ax, #0x0004 ;; start with increment of 4 (512-byte) blocks = 2k
  cmp [0], #0xAA55 ;; look for signature
  cmp [0], #0xAA55 ;; look for signature
  jne  rom_scan_increment
  jne  rom_scan_increment
  call rom_checksum
  call rom_checksum
  jnz  rom_scan_increment
  jnz  rom_scan_increment
  mov  al, [2]  ;; change increment to ROM length in 512-byte blocks
  mov  al, [2]  ;; change increment to ROM length in 512-byte blocks
 
 
  ;; We want our increment in 512-byte quantities, rounded to
  ;; We want our increment in 512-byte quantities, rounded to
  ;; the nearest 2k quantity, since we only scan at 2k intervals.
  ;; the nearest 2k quantity, since we only scan at 2k intervals.
  test al, #0x03
  test al, #0x03
  jz   block_count_rounded
  jz   block_count_rounded
  and  al, #0xfc ;; needs rounding up
  and  al, #0xfc ;; needs rounding up
  add  al, #0x04
  add  al, #0x04
block_count_rounded:
block_count_rounded:
 
 
  xor  bx, bx   ;; Restore DS back to 0000:
  xor  bx, bx   ;; Restore DS back to 0000:
  mov  ds, bx
  mov  ds, bx
  push ax       ;; Save AX
  push ax       ;; Save AX
  push di       ;; Save DI
  push di       ;; Save DI
  ;; Push addr of ROM entry point
  ;; Push addr of ROM entry point
  push cx       ;; Push seg
  push cx       ;; Push seg
  ;; push #0x0003  ;; Push offset - not an 8086 valid operand
  ;; push #0x0003  ;; Push offset - not an 8086 valid operand
  mov ax, #0x0003
  mov ax, #0x0003
  push ax
  push ax
 
 
  ;; Point ES:DI at "$PnP", which tells the ROM that we are a PnP BIOS.
  ;; Point ES:DI at "$PnP", which tells the ROM that we are a PnP BIOS.
  ;; That should stop it grabbing INT 19h; we will use its BEV instead.
  ;; That should stop it grabbing INT 19h; we will use its BEV instead.
  mov  ax, #0xf000
  mov  ax, #0xf000
  mov  es, ax
  mov  es, ax
  lea  di, pnp_string
  lea  di, pnp_string
 
 
  mov  bp, sp   ;; Call ROM init routine using seg:off on stack
  mov  bp, sp   ;; Call ROM init routine using seg:off on stack
  db   0xff     ;; call_far ss:[bp+0]
  db   0xff     ;; call_far ss:[bp+0]
  db   0x5e
  db   0x5e
  db   0
  db   0
  cli           ;; In case expansion ROM BIOS turns IF on
  cli           ;; In case expansion ROM BIOS turns IF on
  add  sp, #2   ;; Pop offset value
  add  sp, #2   ;; Pop offset value
  pop  cx       ;; Pop seg value (restore CX)
  pop  cx       ;; Pop seg value (restore CX)
 
 
  ;; Look at the ROM's PnP Expansion header.  Properly, we're supposed
  ;; Look at the ROM's PnP Expansion header.  Properly, we're supposed
  ;; to init all the ROMs and then go back and build an IPL table of
  ;; to init all the ROMs and then go back and build an IPL table of
  ;; all the bootable devices, but we can get away with one pass.
  ;; all the bootable devices, but we can get away with one pass.
  mov  ds, cx       ;; ROM base
  mov  ds, cx       ;; ROM base
  mov  bx, 0x001a   ;; 0x1A is the offset into ROM header that contains...
  mov  bx, 0x001a   ;; 0x1A is the offset into ROM header that contains...
  mov  ax, [bx]     ;; the offset of PnP expansion header, where...
  mov  ax, [bx]     ;; the offset of PnP expansion header, where...
  cmp  ax, #0x5024  ;; we look for signature "$PnP"
  cmp  ax, #0x5024  ;; we look for signature "$PnP"
  jne  no_bev
  jne  no_bev
  mov  ax, 2[bx]
  mov  ax, 2[bx]
  cmp  ax, #0x506e
  cmp  ax, #0x506e
  jne  no_bev
  jne  no_bev
  mov  ax, 0x1a[bx] ;; 0x1A is also the offset into the expansion header of...
  mov  ax, 0x1a[bx] ;; 0x1A is also the offset into the expansion header of...
  cmp  ax, #0x0000  ;; the Bootstrap Entry Vector, or zero if there is none.
  cmp  ax, #0x0000  ;; the Bootstrap Entry Vector, or zero if there is none.
  je   no_bev
  je   no_bev
 
 
  ;; Found a device that thinks it can boot the system.  Record its BEV and product name string.
  ;; Found a device that thinks it can boot the system.  Record its BEV and product name string.
  mov  di, 0x10[bx]            ;; Pointer to the product name string or zero if none
  mov  di, 0x10[bx]            ;; Pointer to the product name string or zero if none
  mov  bx, #IPL_SEG            ;; Go to the segment where the IPL table lives
  mov  bx, #IPL_SEG            ;; Go to the segment where the IPL table lives
  mov  ds, bx
  mov  ds, bx
  mov  bx, IPL_COUNT_OFFSET    ;; Read the number of entries so far
  mov  bx, IPL_COUNT_OFFSET    ;; Read the number of entries so far
  cmp  bx, #IPL_TABLE_ENTRIES
  cmp  bx, #IPL_TABLE_ENTRIES
  je   no_bev                  ;; Get out if the table is full
  je   no_bev                  ;; Get out if the table is full
  push cx
  push cx
  mov  cx, #0x4                ;; Zet: Needed to be compatible with 8086
  mov  cx, #0x4                ;; Zet: Needed to be compatible with 8086
  shl  bx, cl                  ;; Turn count into offset (entries are 16 bytes)
  shl  bx, cl                  ;; Turn count into offset (entries are 16 bytes)
  pop  cx
  pop  cx
  mov  0[bx], #IPL_TYPE_BEV    ;; This entry is a BEV device
  mov  0[bx], #IPL_TYPE_BEV    ;; This entry is a BEV device
  mov  6[bx], cx               ;; Build a far pointer from the segment...
  mov  6[bx], cx               ;; Build a far pointer from the segment...
  mov  4[bx], ax               ;; and the offset
  mov  4[bx], ax               ;; and the offset
  cmp  di, #0x0000
  cmp  di, #0x0000
  je   no_prod_str
  je   no_prod_str
  mov  0xA[bx], cx             ;; Build a far pointer from the segment...
  mov  0xA[bx], cx             ;; Build a far pointer from the segment...
  mov  8[bx], di               ;; and the offset
  mov  8[bx], di               ;; and the offset
no_prod_str:
no_prod_str:
  push cx
  push cx
  mov  cx, #0x4
  mov  cx, #0x4
  shr  bx, cl                  ;; Turn the offset back into a count
  shr  bx, cl                  ;; Turn the offset back into a count
  pop  cx
  pop  cx
  inc  bx                      ;; We have one more entry now
  inc  bx                      ;; We have one more entry now
  mov  IPL_COUNT_OFFSET, bx    ;; Remember that.
  mov  IPL_COUNT_OFFSET, bx    ;; Remember that.
 
 
no_bev:
no_bev:
  pop  di       ;; Restore DI
  pop  di       ;; Restore DI
  pop  ax       ;; Restore AX
  pop  ax       ;; Restore AX
rom_scan_increment:
rom_scan_increment:
  push cx
  push cx
  mov  cx, #5
  mov  cx, #5
  shl  ax, cl   ;; convert 512-bytes blocks to 16-byte increments
  shl  ax, cl   ;; convert 512-bytes blocks to 16-byte increments
                ;; because the segment selector is shifted left 4 bits.
                ;; because the segment selector is shifted left 4 bits.
  pop  cx
  pop  cx
  add  cx, ax
  add  cx, ax
  pop  ax       ;; Restore AX
  pop  ax       ;; Restore AX
  cmp  cx, ax
  cmp  cx, ax
  jbe  rom_scan_loop
  jbe  rom_scan_loop
 
 
  xor  ax, ax   ;; Restore DS back to 0000:
  xor  ax, ax   ;; Restore DS back to 0000:
  mov  ds, ax
  mov  ds, ax
  ret
  ret
 
 
;; for 'C' strings and other data, insert them here with
;; for 'C' strings and other data, insert them here with
;; a the following hack:
;; a the following hack:
;; DATA_SEG_DEFS_HERE
;; DATA_SEG_DEFS_HERE
 
 
 
 
;; the following area can be used to write dynamically generated tables
;; the following area can be used to write dynamically generated tables
  .align 16
  .align 16
bios_table_area_start:
bios_table_area_start:
  dd 0xaafb4442
  dd 0xaafb4442
  dd bios_table_area_end - bios_table_area_start - 8;
  dd bios_table_area_end - bios_table_area_start - 8;
 
 
;--------
;--------
;- POST -
;- POST -
;--------
;--------
.org 0xe05b ; POST Entry Point
.org 0xe05b ; POST Entry Point
post:
post:
  xor ax, ax
  xor ax, ax
 
 
normal_post:
normal_post:
  ; case 0: normal startup
  ; case 0: normal startup
 
 
  cli
  cli
  mov  ax, #0xfffe
  mov  ax, #0xfffe
  mov  sp, ax
  mov  sp, ax
  xor  ax, ax
  xor  ax, ax
  mov  ds, ax
  mov  ds, ax
  mov  ss, ax
  mov  ss, ax
 
 
  ;; zero out BIOS data area (40:00..40:ff)
  ;; zero out BIOS data area (40:00..40:ff)
  mov  es, ax
  mov  es, ax
  mov  cx, #0x0080 ;; 128 words
  mov  cx, #0x0080 ;; 128 words
  mov  di, #0x0400
  mov  di, #0x0400
  cld
  cld
  rep
  rep
    stosw
    stosw
 
 
  ;; set all interrupts to default handler
  ;; set all interrupts to default handler
  xor  bx, bx         ;; offset index
  xor  bx, bx         ;; offset index
  mov  cx, #0x0100    ;; counter (256 interrupts)
  mov  cx, #0x0100    ;; counter (256 interrupts)
  mov  ax, #dummy_iret_handler
  mov  ax, #dummy_iret_handler
  mov  dx, #0xF000
  mov  dx, #0xF000
 
 
post_default_ints:
post_default_ints:
  mov  [bx], ax
  mov  [bx], ax
  add  bx, #2
  add  bx, #2
  mov  [bx], dx
  mov  [bx], dx
  add  bx, #2
  add  bx, #2
  loop post_default_ints
  loop post_default_ints
 
 
  ;; set vector 0x79 to zero
  ;; set vector 0x79 to zero
  ;; this is used by 'gardian angel' protection system
  ;; this is used by 'gardian angel' protection system
  SET_INT_VECTOR(0x79, #0, #0)
  SET_INT_VECTOR(0x79, #0, #0)
 
 
  ;; base memory in K 40:13 (word)
  ;; base memory in K 40:13 (word)
  mov  ax, #BASE_MEM_IN_K
  mov  ax, #BASE_MEM_IN_K
  mov  0x0413, ax
  mov  0x0413, ax
 
 
 
 
  ;; Manufacturing Test 40:12
  ;; Manufacturing Test 40:12
  ;;   zerod out above
  ;;   zerod out above
 
 
  ;; Warm Boot Flag 0040:0072
  ;; Warm Boot Flag 0040:0072
  ;;   value of 1234h = skip memory checks
  ;;   value of 1234h = skip memory checks
  ;;   zerod out above
  ;;   zerod out above
 
 
  ;; Bootstrap failure vector
  ;; Bootstrap failure vector
  SET_INT_VECTOR(0x18, #0xF000, #int18_handler)
  SET_INT_VECTOR(0x18, #0xF000, #int18_handler)
 
 
  ;; Bootstrap Loader vector
  ;; Bootstrap Loader vector
  SET_INT_VECTOR(0x19, #0xF000, #int19_handler)
  SET_INT_VECTOR(0x19, #0xF000, #int19_handler)
 
 
  ;; User Timer Tick vector
  ;; User Timer Tick vector
  SET_INT_VECTOR(0x1c, #0xF000, #int1c_handler)
  SET_INT_VECTOR(0x1c, #0xF000, #int1c_handler)
 
 
  ;; Memory Size Check vector
  ;; Memory Size Check vector
  SET_INT_VECTOR(0x12, #0xF000, #int12_handler)
  SET_INT_VECTOR(0x12, #0xF000, #int12_handler)
 
 
  ;; Equipment Configuration Check vector
  ;; Equipment Configuration Check vector
  SET_INT_VECTOR(0x11, #0xF000, #int11_handler)
  SET_INT_VECTOR(0x11, #0xF000, #int11_handler)
 
 
  ;; EBDA setup
  ;; EBDA setup
  call ebda_post
  call ebda_post
 
 
  ;; Keyboard
  ;; PIT setup
  SET_INT_VECTOR(0x09, #0xF000, #int09_handler)
  SET_INT_VECTOR(0x08, #0xF000, #int08_handler)
  SET_INT_VECTOR(0x16, #0xF000, #int16_handler)
  ;; int 1C already points at dummy_iret_handler (above)
 
 
 
  ;; Keyboard
 
  SET_INT_VECTOR(0x09, #0xF000, #int09_handler)
 
  SET_INT_VECTOR(0x16, #0xF000, #int16_handler)
 
 
 
  xor  ax, ax
 
  mov  ds, ax
 
  mov  0x0417, al /* keyboard shift flags, set 1 */
 
  mov  0x0418, al /* keyboard shift flags, set 2 */
 
  mov  0x0419, al /* keyboard alt-numpad work area */
 
  mov  0x0471, al /* keyboard ctrl-break flag */
 
  mov  0x0497, al /* keyboard status flags 4 */
 
  mov  al, #0x10
 
  mov  0x0496, al /* keyboard status flags 3 */
 
 
 
  /* keyboard head of buffer pointer */
 
  mov  bx, #0x001E
 
  mov  0x041A, bx
 
 
 
  /* keyboard end of buffer pointer */
 
  mov  0x041C, bx
 
 
 
  /* keyboard pointer to start of buffer */
 
  mov  bx, #0x001E
 
  mov  0x0480, bx
 
 
 
  /* keyboard pointer to end of buffer */
 
  mov  bx, #0x003E
 
  mov  0x0482, bx
 
 
  xor  ax, ax
  ;; CMOS RTC
  mov  ds, ax
  SET_INT_VECTOR(0x1A, #0xF000, #int1a_handler)
  mov  0x0417, al /* keyboard shift flags, set 1 */
 
  mov  0x0418, al /* keyboard shift flags, set 2 */
 
  mov  0x0419, al /* keyboard alt-numpad work area */
 
  mov  0x0471, al /* keyboard ctrl-break flag */
 
  mov  0x0497, al /* keyboard status flags 4 */
 
  mov  al, #0x10
 
  mov  0x0496, al /* keyboard status flags 3 */
 
 
 
  /* keyboard head of buffer pointer */
 
  mov  bx, #0x001E
 
  mov  0x041A, bx
 
 
 
  /* keyboard end of buffer pointer */
 
  mov  0x041C, bx
 
 
 
  /* keyboard pointer to start of buffer */
 
  mov  bx, #0x001E
 
  mov  0x0480, bx
 
 
 
  /* keyboard pointer to end of buffer */
 
  mov  bx, #0x003E
 
  mov  0x0482, bx
 
 
 
  ;; CMOS RTC
 
  SET_INT_VECTOR(0x1A, #0xF000, #int1a_handler)
 
 
 
  ;; Video setup
  ;; Video setup
  SET_INT_VECTOR(0x10, #0xF000, #int10_handler)
  SET_INT_VECTOR(0x10, #0xF000, #int10_handler)
 
 
  mov  cx, #0xc000  ;; init vga bios
  mov  cx, #0xc000  ;; init vga bios
  mov  ax, #0xc780
  mov  ax, #0xc780
 
 
  call rom_scan
  call rom_scan
 
 
  call _print_bios_banner
  call _print_bios_banner
 
 
  ;; Floppy setup
  ;;
  SET_INT_VECTOR(0x13, #0xF000, #int13_handler)
  ;; Hard Drive setup
 
  ;;
 
  call hard_drive_post
 
 
  call _init_boot_vectors
  call _init_boot_vectors
 
 
  mov  cx, #0xc800  ;; init option roms
  mov  cx, #0xc800  ;; init option roms
  mov  ax, #0xe000
  mov  ax, #0xe000
  call rom_scan
  call rom_scan
 
 
  sti        ;; enable interrupts
  sti        ;; enable interrupts
  int  #0x19
  int  #0x19
 
 
;-------------------------------------------
;-------------------------------------------
;- INT 13h Fixed Disk Services Entry Point -
;- INT 13h Fixed Disk Services Entry Point -
;-------------------------------------------
;-------------------------------------------
.org 0xe3fe ; INT 13h Fixed Disk Services Entry Point
.org 0xe3fe ; INT 13h Fixed Disk Services Entry Point
int13_handler:
int13_handler:
  //JMPL(int13_relocated)
  //JMPL(int13_relocated)
  jmp int13_relocated
  jmp int13_relocated
 
 
.org 0xe401 ; Fixed Disk Parameter Table
.org 0xe401 ; Fixed Disk Parameter Table
 
 
;----------
;----------
;- INT19h -
;- INT19h -
;----------
;----------
.org 0xe6f2 ; INT 19h Boot Load Service Entry Point
.org 0xe6f2 ; INT 19h Boot Load Service Entry Point
int19_handler:
int19_handler:
 
 
  jmp int19_relocated
  jmp int19_relocated
 
 
 
 
;----------------------------------------
;----------------------------------------
;- INT 16h Keyboard Service Entry Point -
;- INT 16h Keyboard Service Entry Point -
;----------------------------------------
;----------------------------------------
.org 0xe82e
.org 0xe82e
int16_handler:
int16_handler:
 
 
  sti
  sti
  push  ds
  push  ds
  pushf
  pushf
  ;pusha ; we do this instead:
  ;pusha ; we do this instead:
  push ax
  push ax
  push cx
  push cx
  push dx
  push dx
  push bx
  push bx
  push sp
  push sp
  mov  bx, sp
  mov  bx, sp
  sseg
  sseg
    add  [bx], #10
    add  [bx], #10
  sseg
  sseg
    mov  bx, [bx+2]
    mov  bx, [bx+2]
  push bp
  push bp
  push si
  push si
  push di
  push di
 
 
  cmp   ah, #0x00
  cmp   ah, #0x00
  je    int16_F00
  je    int16_F00
  cmp   ah, #0x10
  cmp   ah, #0x10
  je    int16_F00
  je    int16_F00
 
 
  mov  bx, #0xf000
  mov  bx, #0xf000
  mov  ds, bx
  mov  ds, bx
  call _int16_function
  call _int16_function
  ; popa ; we do this instead:
  ; popa ; we do this instead:
  pop di
  pop di
  pop si
  pop si
  pop bp
  pop bp
  add sp, #2
  add sp, #2
  pop bx
  pop bx
  pop dx
  pop dx
  pop cx
  pop cx
  pop ax
  pop ax
  popf
  popf
  pop  ds
  pop  ds
  jz   int16_zero_set
  jz   int16_zero_set
 
 
int16_zero_clear:
int16_zero_clear:
  push bp
  push bp
  mov  bp, sp
  mov  bp, sp
  //SEG SS
  //SEG SS
  and  BYTE [bp + 0x06], #0xbf
  and  BYTE [bp + 0x06], #0xbf
  pop  bp
  pop  bp
  iret
  iret
 
 
int16_zero_set:
int16_zero_set:
  push bp
  push bp
  mov  bp, sp
  mov  bp, sp
  //SEG SS
  //SEG SS
  or   BYTE [bp + 0x06], #0x40
  or   BYTE [bp + 0x06], #0x40
  pop  bp
  pop  bp
  iret
  iret
 
 
int16_F00:
int16_F00:
  mov  bx, #0x0040
  mov  bx, #0x0040
  mov  ds, bx
  mov  ds, bx
 
 
int16_wait_for_key:
int16_wait_for_key:
  cli
  cli
  mov  bx, 0x001a
  mov  bx, 0x001a
  cmp  bx, 0x001c
  cmp  bx, 0x001c
  jne  int16_key_found
  jne  int16_key_found
  sti
  sti
  nop
  nop
#if 0
#if 0
                           /* no key yet, call int 15h, function AX=9002 */
                           /* no key yet, call int 15h, function AX=9002 */
  0x50,                    /* push AX */
  0x50,                    /* push AX */
  0xb8, 0x02, 0x90,        /* mov AX, #0x9002 */
  0xb8, 0x02, 0x90,        /* mov AX, #0x9002 */
  0xcd, 0x15,              /* int 15h */
  0xcd, 0x15,              /* int 15h */
  0x58,                    /* pop  AX */
  0x58,                    /* pop  AX */
  0xeb, 0xea,              /* jmp   WAIT_FOR_KEY */
  0xeb, 0xea,              /* jmp   WAIT_FOR_KEY */
#endif
#endif
  jmp  int16_wait_for_key
  jmp  int16_wait_for_key
 
 
int16_key_found:
int16_key_found:
  mov  bx, #0xf000
  mov  bx, #0xf000
  mov  ds, bx
  mov  ds, bx
  call _int16_function
  call _int16_function
  ; popa ; we do this instead:
  ; popa ; we do this instead:
  pop di
  pop di
  pop si
  pop si
  pop bp
  pop bp
  add sp, #2
  add sp, #2
  pop bx
  pop bx
  pop dx
  pop dx
  pop cx
  pop cx
  pop ax
  pop ax
  popf
  popf
  pop  ds
  pop  ds
#if 0
#if 0
                           /* notify int16 complete w/ int 15h, function AX=9102 */
                           /* notify int16 complete w/ int 15h, function AX=9102 */
  0x50,                    /* push AX */
  0x50,                    /* push AX */
  0xb8, 0x02, 0x91,        /* mov AX, #0x9102 */
  0xb8, 0x02, 0x91,        /* mov AX, #0x9102 */
  0xcd, 0x15,              /* int 15h */
  0xcd, 0x15,              /* int 15h */
  0x58,                    /* pop  AX */
  0x58,                    /* pop  AX */
#endif
#endif
  iret
  iret
 
 
 
 
 
 
;-------------------------------------------------
;-------------------------------------------------
;- INT09h : Keyboard Hardware Service Entry Point -
;- INT09h : Keyboard Hardware Service Entry Point -
;-------------------------------------------------
;-------------------------------------------------
.org 0xe987
.org 0xe987
int09_handler:
int09_handler:
  cli
  cli
  push ax
  push ax
  in  al, #0x60             ;;read key from keyboard controller
  in  al, #0x60             ;;read key from keyboard controller
  sti
  sti
 
 
  push  ds
  push  ds
  ;pusha ; we do this instead:
  ;pusha ; we do this instead:
 
 
  push ax
  push ax
  push cx
  push cx
  push dx
  push dx
  push bx
  push bx
  push sp
  push sp
  mov  bx, sp
  mov  bx, sp
  sseg
  sseg
    add  [bx], #10
    add  [bx], #10
  sseg
  sseg
    mov  bx, [bx+2]
    mov  bx, [bx+2]
  push bp
  push bp
  push si
  push si
  push di
  push di
 
 
  ;; check for extended key
  ;; check for extended key
  cmp  al, #0xe0
  cmp  al, #0xe0
  jne int09_check_pause
  jne int09_check_pause
  xor  ax, ax
  xor  ax, ax
  mov  ds, ax
  mov  ds, ax
  mov  al, BYTE [0x496]     ;; mf2_state |= 0x02
  mov  al, BYTE [0x496]     ;; mf2_state |= 0x02
  or   al, #0x02
  or   al, #0x02
  mov  BYTE [0x496], al
  mov  BYTE [0x496], al
  jmp int09_done
  jmp int09_done
 
 
int09_check_pause: ;; check for pause key
int09_check_pause: ;; check for pause key
  cmp  al, #0xe1
  cmp  al, #0xe1
  jne int09_process_key
  jne int09_process_key
  xor  ax, ax
  xor  ax, ax
  mov  ds, ax
  mov  ds, ax
  mov  al, BYTE [0x496]     ;; mf2_state |= 0x01
  mov  al, BYTE [0x496]     ;; mf2_state |= 0x01
  or   al, #0x01
  or   al, #0x01
  mov  BYTE [0x496], al
  mov  BYTE [0x496], al
  jmp int09_done
  jmp int09_done
 
 
int09_process_key:
int09_process_key:
  mov   bx, #0xf000
  mov   bx, #0xf000
  mov   ds, bx
  mov   ds, bx
  call  _int09_function
  call  _int09_function
int09_done:
int09_done:
  ; popa ; we do this instead:
  ; popa ; we do this instead:
  pop di
  pop di
  pop si
  pop si
  pop bp
  pop bp
  add sp, #2
  add sp, #2
  pop bx
  pop bx
  pop dx
  pop dx
  pop cx
  pop cx
  pop ax
  pop ax
 
 
Line 2473... Line 3061...
  cli
  cli
  pop ax
  pop ax
  iret
  iret
 
 
 
 
;----------
;----------
;- INT10h -
;- INT10h -
;----------
;----------
.org 0xf065 ; INT 10h Video Support Service Entry Point
.org 0xf065 ; INT 10h Video Support Service Entry Point
int10_handler:
int10_handler:
  ;; dont do anything, since the VGA BIOS handles int10h requests
  ;; dont do anything, since the VGA BIOS handles int10h requests
  iret
  iret
 
 
.org 0xf0a4 ; MDA/CGA Video Parameter Table (INT 1Dh)
.org 0xf0a4 ; MDA/CGA Video Parameter Table (INT 1Dh)
 
 
;----------
;----------
;- INT12h -
;- INT12h -
;----------
;----------
.org 0xf841 ; INT 12h Memory Size Service Entry Point
.org 0xf841 ; INT 12h Memory Size Service Entry Point
; ??? different for Pentium (machine check)?
; ??? different for Pentium (machine check)?
int12_handler:
int12_handler:
  push ds
  push ds
  mov  ax, #0x0040
  mov  ax, #0x0040
  mov  ds, ax
  mov  ds, ax
  mov  ax, 0x0013
  mov  ax, 0x0013
  pop  ds
  pop  ds
  iret
  iret
 
 
;----------
;----------
;- INT11h -
;- INT11h -
;----------
;----------
.org 0xf84d ; INT 11h Equipment List Service Entry Point
.org 0xf84d ; INT 11h Equipment List Service Entry Point
int11_handler:
int11_handler:
  push ds
  push ds
  mov  ax, #0x0040
  mov  ax, #0x0040
  mov  ds, ax
  mov  ds, ax
  mov  ax, 0x0010
  mov  ax, 0x0010
  pop  ds
  pop  ds
  iret
  iret
 
 
;----------
;----------
;- INT1Ah -
;- INT1Ah -
;----------
;----------
.org 0xfe6e ; INT 1Ah Time-of-day Service Entry Point
.org 0xfe6e ; INT 1Ah Time-of-day Service Entry Point
int1a_handler:
int1a_handler:
  push ds
  push ds
  ;pusha ; we do this instead:
  ;pusha ; we do this instead:
  push ax
  push ax
  push cx
  push cx
  push dx
  push dx
  push bx
  push bx
  push sp
  push sp
  mov  bx, sp
  mov  bx, sp
  sseg
  sseg
    add  [bx], #10
    add  [bx], #10
  sseg
  sseg
    mov  bx, [bx+2]
    mov  bx, [bx+2]
  push bp
  push bp
  push si
  push si
  push di
  push di
 
 
  xor  ax, ax
  xor  ax, ax
  mov  ds, ax
  mov  ds, ax
int1a_callfunction:
int1a_callfunction:
  call _int1a_function
  call _int1a_function
  ; popa ; we do this instead:
  ; popa ; we do this instead:
  pop di
  pop di
  pop si
  pop si
  pop bp
  pop bp
  add sp, #2
  add sp, #2
  pop bx
  pop bx
  pop dx
  pop dx
  pop cx
  pop cx
  pop ax
  pop ax
 
 
  pop  ds
  pop  ds
  iret
  iret
 
 
;------------------------------------------------
;---------
;- IRET Instruction for Dummy Interrupt Handler -
;- INT08 -
;------------------------------------------------
;---------
.org 0xff53 ; IRET Instruction for Dummy Interrupt Handler
.org 0xfea5 ; INT 08h System Timer ISR Entry Point
dummy_iret_handler:
int08_handler:
 
  sti
 
  push ax
 
  push bx
 
  push ds
 
  xor ax, ax
 
  mov ds, ax
 
 
 
  mov ax, 0x046c ;; get ticks dword
 
  mov bx, 0x046e
 
  inc ax
 
  jne i08_linc_done
 
  inc bx         ;; inc high word
 
 
 
i08_linc_done:
 
  push bx
 
  ;; compare eax to one days worth of timer ticks at 18.2 hz
 
  sub bx, #0x0018
 
  jne i08_lcmp_done
 
  cmp ax, #0x00B0
 
  jb  i08_lcmp_b_and_lt
 
  jge i08_lcmp_done
 
  inc bx
 
  jmp i08_lcmp_done
 
 
 
i08_lcmp_b_and_lt:
 
  dec bx
 
 
 
i08_lcmp_done:
 
  pop bx
 
  jb  int08_store_ticks
 
  ;; there has been a midnight rollover at this point
 
  xor ax, ax      ;; zero out counter
 
  xor bx, bx
 
  inc BYTE 0x0470 ;; increment rollover flag
 
 
 
int08_store_ticks:
 
  mov 0x046c, ax ;; store new ticks dword
 
  mov 0x046e, bx
 
  ;; chain to user timer tick INT #0x1c
 
  //pushf
 
  //;; call_ep [ds:loc]
 
  //CALL_EP( 0x1c << 2 )
 
  int #0x1c
 
  cli
 
  ;; call eoi_master_pic
 
  pop ds
 
  pop bx
 
  pop ax
 
  iret
 
 
 
.org 0xfef3 ; Initial Interrupt Vector Offsets Loaded by POST
 
 
 
 
 
.org 0xff00
 
.ascii BIOS_COPYRIGHT_STRING
 
 
 
;------------------------------------------------
 
;- IRET Instruction for Dummy Interrupt Handler -
 
;------------------------------------------------
 
.org 0xff53 ; IRET Instruction for Dummy Interrupt Handler
 
dummy_iret_handler:
  iret
  iret
 
 
.org 0xfff0 ; Power-up Entry Point
.org 0xfff0 ; Power-up Entry Point
;  hlt
;  hlt
  jmp 0xf000:post
  jmp 0xf000:post
 
 
.org 0xfff5 ; ASCII Date ROM was built - 8 characters in MM/DD/YY
.org 0xfff5 ; ASCII Date ROM was built - 8 characters in MM/DD/YY
.ascii BIOS_BUILD_DATE
.ascii BIOS_BUILD_DATE
 
 
.org 0xfffe ; System Model ID
.org 0xfffe ; System Model ID
db SYS_MODEL_ID
db SYS_MODEL_ID
db 0x00   ; filler
db 0x00   ; filler
ASM_END
ASM_END
 
 
ASM_START
ASM_START
.org 0xcc00
.org 0xcc00
bios_table_area_end:
bios_table_area_end:
// bcc-generated data will be placed here
// bcc-generated data will be placed here
ASM_END
ASM_END
 
 
 No newline at end of file
 No newline at end of file
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.