Unify checksum functions.
[seabios.git] / src / post.c
index aecb2e30906edfd8c3d722c3e75d3717ab7094d6..e211bd45426bc1a576149de3953dc236936d91cd 100644 (file)
 #include "cmos.h" // CMOS_*
 #include "util.h" // memset
 #include "biosvar.h" // struct bios_data_area_s
+#include "ata.h"
+#include "kbd.h"
 
 #define bda ((struct bios_data_area_s *)0)
 #define ebda ((struct extended_bios_data_area_s *)(EBDA_SEG<<4))
-#define ipl ((struct ipl_s *)(IPL_SEG<<4))
-
-static u8
-checksum(u8 *p, u32 len)
-{
-    u32 i;
-    u8 sum = 0;
-    for (i=0; i<len; i++)
-        sum += p[i];
-    return sum;
-}
 
 static void
 init_bda()
@@ -33,14 +24,14 @@ init_bda()
 
     int i;
     for (i=0; i<256; i++) {
-        bda->ivecs[i].seg = SEG_BIOS;
-        bda->ivecs[i].offset = OFFSET_dummy_iret_handler;
+        SET_BDA(ivecs[i].seg, SEG_BIOS);
+        SET_BDA(ivecs[i].offset, OFFSET_dummy_iret_handler);
     }
 
-    bda->mem_size_kb = BASE_MEM_IN_K;
+    SET_BDA(mem_size_kb, BASE_MEM_IN_K);
 
     // mov CMOS Equipment Byte to BDA Equipment Word
-    bda->equipment_list_flags = inb_cmos(CMOS_EQUIPMENT_INFO);
+    SET_BDA(equipment_list_flags, inb_cmos(CMOS_EQUIPMENT_INFO));
 }
 
 static void
@@ -48,29 +39,29 @@ init_handlers()
 {
     // set vector 0x79 to zero
     // this is used by 'gardian angel' protection system
-    bda->ivecs[0x79].seg = 0;
-    bda->ivecs[0x79].offset = 0;
-
-    bda->ivecs[0x40].offset = OFFSET_entry_40;
-    bda->ivecs[0x0e].offset = OFFSET_entry_0e;
-    bda->ivecs[0x13].offset = OFFSET_entry_13;
-    bda->ivecs[0x76].offset = OFFSET_entry_76;
-    bda->ivecs[0x17].offset = OFFSET_entry_17;
-    bda->ivecs[0x18].offset = OFFSET_entry_18;
-    bda->ivecs[0x19].offset = OFFSET_entry_19;
-    bda->ivecs[0x1c].offset = OFFSET_entry_1c;
-    bda->ivecs[0x12].offset = OFFSET_entry_12;
-    bda->ivecs[0x11].offset = OFFSET_entry_11;
-    bda->ivecs[0x15].offset = OFFSET_entry_15;
-    bda->ivecs[0x08].offset = OFFSET_entry_08;
-    bda->ivecs[0x09].offset = OFFSET_entry_09;
-    bda->ivecs[0x16].offset = OFFSET_entry_16;
-    bda->ivecs[0x14].offset = OFFSET_entry_14;
-    bda->ivecs[0x1a].offset = OFFSET_entry_1a;
-    bda->ivecs[0x70].offset = OFFSET_entry_70;
-    bda->ivecs[0x74].offset = OFFSET_entry_74;
-    bda->ivecs[0x75].offset = OFFSET_entry_75;
-    bda->ivecs[0x10].offset = OFFSET_entry_10;
+    SET_BDA(ivecs[0x79].seg, 0);
+    SET_BDA(ivecs[0x79].offset, 0);
+
+    SET_BDA(ivecs[0x40].offset, OFFSET_entry_40);
+    SET_BDA(ivecs[0x0e].offset, OFFSET_entry_0e);
+    SET_BDA(ivecs[0x13].offset, OFFSET_entry_13);
+    SET_BDA(ivecs[0x76].offset, OFFSET_entry_76);
+    SET_BDA(ivecs[0x17].offset, OFFSET_entry_17);
+    SET_BDA(ivecs[0x18].offset, OFFSET_entry_18);
+    SET_BDA(ivecs[0x19].offset, OFFSET_entry_19);
+    SET_BDA(ivecs[0x1c].offset, OFFSET_entry_1c);
+    SET_BDA(ivecs[0x12].offset, OFFSET_entry_12);
+    SET_BDA(ivecs[0x11].offset, OFFSET_entry_11);
+    SET_BDA(ivecs[0x15].offset, OFFSET_entry_15);
+    SET_BDA(ivecs[0x08].offset, OFFSET_entry_08);
+    SET_BDA(ivecs[0x09].offset, OFFSET_entry_09);
+    SET_BDA(ivecs[0x16].offset, OFFSET_entry_16);
+    SET_BDA(ivecs[0x14].offset, OFFSET_entry_14);
+    SET_BDA(ivecs[0x1a].offset, OFFSET_entry_1a);
+    SET_BDA(ivecs[0x70].offset, OFFSET_entry_70);
+    SET_BDA(ivecs[0x74].offset, OFFSET_entry_74);
+    SET_BDA(ivecs[0x75].offset, OFFSET_entry_75);
+    SET_BDA(ivecs[0x10].offset, OFFSET_entry_10);
 }
 
 static void
