158a2b000SEvgeniy Ivanov /* $NetBSD: pcio.c,v 1.30 2011/06/08 16:04:40 joerg Exp $ */ 258a2b000SEvgeniy Ivanov 358a2b000SEvgeniy Ivanov /* 458a2b000SEvgeniy Ivanov * Copyright (c) 1996, 1997 558a2b000SEvgeniy Ivanov * Matthias Drochner. All rights reserved. 658a2b000SEvgeniy Ivanov * 758a2b000SEvgeniy Ivanov * Redistribution and use in source and binary forms, with or without 858a2b000SEvgeniy Ivanov * modification, are permitted provided that the following conditions 958a2b000SEvgeniy Ivanov * are met: 1058a2b000SEvgeniy Ivanov * 1. Redistributions of source code must retain the above copyright 1158a2b000SEvgeniy Ivanov * notice, this list of conditions and the following disclaimer. 1258a2b000SEvgeniy Ivanov * 2. Redistributions in binary form must reproduce the above copyright 1358a2b000SEvgeniy Ivanov * notice, this list of conditions and the following disclaimer in the 1458a2b000SEvgeniy Ivanov * documentation and/or other materials provided with the distribution. 1558a2b000SEvgeniy Ivanov * 1658a2b000SEvgeniy Ivanov * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1758a2b000SEvgeniy Ivanov * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1858a2b000SEvgeniy Ivanov * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1958a2b000SEvgeniy Ivanov * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2058a2b000SEvgeniy Ivanov * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2158a2b000SEvgeniy Ivanov * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2258a2b000SEvgeniy Ivanov * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2358a2b000SEvgeniy Ivanov * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2458a2b000SEvgeniy Ivanov * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2558a2b000SEvgeniy Ivanov * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2658a2b000SEvgeniy Ivanov * 2758a2b000SEvgeniy Ivanov */ 2858a2b000SEvgeniy Ivanov 2958a2b000SEvgeniy Ivanov /* 3058a2b000SEvgeniy Ivanov * console I/O 3158a2b000SEvgeniy Ivanov * needs lowlevel routines from conio.S and comio.S 3258a2b000SEvgeniy Ivanov */ 3358a2b000SEvgeniy Ivanov 3458a2b000SEvgeniy Ivanov #include <lib/libsa/stand.h> 3558a2b000SEvgeniy Ivanov #include <lib/libkern/libkern.h> 3658a2b000SEvgeniy Ivanov #include <sys/bootblock.h> 3758a2b000SEvgeniy Ivanov 3858a2b000SEvgeniy Ivanov #include "libi386.h" 3958a2b000SEvgeniy Ivanov #include "bootinfo.h" 4058a2b000SEvgeniy Ivanov 4158a2b000SEvgeniy Ivanov extern struct x86_boot_params boot_params; 4258a2b000SEvgeniy Ivanov 4358a2b000SEvgeniy Ivanov struct btinfo_console btinfo_console; 4458a2b000SEvgeniy Ivanov 4558a2b000SEvgeniy Ivanov #ifdef SUPPORT_SERIAL 4658a2b000SEvgeniy Ivanov static int iodev; 4758a2b000SEvgeniy Ivanov 4858a2b000SEvgeniy Ivanov #ifdef DIRECT_SERIAL 4958a2b000SEvgeniy Ivanov #include "comio_direct.h" 5058a2b000SEvgeniy Ivanov 5158a2b000SEvgeniy Ivanov #define cominit_x() btinfo_console.speed = \ 5258a2b000SEvgeniy Ivanov cominit_d(btinfo_console.addr, btinfo_console.speed) 5358a2b000SEvgeniy Ivanov #define computc_x(ch) computc_d(ch, btinfo_console.addr) 5458a2b000SEvgeniy Ivanov #define comgetc_x() comgetc_d(btinfo_console.addr) 5558a2b000SEvgeniy Ivanov #define comstatus_x() comstatus_d(btinfo_console.addr) 5658a2b000SEvgeniy Ivanov 5758a2b000SEvgeniy Ivanov #else 5858a2b000SEvgeniy Ivanov #define cominit_x() cominit(iodev - CONSDEV_COM0) 5958a2b000SEvgeniy Ivanov #define computc_x(ch) computc(ch, iodev - CONSDEV_COM0) 6058a2b000SEvgeniy Ivanov #define comgetc_x() comgetc(iodev - CONSDEV_COM0) 6158a2b000SEvgeniy Ivanov #define comstatus_x() comstatus(iodev - CONSDEV_COM0) 6258a2b000SEvgeniy Ivanov 6358a2b000SEvgeniy Ivanov #endif /* DIRECT_SERIAL */ 6458a2b000SEvgeniy Ivanov 6558a2b000SEvgeniy Ivanov static int getcomaddr(int); 6658a2b000SEvgeniy Ivanov #endif /* SUPPORT_SERIAL */ 6758a2b000SEvgeniy Ivanov 6858a2b000SEvgeniy Ivanov #define POLL_FREQ 10 6958a2b000SEvgeniy Ivanov 7058a2b000SEvgeniy Ivanov static void 7158a2b000SEvgeniy Ivanov wait(int us) 7258a2b000SEvgeniy Ivanov { 7358a2b000SEvgeniy Ivanov int prev = biosgetsystime(); 7458a2b000SEvgeniy Ivanov int tgt = prev + (20 * us) / 1000000; 7558a2b000SEvgeniy Ivanov int new; 7658a2b000SEvgeniy Ivanov 7758a2b000SEvgeniy Ivanov while ((new = biosgetsystime()) < tgt) { 7858a2b000SEvgeniy Ivanov if (new < prev) /* XXX timer wrapped */ 7958a2b000SEvgeniy Ivanov break; 8058a2b000SEvgeniy Ivanov prev = new; 8158a2b000SEvgeniy Ivanov } 8258a2b000SEvgeniy Ivanov } 8358a2b000SEvgeniy Ivanov 8458a2b000SEvgeniy Ivanov #ifdef SUPPORT_SERIAL 8558a2b000SEvgeniy Ivanov static int 8658a2b000SEvgeniy Ivanov getcomaddr(int idx) 8758a2b000SEvgeniy Ivanov { 8858a2b000SEvgeniy Ivanov short addr; 8958a2b000SEvgeniy Ivanov #ifdef CONSADDR 9058a2b000SEvgeniy Ivanov if (CONSADDR != 0) 9158a2b000SEvgeniy Ivanov return CONSADDR; 9258a2b000SEvgeniy Ivanov #endif 9358a2b000SEvgeniy Ivanov /* read in BIOS data area */ 9458a2b000SEvgeniy Ivanov pvbcopy((void *)(0x400 + 2 * idx), &addr, 2); 9558a2b000SEvgeniy Ivanov return addr; 9658a2b000SEvgeniy Ivanov } 9758a2b000SEvgeniy Ivanov #endif 9858a2b000SEvgeniy Ivanov 9958a2b000SEvgeniy Ivanov void 10058a2b000SEvgeniy Ivanov clear_pc_screen(void) 10158a2b000SEvgeniy Ivanov { 10258a2b000SEvgeniy Ivanov #ifdef SUPPORT_SERIAL 10358a2b000SEvgeniy Ivanov /* Clear the screen if we are on a glass tty. */ 10458a2b000SEvgeniy Ivanov if (iodev == CONSDEV_PC) 10558a2b000SEvgeniy Ivanov conclr(); 10658a2b000SEvgeniy Ivanov #endif 10758a2b000SEvgeniy Ivanov } 10858a2b000SEvgeniy Ivanov 10958a2b000SEvgeniy Ivanov void 11058a2b000SEvgeniy Ivanov initio(int dev) 11158a2b000SEvgeniy Ivanov { 11258a2b000SEvgeniy Ivanov #ifdef SUPPORT_SERIAL 11358a2b000SEvgeniy Ivanov int i; 11458a2b000SEvgeniy Ivanov 11558a2b000SEvgeniy Ivanov #if defined(DIRECT_SERIAL) && defined(CONSPEED) 11658a2b000SEvgeniy Ivanov btinfo_console.speed = CONSPEED; 11758a2b000SEvgeniy Ivanov #else 11858a2b000SEvgeniy Ivanov btinfo_console.speed = 9600; 11958a2b000SEvgeniy Ivanov #endif 12058a2b000SEvgeniy Ivanov 12158a2b000SEvgeniy Ivanov switch (dev) { 12258a2b000SEvgeniy Ivanov case CONSDEV_AUTO: 12358a2b000SEvgeniy Ivanov for (i = 0; i < 3; i++) { 12458a2b000SEvgeniy Ivanov iodev = CONSDEV_COM0 + i; 12558a2b000SEvgeniy Ivanov btinfo_console.addr = getcomaddr(i); 12658a2b000SEvgeniy Ivanov if (!btinfo_console.addr) 12758a2b000SEvgeniy Ivanov break; 12858a2b000SEvgeniy Ivanov conputc('0' + i); /* to tell user what happens */ 12958a2b000SEvgeniy Ivanov cominit_x(); 13058a2b000SEvgeniy Ivanov #ifdef DIRECT_SERIAL 13158a2b000SEvgeniy Ivanov /* check for: 13258a2b000SEvgeniy Ivanov * 1. successful output 13358a2b000SEvgeniy Ivanov * 2. optionally, keypress within 7s 13458a2b000SEvgeniy Ivanov */ 13558a2b000SEvgeniy Ivanov if ( computc_x(':') && 13658a2b000SEvgeniy Ivanov computc_x('-') && 13758a2b000SEvgeniy Ivanov computc_x('(') 13858a2b000SEvgeniy Ivanov #ifdef COMCONS_KEYPRESS 13958a2b000SEvgeniy Ivanov && awaitkey(7, 0) 14058a2b000SEvgeniy Ivanov #endif 14158a2b000SEvgeniy Ivanov ) 14258a2b000SEvgeniy Ivanov goto ok; 14358a2b000SEvgeniy Ivanov #else /* ! DIRECT_SERIAL */ 14458a2b000SEvgeniy Ivanov /* 14558a2b000SEvgeniy Ivanov * serial console must have hardware handshake! 14658a2b000SEvgeniy Ivanov * check: 14758a2b000SEvgeniy Ivanov * 1. character output without error 14858a2b000SEvgeniy Ivanov * 2. status bits for modem ready set 14958a2b000SEvgeniy Ivanov * (status seems only useful after character output) 15058a2b000SEvgeniy Ivanov * 3. optionally, keypress within 7s 15158a2b000SEvgeniy Ivanov */ 15258a2b000SEvgeniy Ivanov if (!(computc_x('@') & 0x80) 15358a2b000SEvgeniy Ivanov && (comstatus_x() & 0x00b0) 15458a2b000SEvgeniy Ivanov #ifdef COMCONS_KEYPRESS 15558a2b000SEvgeniy Ivanov && awaitkey(7, 0) 15658a2b000SEvgeniy Ivanov #endif 15758a2b000SEvgeniy Ivanov ) 15858a2b000SEvgeniy Ivanov goto ok; 15958a2b000SEvgeniy Ivanov #endif /* DIRECT_SERIAL */ 16058a2b000SEvgeniy Ivanov } 16158a2b000SEvgeniy Ivanov iodev = CONSDEV_PC; 16258a2b000SEvgeniy Ivanov ok: 16358a2b000SEvgeniy Ivanov break; 16458a2b000SEvgeniy Ivanov case CONSDEV_COM0: 16558a2b000SEvgeniy Ivanov case CONSDEV_COM1: 16658a2b000SEvgeniy Ivanov case CONSDEV_COM2: 16758a2b000SEvgeniy Ivanov case CONSDEV_COM3: 16858a2b000SEvgeniy Ivanov iodev = dev; 16958a2b000SEvgeniy Ivanov btinfo_console.addr = getcomaddr(iodev - CONSDEV_COM0); 17058a2b000SEvgeniy Ivanov if (!btinfo_console.addr) 17158a2b000SEvgeniy Ivanov goto nocom; 17258a2b000SEvgeniy Ivanov cominit_x(); 17358a2b000SEvgeniy Ivanov break; 17458a2b000SEvgeniy Ivanov case CONSDEV_COM0KBD: 17558a2b000SEvgeniy Ivanov case CONSDEV_COM1KBD: 17658a2b000SEvgeniy Ivanov case CONSDEV_COM2KBD: 17758a2b000SEvgeniy Ivanov case CONSDEV_COM3KBD: 17858a2b000SEvgeniy Ivanov iodev = dev - CONSDEV_COM0KBD + CONSDEV_COM0; 17958a2b000SEvgeniy Ivanov i = iodev - CONSDEV_COM0; 18058a2b000SEvgeniy Ivanov btinfo_console.addr = getcomaddr(i); 18158a2b000SEvgeniy Ivanov if (!btinfo_console.addr) 18258a2b000SEvgeniy Ivanov goto nocom; 18358a2b000SEvgeniy Ivanov conputc('0' + i); /* to tell user what happens */ 18458a2b000SEvgeniy Ivanov cominit_x(); 18558a2b000SEvgeniy Ivanov #ifdef DIRECT_SERIAL 18658a2b000SEvgeniy Ivanov /* check for: 18758a2b000SEvgeniy Ivanov * 1. successful output 18858a2b000SEvgeniy Ivanov * 2. optionally, keypress within 7s 18958a2b000SEvgeniy Ivanov */ 19058a2b000SEvgeniy Ivanov if ( computc_x(':') && 19158a2b000SEvgeniy Ivanov computc_x('-') && 19258a2b000SEvgeniy Ivanov computc_x('(') 19358a2b000SEvgeniy Ivanov #ifdef COMCONS_KEYPRESS 19458a2b000SEvgeniy Ivanov && awaitkey(7, 0) 19558a2b000SEvgeniy Ivanov #endif 19658a2b000SEvgeniy Ivanov ) 19758a2b000SEvgeniy Ivanov break; 19858a2b000SEvgeniy Ivanov #else /* ! DIRECT_SERIAL */ 19958a2b000SEvgeniy Ivanov /* 20058a2b000SEvgeniy Ivanov * serial console must have hardware handshake! 20158a2b000SEvgeniy Ivanov * check: 20258a2b000SEvgeniy Ivanov * 1. character output without error 20358a2b000SEvgeniy Ivanov * 2. status bits for modem ready set 20458a2b000SEvgeniy Ivanov * (status seems only useful after character output) 20558a2b000SEvgeniy Ivanov * 3. optionally, keypress within 7s 20658a2b000SEvgeniy Ivanov */ 20758a2b000SEvgeniy Ivanov if (!(computc_x('@') & 0x80) 20858a2b000SEvgeniy Ivanov && (comstatus_x() & 0x00b0) 20958a2b000SEvgeniy Ivanov #ifdef COMCONS_KEYPRESS 21058a2b000SEvgeniy Ivanov && awaitkey(7, 0) 21158a2b000SEvgeniy Ivanov #endif 21258a2b000SEvgeniy Ivanov ) 21358a2b000SEvgeniy Ivanov break; 21458a2b000SEvgeniy Ivanov #endif /* DIRECT_SERIAL */ 21558a2b000SEvgeniy Ivanov default: 21658a2b000SEvgeniy Ivanov nocom: 21758a2b000SEvgeniy Ivanov iodev = CONSDEV_PC; 21858a2b000SEvgeniy Ivanov break; 21958a2b000SEvgeniy Ivanov } 22058a2b000SEvgeniy Ivanov conputc('\015'); 22158a2b000SEvgeniy Ivanov conputc('\n'); 22258a2b000SEvgeniy Ivanov strncpy(btinfo_console.devname, iodev == CONSDEV_PC ? "pc" : "com", 16); 22358a2b000SEvgeniy Ivanov 22458a2b000SEvgeniy Ivanov #else /* !SUPPORT_SERIAL */ 22558a2b000SEvgeniy Ivanov btinfo_console.devname[0] = 'p'; 22658a2b000SEvgeniy Ivanov btinfo_console.devname[1] = 'c'; 22758a2b000SEvgeniy Ivanov btinfo_console.devname[2] = 0; 22858a2b000SEvgeniy Ivanov #endif /* SUPPORT_SERIAL */ 22958a2b000SEvgeniy Ivanov } 23058a2b000SEvgeniy Ivanov 23158a2b000SEvgeniy Ivanov static inline void internal_putchar(int); 23258a2b000SEvgeniy Ivanov 23358a2b000SEvgeniy Ivanov static inline void 23458a2b000SEvgeniy Ivanov internal_putchar(int c) 23558a2b000SEvgeniy Ivanov { 23658a2b000SEvgeniy Ivanov #ifdef SUPPORT_SERIAL 23758a2b000SEvgeniy Ivanov switch (iodev) { 23858a2b000SEvgeniy Ivanov case CONSDEV_PC: 23958a2b000SEvgeniy Ivanov #endif 24058a2b000SEvgeniy Ivanov conputc(c); 24158a2b000SEvgeniy Ivanov #ifdef SUPPORT_SERIAL 24258a2b000SEvgeniy Ivanov break; 24358a2b000SEvgeniy Ivanov case CONSDEV_COM0: 24458a2b000SEvgeniy Ivanov case CONSDEV_COM1: 24558a2b000SEvgeniy Ivanov case CONSDEV_COM2: 24658a2b000SEvgeniy Ivanov case CONSDEV_COM3: 24758a2b000SEvgeniy Ivanov computc_x(c); 24858a2b000SEvgeniy Ivanov break; 24958a2b000SEvgeniy Ivanov } 25058a2b000SEvgeniy Ivanov #endif 25158a2b000SEvgeniy Ivanov } 25258a2b000SEvgeniy Ivanov 25358a2b000SEvgeniy Ivanov void 25458a2b000SEvgeniy Ivanov putchar(int c) 25558a2b000SEvgeniy Ivanov { 25658a2b000SEvgeniy Ivanov if (c == '\n') 25758a2b000SEvgeniy Ivanov internal_putchar('\r'); 25858a2b000SEvgeniy Ivanov internal_putchar(c); 25958a2b000SEvgeniy Ivanov } 26058a2b000SEvgeniy Ivanov 26158a2b000SEvgeniy Ivanov int 262*9733fcdbSDavid van Moolenbroek getchar_ex(void) 26358a2b000SEvgeniy Ivanov { 26458a2b000SEvgeniy Ivanov int c; 26558a2b000SEvgeniy Ivanov #ifdef SUPPORT_SERIAL 26658a2b000SEvgeniy Ivanov switch (iodev) { 26758a2b000SEvgeniy Ivanov default: /* to make gcc -Wall happy... */ 26858a2b000SEvgeniy Ivanov case CONSDEV_PC: 26958a2b000SEvgeniy Ivanov #endif 27058a2b000SEvgeniy Ivanov while (!coniskey()) 27158a2b000SEvgeniy Ivanov ; 27258a2b000SEvgeniy Ivanov c = congetc(); 27358a2b000SEvgeniy Ivanov #ifdef CONSOLE_KEYMAP 27458a2b000SEvgeniy Ivanov { 275*9733fcdbSDavid van Moolenbroek char *cp = strchr(CONSOLE_KEYMAP, c & 0xff); 27658a2b000SEvgeniy Ivanov if (cp != 0 && cp[1] != 0) 277*9733fcdbSDavid van Moolenbroek c = cp[1] | (c & 0xff00); 27858a2b000SEvgeniy Ivanov } 27958a2b000SEvgeniy Ivanov #endif 28058a2b000SEvgeniy Ivanov return c; 28158a2b000SEvgeniy Ivanov #ifdef SUPPORT_SERIAL 28258a2b000SEvgeniy Ivanov case CONSDEV_COM0: 28358a2b000SEvgeniy Ivanov case CONSDEV_COM1: 28458a2b000SEvgeniy Ivanov case CONSDEV_COM2: 28558a2b000SEvgeniy Ivanov case CONSDEV_COM3: 28658a2b000SEvgeniy Ivanov #ifdef DIRECT_SERIAL 28758a2b000SEvgeniy Ivanov c = comgetc_x(); 28858a2b000SEvgeniy Ivanov #else 28958a2b000SEvgeniy Ivanov do { 29058a2b000SEvgeniy Ivanov c = comgetc_x(); 29158a2b000SEvgeniy Ivanov } while ((c >> 8) == 0xe0); /* catch timeout */ 29258a2b000SEvgeniy Ivanov #ifdef COMDEBUG 29358a2b000SEvgeniy Ivanov if (c & 0x8000) { 29458a2b000SEvgeniy Ivanov printf("com input %x, status %x\n", 29558a2b000SEvgeniy Ivanov c, comstatus_x()); 29658a2b000SEvgeniy Ivanov } 29758a2b000SEvgeniy Ivanov #endif 29858a2b000SEvgeniy Ivanov c &= 0xff; 29958a2b000SEvgeniy Ivanov #endif /* DIRECT_SERIAL */ 30058a2b000SEvgeniy Ivanov return c; 30158a2b000SEvgeniy Ivanov } 30258a2b000SEvgeniy Ivanov #endif /* SUPPORT_SERIAL */ 30358a2b000SEvgeniy Ivanov } 30458a2b000SEvgeniy Ivanov 30558a2b000SEvgeniy Ivanov int 306*9733fcdbSDavid van Moolenbroek getchar(void) 307*9733fcdbSDavid van Moolenbroek { 308*9733fcdbSDavid van Moolenbroek return getchar_ex() & 0xff; 309*9733fcdbSDavid van Moolenbroek } 310*9733fcdbSDavid van Moolenbroek 311*9733fcdbSDavid van Moolenbroek int 31258a2b000SEvgeniy Ivanov iskey(int intr) 31358a2b000SEvgeniy Ivanov { 31458a2b000SEvgeniy Ivanov #ifdef SUPPORT_SERIAL 31558a2b000SEvgeniy Ivanov switch (iodev) { 31658a2b000SEvgeniy Ivanov default: /* to make gcc -Wall happy... */ 31758a2b000SEvgeniy Ivanov case CONSDEV_PC: 31858a2b000SEvgeniy Ivanov #endif 31958a2b000SEvgeniy Ivanov return (intr && conisshift()) || coniskey(); 32058a2b000SEvgeniy Ivanov #ifdef SUPPORT_SERIAL 32158a2b000SEvgeniy Ivanov case CONSDEV_COM0: 32258a2b000SEvgeniy Ivanov case CONSDEV_COM1: 32358a2b000SEvgeniy Ivanov case CONSDEV_COM2: 32458a2b000SEvgeniy Ivanov case CONSDEV_COM3: 32558a2b000SEvgeniy Ivanov #ifdef DIRECT_SERIAL 32658a2b000SEvgeniy Ivanov return !!comstatus_x(); 32758a2b000SEvgeniy Ivanov #else 32858a2b000SEvgeniy Ivanov return !!(comstatus_x() & 0x0100); 32958a2b000SEvgeniy Ivanov #endif 33058a2b000SEvgeniy Ivanov } 33158a2b000SEvgeniy Ivanov #endif /* SUPPORT_SERIAL */ 33258a2b000SEvgeniy Ivanov } 33358a2b000SEvgeniy Ivanov 33458a2b000SEvgeniy Ivanov char 33558a2b000SEvgeniy Ivanov awaitkey(int timeout, int tell) 33658a2b000SEvgeniy Ivanov { 33758a2b000SEvgeniy Ivanov int i; 33858a2b000SEvgeniy Ivanov char c = 0; 33958a2b000SEvgeniy Ivanov 34058a2b000SEvgeniy Ivanov i = timeout * POLL_FREQ; 34158a2b000SEvgeniy Ivanov 34258a2b000SEvgeniy Ivanov for (;;) { 34358a2b000SEvgeniy Ivanov if (tell && (i % POLL_FREQ) == 0) { 34458a2b000SEvgeniy Ivanov char numbuf[32]; 34558a2b000SEvgeniy Ivanov int len; 34658a2b000SEvgeniy Ivanov 34758a2b000SEvgeniy Ivanov len = snprintf(numbuf, sizeof(numbuf), "%d seconds. ", 34858a2b000SEvgeniy Ivanov i/POLL_FREQ); 34958a2b000SEvgeniy Ivanov if (len > 0 && len < sizeof(numbuf)) { 35058a2b000SEvgeniy Ivanov char *p = numbuf; 35158a2b000SEvgeniy Ivanov 35258a2b000SEvgeniy Ivanov printf("%s", numbuf); 35358a2b000SEvgeniy Ivanov while (*p) 35458a2b000SEvgeniy Ivanov *p++ = '\b'; 35558a2b000SEvgeniy Ivanov printf("%s", numbuf); 35658a2b000SEvgeniy Ivanov } 35758a2b000SEvgeniy Ivanov } 35858a2b000SEvgeniy Ivanov if (iskey(1)) { 35958a2b000SEvgeniy Ivanov /* flush input buffer */ 36058a2b000SEvgeniy Ivanov while (iskey(0)) 36158a2b000SEvgeniy Ivanov c = getchar(); 36258a2b000SEvgeniy Ivanov if (c == 0) 36358a2b000SEvgeniy Ivanov c = -1; 36458a2b000SEvgeniy Ivanov goto out; 36558a2b000SEvgeniy Ivanov } 36658a2b000SEvgeniy Ivanov if (i--) 36758a2b000SEvgeniy Ivanov wait(1000000 / POLL_FREQ); 36858a2b000SEvgeniy Ivanov else 36958a2b000SEvgeniy Ivanov break; 37058a2b000SEvgeniy Ivanov } 37158a2b000SEvgeniy Ivanov 37258a2b000SEvgeniy Ivanov out: 37358a2b000SEvgeniy Ivanov if (tell) 37458a2b000SEvgeniy Ivanov printf("0 seconds. \n"); 37558a2b000SEvgeniy Ivanov 37658a2b000SEvgeniy Ivanov return c; 37758a2b000SEvgeniy Ivanov } 37858a2b000SEvgeniy Ivanov 37958a2b000SEvgeniy Ivanov void 38058a2b000SEvgeniy Ivanov wait_sec(int sec) 38158a2b000SEvgeniy Ivanov { 38258a2b000SEvgeniy Ivanov 38358a2b000SEvgeniy Ivanov wait(sec * 1000000); 38458a2b000SEvgeniy Ivanov } 385