patch-2.4.19 linux-2.4.19/drivers/char/dz.c
Next file: linux-2.4.19/drivers/char/dz.h
Previous file: linux-2.4.19/drivers/char/dummy_keyb.c
Back to the patch index
Back to the overall index
- Lines: 1608
- Date:
Fri Aug 2 17:39:43 2002
- Orig file:
linux-2.4.18/drivers/char/dz.c
- Orig date:
Sun Sep 9 10:43:02 2001
diff -urN linux-2.4.18/drivers/char/dz.c linux-2.4.19/drivers/char/dz.c
@@ -14,41 +14,31 @@
* after patches by harald to irq code.
* [09-JAN-99] triemer minor fix for schedule - due to removal of timeout
* field from "current" - somewhere between 2.1.121 and 2.1.131
-Qua Jun 27 15:02:26 BRT 2001
+ Qua Jun 27 15:02:26 BRT 2001
* [27-JUN-2001] Arnaldo Carvalho de Melo <acme@conectiva.com.br> - cleanups
*
* Parts (C) 1999 David Airlie, airlied@linux.ie
* [07-SEP-99] Bugfixes
*/
-/* #define DEBUG_DZ 1 */
-
-#include <linux/version.h>
-#include <linux/module.h>
+#define DEBUG_DZ 1
#include <linux/config.h>
+#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/sched.h>
-#include <linux/init.h>
+#include <linux/init.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/major.h>
+#include <linux/module.h>
#include <linux/param.h>
#include <linux/tqueue.h>
#include <linux/interrupt.h>
-#include <linux/serial.h>
-#include <linux/serialP.h>
#include <asm-mips/wbflush.h>
-#include <asm/dec/interrupts.h> /* for definition of SERIAL */
+#include <asm/dec/interrupts.h>
-/* for definition of struct console */
-#ifdef CONFIG_SERIAL_CONSOLE
-#define CONSOLE_LINE (3)
-#endif /* ifdef CONFIG_SERIAL_CONSOLE */
-#if defined(CONFIG_SERIAL_CONSOLE) || defined(DEBUG_DZ)
#include <linux/console.h>
-#endif /* if defined(CONFIG_SERIAL_CONSOLE) || defined(DEBUG_DZ) */
-
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial.h>
@@ -59,15 +49,13 @@
#include <asm/dec/kn01.h>
#include <asm/dec/kn02.h>
-#ifdef DEBUG_DZ
#include <linux/ptrace.h>
#include <linux/fs.h>
#include <asm/bootinfo.h>
-extern int (*prom_printf) (char *,...);
-#endif
-
+#define CONSOLE_LINE (3) /* for definition of struct console */
+extern int (*prom_printf) (char *,...);
#include "dz.h"
@@ -75,17 +63,14 @@
DECLARE_TASK_QUEUE(tq_serial);
-extern wait_queue_head_t keypress_wait;
static struct dz_serial *lines[4];
static unsigned char tmp_buffer[256];
-
-
#ifdef DEBUG_DZ
/*
* debugging code to send out chars via prom
*/
-static void debug_console( const char *s,int count)
+static void debug_console(const char *s, int count)
{
unsigned i;
@@ -106,17 +91,19 @@
* ------------------------------------------------------------
*/
-static inline unsigned short dz_in (struct dz_serial *info, unsigned offset)
+static inline unsigned short dz_in(struct dz_serial *info, unsigned offset)
{
- volatile u16 *addr = (volatile u16 *)(info->port + offset);
-
+ volatile unsigned short *addr =
+ (volatile unsigned short *) (info->port + offset);
return *addr;
}
-static inline void dz_out (struct dz_serial *info, unsigned offset,
- unsigned short value)
+static inline void dz_out(struct dz_serial *info, unsigned offset,
+ unsigned short value)
{
- volatile u16 *addr = (volatile u16 *)(info->port + offset);
+
+ volatile unsigned short *addr =
+ (volatile unsigned short *) (info->port + offset);
*addr = value;
}
@@ -130,33 +117,34 @@
* ------------------------------------------------------------
*/
-static void dz_stop (struct tty_struct *tty)
+static void dz_stop(struct tty_struct *tty)
{
- struct dz_serial *info;
+ struct dz_serial *info;
unsigned short mask, tmp;
- if (!tty)
- return;
-
- info = (struct dz_serial *)tty->driver_data;
+ if (tty == 0)
+ return;
+
+ info = (struct dz_serial *) tty->driver_data;
mask = 1 << info->line;
- tmp = dz_in (info, DZ_TCR); /* read the TX flag */
+ tmp = dz_in(info, DZ_TCR); /* read the TX flag */
- tmp &= ~mask; /* clear the TX flag */
- dz_out (info, DZ_TCR, tmp);
+ tmp &= ~mask; /* clear the TX flag */
+ dz_out(info, DZ_TCR, tmp);
}
-static void dz_start (struct tty_struct *tty)
+static void dz_start(struct tty_struct *tty)
{
- struct dz_serial *info = (struct dz_serial *)tty->driver_data;
+ struct dz_serial *info = (struct dz_serial *) tty->driver_data;
unsigned short mask, tmp;
mask = 1 << info->line;
- tmp = dz_in (info, DZ_TCR); /* read the TX flag */
+ tmp = dz_in(info, DZ_TCR); /* read the TX flag */
+
+ tmp |= mask; /* set the TX flag */
+ dz_out(info, DZ_TCR, tmp);
- tmp |= mask; /* set the TX flag */
- dz_out (info, DZ_TCR, tmp);
}
/*
@@ -187,7 +175,7 @@
* processing in the software interrupt portion of the driver.
* ------------------------------------------------------------
*/
-static inline void dz_sched_event (struct dz_serial *info, int event)
+static inline void dz_sched_event(struct dz_serial *info, int event)
{
info->event |= 1 << event;
queue_task(&info->tqueue, &tq_serial);
@@ -201,8 +189,9 @@
* This routine deals with inputs from any lines.
* ------------------------------------------------------------
*/
-static inline void receive_chars (struct dz_serial *info_in)
+static inline void receive_chars(struct dz_serial *info_in)
{
+
struct dz_serial *info;
struct tty_struct *tty = 0;
struct async_icount *icount;
@@ -210,26 +199,25 @@
unsigned short status, tmp;
unsigned char ch;
- /*
- * This code is going to be a problem... the call to tty_flip_buffer
- * is going to need to be rethought...
+ /* this code is going to be a problem...
+ the call to tty_flip_buffer is going to need
+ to be rethought...
*/
do {
- status = dz_in (info_in, DZ_RBUF);
+ status = dz_in(info_in, DZ_RBUF);
info = lines[LINE(status)];
/* punt so we don't get duplicate characters */
if (!(status & DZ_DVAL))
goto ignore_char;
- ch = UCHAR(status); /* grab the char */
+
+ ch = UCHAR(status); /* grab the char */
#if 0
if (info->is_console) {
if (ch == 0)
- return; /* it's a break ... */
-
- wake_up (&keypress_wait); /* It is a 'keyboard interrupt' ;-) */
+ return; /* it's a break ... */
}
#endif
@@ -238,7 +226,8 @@
if (!tty)
break;
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) break;
+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+ break;
*tty->flip.char_buf_ptr = ch;
*tty->flip.flag_buf_ptr = 0;
@@ -246,16 +235,15 @@
/* keep track of the statistics */
if (status & (DZ_OERR | DZ_FERR | DZ_PERR)) {
- if (status & DZ_PERR) /* parity error */
+ if (status & DZ_PERR) /* parity error */
icount->parity++;
else if (status & DZ_FERR) /* frame error */
icount->frame++;
- if (status & DZ_OERR) /* overrun error */
+ if (status & DZ_OERR) /* overrun error */
icount->overrun++;
- /*
- * Check to see if we should ignore the character and
- * mask off conditions that should be ignored
+ /* check to see if we should ignore the character
+ and mask off conditions that should be ignored
*/
if (status & info->ignore_status_mask) {
@@ -263,24 +251,18 @@
break;
goto ignore_char;
}
-
/* mask off the error conditions we want to ignore */
tmp = status & info->read_status_mask;
if (tmp & DZ_PERR) {
*tty->flip.flag_buf_ptr = TTY_PARITY;
-#ifdef DEBUG_DZ
- debug_console("PERR\n",5);
-#endif /* DEBUG_DZ */
+ debug_console("PERR\n", 5);
} else if (tmp & DZ_FERR) {
*tty->flip.flag_buf_ptr = TTY_FRAME;
-#ifdef DEBUG_DZ
- debug_console("FERR\n",5);
-#endif /* DEBUG_DZ */
- } if (tmp & DZ_OERR) {
-#ifdef DEBUG_DZ
- debug_console("OERR\n",5);
-#endif /* DEBUG_DZ */
+ debug_console("FERR\n", 5);
+ }
+ if (tmp & DZ_OERR) {
+ debug_console("OERR\n", 5);
if (tty->flip.count < TTY_FLIPBUF_SIZE) {
tty->flip.count++;
tty->flip.flag_buf_ptr++;
@@ -289,11 +271,10 @@
}
}
}
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
-ignore_char:
- ;
+ tty->flip.flag_buf_ptr++;
+ tty->flip.char_buf_ptr++;
+ tty->flip.count++;
+ ignore_char:
} while (status & DZ_DVAL);
if (tty)
@@ -307,26 +288,25 @@
* This routine deals with outputs to any lines.
* ------------------------------------------------------------
*/
-static inline void transmit_chars (struct dz_serial *info)
+static inline void transmit_chars(struct dz_serial *info)
{
unsigned char tmp;
- if (info->x_char) { /* XON/XOFF chars */
+
+
+ if (info->x_char) { /* XON/XOFF chars */
dz_out(info, DZ_TDR, info->x_char);
info->icount.tx++;
info->x_char = 0;
return;
}
-
/* if nothing to do or stopped or hardware stopped */
- if ((info->xmit_cnt <= 0) || info->tty->stopped ||
- info->tty->hw_stopped) {
+ if ((info->xmit_cnt <= 0) || info->tty->stopped || info->tty->hw_stopped) {
dz_stop(info->tty);
return;
}
-
/*
- * If something to do ... (rember the dz has no output fifo so we go
+ * if something to do ... (rember the dz has no output fifo so we go
* one char at a time :-<
*/
tmp = (unsigned short) info->xmit_buf[info->xmit_tail++];
@@ -335,7 +315,8 @@
info->icount.tx++;
if (--info->xmit_cnt < WAKEUP_CHARS)
- dz_sched_event(info, DZ_EVENT_WRITE_WAKEUP);
+ dz_sched_event(info, DZ_EVENT_WRITE_WAKEUP);
+
/* Are we done */
if (info->xmit_cnt <= 0)
@@ -349,7 +330,7 @@
* Only valid for the MODEM line duh !
* ------------------------------------------------------------
*/
-static inline void check_modem_status (struct dz_serial *info)
+static inline void check_modem_status(struct dz_serial *info)
{
unsigned short status;
@@ -358,7 +339,7 @@
return;
status = dz_in(info, DZ_MSR);
-
+
/* it's easy, since DSR2 is the only bit in the register */
if (status)
info->icount.dsr++;
@@ -372,20 +353,20 @@
* It deals with the multiple ports.
* ------------------------------------------------------------
*/
-static void dz_interrupt (int irq, void *dev, struct pt_regs *regs)
+static void dz_interrupt(int irq, void *dev, struct pt_regs *regs)
{
struct dz_serial *info;
unsigned short status;
- /* get the reason why we just got an irq */
- status = dz_in((struct dz_serial *)dev, DZ_CSR);
- info = lines[LINE(status)]; /* re-arrange info the proper port */
+ /* get the reason why we just got an irq */
+ status = dz_in((struct dz_serial *) dev, DZ_CSR);
+ info = lines[LINE(status)]; /* re-arrange info the proper port */
- if (status & DZ_RDONE)
+ if (status & DZ_RDONE)
receive_chars(info); /* the receive function */
- if (status & DZ_TRDY)
- transmit_chars (info);
+ if (status & DZ_TRDY)
+ transmit_chars(info);
}
/*
@@ -403,12 +384,12 @@
* interrupt driver proper are done; the interrupt driver schedules
* them using rs_sched_event(), and they get done here.
*/
-static void do_serial_bh (void)
+static void do_serial_bh(void)
{
- run_task_queue (&tq_serial);
+ run_task_queue(&tq_serial);
}
-static void do_softint (void *private_data)
+static void do_softint(void *private_data)
{
struct dz_serial *info = (struct dz_serial *) private_data;
struct tty_struct *tty = info->tty;
@@ -417,10 +398,9 @@
return;
if (test_and_clear_bit(DZ_EVENT_WRITE_WAKEUP, &info->event)) {
- if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
- tty->ldisc.write_wakeup)
+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
(tty->ldisc.write_wakeup) (tty);
- wake_up_interruptible (&tty->write_wait);
+ wake_up_interruptible(&tty->write_wait);
}
}
@@ -434,11 +414,11 @@
* do_serial_hangup() -> tty->hangup() -> rs_hangup()
* -------------------------------------------------------------------
*/
-static void do_serial_hangup (void *private_data)
+static void do_serial_hangup(void *private_data)
{
struct dz_serial *info = (struct dz_serial *) private_data;
struct tty_struct *tty = info->tty;;
-
+
if (!tty)
return;
@@ -452,31 +432,31 @@
* various initialization tasks
* -------------------------------------------------------------------
*/
-static int startup (struct dz_serial *info)
+static int startup(struct dz_serial *info)
{
unsigned long page, flags;
unsigned short tmp;
if (info->is_initialized)
return 0;
-
- save_and_cli(flags);
+
+ save_flags(flags);
+ cli();
if (!info->port) {
- if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags);
+ if (info->tty)
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
restore_flags(flags);
return -ENODEV;
}
-
if (!info->xmit_buf) {
page = get_free_page(GFP_KERNEL);
if (!page) {
- restore_flags (flags);
- return -ENOMEM;
+ restore_flags(flags);
+ return -ENOMEM;
}
- info->xmit_buf = (unsigned char *)page;
+ info->xmit_buf = (unsigned char *) page;
}
-
if (info->tty)
clear_bit(TTY_IO_ERROR, &info->tty->flags);
@@ -487,18 +467,24 @@
info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
- change_speed(info); /* set up the speed */
+ /* set up the speed */
+ change_speed(info);
- /*
- * Clear the line transmitter buffer I can't figure out why I need to
- * do this - but its necessary - in order for the console portion and
- * the interrupt portion to live happily side by side.
+ /* clear the line transmitter buffer
+ I can't figure out why I need to do this - but
+ its necessary - in order for the console portion
+ and the interrupt portion to live happily side by side.
+ */
+
+ /* clear the line transmitter buffer
+ I can't figure out why I need to do this - but
+ its necessary - in order for the console portion
+ and the interrupt portion to live happily side by side.
*/
info->is_initialized = 1;
restore_flags(flags);
-
return 0;
}
@@ -510,7 +496,7 @@
* DTR is dropped if the hangup on close termio flag is on.
* -------------------------------------------------------------------
*/
-static void shutdown (struct dz_serial *info)
+static void shutdown(struct dz_serial *info)
{
unsigned long flags;
unsigned short tmp;
@@ -518,18 +504,20 @@
if (!info->is_initialized)
return;
- save_and_cli(flags);
+ save_flags(flags);
+ cli();
+
+ dz_stop(info->tty);
+
- dz_stop (info->tty);
info->cflags &= ~DZ_CREAD; /* turn off receive enable flag */
dz_out(info, DZ_LPR, info->cflags);
- if (info->xmit_buf) { /* free Tx buffer */
- free_page((unsigned long)info->xmit_buf);
+ if (info->xmit_buf) { /* free Tx buffer */
+ free_page((unsigned long) info->xmit_buf);
info->xmit_buf = 0;
}
-
if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
tmp = dz_in(info, DZ_TCR);
if (tmp & DZ_MODEM_DTR) {
@@ -537,13 +525,11 @@
dz_out(info, DZ_TCR, tmp);
}
}
-
if (info->tty)
- set_bit (TTY_IO_ERROR, &info->tty->flags);
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
info->is_initialized = 0;
-
- restore_flags (flags);
+ restore_flags(flags);
}
/*
@@ -553,7 +539,7 @@
* set the baud rate.
* -------------------------------------------------------------------
*/
-static void change_speed (struct dz_serial *info)
+static void change_speed(struct dz_serial *info)
{
unsigned long flags;
unsigned cflag;
@@ -561,26 +547,27 @@
if (!info->tty || !info->tty->termios)
return;
-
- save_and_cli(flags);
-
+
+ save_flags(flags);
+ cli();
+
info->cflags = info->line;
cflag = info->tty->termios->c_cflag;
switch (cflag & CSIZE) {
- case CS5:
- info->cflags |= DZ_CS5;
- break;
- case CS6:
- info->cflags |= DZ_CS6;
- break;
- case CS7:
- info->cflags |= DZ_CS7;
- break;
- case CS8:
- default:
- info->cflags |= DZ_CS8;
+ case CS5:
+ info->cflags |= DZ_CS5;
+ break;
+ case CS6:
+ info->cflags |= DZ_CS6;
+ break;
+ case CS7:
+ info->cflags |= DZ_CS7;
+ break;
+ case CS8:
+ default:
+ info->cflags |= DZ_CS8;
}
if (cflag & CSTOPB)
@@ -589,7 +576,7 @@
info->cflags |= DZ_PARENB;
if (cflag & PARODD)
info->cflags |= DZ_PARODD;
-
+
baud = tty_get_baud_rate(info->tty);
switch (baud) {
case 50:
@@ -603,19 +590,19 @@
break;
case 134:
info->cflags |= DZ_B134;
- break;
+ break;
case 150:
info->cflags |= DZ_B150;
break;
case 300:
info->cflags |= DZ_B300;
- break;
+ break;
case 600:
info->cflags |= DZ_B600;
break;
case 1200:
info->cflags |= DZ_B1200;
- break;
+ break;
case 1800:
info->cflags |= DZ_B1800;
break;
@@ -627,16 +614,16 @@
break;
case 3600:
info->cflags |= DZ_B3600;
- break;
+ break;
case 4800:
info->cflags |= DZ_B4800;
break;
case 7200:
info->cflags |= DZ_B7200;
- break;
- case 9600:
+ break;
+ case 9600:
default:
- info->cflags |= DZ_B9600;
+ info->cflags |= DZ_B9600;
}
info->cflags |= DZ_RXENAB;
@@ -645,8 +632,8 @@
/* setup accept flag */
info->read_status_mask = DZ_OERR;
if (I_INPCK(info->tty))
- info->read_status_mask |= (DZ_FERR | DZ_PERR);
-
+ info->read_status_mask |= (DZ_FERR | DZ_PERR);
+
/* characters to ignore */
info->ignore_status_mask = 0;
if (I_IGNPAR(info->tty))
@@ -662,17 +649,19 @@
* Flush the buffer.
* -------------------------------------------------------------------
*/
-static void dz_flush_chars (struct tty_struct *tty)
+static void dz_flush_chars(struct tty_struct *tty)
{
- struct dz_serial *info = (struct dz_serial *)tty->driver_data;
+ struct dz_serial *info = (struct dz_serial *) tty->driver_data;
unsigned long flags;
- if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
- !info->xmit_buf)
+ if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || !info->xmit_buf)
return;
- save_and_cli(flags);
- dz_start (info->tty);
+ save_flags(flags);
+ cli();
+
+ dz_start(info->tty);
+
restore_flags(flags);
}
@@ -684,64 +673,67 @@
* main output routine.
* -------------------------------------------------------------------
*/
-static int dz_write (struct tty_struct *tty, int from_user,
- const unsigned char *buf, int count)
+static int dz_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count)
{
- struct dz_serial *info = (struct dz_serial *)tty->driver_data;
+ struct dz_serial *info = (struct dz_serial *) tty->driver_data;
unsigned long flags;
int c, ret = 0;
- if (!tty )
+ if (!tty)
return ret;
if (!info->xmit_buf)
return ret;
if (!tmp_buf)
tmp_buf = tmp_buffer;
+
+
if (from_user) {
- down (&tmp_buf_sem);
+
+ down(&tmp_buf_sem);
while (1) {
- c = MIN(count, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1,
- DZ_XMIT_SIZE - info->xmit_head));
+ c = MIN(count, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head));
if (c <= 0)
break;
- c -= copy_from_user (tmp_buf, buf, c);
+ c -= copy_from_user(tmp_buf, buf, c);
if (!c) {
if (!ret)
ret = -EFAULT;
break;
}
+ save_flags(flags);
+ cli();
- save_and_cli(flags);
-
- c = MIN(c, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1,
- DZ_XMIT_SIZE - info->xmit_head));
+ c = MIN(c, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head));
memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
- info->xmit_head = ((info->xmit_head + c) &
- (DZ_XMIT_SIZE - 1));
+ info->xmit_head = ((info->xmit_head + c) & (DZ_XMIT_SIZE - 1));
info->xmit_cnt += c;
+
restore_flags(flags);
buf += c;
count -= c;
ret += c;
}
+
up(&tmp_buf_sem);
} else {
+
+
while (1) {
- save_and_cli(flags);
+ save_flags(flags);
+ cli();
- c = MIN(count, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1,
- DZ_XMIT_SIZE - info->xmit_head));
+ c = MIN(count, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head));
if (c <= 0) {
- restore_flags (flags);
+ restore_flags(flags);
break;
}
memcpy(info->xmit_buf + info->xmit_head, buf, c);
- info->xmit_head = ((info->xmit_head + c) &
- (DZ_XMIT_SIZE-1));
+ info->xmit_head = ((info->xmit_head + c) & (DZ_XMIT_SIZE - 1));
info->xmit_cnt += c;
+
restore_flags(flags);
buf += c;
@@ -750,14 +742,14 @@
}
}
+
if (info->xmit_cnt) {
if (!tty->stopped) {
if (!tty->hw_stopped) {
- dz_start (info->tty);
+ dz_start(info->tty);
}
}
}
-
return ret;
}
@@ -768,15 +760,14 @@
* compute the amount of space available for writing.
* -------------------------------------------------------------------
*/
-static int dz_write_room (struct tty_struct *tty)
+static int dz_write_room(struct tty_struct *tty)
{
- struct dz_serial *info = (struct dz_serial *)tty->driver_data;
+ struct dz_serial *info = (struct dz_serial *) tty->driver_data;
int ret;
ret = DZ_XMIT_SIZE - info->xmit_cnt - 1;
if (ret < 0)
ret = 0;
-
return ret;
}
@@ -787,10 +778,10 @@
* compute the amount of char left to be transmitted
* -------------------------------------------------------------------
*/
-static int dz_chars_in_buffer (struct tty_struct *tty)
+static int dz_chars_in_buffer(struct tty_struct *tty)
{
- struct dz_serial *info = (struct dz_serial *)tty->driver_data;
-
+ struct dz_serial *info = (struct dz_serial *) tty->driver_data;
+
return info->xmit_cnt;
}
@@ -801,19 +792,18 @@
* Empty the output buffer
* -------------------------------------------------------------------
*/
-static void dz_flush_buffer (struct tty_struct *tty)
+static void dz_flush_buffer(struct tty_struct *tty)
{
- struct dz_serial *info = (struct dz_serial *)tty->driver_data;
-
+ struct dz_serial *info = (struct dz_serial *) tty->driver_data;
+
cli();
info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
sti();
- wake_up_interruptible (&tty->write_wait);
+ wake_up_interruptible(&tty->write_wait);
- if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
- tty->ldisc.write_wakeup)
- tty->ldisc.write_wakeup(tty);
+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
+ (tty->ldisc.write_wakeup) (tty);
}
/*
@@ -824,17 +814,17 @@
* incoming characters should be throttled (or not).
* ------------------------------------------------------------
*/
-static void dz_throttle (struct tty_struct *tty)
+static void dz_throttle(struct tty_struct *tty)
{
- struct dz_serial *info = (struct dz_serial *)tty->driver_data;
+ struct dz_serial *info = (struct dz_serial *) tty->driver_data;
if (I_IXOFF(tty))
info->x_char = STOP_CHAR(tty);
}
-static void dz_unthrottle (struct tty_struct *tty)
+static void dz_unthrottle(struct tty_struct *tty)
{
- struct dz_serial *info = (struct dz_serial *)tty->driver_data;
+ struct dz_serial *info = (struct dz_serial *) tty->driver_data;
if (I_IXOFF(tty)) {
if (info->x_char)
@@ -844,9 +834,9 @@
}
}
-static void dz_send_xchar (struct tty_struct *tty, char ch)
+static void dz_send_xchar(struct tty_struct *tty, char ch)
{
- struct dz_serial *info = (struct dz_serial *)tty->driver_data;
+ struct dz_serial *info = (struct dz_serial *) tty->driver_data;
info->x_char = ch;
@@ -863,11 +853,11 @@
struct serial_struct *retinfo)
{
struct serial_struct tmp;
-
+
if (!retinfo)
return -EFAULT;
- memset (&tmp, 0, sizeof(tmp));
+ memset(&tmp, 0, sizeof(tmp));
tmp.type = info->type;
tmp.line = info->line;
@@ -881,8 +871,8 @@
return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
}
-static int set_serial_info (struct dz_serial *info,
- struct serial_struct *new_info)
+static int set_serial_info(struct dz_serial *info,
+ struct serial_struct *new_info)
{
struct serial_struct new_serial;
struct dz_serial old_info;
@@ -913,7 +903,6 @@
info->closing_wait = new_serial.closing_wait;
retval = startup(info);
-
return retval;
}
@@ -927,17 +916,17 @@
* transmit holding register is empty. This functionality
* allows an RS485 driver to be written in user space.
*/
-static int get_lsr_info (struct dz_serial *info, unsigned int *value)
+static int get_lsr_info(struct dz_serial *info, unsigned int *value)
{
- unsigned short status = dz_in (info, DZ_LPR);
+ unsigned short status = dz_in(info, DZ_LPR);
- return put_user (status, value);
+ return put_user(status, value);
}
/*
* This routine sends a break character out the serial port.
*/
-static void send_break (struct dz_serial *info, int duration)
+static void send_break(struct dz_serial *info, int duration)
{
unsigned long flags;
unsigned short tmp, mask;
@@ -946,33 +935,36 @@
return;
mask = 1 << info->line;
- tmp = dz_in (info, DZ_TCR);
+ tmp = dz_in(info, DZ_TCR);
tmp |= mask;
current->state = TASK_INTERRUPTIBLE;
- save_and_cli(flags);
+ save_flags(flags);
+ cli();
+
dz_out(info, DZ_TCR, tmp);
+
schedule_timeout(duration);
+
tmp &= ~mask;
dz_out(info, DZ_TCR, tmp);
+
restore_flags(flags);
}
static int dz_ioctl(struct tty_struct *tty, struct file *file,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
- int error;
- struct dz_serial * info = (struct dz_serial *)tty->driver_data;
+ struct dz_serial *info = (struct dz_serial *) tty->driver_data;
int retval;
- if (cmd != TIOCGSERIAL && cmd != TIOCSSERIAL &&
- cmd != TIOCSERCONFIG && cmd != TIOCSERGWILD &&
- cmd != TIOCSERSWILD && cmd != TIOCSERGSTRUCT) {
+ if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+ (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) &&
+ (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) {
if (tty->flags & (1 << TTY_IO_ERROR))
return -EIO;
}
-
switch (cmd) {
case TCSBRK: /* SVID version: non-zero arg --> no break */
retval = tty_check_change(tty);
@@ -980,7 +972,7 @@
return retval;
tty_wait_until_sent(tty, 0);
if (!arg)
- send_break(info, HZ/4); /* 1/4 second */
+ send_break(info, HZ / 4); /* 1/4 second */
return 0;
case TCSBRKP: /* support for POSIX tcsendbreak() */
@@ -988,41 +980,32 @@
if (retval)
return retval;
tty_wait_until_sent(tty, 0);
- send_break(info, arg ? arg*(HZ/10) : HZ/4);
+ send_break(info, arg ? arg * (HZ / 10) : HZ / 4);
return 0;
case TIOCGSOFTCAR:
- error = verify_area (VERIFY_WRITE, (void *)arg, sizeof(long));
- if (error)
- return error;
- put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *)arg);
- return 0;
+ return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg);
case TIOCSSOFTCAR:
- if (get_user (arg, (unsigned long *)arg))
+ if (get_user(arg, (unsigned long *) arg))
return -EFAULT;
-
- tty->termios->c_cflag = (tty->termios->c_cflag & ~CLOCAL) |
- (arg ? CLOCAL : 0);
+ tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) |
+ (arg ? CLOCAL : 0));
return 0;
case TIOCGSERIAL:
- error = verify_area(VERIFY_WRITE, (void *)arg,
- sizeof(struct serial_struct));
- if (error)
- return error;
- return get_serial_info(info, (struct serial_struct *)arg);
+ return get_serial_info(info, (struct serial_struct *) arg);
case TIOCSSERIAL:
return set_serial_info(info, (struct serial_struct *) arg);
- case TIOCSERGETLSR: /* Get line status register */
- return get_lsr_info (info, (unsigned int *)arg);
+ case TIOCSERGETLSR: /* Get line status register */
+ return get_lsr_info(info, (unsigned int *) arg);
case TIOCSERGSTRUCT:
- return copy_to_user((struct dz_serial *)arg, info,
- sizeof(struct dz_serial)) ? -EFAULT : 0;
-
+ return copy_to_user((struct dz_serial *) arg, info,
+ sizeof(struct dz_serial)) ? -EFAULT : 0;
+
default:
return -ENOIOCTLCMD;
}
@@ -1030,15 +1013,15 @@
return 0;
}
-static void dz_set_termios (struct tty_struct *tty,
- struct termios *old_termios)
+static void dz_set_termios(struct tty_struct *tty,
+ struct termios *old_termios)
{
- struct dz_serial *info = (struct dz_serial *)tty->driver_data;
+ struct dz_serial *info = (struct dz_serial *) tty->driver_data;
if (tty->termios->c_cflag == old_termios->c_cflag)
return;
- change_speed (info);
+ change_speed(info);
if ((old_termios->c_cflag & CRTSCTS) &&
!(tty->termios->c_cflag & CRTSCTS)) {
@@ -1058,37 +1041,36 @@
*/
static void dz_close(struct tty_struct *tty, struct file *filp)
{
- struct dz_serial * info = (struct dz_serial *)tty->driver_data;
+ struct dz_serial *info = (struct dz_serial *) tty->driver_data;
unsigned long flags;
if (!info)
return;
-
- save_and_cli(flags);
+
+ save_flags(flags);
+ cli();
if (tty_hung_up_p(filp)) {
restore_flags(flags);
return;
}
-
if ((tty->count == 1) && (info->count != 1)) {
/*
- * Uh, oh. tty->count is 1, which means that the tty structure
- * will be freed. Info->count should always be one in these
- * conditions. If it's greater than one, we've got real
- * problems, since it means the serial port won't be shutdown.
+ * Uh, oh. tty->count is 1, which means that the tty
+ * structure will be freed. Info->count should always
+ * be one in these conditions. If it's greater than
+ * one, we've got real problems, since it means the
+ * serial port won't be shutdown.
*/
printk("dz_close: bad serial port count; tty->count is 1, "
"info->count is %d\n", info->count);
info->count = 1;
}
-
if (--info->count < 0) {
printk("ds_close: bad serial port count for ttyS%02d: %d\n",
info->line, info->count);
info->count = 0;
}
-
if (info->count) {
restore_flags(flags);
return;
@@ -1103,8 +1085,8 @@
if (info->flags & DZ_CALLOUT_ACTIVE)
info->callout_termios = *tty->termios;
/*
- * Now we wait for the transmit buffer to clear; and we notify the line
- * discipline to only process XON/XOFF characters.
+ * Now we wait for the transmit buffer to clear; and we notify
+ * the line discipline to only process XON/XOFF characters.
*/
tty->closing = 1;
@@ -1112,26 +1094,27 @@
tty_wait_until_sent(tty, info->closing_wait);
/*
- * At this point we stop accepting input. To do this, we disable the
- * receive line status interrupts.
+ * At this point we stop accepting input. To do this, we
+ * disable the receive line status interrupts.
*/
+
shutdown(info);
if (tty->driver.flush_buffer)
- tty->driver.flush_buffer (tty);
+ tty->driver.flush_buffer(tty);
if (tty->ldisc.flush_buffer)
- tty->ldisc.flush_buffer (tty);
+ tty->ldisc.flush_buffer(tty);
tty->closing = 0;
info->event = 0;
info->tty = 0;
if (tty->ldisc.num != ldiscs[N_TTY].num) {
if (tty->ldisc.close)
- tty->ldisc.close(tty);
+ (tty->ldisc.close) (tty);
tty->ldisc = ldiscs[N_TTY];
tty->termios->c_line = N_TTY;
if (tty->ldisc.open)
- tty->ldisc.open(tty);
+ (tty->ldisc.open) (tty);
}
if (info->blocked_open) {
if (info->close_delay) {
@@ -1140,7 +1123,6 @@
}
wake_up_interruptible(&info->open_wait);
}
-
info->flags &= ~(DZ_NORMAL_ACTIVE | DZ_CALLOUT_ACTIVE | DZ_CLOSING);
wake_up_interruptible(&info->close_wait);
@@ -1150,10 +1132,10 @@
/*
* dz_hangup () --- called by tty_hangup() when a hangup is signaled.
*/
-static void dz_hangup (struct tty_struct *tty)
+static void dz_hangup(struct tty_struct *tty)
{
struct dz_serial *info = (struct dz_serial *) tty->driver_data;
-
+
dz_flush_buffer(tty);
shutdown(info);
info->event = 0;
@@ -1168,10 +1150,9 @@
* rs_open() and friends
* ------------------------------------------------------------
*/
-static int block_til_ready(struct tty_struct *tty, struct file *filp,
- struct dz_serial *info)
+static int block_til_ready(struct tty_struct *tty, struct file *filp, struct dz_serial *info)
{
- DECLARE_WAITQUEUE(wait, current);
+ DECLARE_WAITQUEUE(wait, current);
int retval;
int do_clocal = 0;
@@ -1183,7 +1164,6 @@
interruptible_sleep_on(&info->close_wait);
return -EAGAIN;
}
-
/*
* If this is a callout device, then just make sure the normal
* device isn't being used.
@@ -1191,47 +1171,44 @@
if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
if (info->flags & DZ_NORMAL_ACTIVE)
return -EBUSY;
-
+
if ((info->flags & DZ_CALLOUT_ACTIVE) &&
(info->flags & DZ_SESSION_LOCKOUT) &&
(info->session != current->session))
return -EBUSY;
-
+
if ((info->flags & DZ_CALLOUT_ACTIVE) &&
(info->flags & DZ_PGRP_LOCKOUT) &&
(info->pgrp != current->pgrp))
return -EBUSY;
-
info->flags |= DZ_CALLOUT_ACTIVE;
return 0;
}
-
/*
- * If non-blocking mode is set, or the port is not enabled, then make
- * the check up front and then exit.
+ * If non-blocking mode is set, or the port is not enabled,
+ * then make the check up front and then exit.
*/
if ((filp->f_flags & O_NONBLOCK) ||
(tty->flags & (1 << TTY_IO_ERROR))) {
if (info->flags & DZ_CALLOUT_ACTIVE)
return -EBUSY;
info->flags |= DZ_NORMAL_ACTIVE;
-
return 0;
}
-
if (info->flags & DZ_CALLOUT_ACTIVE) {
if (info->normal_termios.c_cflag & CLOCAL)
do_clocal = 1;
} else {
if (tty->termios->c_cflag & CLOCAL)
- do_clocal = 1;
+ do_clocal = 1;
}
/*
- * Block waiting for the carrier detect and the line to become free
- * (i.e., not in use by the callout). While we are in this loop,
- * info->count is dropped by one, so that dz_close() knows when to free
- * things. We restore it upon exit, either normal or abnormal.
+ * Block waiting for the carrier detect and the line to become
+ * free (i.e., not in use by the callout). While we are in
+ * this loop, info->count is dropped by one, so that
+ * dz_close() knows when to free things. We restore it upon
+ * exit, either normal or abnormal.
*/
retval = 0;
add_wait_queue(&info->open_wait, &wait);
@@ -1240,7 +1217,7 @@
info->blocked_open++;
while (1) {
set_current_state(TASK_INTERRUPTIBLE);
- if (tty_hung_up_p (filp) || !(info->is_initialized)) {
+ if (tty_hung_up_p(filp) || !(info->is_initialized)) {
retval = -EAGAIN;
break;
}
@@ -1253,9 +1230,9 @@
}
schedule();
}
-
+
current->state = TASK_RUNNING;
- remove_wait_queue (&info->open_wait, &wait);
+ remove_wait_queue(&info->open_wait, &wait);
if (!tty_hung_up_p(filp))
info->count++;
info->blocked_open--;
@@ -1271,16 +1248,15 @@
* enables interrupts for a serial port. It also performs the
* serial-specific initialization for the tty structure.
*/
-static int dz_open (struct tty_struct *tty, struct file *filp)
+static int dz_open(struct tty_struct *tty, struct file *filp)
{
struct dz_serial *info;
int retval, line;
line = MINOR(tty->device) - tty->driver.minor_start;
- /*
- * The dz lines for the mouse/keyboard must be opened using their
- * respective drivers.
+ /* The dz lines for the mouse/keyboard must be
+ * opened using their respective drivers.
*/
if ((line < 0) || (line >= DZ_NB_PORT))
return -ENODEV;
@@ -1297,37 +1273,36 @@
/*
* Start up serial port
*/
- retval = startup (info);
+ retval = startup(info);
if (retval)
return retval;
- retval = block_til_ready (tty, filp, info);
+ retval = block_til_ready(tty, filp, info);
if (retval)
return retval;
if ((info->count == 1) && (info->flags & DZ_SPLIT_TERMIOS)) {
if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
*tty->termios = info->normal_termios;
- else
+ else
*tty->termios = info->callout_termios;
change_speed(info);
- }
+ }
info->session = current->session;
info->pgrp = current->pgrp;
-
return 0;
}
-static void show_serial_version (void)
+static void show_serial_version(void)
{
printk("%s%s\n", dz_name, dz_version);
}
-
int __init dz_init(void)
{
- int i, flags;
+ int i, tmp;
+ long flags;
struct dz_serial *info;
/* Setup base handler, and timer table. */
@@ -1374,8 +1349,8 @@
serial_driver.hangup = dz_hangup;
/*
- * The callout device is just like normal device except for major
- * number and the subtype code.
+ * The callout device is just like normal device except for
+ * major number and the subtype code.
*/
callout_driver = serial_driver;
#if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS))
@@ -1386,21 +1361,22 @@
callout_driver.major = TTYAUX_MAJOR;
callout_driver.subtype = SERIAL_TYPE_CALLOUT;
- if (tty_register_driver (&serial_driver))
- panic("Couldn't register serial driver\n");
- if (tty_register_driver (&callout_driver))
- panic("Couldn't register callout driver\n");
-
- save_flags(flags); cli();
- for (i=0; i < DZ_NB_PORT; i++) {
- info = &multi[i];
+ if (tty_register_driver(&serial_driver))
+ panic("Couldn't register serial driver");
+ if (tty_register_driver(&callout_driver))
+ panic("Couldn't register callout driver");
+ save_flags(flags);
+ cli();
+
+ for (i = 0; i < DZ_NB_PORT; i++) {
+ info = &multi[i];
lines[i] = info;
info->magic = SERIAL_MAGIC;
- if ((mips_machtype == MACH_DS23100) ||
- (mips_machtype == MACH_DS5100))
+ if (mips_machtype == MACH_DS23100 ||
+ mips_machtype == MACH_DS5100)
info->port = (unsigned long) KN01_DZ11_BASE;
- else
+ else
info->port = (unsigned long) KN02_DZ11_BASE;
info->line = i;
@@ -1417,76 +1393,71 @@
info->tqueue_hangup.data = info;
info->callout_termios = callout_driver.init_termios;
info->normal_termios = serial_driver.init_termios;
- init_waitqueue_head(&info->open_wait);
- init_waitqueue_head(&info->close_wait);
+ init_waitqueue_head(&info->open_wait);
+ init_waitqueue_head(&info->close_wait);
/*
* If we are pointing to address zero then punt - not correctly
* set up in setup.c to handle this.
*/
- if (! info->port)
+ if (!info->port)
return 0;
printk("ttyS%02d at 0x%08x (irq = %d)\n", info->line,
info->port, SERIAL);
tty_register_devfs(&serial_driver, 0,
- serial_driver.minor_start + info->line);
+ serial_driver.minor_start + info->line);
tty_register_devfs(&callout_driver, 0,
- callout_driver.minor_start + info->line);
+ callout_driver.minor_start + info->line);
}
- /* Reset the chip */
+ /* reset the chip */
#ifndef CONFIG_SERIAL_CONSOLE
- {
- int tmp;
- dz_out(info, DZ_CSR, DZ_CLR);
- while ((tmp = dz_in(info,DZ_CSR)) & DZ_CLR);
- wbflush();
-
- /* Enable scanning */
- dz_out(info, DZ_CSR, DZ_MSE);
- }
+ dz_out(info, DZ_CSR, DZ_CLR);
+ while ((tmp = dz_in(info, DZ_CSR)) & DZ_CLR);
+ wbflush();
+
+ /* enable scanning */
+ dz_out(info, DZ_CSR, DZ_MSE);
#endif
-
- /*
- * Order matters here... the trick is that flags is updated... in
- * request_irq - to immediatedly obliterate it is unwise.
- */
+
+ /* order matters here... the trick is that flags
+ is updated... in request_irq - to immediatedly obliterate
+ it is unwise. */
restore_flags(flags);
+
if (request_irq(SERIAL, dz_interrupt, SA_INTERRUPT, "DZ", lines[0]))
- panic("Unable to register DZ interrupt\n");
-
+ panic("Unable to register DZ interrupt");
+
return 0;
}
#ifdef CONFIG_SERIAL_CONSOLE
-static void dz_console_put_char (unsigned char ch)
+static void dz_console_put_char(unsigned char ch)
{
unsigned long flags;
- int loops = 2500;
+ int loops = 2500;
unsigned short tmp = ch;
- /*
- * this code sends stuff out to serial device - spinning its wheels and
- * waiting.
- */
+ /* this code sends stuff out to serial device - spinning its
+ wheels and waiting. */
- /* force the issue - point it at lines[3]*/
+ /* force the issue - point it at lines[3] */
dz_console = &multi[CONSOLE_LINE];
- save_and_cli(flags);
+ save_flags(flags);
+ cli();
+
/* spin our wheels */
- while (((dz_in(dz_console, DZ_CSR) & DZ_TRDY) != DZ_TRDY) && loops--)
- ;
-
+ while (((dz_in(dz_console, DZ_CSR) & DZ_TRDY) != DZ_TRDY) && loops--);
+
/* Actually transmit the character. */
dz_out(dz_console, DZ_TDR, tmp);
- restore_flags(flags);
+ restore_flags(flags);
}
-
/*
* -------------------------------------------------------------------
* dz_console_print ()
@@ -1495,12 +1466,12 @@
* The console must be locked when we get here.
* -------------------------------------------------------------------
*/
-static void dz_console_print (struct console *cons,
- const char *str,
- unsigned int count)
+static void dz_console_print(struct console *cons,
+ const char *str,
+ unsigned int count)
{
#ifdef DEBUG_DZ
- prom_printf((char *)str);
+ prom_printf((char *) str);
#endif
while (count--) {
if (*str == '\n')
@@ -1509,11 +1480,6 @@
}
}
-static int dz_console_wait_key(struct console *co)
-{
- return 0;
-}
-
static kdev_t dz_console_device(struct console *c)
{
return MKDEV(TTY_MAJOR, 64 + c->index);
@@ -1526,7 +1492,7 @@
int parity = 'n';
int cflag = CREAD | HUPCL | CLOCAL;
char *s;
- unsigned short mask,tmp;
+ unsigned short mask, tmp;
if (options) {
baud = simple_strtoul(options, NULL, 10);
@@ -1536,11 +1502,10 @@
if (*s)
parity = *s++;
if (*s)
- bits = *s - '0';
+ bits = *s - '0';
}
-
/*
- * Now construct a cflag setting.
+ * Now construct a cflag setting.
*/
switch (baud) {
case 1200:
@@ -1580,18 +1545,17 @@
/* TOFIX: force to console line */
dz_console = &multi[CONSOLE_LINE];
- if ((mips_machtype == MACH_DS23100) || (mips_machtype == MACH_DS5100))
+ if ((mips_machtype == MACH_DS23100) || (mips_machtype == MACH_DS5100))
dz_console->port = KN01_DZ11_BASE;
- else
- dz_console->port = KN02_DZ11_BASE;
+ else
+ dz_console->port = KN02_DZ11_BASE;
dz_console->line = CONSOLE_LINE;
dz_out(dz_console, DZ_CSR, DZ_CLR);
- while ((tmp = dz_in(dz_console,DZ_CSR)) & DZ_CLR)
- ;
+ while ((tmp = dz_in(dz_console, DZ_CSR)) & DZ_CLR);
/* enable scanning */
- dz_out(dz_console, DZ_CSR, DZ_MSE);
+ dz_out(dz_console, DZ_CSR, DZ_MSE);
/* Set up flags... */
dz_console->cflags = 0;
@@ -1601,20 +1565,19 @@
dz_out(dz_console, DZ_LPR, dz_console->cflags);
mask = 1 << dz_console->line;
- tmp = dz_in (dz_console, DZ_TCR); /* read the TX flag */
+ tmp = dz_in(dz_console, DZ_TCR); /* read the TX flag */
if (!(tmp & mask)) {
- tmp |= mask; /* set the TX flag */
- dz_out (dz_console, DZ_TCR, tmp);
+ tmp |= mask; /* set the TX flag */
+ dz_out(dz_console, DZ_TCR, tmp);
}
-
return 0;
}
-static struct console dz_sercons = {
+static struct console dz_sercons =
+{
name: "ttyS",
write: dz_console_print,
device: dz_console_device,
- wait_key: dz_console_wait_key,
setup: dz_console_setup,
flags: CON_CONSDEV | CON_PRINTBUFFER,
index: CONSOLE_LINE,
@@ -1625,6 +1588,6 @@
register_console(&dz_sercons);
}
-#endif /* ifdef CONFIG_SERIAL_CONSOLE */
+#endif /* CONFIG_SERIAL_CONSOLE */
MODULE_LICENSE("GPL");
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)