Commit f4861b30 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] tty_driver refcounting

drivers/char/epca.c converted to dynamic allocation
parent 5d85b66a
......@@ -97,8 +97,8 @@ static struct board_info boards[MAXBOARDS];
/* ------------- Begin structures used for driver registeration ---------- */
struct tty_driver pc_driver;
struct tty_driver pc_info;
static struct tty_driver *pc_driver;
static struct tty_driver *pc_info;
/* ------------------ Begin Digi specific structures -------------------- */
......@@ -204,6 +204,8 @@ static void epcaparam(struct tty_struct *, struct channel *);
static void receive_data(struct channel *);
static int pc_ioctl(struct tty_struct *, struct file *,
unsigned int, unsigned long);
static int info_ioctl(struct tty_struct *, struct file *,
unsigned int, unsigned long);
static void pc_set_termios(struct tty_struct *, struct termios *);
static void do_softint(void *);
static void pc_stop(struct tty_struct *);
......@@ -491,12 +493,6 @@ static void pc_close(struct tty_struct * tty, struct file * filp)
struct channel *ch;
unsigned long flags;
if (tty->driver->subtype == SERIAL_TYPE_INFO)
{
return;
}
/* ---------------------------------------------------------
verifyChannel returns the channel from the tty struct
if it is valid. This serves as a sanity check.
......@@ -704,13 +700,6 @@ static int pc_write(struct tty_struct * tty, int from_user,
brought into the driver.
------------------------------------------------------------------- */
/* Stop users from hurting themselves on control minor */
if (tty->driver->subtype == SERIAL_TYPE_INFO)
{
return (0) ;
}
/* ---------------------------------------------------------
verifyChannel returns the channel from the tty struct
if it is valid. This serves as a sanity check.
......@@ -1306,13 +1295,6 @@ static int pc_open(struct tty_struct *tty, struct file * filp)
volatile struct board_chan *bc;
volatile unsigned int head;
/* Nothing "real" happens in open of control device */
if (tty->driver->subtype == SERIAL_TYPE_INFO)
{
return (0) ;
}
line = tty->index;
if (line < 0 || line >= nbdevs)
{
......@@ -1485,13 +1467,15 @@ static void __exit epca_module_exit(void)
save_flags(flags);
cli();
if ((tty_unregister_driver(&pc_driver)) ||
(tty_unregister_driver(&pc_info)))
if ((tty_unregister_driver(pc_driver)) ||
(tty_unregister_driver(pc_info)))
{
printk(KERN_WARNING "<Error> - DIGI : cleanup_module failed to un-register tty driver\n");
restore_flags(flags);
return;
}
put_tty_driver(pc_driver);
put_tty_driver(pc_info);
for (crd = 0; crd < num_cards; crd++)
{ /* Begin for each card */
......@@ -1529,6 +1513,34 @@ static void __exit epca_module_exit(void)
module_exit(epca_module_exit);
#endif /* MODULE */
static struct tty_operations pc_ops = {
.open = pc_open,
.close = pc_close,
.write = pc_write,
.write_room = pc_write_room,
.flush_buffer = pc_flush_buffer,
.chars_in_buffer = pc_chars_in_buffer,
.flush_chars = pc_flush_chars,
.put_char = pc_put_char,
.ioctl = pc_ioctl,
.set_termios = pc_set_termios,
.stop = pc_stop,
.start = pc_start,
.throttle = pc_throttle,
.unthrottle = pc_unthrottle,
.hangup = pc_hangup,
};
static int info_open(struct tty_struct *tty, struct file * filp)
{
return 0;
}
static struct tty_operations info_ops = {
.open = info_open,
.ioctl = info_ioctl,
};
/* ------------------ Begin pc_init ---------------------- */
int __init pc_init(void)
......@@ -1553,7 +1565,6 @@ int __init pc_init(void)
int crd;
struct board_info *bd;
unsigned char board_id = 0;
#ifdef ENABLE_PCI
int pci_boards_found, pci_count;
......@@ -1561,6 +1572,16 @@ int __init pc_init(void)
pci_count = 0;
#endif /* ENABLE_PCI */
pc_driver = alloc_tty_driver(MAX_ALLOC);
if (!pc_driver)
return -ENOMEM;
pc_info = alloc_tty_driver(MAX_ALLOC);
if (!pc_info) {
put_tty_driver(pc_driver);
return -ENOMEM;
}
/* -----------------------------------------------------------------------
If epca_setup has not been ran by LILO set num_cards to defaults; copy
board structure defined by digiConfig into drivers board structure.
......@@ -1620,53 +1641,33 @@ int __init pc_init(void)
#endif /* ENABLE_PCI */
memset(&pc_driver, 0, sizeof(struct tty_driver));
memset(&pc_info, 0, sizeof(struct tty_driver));
pc_driver.magic = TTY_DRIVER_MAGIC;
pc_driver.owner = THIS_MODULE;
pc_driver.name = "ttyD";
pc_driver.major = DIGI_MAJOR;
pc_driver.minor_start = 0;
pc_driver.num = MAX_ALLOC;
pc_driver.type = TTY_DRIVER_TYPE_SERIAL;
pc_driver.subtype = SERIAL_TYPE_NORMAL;
pc_driver.init_termios = tty_std_termios;
pc_driver.init_termios.c_iflag = 0;
pc_driver.init_termios.c_oflag = 0;
pc_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
pc_driver.init_termios.c_lflag = 0;
pc_driver.flags = TTY_DRIVER_REAL_RAW;
/* ------------------------------------------------------------------
Setup entry points for the driver. These are primarily called by
the kernel in tty_io.c and n_tty.c
--------------------------------------------------------------------- */
pc_driver.open = pc_open;
pc_driver.close = pc_close;
pc_driver.write = pc_write;
pc_driver.write_room = pc_write_room;
pc_driver.flush_buffer = pc_flush_buffer;
pc_driver.chars_in_buffer = pc_chars_in_buffer;
pc_driver.flush_chars = pc_flush_chars;
pc_driver.put_char = pc_put_char;
pc_driver.ioctl = pc_ioctl;
pc_driver.set_termios = pc_set_termios;
pc_driver.stop = pc_stop;
pc_driver.start = pc_start;
pc_driver.throttle = pc_throttle;
pc_driver.unthrottle = pc_unthrottle;
pc_driver.hangup = pc_hangup;
pc_info = pc_driver;
pc_info.name = "digi_ctl";
pc_info.major = DIGIINFOMAJOR;
pc_info.minor_start = 0;
pc_info.num = 1;
pc_info.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
pc_info.subtype = SERIAL_TYPE_INFO;
pc_driver->owner = THIS_MODULE;
pc_driver->name = "ttyD";
pc_driver->major = DIGI_MAJOR;
pc_driver->minor_start = 0;
pc_driver->type = TTY_DRIVER_TYPE_SERIAL;
pc_driver->subtype = SERIAL_TYPE_NORMAL;
pc_driver->init_termios = tty_std_termios;
pc_driver->init_termios.c_iflag = 0;
pc_driver->init_termios.c_oflag = 0;
pc_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
pc_driver->init_termios.c_lflag = 0;
pc_driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(pc_driver, &pc_ops);
pc_info->owner = THIS_MODULE;
pc_info->name = "digi_ctl";
pc_info->major = DIGIINFOMAJOR;
pc_info->minor_start = 0;
pc_info->type = TTY_DRIVER_TYPE_SERIAL;
pc_info->subtype = SERIAL_TYPE_INFO;
pc_info->init_termios = tty_std_termios;
pc_info->init_termios.c_iflag = 0;
pc_info->init_termios.c_oflag = 0;
pc_info->init_termios.c_lflag = 0;
pc_info->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
pc_info->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(pc_info, &info_ops);
save_flags(flags);
......@@ -1791,10 +1792,10 @@ int __init pc_init(void)
} /* End for each card */
if (tty_register_driver(&pc_driver))
if (tty_register_driver(pc_driver))
panic("Couldn't register Digi PC/ driver");
if (tty_register_driver(&pc_info))
if (tty_register_driver(pc_info))
panic("Couldn't register Digi PC/ info ");
/* -------------------------------------------------------------------
......@@ -2845,103 +2846,102 @@ static void receive_data(struct channel *ch)
} /* End receive_data */
/* --------------------- Begin pc_ioctl ----------------------- */
static int pc_ioctl(struct tty_struct *tty, struct file * file,
static int info_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
{ /* Begin pc_ioctl */
digiflow_t dflow;
int retval, error;
unsigned long flags;
unsigned int mflag, mstat;
unsigned char startc, stopc;
volatile struct board_chan *bc;
struct channel *ch = (struct channel *) tty->driver_data;
{
int error;
/* The control device has it's own set of commands */
if (tty->driver->subtype == SERIAL_TYPE_INFO)
{ /* Begin if subtype is the control device */
switch (cmd)
{ /* Begin switch cmd */
switch (cmd)
{ /* Begin switch cmd */
case DIGI_GETINFO:
{ /* Begin case DIGI_GETINFO */
case DIGI_GETINFO:
{ /* Begin case DIGI_GETINFO */
struct digi_info di ;
int brd;
struct digi_info di ;
int brd;
getUser(brd, (unsigned int *)arg);
getUser(brd, (unsigned int *)arg);
if ((error = verify_area(VERIFY_WRITE, (char*)arg, sizeof(di))))
{
printk(KERN_ERR "DIGI_GETINFO : verify area size 0x%x failed\n",sizeof(di));
return(error);
}
if ((error = verify_area(VERIFY_WRITE, (char*)arg, sizeof(di))))
{
printk(KERN_ERR "DIGI_GETINFO : verify area size 0x%x failed\n",sizeof(di));
return(error);
}
if ((brd < 0) || (brd >= num_cards) || (num_cards == 0))
return (-ENODEV);
if ((brd < 0) || (brd >= num_cards) || (num_cards == 0))
return (-ENODEV);
memset(&di, 0, sizeof(di));
memset(&di, 0, sizeof(di));
di.board = brd ;
di.status = boards[brd].status;
di.type = boards[brd].type ;
di.numports = boards[brd].numports ;
di.port = boards[brd].port ;
di.membase = boards[brd].membase ;
di.board = brd ;
di.status = boards[brd].status;
di.type = boards[brd].type ;
di.numports = boards[brd].numports ;
di.port = boards[brd].port ;
di.membase = boards[brd].membase ;
if (copy_to_user((char *)arg, &di, sizeof (di)))
return -EFAULT;
break;
if (copy_to_user((char *)arg, &di, sizeof (di)))
return -EFAULT;
break;
} /* End case DIGI_GETINFO */
} /* End case DIGI_GETINFO */
case DIGI_POLLER:
{ /* Begin case DIGI_POLLER */
case DIGI_POLLER:
{ /* Begin case DIGI_POLLER */
int brd = arg & 0xff000000 >> 16 ;
unsigned char state = arg & 0xff ;
int brd = arg & 0xff000000 >> 16 ;
unsigned char state = arg & 0xff ;
if ((brd < 0) || (brd >= num_cards))
{
printk(KERN_ERR "<Error> - DIGI POLLER : brd not valid!\n");
return (-ENODEV);
}
if ((brd < 0) || (brd >= num_cards))
{
printk(KERN_ERR "<Error> - DIGI POLLER : brd not valid!\n");
return (-ENODEV);
}
digi_poller_inhibited = state ;
break ;
digi_poller_inhibited = state ;
break ;
} /* End case DIGI_POLLER */
} /* End case DIGI_POLLER */
case DIGI_INIT:
{ /* Begin case DIGI_INIT */
case DIGI_INIT:
{ /* Begin case DIGI_INIT */
/* ------------------------------------------------------------
This call is made by the apps to complete the initilization
of the board(s). This routine is responsible for setting
the card to its initial state and setting the drivers control
fields to the sutianle settings for the card in question.
---------------------------------------------------------------- */
int crd ;
for (crd = 0; crd < num_cards; crd++)
post_fep_init (crd);
/* ------------------------------------------------------------
This call is made by the apps to complete the initilization
of the board(s). This routine is responsible for setting
the card to its initial state and setting the drivers control
fields to the sutianle settings for the card in question.
---------------------------------------------------------------- */
int crd ;
for (crd = 0; crd < num_cards; crd++)
post_fep_init (crd);
break ;
break ;
} /* End case DIGI_INIT */
} /* End case DIGI_INIT */
default:
return -ENOIOCTLCMD;
default:
return -ENOIOCTLCMD;
} /* End switch cmd */
return (0) ;
} /* End switch cmd */
return (0) ;
}
/* --------------------- Begin pc_ioctl ----------------------- */
} /* End if subtype is the control device */
static int pc_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
{ /* Begin pc_ioctl */
digiflow_t dflow;
int retval, error;
unsigned long flags;
unsigned int mflag, mstat;
unsigned char startc, stopc;
volatile struct board_chan *bc;
struct channel *ch = (struct channel *) tty->driver_data;
if (ch)
bc = ch->brdchan;
else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment