patch-2.2.18 linux/include/linux/isicom.h
Next file: linux/include/linux/ixjuser.h
Previous file: linux/include/linux/isdnif.h
Back to the patch index
Back to the overall index
- Lines: 299
- Date:
Wed Jun 21 06:42:02 2000
- Orig file:
v2.2.17/include/linux/isicom.h
- Orig date:
Fri Apr 21 12:46:59 2000
diff -u --new-file --recursive --exclude-from /usr/src/exclude v2.2.17/include/linux/isicom.h linux/include/linux/isicom.h
@@ -55,7 +55,6 @@
* PCI definitions
*/
- #define DEVID_COUNT 9
#define VENDOR_ID 0x10b5
/*
@@ -137,6 +136,8 @@
struct isi_port * ports;
signed char count;
unsigned char isa;
+ spinlock_t card_lock; /* Card wide lock 11/5/00 -sameer */
+ unsigned long flags;
};
struct isi_port {
@@ -164,6 +165,70 @@
struct termios callout_termios;
};
+/*
+ * Locking/UnLocking primitives...
+ */
+
+extern inline unsigned char lock_card(struct isi_board *card)
+{
+ char retries;
+ unsigned short base = card->base;
+
+ for (retries = 0; retries < 100; retries++) {
+ spin_lock_irqsave(&card->card_lock, card->flags);
+
+ if (inw(base + 0xe) & 0x1) {
+#ifdef ISICOM_DEBUG
+/* printk(KERN_DEBUG "ISICOM:lock_card(0x%x)\n",
+ card->base);*/
+#endif
+ return 1;
+ }
+ else {
+ spin_unlock_irqrestore(&card->card_lock, card->flags);
+ schedule_timeout(HZ/100); /* 10ms */
+ }
+ }
+#ifdef ISICOM_DEBUG
+ printk(KERN_WARNING "ISICOM: Failed to lock Card (0x%x)\n", card->base);
+#endif /* ISICOM_DEBUG */
+ return 0; /* Failed to aquire the card! */
+}
+
+extern inline unsigned char lock_card_at_interrupt(struct isi_board *card)
+{
+ unsigned char retries;
+ unsigned short base = card->base;
+
+ for (retries = 0; retries < 200; retries++) {
+ spin_lock_irqsave(&card->card_lock, card->flags);
+
+ if (inw(base + 0xe) & 0x1) {
+#ifdef ISICOM_DEBUG
+/* printk(KERN_DEBUG "ISICOM:lock_card_at_interrupt(0x%x)"
+ "\n",
+ card->base);*/
+#endif
+ return 1;
+ }
+ else {
+ spin_unlock_irqrestore(&card->card_lock, card->flags);
+ }
+ }
+#ifdef ISICOM_DEBUG
+ printk(KERN_WARNING "ISICOM: Failed to lock Card (0x%x)\n", card->base);
+#endif /* ISICOM_DEBUG */
+ return 0; /* Failed to aquire the card! */
+}
+
+extern inline void unlock_card(struct isi_board *card)
+{
+ spin_unlock_irqrestore(&card->card_lock, card->flags);
+#ifdef ISICOM_DEBUG
+/* printk(KERN_DEBUG "ISICOM:unlock_card(0x%x)\n",
+ card->base);*/
+#endif
+}
/*
* ISI Card specific ops ...
@@ -174,12 +239,18 @@
struct isi_board * card = port->card;
unsigned short base = card->base;
unsigned char channel = port->channel;
- short wait=400;
+
+/* short wait=400; SMPCHG
while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
if (wait <= 0) {
printk(KERN_WARNING "ISICOM: Card found busy in raise_dtr.\n");
return;
}
+*/
+ if (!lock_card(card)) {
+ printk(KERN_WARNING "ISICOM: Card found busy in raise_dtr.\n");
+ return;
+ }
#ifdef ISICOM_DEBUG_DTR_RTS
printk(KERN_DEBUG "ISICOM: raise_dtr.\n");
#endif
@@ -187,6 +258,7 @@
outw(0x0504, base);
InterruptTheCard(base);
port->status |= ISI_DTR;
+ unlock_card(card);
}
extern inline void drop_dtr(struct isi_port * port)
@@ -194,12 +266,18 @@
struct isi_board * card = port->card;
unsigned short base = card->base;
unsigned char channel = port->channel;
- short wait=400;
+
+/* short wait=400; SMPCHG
while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
if (wait <= 0) {
printk(KERN_WARNING "ISICOM: Card found busy in drop_dtr.\n");
return;
}
+*/
+ if (!lock_card(card)) {
+ printk(KERN_WARNING "ISICOM: Card found busy in drop_dtr.\n");
+ return;
+ }
#ifdef ISICOM_DEBUG_DTR_RTS
printk(KERN_DEBUG "ISICOM: drop_dtr.\n");
#endif
@@ -207,18 +285,25 @@
outw(0x0404, base);
InterruptTheCard(base);
port->status &= ~ISI_DTR;
+ unlock_card(card);
}
extern inline void raise_rts(struct isi_port * port)
{
struct isi_board * card = port->card;
unsigned short base = card->base;
unsigned char channel = port->channel;
- short wait=400;
+
+/* short wait=400; SMPCHG
while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
if (wait <= 0) {
printk(KERN_WARNING "ISICOM: Card found busy in raise_rts.\n");
return;
}
+*/
+ if (!lock_card(card)) {
+ printk(KERN_WARNING "ISICOM: Card found busy in raise_rts.\n");
+ return;
+ }
#ifdef ISICOM_DEBUG_DTR_RTS
printk(KERN_DEBUG "ISICOM: raise_rts.\n");
#endif
@@ -226,18 +311,25 @@
outw(0x0a04, base);
InterruptTheCard(base);
port->status |= ISI_RTS;
+ unlock_card(card);
}
extern inline void drop_rts(struct isi_port * port)
{
struct isi_board * card = port->card;
unsigned short base = card->base;
unsigned char channel = port->channel;
- short wait=400;
+
+/* short wait=400; SMPCHG
while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
if (wait <= 0) {
printk(KERN_WARNING "ISICOM: Card found busy in drop_rts.\n");
return;
}
+*/
+ if (!lock_card(card)) {
+ printk(KERN_WARNING "ISICOM: Card found busy in drop_rts.\n");
+ return;
+ }
#ifdef ISICOM_DEBUG_DTR_RTS
printk(KERN_DEBUG "ISICOM: drop_rts.\n");
#endif
@@ -245,18 +337,25 @@
outw(0x0804, base);
InterruptTheCard(base);
port->status &= ~ISI_RTS;
+ unlock_card(card);
}
extern inline void raise_dtr_rts(struct isi_port * port)
{
struct isi_board * card = port->card;
unsigned short base = card->base;
unsigned char channel = port->channel;
- short wait=400;
+
+/* short wait=400; SMPCHG
while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
if (wait <= 0) {
printk(KERN_WARNING "ISICOM: Card found busy in raise_dtr_rts.\n");
return;
}
+*/
+ if (!lock_card(card)) {
+ printk(KERN_WARNING "ISICOM: Card found busy in raise_dtr_rts.\n");
+ return;
+ }
#ifdef ISICOM_DEBUG_DTR_RTS
printk(KERN_DEBUG "ISICOM: raise_dtr_rts.\n");
#endif
@@ -264,18 +363,25 @@
outw(0x0f04, base);
InterruptTheCard(base);
port->status |= (ISI_DTR | ISI_RTS);
+ unlock_card(card);
}
extern inline void drop_dtr_rts(struct isi_port * port)
{
struct isi_board * card = port->card;
unsigned short base = card->base;
unsigned char channel = port->channel;
- short wait=400;
+
+/* short wait=400;
while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
if (wait <= 0) {
printk(KERN_WARNING "ISICOM: Card found busy in drop_dtr_rts.\n");
return;
}
+*/
+ if (!lock_card(card)) {
+ printk(KERN_WARNING "ISICOM: Card found busy in drop_dtr_rts.\n");
+ return;
+ }
#ifdef ISICOM_DEBUG_DTR_RTS
printk(KERN_DEBUG "ISICOM: drop_dtr_rts.\n");
#endif
@@ -283,6 +389,7 @@
outw(0x0c04, base);
InterruptTheCard(base);
port->status &= ~(ISI_RTS | ISI_DTR);
+ unlock_card(card);
}
extern inline void kill_queue(struct isi_port * port, short queue)
@@ -290,18 +397,45 @@
struct isi_board * card = port->card;
unsigned short base = card->base;
unsigned char channel = port->channel;
- short wait=400;
+
+/* short wait=400; SMPCHG
while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
if (wait <= 0) {
printk(KERN_WARNING "ISICOM: Card found busy in kill_queue.\n");
return;
}
+*/
+ if (!lock_card(card)) {
+ printk(KERN_WARNING "ISICOM: Card found busy in kill_queue.\n");
+ return;
+ }
#ifdef ISICOM_DEBUG
printk(KERN_DEBUG "ISICOM: kill_queue 0x%x.\n", queue);
#endif
outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
outw((queue << 8) | 0x06, base);
InterruptTheCard(base);
+ unlock_card(card);
+}
+
+extern inline void set_signal_mask(struct isi_port * port, char mask)
+{
+ struct isi_board * card = port->card;
+ unsigned short base = card->base;
+ unsigned char channel = port->channel;
+
+ if (!lock_card(card)) {
+ printk(KERN_WARNING "ISICOM: Card found busy"
+ "in set_signal_mask.\n");
+ return;
+ }
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: set_signal_mask 0x%x.\n", mask);
+#endif
+ outw(0x8000 | (channel << card->shift_count) | 0x02, base);
+ outw((mask << 8) | 0x7, base);
+ InterruptTheCard(base);
+ unlock_card(card);
}
#endif /* __KERNEL__ */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)