* Documentation/specialix.txt
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <asm/io.h>
#define RS_EVENT_WRITE_WAKEUP 0
static struct tty_driver *specialix_driver;
-static unsigned char * tmp_buf;
-
-static unsigned long baud_table[] = {
- 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
- 9600, 19200, 38400, 57600, 115200, 0,
-};
static struct specialix_board sx_board[SX_NBOARD] = {
{ 0, SX_IOBASE1, 9, },
#ifdef SPECIALIX_TIMER
static struct timer_list missed_irq_timer;
-static irqreturn_t sx_interrupt(int irq, void * dev_id, struct pt_regs * regs);
+static irqreturn_t sx_interrupt(int irq, void * dev_id);
#endif
if (irq) {
printk (KERN_INFO "Missed interrupt... Calling int from timer. \n");
sx_interrupt (((struct specialix_board *)data)->irq,
- (void*)data, NULL);
+ (void*)data);
}
missed_irq_timer.expires = jiffies + sx_poll;
add_timer (&missed_irq_timer);
/* The main interrupt processing routine */
-static irqreturn_t sx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sx_interrupt(int irq, void *dev_id)
{
unsigned char status;
unsigned char ack;
spin_lock_irqsave(&bp->lock, flags);
dprintk (SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __FUNCTION__, port_No(sx_get_port(bp, "INT")), SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1);
- if (!bp || !(bp->flags & SX_BOARD_ACTIVE)) {
+ if (!(bp->flags & SX_BOARD_ACTIVE)) {
dprintk (SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", irq);
spin_unlock_irqrestore(&bp->lock, flags);
func_exit();
return 0;
if (bp->flags & SX_BOARD_IS_PCI)
- error = request_irq(bp->irq, sx_interrupt, SA_INTERRUPT | SA_SHIRQ, "specialix IO8+", bp);
+ error = request_irq(bp->irq, sx_interrupt, IRQF_DISABLED | IRQF_SHARED, "specialix IO8+", bp);
else
- error = request_irq(bp->irq, sx_interrupt, SA_INTERRUPT, "specialix IO8+", bp);
+ error = request_irq(bp->irq, sx_interrupt, IRQF_DISABLED, "specialix IO8+", bp);
if (error)
return error;
port->MSVR = (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
spin_unlock_irqrestore(&bp->lock, flags);
dprintk (SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR);
- baud = C_BAUD(tty);
+ baud = tty_get_baud_rate(tty);
- if (baud & CBAUDEX) {
- baud &= ~CBAUDEX;
- if (baud < 1 || baud > 2)
- port->tty->termios->c_cflag &= ~CBAUDEX;
- else
- baud += 15;
- }
- if (baud == 15) {
+ if (baud == 38400) {
if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
- baud ++;
+ baud = 57600;
if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
- baud += 2;
+ baud = 115200;
}
-
- if (!baud_table[baud]) {
+ if (!baud) {
/* Drop DTR & exit */
dprintk (SX_DEBUG_TERMIOS, "Dropping DTR... Hmm....\n");
if (!SX_CRTSCTS (tty)) {
"This is an untested option, please be carefull.\n",
port_No (port), tmp);
else
- tmp = (((SX_OSCFREQ + baud_table[baud]/2) / baud_table[baud] +
+ tmp = (((SX_OSCFREQ + baud/2) / baud +
CD186x_TPC/2) / CD186x_TPC);
if ((tmp < 0x10) && time_before(again, jiffies)) {
sx_out(bp, CD186x_RBPRL, tmp & 0xff);
sx_out(bp, CD186x_TBPRL, tmp & 0xff);
spin_unlock_irqrestore(&bp->lock, flags);
- if (port->custom_divisor) {
+ if (port->custom_divisor)
baud = (SX_OSCFREQ + port->custom_divisor/2) / port->custom_divisor;
- baud = ( baud + 5 ) / 10;
- } else
- baud = (baud_table[baud] + 5) / 10; /* Estimated CPS */
+ baud = (baud + 5) / 10; /* Estimated CPS */
/* Two timer ticks seems enough to wakeup something like SLIP driver */
tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO;
bp = port_Board(port);
- if (!tty || !port->xmit_buf || !tmp_buf) {
+ if (!port->xmit_buf) {
func_exit();
return 0;
}
return;
}
dprintk (SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf);
- if (!tty || !port->xmit_buf) {
+ if (!port->xmit_buf) {
func_exit();
return;
}
* do_sx_hangup() -> tty->hangup() -> sx_hangup()
*
*/
-static void do_sx_hangup(void *private_)
+static void do_sx_hangup(struct work_struct *work)
{
- struct specialix_port *port = (struct specialix_port *) private_;
+ struct specialix_port *port =
+ container_of(work, struct specialix_port, tqueue_hangup);
struct tty_struct *tty;
func_enter();
}
-static void sx_set_termios(struct tty_struct * tty, struct termios * old_termios)
+static void sx_set_termios(struct tty_struct * tty, struct ktermios * old_termios)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
unsigned long flags;
}
-static void do_softint(void *private_)
+static void do_softint(struct work_struct *work)
{
- struct specialix_port *port = (struct specialix_port *) private_;
+ struct specialix_port *port =
+ container_of(work, struct specialix_port, tqueue);
struct tty_struct *tty;
func_enter();
func_exit();
}
-static struct tty_operations sx_ops = {
+static const struct tty_operations sx_ops = {
.open = sx_open,
.close = sx_close,
.write = sx_write,
return 1;
}
- if (!(tmp_buf = (unsigned char *) get_zeroed_page(GFP_KERNEL))) {
- printk(KERN_ERR "sx: Couldn't get free page.\n");
- put_tty_driver(specialix_driver);
- func_exit();
- return 1;
- }
specialix_driver->owner = THIS_MODULE;
specialix_driver->name = "ttyW";
specialix_driver->major = SPECIALIX_NORMAL_MAJOR;
specialix_driver->init_termios = tty_std_termios;
specialix_driver->init_termios.c_cflag =
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ specialix_driver->init_termios.c_ispeed = 9600;
+ specialix_driver->init_termios.c_ospeed = 9600;
specialix_driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(specialix_driver, &sx_ops);
if ((error = tty_register_driver(specialix_driver))) {
put_tty_driver(specialix_driver);
- free_page((unsigned long)tmp_buf);
printk(KERN_ERR "sx: Couldn't register specialix IO8+ driver, error = %d\n",
error);
func_exit();
memset(sx_port, 0, sizeof(sx_port));
for (i = 0; i < SX_NPORT * SX_NBOARD; i++) {
sx_port[i].magic = SPECIALIX_MAGIC;
- INIT_WORK(&sx_port[i].tqueue, do_softint, &sx_port[i]);
- INIT_WORK(&sx_port[i].tqueue_hangup, do_sx_hangup, &sx_port[i]);
+ INIT_WORK(&sx_port[i].tqueue, do_softint);
+ INIT_WORK(&sx_port[i].tqueue_hangup, do_sx_hangup);
sx_port[i].close_delay = 50 * HZ/100;
sx_port[i].closing_wait = 3000 * HZ/100;
init_waitqueue_head(&sx_port[i].open_wait);
{
func_enter();
- free_page((unsigned long)tmp_buf);
tty_unregister_driver(specialix_driver);
put_tty_driver(specialix_driver);
func_exit();
#endif
for (i = 0; i < SX_NBOARD; i++)
- sx_board[i].lock = SPIN_LOCK_UNLOCKED;
+ spin_lock_init(&sx_board[i].lock);
if (sx_init_drivers()) {
func_exit();
i++;
continue;
}
- pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX,
+ pdev = pci_get_device (PCI_VENDOR_ID_SPECIALIX,
PCI_DEVICE_ID_SPECIALIX_IO8,
pdev);
if (!pdev) break;
if (!sx_probe(&sx_board[i]))
found ++;
}
+ /* May exit pci_get sequence early with lots of boards */
+ if (pdev != NULL)
+ pci_dev_put(pdev);
}
#endif
func_exit();
}
+static struct pci_device_id specialx_pci_tbl[] __devinitdata = {
+ { PCI_DEVICE(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_IO8) },
+ { }
+};
+MODULE_DEVICE_TABLE(pci, specialx_pci_tbl);
+
module_init(specialix_init_module);
module_exit(specialix_exit_module);