@@ -78,11 +69,13 @@ init_ebda()
 {
     memset(ebda, 0, sizeof(*ebda));
     ebda->size = EBDA_SIZE;
-    bda->ebda_seg = EBDA_SEG;
-    bda->ivecs[0x41].seg = EBDA_SEG;
-    bda->ivecs[0x41].offset = offsetof(struct extended_bios_data_area_s, fdpt0);
-    bda->ivecs[0x46].seg = EBDA_SEG;
-    bda->ivecs[0x41].offset = offsetof(struct extended_bios_data_area_s, fdpt1);
+    SET_BDA(ebda_seg, EBDA_SEG);
+    SET_BDA(ivecs[0x41].seg, EBDA_SEG);
+    SET_BDA(ivecs[0x41].offset
+            , offsetof(struct extended_bios_data_area_s, fdpt0));
+    SET_BDA(ivecs[0x46].seg, EBDA_SEG);
+    SET_BDA(ivecs[0x41].offset
+            , offsetof(struct extended_bios_data_area_s, fdpt1));
 }
 
 static void
@@ -95,152 +88,6 @@ pit_setup()
     outb(0x0, PORT_PIT_COUNTER0);
 }
 
-//--------------------------------------------------------------------------
-// keyboard_panic
-//--------------------------------------------------------------------------
-static void
-keyboard_panic(u16 status)
-{
-  // If you're getting a 993 keyboard panic here,
-  // please see the comment in keyboard_init
-
-  BX_PANIC("Keyboard error:%u\n",status);
-}
-
-static void
-kbd_flush(u8 code)
-{
-    u16 max = 0xffff;
-    while ((inb(PORT_PS2_STATUS) & 0x02) && (--max > 0))
-        outb(code, PORT_DIAG);
-    if (!max && code != 0xff)
-        keyboard_panic(code);
-}
-
-static void
-kbd_waitdata(u8 code)
-{
-    u16 max = 0xffff;
-    while ( ((inb(PORT_PS2_STATUS) & 0x01) == 0) && (--max>0) )
-        outb(code, PORT_DIAG);
-    if (!max)
-        keyboard_panic(code);
-}
-
-//--------------------------------------------------------------------------
-// keyboard_init
-//--------------------------------------------------------------------------
-// this file is based on LinuxBIOS implementation of keyboard.c
-// could convert to #asm to gain space
-static void
-keyboard_init()
-{
-    /* ------------------- Flush buffers ------------------------*/
-    /* Wait until buffer is empty */
-    kbd_flush(0xff);
-
-    /* flush incoming keys */
-    u16 max=0x2000;
-    while (--max > 0) {
-        outb(0x00, PORT_DIAG);
-        if (inb(PORT_PS2_STATUS) & 0x01) {
-            inb(PORT_PS2_DATA);
-            max = 0x2000;
-            }
-        }
-
-    // Due to timer issues, and if the IPS setting is > 15000000,
-    // the incoming keys might not be flushed here. That will
-    // cause a panic a few lines below.  See sourceforge bug report :
-    // [ 642031 ] FATAL: Keyboard RESET error:993
-
-    /* ------------------- controller side ----------------------*/
-    /* send cmd = 0xAA, self test 8042 */
-    outb(0xaa, PORT_PS2_STATUS);
-
-    kbd_flush(0x00);
-    kbd_waitdata(0x01);
-
-    /* read self-test result, 0x55 should be returned from 0x60 */
-    if (inb(PORT_PS2_DATA) != 0x55)
-        keyboard_panic(991);
-
-    /* send cmd = 0xAB, keyboard interface test */
-    outb(0xab, PORT_PS2_STATUS);
-
-    kbd_flush(0x10);
-    kbd_waitdata(0x11);
-
-    /* read keyboard interface test result, */
-    /* 0x00 should be returned form 0x60 */
-    if (inb(PORT_PS2_DATA) != 0x00)
-        keyboard_panic(992);
-
-    /* Enable Keyboard clock */
-    outb(0xae, PORT_PS2_STATUS);
-    outb(0xa8, PORT_PS2_STATUS);
-
-    /* ------------------- keyboard side ------------------------*/
-    /* reset kerboard and self test  (keyboard side) */
-    outb(0xff, PORT_PS2_DATA);
-
-    kbd_flush(0x20);
-    kbd_waitdata(0x21);
-
-    /* keyboard should return ACK */
-    if (inb(PORT_PS2_DATA) != 0xfa)
-        keyboard_panic(993);
-
-    kbd_waitdata(0x31);
-
-    if (inb(PORT_PS2_DATA) != 0xaa)
-        keyboard_panic(994);
-
-    /* Disable keyboard */
-    outb(0xf5, PORT_PS2_DATA);
-
-    kbd_flush(0x40);
-    kbd_waitdata(0x41);
-
-    /* keyboard should return ACK */
-    if (inb(PORT_PS2_DATA) != 0xfa)
-        keyboard_panic(995);
-
-    /* Write Keyboard Mode */
-    outb(0x60, PORT_PS2_STATUS);
-
-    kbd_flush(0x50);
-
-    /* send cmd: scan code convert, disable mouse, enable IRQ 1 */
-    outb(0x61, PORT_PS2_DATA);
-
-    kbd_flush(0x60);
-
-    /* Enable keyboard */
-    outb(0xf4, PORT_PS2_DATA);
-
-    kbd_flush(0x70);
-    kbd_waitdata(0x71);
-
-    /* keyboard should return ACK */
-    if (inb(PORT_PS2_DATA) != 0xfa)
-        keyboard_panic(996);
-
-    outb(0x77, PORT_DIAG);
-}
-
-static void
-kbd_setup()
-{
-    bda->kbd_mode = 0x10;
-    bda->kbd_buf_head = bda->kbd_buf_tail = bda->kbd_buf_start_offset
-        = offsetof(struct bios_data_area_s, kbd_buf) - 0x400;
-    bda->kbd_buf_end_offset
-        = (offsetof(struct bios_data_area_s, kbd_buf[sizeof(bda->kbd_buf)])
-           - 0x400);
-    keyboard_init();
-}
-
 static u16
 detect_parport(u16 port, u8 timeout, u8 count)
 {
@@ -251,8 +98,8 @@ detect_parport(u16 port, u8 timeout, u8 count)
     if (inb(port) != 0xaa)
         // Not present
         return 0;
-    bda->port_lpt[count] = port;
-    bda->lpt_timeout[count] = timeout;
+    SET_BDA(port_lpt[count], port);
+    SET_BDA(lpt_timeout[count], timeout);
     return 1;
 }
 
