Date: Fri, 12 Oct 2012 16:30:11 -0700 From: Xin Li <delphij@delphij.net> To: freebsd-current@freebsd.org Subject: boot2/loader: serial port handling Message-ID: <5078A803.7070705@delphij.net>
next in thread | raw e-mail | index | archive | help
This is an OpenPGP/MIME signed message (RFC 2440 and 3156) --------------enig376A8025F32C79CA8D672BE6 Content-Type: multipart/mixed; boundary="------------010102070108080400010606" This is a multi-part message in MIME format. --------------010102070108080400010606 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Hi, We have some rather hacky quick hack at $WORK that addresses a problem we have found with boot2/loader and wants to share it and see if we can have more neat solution. Here is the problem: the current boot2 and loader have various places where it considers serial port to exist. When the port is not there, the code would hang because it tests whether the hardware's -READY bit, basically something like: do { } while (inpb(state register) & READY_BIT); This unfortunately would enter an infinite loop when the device is not present -- all in operations would get all bits set. To reproduce this, one can compile boot2/loader with non-existent port and the system will hang at very early stage of boot. --- Because boot2 is size constrained we can not use very sophisticated detection logic there, what I did is to use something like: outb(line control register, word) if (inb(line control register) !=3D word) Disable the serial port read/write For loader I'm not sure if we should use better detection logic. By the way, it seems that the system may force using the default console in loader regardless if the detection logic said no, if it decides that's the only usable one. So what would be the right way to solve these issue? Cheers, --=20 Xin LI <delphij@delphij.net> https://www.delphij.net/ FreeBSD - The Power to Serve! Live free or die --------------010102070108080400010606 Content-Type: text/plain; charset=UTF-8; name="freebsd-bootsio.diff" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="freebsd-bootsio.diff" Index: sys/boot/i386/boot2/boot2.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- sys/boot/i386/boot2/boot2.c (revision 241434) +++ sys/boot/i386/boot2/boot2.c (working copy) @@ -415,8 +415,10 @@ parse() } ioctrl =3D OPT_CHECK(RBX_DUAL) ? (IO_SERIAL|IO_KEYBOARD) : OPT_CHECK(RBX_SERIAL) ? IO_SERIAL : IO_KEYBOARD; - if (ioctrl & IO_SERIAL) - sio_init(115200 / comspeed); + if (ioctrl & IO_SERIAL) { + if (sio_init(115200 / comspeed)) + ioctrl &=3D ~IO_SERIAL; + } } else { for (q =3D arg--; *q && *q !=3D '('; q++); if (*q) { Index: sys/boot/i386/boot2/lib.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- sys/boot/i386/boot2/lib.h (revision 241434) +++ sys/boot/i386/boot2/lib.h (working copy) @@ -17,7 +17,7 @@ * $FreeBSD$ */ =20 -void sio_init(int) __attribute__((regparm (3))); +int sio_init(int) __attribute__((regparm (3))); void sio_flush(void); void sio_putc(int) __attribute__((regparm (3))); int sio_getc(void); Index: sys/boot/i386/boot2/sio.S =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- sys/boot/i386/boot2/sio.S (revision 241434) +++ sys/boot/i386/boot2/sio.S (working copy) @@ -24,12 +24,15 @@ .globl sio_getc .globl sio_ischar =20 -/* void sio_init(int div) */ +/* int sio_init(int div) */ =20 sio_init: pushl %eax movw $SIO_PRT+0x3,%dx # Data format reg movb $SIO_FMT|0x80,%al # Set format outb %al,(%dx) # and DLAB + inb (%dx),%al + cmpb $SIO_FMT|0x80,%al + jnz sio_init.1 subb $0x3,%dl # Divisor latch reg popl %eax outw %ax,(%dx) # BPS @@ -41,8 +44,13 @@ sio_init: pushl %eax outb %al,(%dx) # DTR incl %edx # Line status reg call sio_flush + xor %eax,%eax ret +sio_init.1: popl %eax + movb $0x1,%al + ret =20 + /* void sio_flush(void) */ =20 sio_flush.0: call sio_getc.1 # Get character Index: sys/boot/i386/libi386/comconsole.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- sys/boot/i386/libi386/comconsole.c (revision 241434) +++ sys/boot/i386/libi386/comconsole.c (working copy) @@ -33,7 +33,7 @@ __FBSDID("$FreeBSD$"); #include "libi386.h" =20 #define COMC_FMT 0x3 /* 8N1 */ -#define COMC_TXWAIT 0x40000 /* transmit timeout */ +#define COMC_TXWAIT 0x80 /* transmit timeout */ #define COMC_BPS(x) (115200 / (x)) /* speed to DLAB divisor */ #define COMC_DIV2BPS(x) (115200 / (x)) /* DLAB divisor to speed */ =20 @@ -57,6 +57,7 @@ static int comc_speed_set(struct env_var *ev, int =20 static int comc_started; static int comc_curspeed; +static int comc_disabled; =20 struct console comconsole =3D { "comconsole", @@ -76,9 +77,12 @@ comc_probe(struct console *cp) char *cons, *speedenv; int speed; =20 - /* XXX check the BIOS equipment list? */ - cp->c_flags |=3D (C_PRESENTIN | C_PRESENTOUT); + u_char dlbh; + u_char dlbl; + u_char cfcr; =20 + comc_disabled =3D 0; + if (comc_curspeed =3D=3D 0) { comc_curspeed =3D COMSPEED; /* @@ -102,6 +106,22 @@ comc_probe(struct console *cp) env_setenv("comconsole_speed", EV_VOLATILE, speedbuf, comc_speed_set, env_nounset); } + + cfcr =3D inb(COMPORT + com_cfcr); + outb(COMPORT + com_cfcr, CFCR_DLAB | cfcr); + + dlbl =3D inb(COMPORT + com_dlbl); + dlbh =3D inb(COMPORT + com_dlbh); + + outb(COMPORT + com_cfcr, cfcr); + + if (dlbl =3D=3D 0xff && dlbh =3D=3D 0xff && cfcr =3D=3D 0xff) { + cp->c_flags &=3D ~(C_PRESENTIN | C_PRESENTOUT); + comc_disabled =3D 1; + return; + } + + cp->c_flags |=3D (C_PRESENTIN | C_PRESENTOUT); } =20 static int @@ -121,6 +141,9 @@ comc_putchar(int c) { int wait; =20 + if (comc_disabled) + return; + for (wait =3D COMC_TXWAIT; wait > 0; wait--) if (inb(COMPORT + com_lsr) & LSR_TXRDY) { outb(COMPORT + com_data, (u_char)c); @@ -131,6 +154,10 @@ comc_putchar(int c) static int comc_getchar(void) { + + if (comc_disabled) + return -1; + return(comc_ischar() ? inb(COMPORT + com_data) : -1); } =20 @@ -161,6 +188,7 @@ comc_speed_set(struct env_var *ev, int flags, cons static void comc_setup(int speed) { + int retry =3D 0x80; =20 comc_curspeed =3D speed; =20 @@ -172,7 +200,7 @@ comc_setup(int speed) =20 do inb(COMPORT + com_data); - while (inb(COMPORT + com_lsr) & LSR_RXRDY); + while (inb(COMPORT + com_lsr) & LSR_RXRDY && (--retry > 0)); } =20 static int --------------010102070108080400010606-- --------------enig376A8025F32C79CA8D672BE6 Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- iQEcBAEBCAAGBQJQeKgGAAoJEG80Jeu8UPuzv7oIALWQZ8oyv5OPv4z1h3iprmcY fP4vbKi16Azn7SYKMdKDlxdHP0VPoIPsNVoHD+11S9fLmbxsFEB95HBLhPq/XiPE 8C0vp4QLHsyGKjEbJWj1UCs0bizuwn06K444Zu/AbWbv913CTBGuaI7anKfoFafd qnICC6lbz2Exncxyd/Yswj1WO2CE2d5OxYR89eEWeuGyfxzoAOOfTvwx/rB6q0VT UJhOjIaZMS3JwUuPPx4eUnqpucBEO+kgSuW7ny9KmaiYCqNoh0odWt86GpUNKMcN Ft9Pg22j4Tu0YgSnVUoLfeZVnp87jfkNutzIH8gQYxyznbbH9m9Glr7Ipn5j7qo= =ywkO -----END PGP SIGNATURE----- --------------enig376A8025F32C79CA8D672BE6--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?5078A803.7070705>