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