7 #include <syslinux/config.h>
27 int serial_init(struct serial_if
*sif
, const char *argv
[])
29 const struct syslinux_serial_console_info
*sci
30 = syslinux_serial_console_info();
33 uint8_t dll
, dlm
, lcr
;
39 printf("No port number specified and not using serial console!\n");
43 port
= strtoul(argv
[0], NULL
, 0);
45 uint16_t addr
= ((uint16_t *)0x400)[port
];
47 printf("No serial port address found!\n");
50 printf("Serial port %u is at 0x%04x\n", port
, addr
);
58 divisor
= 1; /* Default speed = 115200 bps */
60 /* Check to see if this is the same as the serial console */
61 if (port
== sci
->iobase
) {
62 /* Overlaying the console... */
65 /* Default to already configured speed */
66 divisor
= sci
->divisor
;
68 /* Shut down I/O to the console for the time being */
69 openconsole(&dev_null_r
, &dev_null_w
);
72 if (argv
[0] && argv
[1])
73 divisor
= 115200/strtoul(argv
[1], NULL
, 0);
75 cli(); /* Just in case... */
77 /* Save old register settings */
78 sif
->old
.lcr
= inb(port
+ LCR
);
79 sif
->old
.mcr
= inb(port
+ MCR
);
80 sif
->old
.iir
= inb(port
+ IIR
);
83 outb(0x83, port
+ LCR
); /* Enable divisor access */
84 sif
->old
.dll
= inb(port
+ DLL
);
85 sif
->old
.dlm
= inb(port
+ DLM
);
86 outb(divisor
, port
+ DLL
);
87 outb(divisor
>> 8, port
+ DLM
);
88 (void)inb(port
+ IER
); /* Synchronize */
90 dll
= inb(port
+ DLL
);
91 dlm
= inb(port
+ DLM
);
92 lcr
= inb(port
+ LCR
);
93 outb(0x03, port
+ LCR
); /* Enable data access, n81 */
94 (void)inb(port
+ IER
); /* Synchronize */
95 sif
->old
.ier
= inb(port
+ IER
);
97 /* Disable interrupts */
102 if (dll
!= (uint8_t)divisor
||
103 dlm
!= (uint8_t)(divisor
>> 8) ||
106 printf("No serial port detected!\n");
107 return -1; /* This doesn't look like a serial port */
110 /* Enable 16550A FIFOs if available */
111 outb(0x01, port
+ FCR
); /* Enable FIFO */
112 (void)inb(port
+ IER
); /* Synchronize */
113 if (inb(port
+ IIR
) < 0xc0)
114 outb(0x00, port
+ FCR
); /* Disable FIFOs if non-functional */
115 (void)inb(port
+ IER
); /* Synchronize */
120 void serial_write(struct serial_if
*sif
, const void *data
, size_t n
)
122 uint16_t port
= sif
->port
;
123 const char *p
= data
;
128 lsr
= inb(port
+ LSR
);
129 } while (!(lsr
& 0x20));
131 outb(*p
++, port
+ THR
);
135 void serial_read(struct serial_if
*sif
, void *data
, size_t n
)
137 uint16_t port
= sif
->port
;
143 lsr
= inb(port
+ LSR
);
144 } while (!(lsr
& 0x01));
146 *p
++ = inb(port
+ RBR
);
150 void serial_cleanup(struct serial_if
*sif
)
152 uint16_t port
= sif
->port
;
154 outb(0x83, port
+ LCR
);
155 (void)inb(port
+ IER
);
156 outb(sif
->old
.dll
, port
+ DLL
);
157 outb(sif
->old
.dlm
, port
+ DLM
);
158 (void)inb(port
+ IER
);
159 outb(sif
->old
.lcr
& 0x7f, port
+ LCR
);
160 (void)inb(port
+ IER
);
161 outb(sif
->old
.mcr
, port
+ MCR
);
162 outb(sif
->old
.ier
, port
+ IER
);
163 if (sif
->old
.iir
< 0xc0)
164 outb(0x00, port
+ FCR
); /* Disable FIFOs */
166 /* Re-enable console messages, if we shut them down */
168 openconsole(&dev_null_r
, &dev_stdcon_w
);