foo
[bootcensus] / src / kmain.c
index fab4e6f..bcd8a91 100644 (file)
@@ -18,55 +18,137 @@ along with this program.  If not, see <https://www.gnu.org/licenses/>.
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
+#include <unistd.h>
 #include "segm.h"
 #include "intr.h"
+#include "mem.h"
 #include "keyb.h"
+#include "psaux.h"
 #include "timer.h"
 #include "contty.h"
-#include "int86.h"
+#include "video.h"
+#include "vbe.h"
+#include "audio.h"
+#include "panic.h"
+#include "census/census.h"
 
-static void set_mode13h(void)
-{
-       struct int86regs regs;
+static int video_init(void);
+static int modecmp(const void *a, const void *b);
 
-       memset(&regs, 0, sizeof regs);
-       regs.eax = 0x13;
-       int86(0x10, &regs);
-}
+static struct video_mode vmode;
+static void *fbptr, *backbuf;
+static int fbsize;
 
-void logohack(void);
 
 void pcboot_main(void)
 {
        init_segm();
        init_intr();
-       kb_init();
+
        con_init();
+       kb_init();
+       init_psaux();
+
+       init_mem();
 
        /* initialize the timer */
        init_timer();
 
+       audio_init();
+
        enable_intr();
 
        printf("PCBoot kernel initialized\n");
 
+       if(video_init() == -1) {
+               panic("Failed to find suitable video mode");
+       }
+       fbsize = vmode.width * vmode.height * vmode.bpp / 8;
+       if(!(backbuf = malloc(fbsize))) {
+               panic("Failed to allocate back buffer");
+       }
+       init_census(backbuf, vmode.width, vmode.height);
+
        for(;;) {
-               int c;
+               draw_census();
 
-               halt_cpu();
-               while((c = kb_getkey()) >= 0) {
-                       if(c >= KB_F1 && c <= KB_F12) {
-                               set_mode13h();
-                               logohack();
-                       }
-                       if(isprint(c)) {
-                               printf("key: %d '%c'       \n", c, (char)c);
-                       } else {
-                               printf("key: %d            \n", c);
+               wait_vsync();
+               memcpy(fbptr, backbuf, fbsize);
+       }
+}
+
+static int video_init(void)
+{
+       struct vbe_edid edid;
+       struct video_mode vinf, *vmodes;
+       int i, xres, yres, nmodes, mode_idx = -1;
+       const char *vendor;
+
+       if(mode_idx == -1 && (vendor = get_video_vendor()) && strstr(vendor, "SeaBIOS")) {
+               mode_idx = find_video_mode_idx(800, 600, 32);
+       }
+
+       if(mode_idx == -1 && vbe_get_edid(&edid) == 0 && edid_preferred_resolution(&edid, &xres, &yres) == 0) {
+               printf("EDID: preferred resolution: %dx%d\n", xres, yres);
+               mode_idx = find_video_mode_idx(xres, yres, 0);
+       }
+
+       nmodes = video_mode_count();
+       if(!(vmodes = malloc(nmodes * sizeof *vmodes))) {
+               printf("failed to allocate video modes array (%d modes)\n", nmodes);
+               return -1;
+       }
+
+       for(i=0; i<nmodes; i++) {
+               video_mode_info(i, &vinf);
+               vmodes[i] = vinf;
+       }
+
+       if(mode_idx >= 0) {
+               if(!(fbptr = set_video_mode(vmodes[mode_idx].mode))) {
+                       printf("failed to set video mode: %x (%dx%d %dbpp)\n", mode_idx,
+                                       vmodes[mode_idx].width, vmodes[mode_idx].height, vmodes[mode_idx].bpp);
+                       mode_idx = -1;
+               } else {
+                       vmode = vmodes[mode_idx];
+                       printf("video mode: %x (%dx%d %dbpp)\n", vmode.mode, vmode.width,
+                                       vmode.height, vmode.bpp);
+               }
+       }
+
+       if(mode_idx == -1) {
+               qsort(vmodes, nmodes, sizeof *vmodes, modecmp);
+
+               for(i=0; i<nmodes; i++) {
+                       printf("trying video mode: %x (%dx%d %dbpp)\n", vmodes[i].mode, vmodes[i].width,
+                                       vmodes[i].height, vmodes[i].bpp);
+                       usleep(5000000);
+                       if((fbptr = set_video_mode(vmodes[i].mode))) {
+                               vmode = vmodes[i];
+                               break;
                        }
                }
-               if((nticks % 250) == 0) {
-                       printf("ticks: %ld\r", nticks);
+               if(i >= nmodes) {
+                       printf("failed to find a suitable video mode\n");
+                       return -1;
                }
        }
+       free(vmodes);
+
+       return 0;
+}
+
+
+
+static int modecmp(const void *a, const void *b)
+{
+       const struct video_mode *ma = a;
+       const struct video_mode *mb = b;
+       unsigned long aval = ma->width | (ma->height << 16);
+       unsigned long bval = mb->width | (mb->height << 16);
+
+       if(aval != bval) {
+               return bval - aval;
+       }
+       return mb->bpp - ma->bpp;
 }