Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/uart/uart_dev_ns8250.c
Show First 20 Lines • Show All 138 Lines • ▼ Show 20 Lines | ns8250_divisor(int rclk, int baudrate) | ||||
/* enforce maximum error tolerance: */ | /* enforce maximum error tolerance: */ | ||||
if (error < -UART_DEV_TOLERANCE_PCT || error > UART_DEV_TOLERANCE_PCT) | if (error < -UART_DEV_TOLERANCE_PCT || error > UART_DEV_TOLERANCE_PCT) | ||||
return (0); | return (0); | ||||
return (divisor); | return (divisor); | ||||
} | } | ||||
/* | |||||
* As above, but takes a fractional baudrate. | |||||
* This one currently does NOT enforce a maximum deviation. | |||||
*/ | |||||
static int | static int | ||||
ns8250_fdivisor(int rclk, int baudrate_n, int baudrate_d) | |||||
{ | |||||
int divisor; | |||||
int divisor_n, divisor_d; | |||||
if (baudrate_n == 0 || baudrate_d == 0) | |||||
return (0); | |||||
divisor_n = rclk * baudrate_d; | |||||
divisor_d = baudrate_n; | |||||
divisor = (divisor_n / (divisor_d << 3) + 1) >> 1; | |||||
if (divisor == 0 || divisor >= 65536) | |||||
return (0); | |||||
/* TODO: Enforce max 3% error in actual baudrate */ | |||||
return (divisor); | |||||
} | |||||
static int | |||||
ns8250_drain(struct uart_bas *bas, int what) | ns8250_drain(struct uart_bas *bas, int what) | ||||
{ | { | ||||
int delay, limit; | int delay, limit; | ||||
delay = ns8250_delay(bas); | delay = ns8250_delay(bas); | ||||
if (what & UART_DRAIN_TRANSMITTER) { | if (what & UART_DRAIN_TRANSMITTER) { | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 508 Lines • ▼ Show 20 Lines | case UART_IOCTL_BAUD: | ||||
uart_setreg(bas, REG_LCR, lcr); | uart_setreg(bas, REG_LCR, lcr); | ||||
uart_barrier(bas); | uart_barrier(bas); | ||||
baudrate = (divisor > 0) ? bas->rclk / divisor / 16 : 0; | baudrate = (divisor > 0) ? bas->rclk / divisor / 16 : 0; | ||||
if (baudrate > 0) | if (baudrate > 0) | ||||
*(int*)data = baudrate; | *(int*)data = baudrate; | ||||
else | else | ||||
error = ENXIO; | error = ENXIO; | ||||
break; | break; | ||||
case UART_IOCTL_SET_FBAUD: { | |||||
/* Set baudrate. */ | |||||
int *br = (int *)data; | |||||
divisor = ns8250_fdivisor(bas->rclk, br[0], br[1]); | |||||
if (divisor == 0) | |||||
return (EINVAL); | |||||
lcr = uart_getreg(bas, REG_LCR); | |||||
uart_setreg(bas, REG_LCR, lcr | LCR_DLAB); | |||||
uart_barrier(bas); | |||||
uart_setreg(bas, REG_DLL, divisor & 0xff); | |||||
uart_setreg(bas, REG_DLH, (divisor >> 8) & 0xff); | |||||
uart_barrier(bas); | |||||
uart_setreg(bas, REG_LCR, lcr); | |||||
uart_barrier(bas); | |||||
break; | |||||
} | |||||
default: | default: | ||||
error = EINVAL; | error = EINVAL; | ||||
break; | break; | ||||
} | } | ||||
uart_unlock(sc->sc_hwmtx); | uart_unlock(sc->sc_hwmtx); | ||||
return (error); | return (error); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 381 Lines • Show Last 20 Lines |