Index: arch/i386/stand/libsa/apmprobe.c =================================================================== RCS file: /home/mdw/cvs.sys/sys/arch/i386/stand/libsa/apmprobe.c,v retrieving revision 1.1.1.3 retrieving revision 1.3 diff -u -r1.1.1.3 -r1.3 --- arch/i386/stand/libsa/apmprobe.c 30 Jun 2002 22:31:15 -0000 1.1.1.3 +++ arch/i386/stand/libsa/apmprobe.c 27 Jul 2002 00:35:32 -0000 1.3 @@ -68,6 +68,8 @@ extern int debug; +static int apm_is_connected; + static __inline u_int apm_check() { @@ -101,6 +103,7 @@ : "=a" (rv) : "0" (APM_DISCONNECT), "b" (APM_DEV_APM_BIOS) : "%ecx", "%edx", "cc"); + if (!(rv & 0xff)) apm_is_connected = 0; return (rv & 0xff)? rv >> 8 : 0; } @@ -145,6 +148,7 @@ ai->apm_code16_base, ai->apm_code16_len, ai->apm_data_base, ai->apm_data_len); #endif + apm_is_connected = 2; /* inform apm bios about our driver version */ __asm __volatile (DOINT(0x15) "\n\t" "setc %b1\n\t" @@ -158,8 +162,61 @@ return 0; } +static __inline int +apm_driver_version(v) +{ + register u_int16_t rv; + __asm __volatile(DOINT(0x15) "\n\t" + "setc %b0" + : "=a" (rv) + : "0" (APM_DRIVER_VERSION), "b" (APM_DEV_APM_BIOS), "c" (v) + : "%edx", "cc"); + return (rv & 0xff)? rv >> 8 : 0; +} + +static __inline int +apm_connect_real(ai) + bios_apminfo_t *ai; +{ + register u_int16_t f; + __asm __volatile (DOINT(0x15) "\n\t" + "setc %b1\n\t" + "movb %%ah, %h1\n\t" + "movzwl %%ax, %%eax\n\tshll $4, %0\n\t" + "movzwl %%cx, %%ecx\n\tshll $4, %2\n\t" + "movzwl %%dx, %%edx\n\tshll $4, %3\n\t" + : "=a" (ai->apm_code32_base), + "=b" (f), + "=c" (ai->apm_code16_base), + "=d" (ai->apm_data_base) + : "0" (APM_REAL_CONNECT), "1" (APM_DEV_APM_BIOS) + : "cc"); + ai->apm_entry = BIOS_regs.biosr_bx; +#if 0 + ai->apm_code_len = BIOS_regs.biosr_si & 0xffff; + ai->apm_data_len = BIOS_regs.biosr_di & 0xffff; +#else + ai->apm_code_len = 0x10000; + ai->apm_data_len = 0x10000; +#endif + if (!(f & 0xff)) apm_is_connected = 1; + return (f & 0xff)? f >> 8 : 0; +} + static bios_apminfo_t ai; +static __inline int +apm_set_power_state(devices, how) +{ + register u_int16_t rv; + __asm __volatile(DOINT(0x15) "\n\t" + "setc %b0" + : "=a" (rv) + : "0" (APM_SET_PWR_STATE), "b" (devices), "c" (how) + : "%edx", "cc"); + return (rv & 0xff)? rv >> 8 : 0; +} + void apmprobe() { @@ -196,3 +253,49 @@ i386_round_page(ai.apm_data_base + ai.apm_data_len)); } +void +apmturnoff(a1,a2) + int a1, a2; +{ + bios_apminfo_t ai; + int f; + + if (a1 == -1) a1 = APM_DEV_ALLDEVS; + if (a2 == -1) a2 = APM_SYS_OFF; + if ((ai.apm_detail = apm_check())) { + + apm_disconnect(); + if (apm_connect_real(&ai) != 0) + printf("apmturnoff: connect error\n"); + else { + f = apm_driver_version(0x0102); + if (f) + { + f = apm_driver_version(0x0101); + if (f) + printf ("apmturnoff: driver_version returned %x\n", f); + else printf ("apmturnoff: 1.1 connection\n"); + } + + f = apm_set_power_state(a1, a2); + printf ("apmturnoff: apm_set_power_state returned %x\n", + f); + printf ("apmturnoff: detail=%x\n", + ai.apm_detail); + } + } else + printf ("apmturnoff: apm_check returned 0\n"); +} + +/* + * if we are booting into dos, we should not + * leave apm connected in "real mode". Try to + * leave apm in the "reset" state. + */ + +void +apm_reset() +{ + if (apm_is_connected) + apm_disconnect(); +} Index: arch/i386/stand/libsa/cmd_i386.c =================================================================== RCS file: /home/mdw/cvs.sys/sys/arch/i386/stand/libsa/cmd_i386.c,v retrieving revision 1.1.1.2 retrieving revision 1.3 diff -u -r1.1.1.2 -r1.3 --- arch/i386/stand/libsa/cmd_i386.c 24 Apr 2002 12:38:01 -0000 1.1.1.2 +++ arch/i386/stand/libsa/cmd_i386.c 27 Jul 2002 00:35:58 -0000 1.3 @@ -50,6 +50,7 @@ int Xdiskinfo(void); int Xmemory(void); int Xregs(void); +int Xturnoff (void); /* From gidt.S */ int bootbuf(void *, int); @@ -61,6 +62,7 @@ #ifdef DEBUG { "regs", CMDT_CMD, Xregs }, #endif + { "off", CMDT_CMD, Xturnoff }, { NULL, 0 } }; @@ -83,6 +85,27 @@ #endif int +Xturnoff() +{ + int a1, a2; + a1 = a2 = -1; + switch(cmd.argc) + { + case 0: + printf("machine off [dev [how] ]\n"); + return 0; + case 1: + break; + case 3: + a2 = strtol(cmd.argv[2], NULL, 0); + case 2: + a1 = strtol(cmd.argv[1], NULL, 0); + } + apmturnoff(a1, a2); + return 0; +} + +int Xboot() { #ifndef _TEST @@ -112,7 +135,7 @@ dev += (cmd.argv[1][2] - '0'); part = (cmd.argv[1][3] - 'a'); - if (part > 0) + if (part >= 0) printf("[%x,%d]\n", dev, part); else printf("[%x]\n", dev); @@ -122,7 +145,7 @@ if(st) goto bad; /* Frob boot flag in buffer from HD */ - if((dev & 0x80) && (part > 0)){ + if((dev & 0x80) && (part >= 0)){ int i, j; for(i = 0, j = DOSPARTOFF; i < 4; i++, j += 16) @@ -131,6 +154,7 @@ else buf[j] &= ~0x80; } + apm_reset(); /* Load %dl, ljmp */ bcopy(buf, dest, DEV_BSIZE); Index: arch/i386/stand/libsa/diskprobe.c =================================================================== RCS file: /home/mdw/cvs.sys/sys/arch/i386/stand/libsa/diskprobe.c,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- arch/i386/stand/libsa/diskprobe.c 24 Apr 2002 12:38:02 -0000 1.1.1.2 +++ arch/i386/stand/libsa/diskprobe.c 6 Jul 2002 22:43:18 -0000 1.2 @@ -84,10 +84,17 @@ /* Fill out best we can - (fd?) */ dip->bios_info.bsd_dev = MAKEBOOTDEV(2, 0, 0, i, RAW_PART); +#if 0 if((bios_getdisklabel(&dip->bios_info, &dip->disklabel)) != 0) dip->bios_info.flags |= BDI_BADLABEL; else dip->bios_info.flags |= BDI_GOODLABEL; +#else + /* don't try to read the (missing) floppy drive on my laptop; + * I might have the cd-rom drive inserted instead. -mdw + */ + dip->bios_info.flags |= BDI_BADLABEL; +#endif /* Add to queue of disks */ TAILQ_INSERT_TAIL(&disklist, dip, list); Index: arch/i386/stand/libsa/libsa.h =================================================================== RCS file: /home/mdw/cvs.sys/sys/arch/i386/stand/libsa/libsa.h,v retrieving revision 1.1.1.3 retrieving revision 1.2 diff -u -r1.1.1.3 -r1.2 --- arch/i386/stand/libsa/libsa.h 30 Jun 2002 22:31:15 -0000 1.1.1.3 +++ arch/i386/stand/libsa/libsa.h 6 Jul 2002 22:43:18 -0000 1.2 @@ -57,6 +57,12 @@ void *getSYSCONFaddr(void); void *getEBDAaddr(void); +void apmturnoff (int, int); +void apm_reset (void); + +void devboot (dev_t, char *); +void machdep (void); + extern const char bdevs[][4]; extern const int nbdevs; extern u_int cnvmem, extmem; /* XXX global pass memprobe()->machdep_start() */ Index: stand/boot/cmd.c =================================================================== RCS file: /home/mdw/cvs.sys/sys/stand/boot/cmd.c,v retrieving revision 1.1.1.3 retrieving revision 1.4 diff -u -r1.1.1.3 -r1.4 --- stand/boot/cmd.c 26 Jul 2002 20:53:52 -0000 1.1.1.3 +++ stand/boot/cmd.c 11 Aug 2002 05:29:58 -0000 1.4 @@ -86,8 +86,19 @@ { cmd.cmd = NULL; - if (!readline(cmd_buf, sizeof(cmd_buf), cmd.timeout)) + switch (readline(cmd_buf, sizeof(cmd_buf), cmd.timeout)) + { + default: + cmd.timeout = 0; + break; + case 0: + cmd.timeout = 0; cmd.cmd = cmd_table; + break; + case -1: + strncpy(cmd_buf, "boot", 5); + break; + } return docmd(); } @@ -238,11 +249,16 @@ if (!(i++ % 1000) && (getsecs() >= tt)) break; +#if 0 if (!cnischar()) { strncpy(buf, "boot", 5); putchar('\n'); return strlen(buf); } +#else + if (!cnischar()) + return -1; +#endif } else while (!cnischar()) ;