@@ -264,8 +111,8 @@ lpt_setup()
     count += detect_parport(0x278, 0x14, count);
 
     // Equipment word bits 14..15 determing # parallel ports
-    u16 eqb = bda->equipment_list_flags;
-    bda->equipment_list_flags = (eqb & 0x3fff) | (count << 14);
+    u16 eqb = GET_BDA(equipment_list_flags);
+    SET_BDA(equipment_list_flags, (eqb & 0x3fff) | (count << 14));
 }
 
 static u16
@@ -277,8 +124,8 @@ detect_serial(u16 port, u8 timeout, u8 count)
     if (inb(port+2) != 0x02)
         return 0;
     outb(0x00, port+1);
-    bda->port_com[count] = port;
-    bda->com_timeout[count] = timeout;
+    SET_BDA(port_com[count], port);
+    SET_BDA(com_timeout[count], timeout);
     return 1;
 }
 
@@ -292,8 +139,8 @@ serial_setup()
     count += detect_serial(0x2e8, 0x0a, count);
 
     // Equipment word bits 9..11 determing # serial ports
-    u16 eqb = bda->equipment_list_flags;
-    bda->equipment_list_flags = (eqb & 0xf1ff) | (count << 9);
+    u16 eqb = GET_BDA(equipment_list_flags);
+    SET_BDA(equipment_list_flags, (eqb & 0xf1ff) | (count << 9));
 }
 
 static u32
@@ -311,8 +158,8 @@ timer_setup()
     ticks += (minutes * 10923904) / 10000;
     u32 hours = bcd2bin(inb_cmos(CMOS_RTC_HOURS));
     ticks += (hours * 65543427) / 1000;
-    bda->timer_counter = ticks;
-    bda->timer_rollover = 0;
+    SET_BDA(timer_counter, ticks);
+    SET_BDA(timer_rollover, 0);
 }
 
 static void
@@ -342,10 +189,10 @@ floppy_drive_post()
         out |= 0x07;
     if (type & 0x0f)
         out |= 0x70;
-    bda->floppy_harddisk_info = out;
+    SET_BDA(floppy_harddisk_info, out);
     outb(0x02, PORT_DMA1_MASK_REG);
 
-    bda->ivecs[0x1E].offset = OFFSET_diskette_param_table2;
+    SET_BDA(ivecs[0x1E].offset, OFFSET_diskette_param_table2);
 }
 
 static void
