1*517bfc4aSbeck /* $OpenBSD: bioscons.c,v 1.36 2016/05/27 05:37:51 beck Exp $ */
280d96289Smickey
380d96289Smickey /*
4857b0937Smickey * Copyright (c) 1997-1999 Michael Shalayeff
580d96289Smickey * All rights reserved.
680d96289Smickey *
780d96289Smickey * Redistribution and use in source and binary forms, with or without
880d96289Smickey * modification, are permitted provided that the following conditions
980d96289Smickey * are met:
1080d96289Smickey * 1. Redistributions of source code must retain the above copyright
1180d96289Smickey * notice, this list of conditions and the following disclaimer.
1280d96289Smickey * 2. Redistributions in binary form must reproduce the above copyright
1380d96289Smickey * notice, this list of conditions and the following disclaimer in the
1480d96289Smickey * documentation and/or other materials provided with the distribution.
1580d96289Smickey *
1680d96289Smickey * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17857b0937Smickey * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18857b0937Smickey * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19857b0937Smickey * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
20857b0937Smickey * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21857b0937Smickey * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22857b0937Smickey * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23857b0937Smickey * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24857b0937Smickey * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25857b0937Smickey * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26857b0937Smickey * THE POSSIBILITY OF SUCH DAMAGE.
2780d96289Smickey */
2880d96289Smickey
2980d96289Smickey #include <sys/types.h>
3080d96289Smickey #include <machine/biosvar.h>
3180d96289Smickey #include <machine/pio.h>
3280d96289Smickey #include <dev/isa/isareg.h>
3380d96289Smickey #include <dev/ic/mc146818reg.h>
34e20327dbSflipk #include <dev/ic/comreg.h>
35e20327dbSflipk #include <dev/ic/ns16450reg.h>
364da2c3beSmickey /* #include <i386/isa/nvram.h> */
3780d96289Smickey #include <dev/cons.h>
38c657d8f4Sniklas #include <lib/libsa/stand.h>
399f2d58dfSderaadt #include "debug.h"
40599546b3Sderaadt #include "biosdev.h"
4180d96289Smickey
42c657d8f4Sniklas /* XXX cannot trust NVRAM on this. Maybe later we make a real probe. */
43c657d8f4Sniklas #if 0
4480d96289Smickey #define PRESENT_MASK (NVRAM_EQUIPMENT_KBD|NVRAM_EQUIPMENT_DISPLAY)
45c657d8f4Sniklas #else
46c657d8f4Sniklas #define PRESENT_MASK 0
47c657d8f4Sniklas #endif
4880d96289Smickey
4980d96289Smickey void
pc_probe(struct consdev * cn)50599546b3Sderaadt pc_probe(struct consdev *cn)
5180d96289Smickey {
52713cf266Sjsing cn->cn_pri = CN_MIDPRI;
539f2d58dfSderaadt cn->cn_dev = makedev(12, 0);
544b52c9a5Sderaadt printf(" pc%d", minor(cn->cn_dev));
559f2d58dfSderaadt
569f2d58dfSderaadt #if 0
5780d96289Smickey outb(IO_RTC, NVRAM_EQUIPMENT);
5880d96289Smickey if ((inb(IO_RTC+1) & PRESENT_MASK) == PRESENT_MASK) {
59713cf266Sjsing cn->cn_pri = CN_MIDPRI;
6080d96289Smickey /* XXX from i386/conf.c */
6180d96289Smickey cn->cn_dev = makedev(12, 0);
624b52c9a5Sderaadt printf(" pc%d", minor(cn->cn_dev));
6380d96289Smickey }
649f2d58dfSderaadt #endif
6580d96289Smickey }
6680d96289Smickey
6780d96289Smickey void
pc_init(struct consdev * cn)68599546b3Sderaadt pc_init(struct consdev *cn)
6980d96289Smickey {
7080d96289Smickey }
7180d96289Smickey
7280d96289Smickey int
pc_getc(dev_t dev)73599546b3Sderaadt pc_getc(dev_t dev)
7480d96289Smickey {
75a9d53ef8Smickey register int rv;
76b9eba8b7Smickey
77b9eba8b7Smickey if (dev & 0x80) {
782df76cc2Sguenther __asm volatile(DOINT(0x16) "; setnz %b0" : "=a" (rv) :
793f8949d5Smickey "0" (0x100) : "%ecx", "%edx", "cc" );
805a927cd4Smickey return (rv & 0xff);
81b9eba8b7Smickey }
8280d96289Smickey
83657ad163Stom /*
84657ad163Stom * Wait for a character to actually become available. Appears to
85657ad163Stom * be necessary on (at least) the Intel Mac Mini.
86657ad163Stom */
87657ad163Stom do {
882df76cc2Sguenther __asm volatile(DOINT(0x16) "; setnz %b0" : "=a" (rv) :
89657ad163Stom "0" (0x100) : "%ecx", "%edx", "cc" );
90657ad163Stom } while ((rv & 0xff) == 0);
91657ad163Stom
922df76cc2Sguenther __asm volatile(DOINT(0x16) : "=a" (rv) : "0" (0x000) :
936ba77b25Saaron "%ecx", "%edx", "cc" );
9461acb34aStom
955a927cd4Smickey return (rv & 0xff);
9680d96289Smickey }
9780d96289Smickey
987f20cbb1Stom int
pc_getshifts(dev_t dev)997f20cbb1Stom pc_getshifts(dev_t dev)
1007f20cbb1Stom {
1017f20cbb1Stom register int rv;
1027f20cbb1Stom
1032df76cc2Sguenther __asm volatile(DOINT(0x16) : "=a" (rv) : "0" (0x200) :
1047f20cbb1Stom "%ecx", "%edx", "cc" );
1057f20cbb1Stom
1067f20cbb1Stom return (rv & 0xff);
1077f20cbb1Stom }
1087f20cbb1Stom
10980d96289Smickey void
pc_putc(dev_t dev,int c)110599546b3Sderaadt pc_putc(dev_t dev, int c)
11180d96289Smickey {
1122df76cc2Sguenther __asm volatile(DOINT(0x10) : : "a" (c | 0xe00), "b" (1) :
113c657d8f4Sniklas "%ecx", "%edx", "cc" );
11480d96289Smickey }
11580d96289Smickey
1169f2d58dfSderaadt const int comports[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
1173abee3e7Smickey
11880d96289Smickey void
com_probe(struct consdev * cn)119599546b3Sderaadt com_probe(struct consdev *cn)
12080d96289Smickey {
12180d96289Smickey register int i, n;
122c657d8f4Sniklas
123c657d8f4Sniklas /* get equip. (9-11 # of coms) */
1242df76cc2Sguenther __asm volatile(DOINT(0x11) : "=a" (n) : : "%ecx", "%edx", "cc");
12580d96289Smickey n >>= 9;
12680d96289Smickey n &= 7;
12780d96289Smickey for (i = 0; i < n; i++)
1284b52c9a5Sderaadt printf(" com%d", i);
129be66b246Skettenis
130713cf266Sjsing cn->cn_pri = CN_LOWPRI;
131c657d8f4Sniklas /* XXX from i386/conf.c */
132c657d8f4Sniklas cn->cn_dev = makedev(8, 0);
133c657d8f4Sniklas }
13480d96289Smickey
1353490245dSdlg int com_speed = -1;
136a1e303c3Skettenis int com_addr = -1;
1373490245dSdlg
13880d96289Smickey void
com_init(struct consdev * cn)139599546b3Sderaadt com_init(struct consdev *cn)
14080d96289Smickey {
141a1e303c3Skettenis int port = (com_addr == -1) ? comports[minor(cn->cn_dev)] : com_addr;
142*517bfc4aSbeck time_t tt = getsecs() + 1;
143*517bfc4aSbeck u_long i = 1;
144c657d8f4Sniklas
1453490245dSdlg outb(port + com_ier, 0);
1463490245dSdlg if (com_speed == -1)
1473490245dSdlg comspeed(cn->cn_dev, 9600); /* default speed is 9600 baud */
1483490245dSdlg outb(port + com_mcr, MCR_DTR | MCR_RTS);
1493490245dSdlg outb(port + com_fifo, FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST |
1503490245dSdlg FIFO_TRIGGER_1);
151*517bfc4aSbeck (void) inb(port + com_iir);
152*517bfc4aSbeck
153*517bfc4aSbeck /* A few ms delay for the chip, using the getsecs() API */
154*517bfc4aSbeck while (!(i++ % 1000) && getsecs() < tt)
155*517bfc4aSbeck ;
1563490245dSdlg
1573490245dSdlg /* drain the input buffer */
1583490245dSdlg while (inb(port + com_lsr) & LSR_RXRDY)
1593490245dSdlg (void)inb(port + com_data);
16080d96289Smickey }
16180d96289Smickey
16280d96289Smickey int
com_getc(dev_t dev)163599546b3Sderaadt com_getc(dev_t dev)
16480d96289Smickey {
165a1e303c3Skettenis int port = (com_addr == -1) ? comports[minor(dev & 0x7f)] : com_addr;
16680d96289Smickey
1673490245dSdlg if (dev & 0x80)
1683490245dSdlg return (inb(port + com_lsr) & LSR_RXRDY);
16980d96289Smickey
1703490245dSdlg while ((inb(port + com_lsr) & LSR_RXRDY) == 0)
1713490245dSdlg ;
17280d96289Smickey
1733490245dSdlg return (inb(port + com_data) & 0xff);
17480d96289Smickey }
17580d96289Smickey
17681a5a260Smickey /* call with sp == 0 to query the current speed */
17781a5a260Smickey int
comspeed(dev_t dev,int sp)178599546b3Sderaadt comspeed(dev_t dev, int sp)
179e20327dbSflipk {
180a1e303c3Skettenis int port = (com_addr == -1) ? comports[minor(dev)] : com_addr;
18181a5a260Smickey int i, newsp;
18281a5a260Smickey int err;
183e20327dbSflipk
18481a5a260Smickey if (sp <= 0)
18581a5a260Smickey return com_speed;
18681a5a260Smickey /* valid baud rate? */
187bf899d08Smickey if (115200 < sp || sp < 75)
188e20327dbSflipk return -1;
18981a5a260Smickey
190f35eef81Sweingart /*
191f35eef81Sweingart * Accepted speeds:
192f35eef81Sweingart * 75 150 300 600 1200 2400 4800 9600 19200 38400 76800 and
193f35eef81Sweingart * 14400 28800 57600 115200
194f35eef81Sweingart */
195f35eef81Sweingart for (i = sp; i != 75 && i != 14400; i >>= 1)
19681a5a260Smickey if (i & 1)
197e20327dbSflipk return -1;
19881a5a260Smickey
19981a5a260Smickey /* ripped screaming from dev/ic/com.c */
20081a5a260Smickey #define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */
20181a5a260Smickey newsp = divrnd((COM_FREQ / 16), sp);
20281a5a260Smickey if (newsp <= 0)
20381a5a260Smickey return -1;
20481a5a260Smickey err = divrnd((COM_FREQ / 16) * 1000, sp * newsp) - 1000;
205e20327dbSflipk if (err < 0)
206e20327dbSflipk err = -err;
207e20327dbSflipk if (err > COM_TOLERANCE)
208e20327dbSflipk return -1;
2090677d144Sespie #undef divrnd
210e20327dbSflipk
2113490245dSdlg if (com_speed != -1 && cn_tab && cn_tab->cn_dev == dev &&
2123490245dSdlg com_speed != sp) {
2131c8d9fcfSderaadt printf("com%d: changing speed to %d baud in 5 seconds, "
2141c8d9fcfSderaadt "change your terminal to match!\n\a",
2151c8d9fcfSderaadt minor(dev), sp);
2163abee3e7Smickey sleep(5);
217e20327dbSflipk }
21881a5a260Smickey
219a1e303c3Skettenis outb(port + com_cfcr, LCR_DLAB);
220a1e303c3Skettenis outb(port + com_dlbl, newsp);
221a1e303c3Skettenis outb(port + com_dlbh, newsp>>8);
222a1e303c3Skettenis outb(port + com_cfcr, LCR_8BITS);
2233490245dSdlg if (com_speed != -1)
2241c8d9fcfSderaadt printf("\ncom%d: %d baud\n", minor(dev), sp);
22581a5a260Smickey
22681a5a260Smickey newsp = com_speed;
22781a5a260Smickey com_speed = sp;
22881a5a260Smickey return newsp;
229e20327dbSflipk }
230e20327dbSflipk
23180d96289Smickey void
com_putc(dev_t dev,int c)232599546b3Sderaadt com_putc(dev_t dev, int c)
23380d96289Smickey {
234a1e303c3Skettenis int port = (com_addr == -1) ? comports[minor(dev)] : com_addr;
235c657d8f4Sniklas
2363490245dSdlg while ((inb(port + com_lsr) & LSR_TXRDY) == 0)
2373490245dSdlg ;
238096e4ceeSmickey
2393490245dSdlg outb(port + com_data, c);
24080d96289Smickey }
241