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

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)