@@ -401,15 +248,15 @@ fill_hdinfo(struct fdpt_s *info, u8 typecmos, u8 basecmos)
     }
     info->cylinders = cyl;
     info->heads = heads;
-    info->checksum = ~checksum((u8*)info, sizeof(*info)-1) + 1;
+    info->checksum = -checksum((u8*)info, sizeof(*info)-1);
 }
 
 static void
 hard_drive_post()
 {
     outb(0x0a, 0x03f6); // 0000 1010 = reserved, disable IRQ 14
-    bda->disk_count = 1;
-    bda->disk_control_byte = 0xc0;
+    SET_BDA(disk_count, 1);
+    SET_BDA(disk_control_byte, 0xc0);
 
     // move disk geometry data from CMOS to EBDA disk parameter table(s)
     u8 diskinfo = inb_cmos(CMOS_DISK_DATA);
@@ -426,11 +273,8 @@ hard_drive_post()
 static void
 init_boot_vectors()
 {
-    // Clear out the IPL table.
-    memset(ipl, 0, sizeof(*ipl));
-
     // Floppy drive
-    struct ipl_entry_s *ip = &ipl->table[0];
+    struct ipl_entry_s *ip = &ebda->ipl.table[0];
     ip->type = IPL_TYPE_FLOPPY;
     ip++;
 
@@ -444,8 +288,8 @@ init_boot_vectors()
         ip++;
     }
 
-    ipl->count = ip - ipl->table;
-    ipl->sequence = 0xffff;
+    ebda->ipl.count = ip - ebda->ipl.table;
+    ebda->ipl.sequence = 0xffff;
 }
 
 static void
@@ -472,7 +316,7 @@ rom_scan(u32 start, u32 end)
         if (checksum(rom, len) != 0)
             continue;
         p = (u8*)(((u32)p + len) / 2048 * 2048);
-        callrom(PTR_TO_SEG(rom), PTR_TO_OFFSET(rom + 3));
+        callrom(FARPTR_TO_SEG(rom), FARPTR_TO_OFFSET(rom + 3));
 
         // 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
@@ -488,18 +332,18 @@ rom_scan(u32 start, u32 end)
         // Found a device that thinks it can boot the system.  Record
         // its BEV and product name string.
 
-        if (ipl->count >= ARRAY_SIZE(ipl->table))
+        if (ebda->ipl.count >= ARRAY_SIZE(ebda->ipl.table))
             continue;
 
-        struct ipl_entry_s *ip = &ipl->table[ipl->count];
+        struct ipl_entry_s *ip = &ebda->ipl.table[ebda->ipl.count];
         ip->type = IPL_TYPE_BEV;
-        ip->vector = (PTR_TO_SEG(rom) << 16) | entry;
+        ip->vector = (FARPTR_TO_SEG(rom) << 16) | entry;
 
         u16 desc = *(u16*)&rom[0x1a+0x10];
         if (desc)
-            ip->description = (PTR_TO_SEG(rom) << 16) | desc;
+            ip->description = (FARPTR_TO_SEG(rom) << 16) | desc;
 
-        ipl->count++;
+        ebda->ipl.count++;
     }
 }
 
@@ -523,19 +367,33 @@ post()
 
     printf("BIOS - begin\n\n");
 
-    // XXX - need to do pci stuff
-    //pci_setup();
+    // clear bss section -- XXX - shouldn't use globals
+    extern char __bss_start[], __bss_end[];
+    memset(__bss_start, 0, __bss_end - __bss_start);
+
+    rombios32_init();
+
     init_boot_vectors();
 
     floppy_drive_post();
     hard_drive_post();
-    if (CONFIG_ATA)
+    if (CONFIG_ATA) {
         ata_init();
+        ata_detect();
+    }
 
     init_boot_vectors();
+
     rom_scan(0xc8000, 0xe0000);
 
-    callrom(SEG_BIOS, OFFSET_begin_boot);
+    // reset the memory (some boot loaders such as syslinux suppose
+    // that the memory is set to zero)
+    memset((void*)0x40000, 0, 0x40000); // XXX - shouldn't use globals
+
+    // Invoke int 19 to start boot process.
+    struct bregs br;
+    memset(&br, 0, sizeof(br));
+    call16_int(0x19, &br);
 }
 
 static void
@@ -571,8 +429,8 @@ check_restart_status()
     eoi_both_pics();
     struct bregs br;
     memset(&br, 0, sizeof(br));
-    br.cs = bda->jump_cs_ip >> 16;
-    br.ip = bda->jump_cs_ip;
+    br.cs = GET_BDA(jump_cs_ip) >> 16;
+    br.ip = GET_BDA(jump_cs_ip);
     call16(&br);
 }