#define InterruptTheCard(base) outw(0, (base) + 0xc)
#define ClearInterrupt(base) inw((base) + 0x0a)
+#define pr_dbg(str...) pr_debug("ISICOM: " str)
#ifdef DEBUG
-#define pr_dbg(str...) printk(KERN_DEBUG "ISICOM: " str)
#define isicom_paranoia_check(a, b, c) __isicom_paranoia_check((a), (b), (c))
#else
-#define pr_dbg(str...) do { } while (0)
#define isicom_paranoia_check(a, b, c) 0
#endif
static int prev_card = 3; /* start servicing isi_card[0] */
static struct tty_driver *isicom_normal;
-static DECLARE_COMPLETION(isi_timerdone);
-static char re_schedule = 1;
-
static void isicom_tx(unsigned long _data);
static void isicom_start(struct tty_struct *tty);
struct isi_board {
unsigned long base;
- unsigned char irq;
+ int irq;
unsigned char port_count;
unsigned short status;
unsigned short port_status; /* each bit for each port */
* it wants to talk.
*/
-static inline int WaitTillCardIsFree(u16 base)
+static inline int WaitTillCardIsFree(unsigned long base)
{
unsigned int count = 0;
unsigned int a = in_atomic(); /* do we run under spinlock? */
static int lock_card(struct isi_board *card)
{
- char retries;
unsigned long base = card->base;
+ unsigned int retries, a;
- for (retries = 0; retries < 100; retries++) {
+ for (retries = 0; retries < 10; retries++) {
spin_lock_irqsave(&card->card_lock, card->flags);
- if (inw(base + 0xe) & 0x1) {
- return 1;
- } else {
- spin_unlock_irqrestore(&card->card_lock, card->flags);
- udelay(1000); /* 1ms */
+ for (a = 0; a < 10; a++) {
+ if (inw(base + 0xe) & 0x1)
+ return 1;
+ udelay(10);
}
+ spin_unlock_irqrestore(&card->card_lock, card->flags);
+ msleep(10);
}
printk(KERN_WARNING "ISICOM: Failed to lock Card (0x%lx)\n",
card->base);
return 0; /* Failed to acquire the card! */
}
-static int lock_card_at_interrupt(struct isi_board *card)
-{
- unsigned char retries;
- unsigned long base = card->base;
-
- for (retries = 0; retries < 200; retries++) {
- spin_lock_irqsave(&card->card_lock, card->flags);
-
- if (inw(base + 0xe) & 0x1)
- return 1;
- else
- spin_unlock_irqrestore(&card->card_lock, card->flags);
- }
- /* Failing in interrupt is an acceptable event */
- return 0; /* Failed to acquire the card! */
-}
-
static void unlock_card(struct isi_board *card)
{
spin_unlock_irqrestore(&card->card_lock, card->flags);
static void isicom_tx(unsigned long _data)
{
- short count = (BOARD_COUNT-1), card, base;
+ unsigned long flags, base;
+ unsigned int retries;
+ short count = (BOARD_COUNT-1), card;
short txcount, wrd, residue, word_count, cnt;
struct isi_port *port;
struct tty_struct *tty;
count = isi_card[card].port_count;
port = isi_card[card].ports;
base = isi_card[card].base;
+
+ spin_lock_irqsave(&isi_card[card].card_lock, flags);
+ for (retries = 0; retries < 100; retries++) {
+ if (inw(base + 0xe) & 0x1)
+ break;
+ udelay(2);
+ }
+ if (retries >= 100)
+ goto unlock;
+
for (;count > 0;count--, port++) {
- if (!lock_card_at_interrupt(&isi_card[card]))
- continue;
/* port not active or tx disabled to force flow control */
if (!(port->flags & ASYNC_INITIALIZED) ||
!(port->status & ISI_TXOK))
- unlock_card(&isi_card[card]);
continue;
tty = port->tty;
-
- if (tty == NULL) {
- unlock_card(&isi_card[card]);
+ if (tty == NULL)
continue;
- }
txcount = min_t(short, TX_SIZE, port->xmit_cnt);
- if (txcount <= 0 || tty->stopped || tty->hw_stopped) {
- unlock_card(&isi_card[card]);
+ if (txcount <= 0 || tty->stopped || tty->hw_stopped)
continue;
- }
- if (!(inw(base + 0x02) & (1 << port->channel))) {
- unlock_card(&isi_card[card]);
+
+ if (!(inw(base + 0x02) & (1 << port->channel)))
continue;
- }
+
pr_dbg("txing %d bytes, port%d.\n", txcount,
port->channel + 1);
outw((port->channel << isi_card[card].shift_count) | txcount,
port->status &= ~ISI_TXOK;
if (port->xmit_cnt <= WAKEUP_CHARS)
tty_wakeup(tty);
- unlock_card(&isi_card[card]);
}
+unlock:
+ spin_unlock_irqrestore(&isi_card[card].card_lock, flags);
/* schedule another tx for hopefully in about 10ms */
sched_again:
- if (!re_schedule) {
- complete(&isi_timerdone);
- return;
- }
-
mod_timer(&tx, jiffies + msecs_to_jiffies(10));
}
portcount = inw(base + 0x2);
if (!inw(base + 0xe) & 0x1 || (portcount != 0 && portcount != 4 &&
portcount != 8 && portcount != 16)) {
- dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure.",
+ dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure.\n",
card + 1);
retval = -EIO;
goto end;
if ((status = inw(base + 0x4)) != 0) {
dev_warn(&pdev->dev, "Card%d rejected load header:\n"
- "Address:0x%x\nCount:0x%x\nStatus:0x%x\n",
+ KERN_WARNING "Address:0x%x\n"
+ KERN_WARNING "Count:0x%x\n"
+ KERN_WARNING "Status:0x%x\n",
index + 1, frame->addr, frame->count, status);
goto errrelfw;
}
if ((status = inw(base + 0x4)) != 0) {
dev_warn(&pdev->dev, "Card%d rejected verify header:\n"
- "Address:0x%x\nCount:0x%x\nStatus: 0x%x\n",
+ KERN_WARNING "Address:0x%x\n"
+ KERN_WARNING "Count:0x%x\n"
+ KERN_WARNING "Status: 0x%x\n",
index + 1, frame->addr, frame->count, status);
goto errrelfw;
}
static int __devinit isicom_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
- unsigned int ioaddr, signature, index;
+ unsigned int signature, index;
int retval = -EPERM;
- u8 pciirq;
struct isi_board *board = NULL;
if (card_count >= BOARD_COUNT)
goto err;
- ioaddr = pci_resource_start(pdev, 3);
- /* i.e at offset 0x1c in the PCI configuration register space. */
- pciirq = pdev->irq;
dev_info(&pdev->dev, "ISI PCI Card(Device ID 0x%x)\n", ent->device);
/* allot the first empty slot in the array */
}
board->index = index;
- board->base = ioaddr;
- board->irq = pciirq;
+ board->base = pci_resource_start(pdev, 3);
+ board->irq = pdev->irq;
card_count++;
pci_set_drvdata(pdev, board);
static void __exit isicom_exit(void)
{
- re_schedule = 0;
-
- wait_for_completion_timeout(&isi_timerdone, HZ);
+ del_timer_sync(&tx);
pci_unregister_driver(&isicom_driver);
tty_unregister_driver(isicom_normal);