/* baud index mappings from linux defns to isi */
static signed char linuxb_to_isib[] = {
- -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17, 18, 19
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17, 18, 19, 20, 21
};
struct isi_board {
return IRQ_NONE;
base = card->base;
+
+ /* did the card interrupt us? */
+ if (!(inw(base + 0x0e) & 0x02))
+ return IRQ_NONE;
+
spin_lock(&card->card_lock);
/*
* respectively.
*/
- if (baud < 1 || baud > 2)
+ /* 1,2,3,4 => 57.6, 115.2, 230, 460 kbps resp. */
+ if (baud < 1 || baud > 4)
port->tty->termios->c_cflag &= ~CBAUDEX;
else
baud += 15;
baud++; /* 57.6 Kbps */
if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
baud +=2; /* 115 Kbps */
+ if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+ baud += 3; /* 230 kbps*/
+ if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+ baud += 4; /* 460 kbps*/
}
if (linuxb_to_isib[baud] == -1) {
/* hang up */
port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
spin_unlock_irqrestore(&card->card_lock, flags);
- wake_up_interruptible(&tty->write_wait);
tty_wakeup(tty);
}
{
struct isi_board *board = pci_get_drvdata(pdev);
unsigned long base = board->base;
- unsigned int portcount = 0;
+ unsigned int sig, portcount = 0;
int retval = 0;
dev_dbg(&pdev->dev, "ISILoad:Resetting Card%d at 0x%lx\n", card + 1,
inw(base + 0x8);
- mdelay(10);
+ msleep(10);
outw(0, base + 0x8); /* Reset */
- msleep(3000);
+ msleep(1000);
+
+ sig = inw(base + 0x4) & 0xff;
+
+ if (sig != 0xa5 && sig != 0xbb && sig != 0xcc && sig != 0xdd &&
+ sig != 0xee) {
+ dev_warn(&pdev->dev, "ISILoad:Card%u reset failure (Possible "
+ "bad I/O Port Address 0x%lx).\n", card + 1, base);
+ dev_dbg(&pdev->dev, "Sig=0x%x\n", sig);
+ retval = -EIO;
+ goto end;
+ }
- *signature = inw(base + 0x4) & 0xff;
+ msleep(10);
portcount = inw(base + 0x2);
- if (!(inw(base + 0xe) & 0x1) || ((portcount != 0) &&
- (portcount != 4) && (portcount != 8))) {
- dev_dbg(&pdev->dev, "base+0x2=0x%lx, base+0xe=0x%lx\n",
- inw(base + 0x2), inw(base + 0xe));
- dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure "
- "(Possible bad I/O Port Address 0x%lx).\n",
- card + 1, base);
+ if (!inw(base + 0xe) & 0x1 || (portcount != 0 && portcount != 4 &&
+ portcount != 8 && portcount != 16)) {
+ dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure.",
+ card + 1);
retval = -EIO;
goto end;
}
- switch (*signature) {
+ switch (sig) {
case 0xa5:
case 0xbb:
case 0xdd:
board->shift_count = 12;
break;
case 0xcc:
+ case 0xee:
board->port_count = 16;
board->shift_count = 11;
break;
- default:
- dev_warn(&pdev->dev, "ISILoad:Card%d reset failure (Possible "
- "bad I/O Port Address 0x%lx).\n", card + 1, base);
- dev_dbg(&pdev->dev, "Sig=0x%lx\n", signature);
- retval = -EIO;
}
dev_info(&pdev->dev, "-Done\n");
+ *signature = sig;
end:
return retval;
/*
* Insmod can set static symbols so keep these static
*/
-static int card;
+static unsigned int card_count;
static int __devinit isicom_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
u8 pciirq;
struct isi_board *board = NULL;
- if (card >= BOARD_COUNT)
+ if (card_count >= BOARD_COUNT)
goto err;
ioaddr = pci_resource_start(pdev, 3);
board->index = index;
board->base = ioaddr;
board->irq = pciirq;
- card++;
+ card_count++;
pci_set_drvdata(pdev, board);
"will be disabled.\n", board->base, board->base + 15,
index + 1);
retval = -EBUSY;
- goto err;
+ goto errdec;
}
retval = request_irq(board->irq, isicom_interrupt,
free_irq(board->irq, board);
errunrr:
pci_release_region(pdev, 3);
-err:
+errdec:
board->base = 0;
+ card_count--;
+err:
return retval;
}
free_irq(board->irq, board);
pci_release_region(pdev, 3);
+ board->base = 0;
+ card_count--;
}
static int __init isicom_init(void)
int retval, idx, channel;
struct isi_port *port;
- card = 0;
-
for(idx = 0; idx < BOARD_COUNT; idx++) {
port = &isi_ports[idx * 16];
isi_card[idx].ports = port;