Skip to contentSkip to conversation

IO delay, port 0x80, and BIOS POST codes

PATCH In review Andi Kleen 8 participants 16 messages Mar 15, 2002 – Mar 18, 2002 1 message not in the archive

lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

Andi Kleen

author
#1 lore raw
Quoted 7 lines · Martin Wilck
Quoted 4 lines · Thunder from the hill

I also remember this been discussed anually. Making it configurable with a warning might be a solution, but that's nothing we could decide. Maybe add a config option? It night be a [DANGEROUS] one, so the guys and gals who might compile are warned of changing this.

Quoted 7 lines

It doesn't even have to be a config option - a line

/* Port used for dummy writes for I/O delays */ /* Change this only if you know what you're doing ! */ #define DUMMY_IO_PORT 0x80

in a header file would perfectly suffice.

That effectively already exists. You just need to change the __SLOW_DOWN_IO macro in include/asm-i387/io.h

-Andi

#2 lore raw
Quoted 10 lines · Andi Kleen
Quoted 7 lines

It doesn't even have to be a config option - a line

/* Port used for dummy writes for I/O delays */ /* Change this only if you know what you're doing ! */ #define DUMMY_IO_PORT 0x80

in a header file would perfectly suffice.

That effectively already exists. You just need to change the __SLOW_DOWN_IO macro in include/asm-i387/io.h

No, that doesn't cover all accesses to port 80. I am still searching.

Signature · 4 lines
Martin Wilck                Phone: +49 5251 8 15113
Fujitsu Siemens Computers   Fax:   +49 5251 8 20409
Heinz-Nixdorf-Ring 1	    mailto:[email protected]
D-33106 Paderborn           http://www.fujitsu-siemens.com/primergy
author
#3 lore raw
In reply to Andi Kleen
Quoted 8 lines · Martin Wilck
Quoted 6 lines · Andi Kleen
Quoted 6 lines

It doesn't even have to be a config option - a line

/* Port used for dummy writes for I/O delays */ /* Change this only if you know what you're doing ! */ #define DUMMY_IO_PORT 0x80

Quoted 6 lines
Quoted 4 lines
Quoted 1 line

in a header file would perfectly suffice.

That effectively already exists. You just need to change the __SLOW_DOWN_IO macro in include/asm-i387/io.h

No, that doesn't cover all accesses to port 80. I am still searching.

It should. I would consider all other accesses a bug.
It is possible that some driver used it for private debugging and left it in by mistake. These should be removed.

-Andi

#4 lore raw

PATCH 1/1 Cleanup port 0x80 use (was: Re: IO delay ...)

Hi,

this patch makes the use of the "dummy" port 0x80 globally configurable through a macro in the (new) file asm-i386/iodelay.h.
I think nobody wants to see this in the configuration menus.

I have tried to capture all accesses to port 0x80, although some may have escaped.

Even if nobody wants to use anything other than 0x80 in the near future, I think the patch is useful because grepping the source for 0x80 is really no fun.

With the patch, our BIOS post code LEDs really stand still.

I am still wondering, though, why this method of getting a delay is used so often. IMO in most places one could use udelay(1) instead, with much less risk of doing wrong.

Martin

Signature · 208 lines
Martin Wilck                Phone: +49 5251 8 15113
Fujitsu Siemens Computers   Fax:   +49 5251 8 20409
Heinz-Nixdorf-Ring 1	    mailto:[email protected]
D-33106 Paderborn           http://www.fujitsu-siemens.com/primergy



--- ./include/asm-i386/io.h.orig	Fri Mar 15 17:23:15 2002
+++ ./include/asm-i386/io.h	Fri Mar 15 18:30:03 2002
@@ -221,17 +221,9 @@

 #endif /* __KERNEL__ */

-#ifdef SLOW_IO_BY_JUMPING
-#define __SLOW_DOWN_IO "\njmp 1f\n1:\tjmp 1f\n1:"
-#else
-#define __SLOW_DOWN_IO "\noutb %%al,$0x80"
-#endif
-
-#ifdef REALLY_SLOW_IO
-#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO
-#else
-#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO
-#endif
+/* Moved the __SLOW_DOWN_IO macros to a separate file
+ * that can be included by setup.S */
+#include <asm/iodelay.h>

 #ifdef CONFIG_MULTIQUAD
 extern void *xquad_portio;    /* Where the IO area was mapped */
--- ./include/asm-i386/floppy.h.orig	Fri Mar 15 17:23:15 2002
+++ ./include/asm-i386/floppy.h	Fri Mar 15 17:55:04 2002
@@ -89,8 +89,7 @@
 	jmp 5f
 4:     	movb (%2),%0
 	outb %b0,%w4
-5:	decw %w4
-	outb %0,$0x80
+5:	decw %w4" __SLOW_DOWN_IO "
 	decl %1
 	incl %2
 	testl %1,%1
--- ./include/asm-i386/iodelay.h.orig	Fri Mar 15 18:31:01 2002
+++ ./include/asm-i386/iodelay.h	Fri Mar 15 18:30:36 2002
@@ -0,0 +1,25 @@
+#ifndef _ASM_IODELAY_H
+#define _ASM_IODELAY_H
+
+#ifdef SLOW_IO_BY_JUMPING
+#define __SLOW_DOWN_IO "\njmp 1f\n1:\tjmp 1f\n1:"
+#else
+
+  /*
+   * The dummy IO port to use for delays.
+   * Change only if you really know what you're doing
+   * Default value: 0x80
+   * Other values that have been suggested: 0x19, 0x42, 0xe2, 0xed
+   * Both macros must be changed to capture all I/O delays in the kernel.
+   */
+#define __SLOW_DOWN_IO_PORT 0x80
+#define __SLOW_DOWN_IO "\noutb %%al,$0x80"
+#endif
+
+#ifdef REALLY_SLOW_IO
+#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO
+#else
+#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO
+#endif
+
+#endif
--- ./drivers/char/serial.c.orig	Fri Mar 15 17:23:15 2002
+++ ./drivers/char/serial.c	Fri Mar 15 17:24:13 2002
@@ -3661,12 +3661,12 @@
 		scratch = serial_inp(info, UART_IER);
 		serial_outp(info, UART_IER, 0);
 #ifdef __i386__
-		outb(0xff, 0x080);
+		outb(0xff,__SLOW_DOWN_IO_PORT);
 #endif
 		scratch2 = serial_inp(info, UART_IER);
 		serial_outp(info, UART_IER, 0x0F);
 #ifdef __i386__
-		outb(0, 0x080);
+		outb(0xff,__SLOW_DOWN_IO_PORT);
 #endif
 		scratch3 = serial_inp(info, UART_IER);
 		serial_outp(info, UART_IER, scratch);
--- ./drivers/char/riscom8.c.orig	Fri Mar 15 17:23:15 2002
+++ ./drivers/char/riscom8.c	Fri Mar 15 17:24:13 2002
@@ -278,10 +278,10 @@

 	/* Are the I/O ports here ? */
 	rc_out(bp, CD180_PPRL, 0x5a);
-	outb(0xff, 0x80);
+	outb(0xff, __SLOW_DOWN_IO_PORT);
 	val1 = rc_in(bp, CD180_PPRL);
 	rc_out(bp, CD180_PPRL, 0xa5);
-	outb(0x00, 0x80);
+	outb(0x00, __SLOW_DOWN_IO_PORT);
 	val2 = rc_in(bp, CD180_PPRL);

 	if ((val1 != 0x5a) || (val2 != 0xa5))  {
--- ./drivers/scsi/atp870u.c.orig	Fri Mar 15 17:23:15 2002
+++ ./drivers/scsi/atp870u.c	Fri Mar 15 17:24:13 2002
@@ -1042,7 +1042,7 @@
 	tmport = dev->ioport + 0x1b;
 	outb(0x02, tmport);

-	outb(0, 0x80);
+	outb(0, __SLOW_DOWN_IO_PORT);

 	val = 0x0080;		/* bsy	*/
 	tmport = dev->ioport + 0x1c;
@@ -1051,7 +1051,7 @@
 	outw(val, tmport);
 	val |= 0x0004;		/* msg	*/
 	outw(val, tmport);
-	inb(0x80);		/* 2 deskew delay(45ns*2=90ns) */
+	inb(__SLOW_DOWN_IO_PORT);  /* 2 deskew delay(45ns*2=90ns) */
 	val &= 0x007f;		/* no bsy  */
 	outw(val, tmport);
 	mydlyu(0xffff); 	/* recommanded SCAM selection response time */
@@ -1062,7 +1062,7 @@
 	if ((inb(tmport) & 0x04) != 0) {
 		goto wait_nomsg;
 	}
-	outb(1, 0x80);
+	outb(1, __SLOW_DOWN_IO_PORT);
 	mydlyu(100);
 	for (n = 0; n < 0x30000; n++) {
 		if ((inb(tmport) & 0x80) != 0) {	/* bsy ? */
@@ -1078,13 +1078,13 @@
 	}
 	goto TCM_SYNC;
 wait_io1:
-	inb(0x80);
+	inb(__SLOW_DOWN_IO_PORT);
 	val |= 0x8003;		/* io,cd,db7  */
 	outw(val, tmport);
-	inb(0x80);
+	inb(__SLOW_DOWN_IO_PORT);
 	val &= 0x00bf;		/* no sel     */
 	outw(val, tmport);
-	outb(2, 0x80);
+	outb(2, __SLOW_DOWN_IO_PORT);
 TCM_SYNC:
 	mydlyu(0x800);
 	if ((inb(tmport) & 0x80) == 0x00) {	/* bsy ? */
@@ -1103,18 +1103,18 @@
 	val &= 0x00ff;		/* synchronization  */
 	val |= 0x3f00;
 	fun_scam(dev, &val);
-	outb(3, 0x80);
+	outb(3, __SLOW_DOWN_IO_PORT);
 	val &= 0x00ff;		/* isolation	    */
 	val |= 0x2000;
 	fun_scam(dev, &val);
-	outb(4, 0x80);
+	outb(4, __SLOW_DOWN_IO_PORT);
 	i = 8;
 	j = 0;
 TCM_ID:
 	if ((inw(tmport) & 0x2000) == 0) {
 		goto TCM_ID;
 	}
-	outb(5, 0x80);
+	outb(5, __SLOW_DOWN_IO_PORT);
 	val &= 0x00ff;		/* get ID_STRING */
 	val |= 0x2000;
 	k = fun_scam(dev, &val);
--- ./drivers/video/sis/sis_main.c.orig	Fri Mar 15 17:23:15 2002
+++ ./drivers/video/sis/sis_main.c	Fri Mar 15 17:27:16 2002
@@ -2308,7 +2308,7 @@
 	u8 reg;
 	int nRes;

-	outb (0x77, 0x80);
+	outb (0x77, __SLOW_DOWN_IO_PORT);

 	if (sisfb_off)
 		return -ENXIO;
--- ./arch/i386/boot/setup.S.orig	Fri Mar 15 17:23:15 2002
+++ ./arch/i386/boot/setup.S	Fri Mar 15 18:33:12 2002
@@ -54,6 +54,7 @@
 #include <asm/boot.h>
 #include <asm/e820.h>
 #include <asm/page.h>
+#include <asm/iodelay.h>

 /* Signature words to ensure LILO loaded us right */
 #define SIG1	0xAA55
@@ -65,6 +66,7 @@
 				# ... and the former contents of CS

 DELTA_INITSEG = SETUPSEG - INITSEG	# 0x0020
+DELAY_PORT = __SLOW_DOWN_IO_PORT	# port for IO delay (0x80)

 .code16
 .globl begtext, begdata, begbss, endtext, enddata, endbss
@@ -1001,7 +1003,7 @@

 # Delay is needed after doing I/O
 delay:
-	outb	%al,$0x80
+	outb    %al,$DELAY_PORT
 	ret

 # Descriptor tables
#5 lore raw

Re: [PATCH] Cleanup port 0x80 use (was: Re: IO delay ...)

Quoted 3 lines

I am still wondering, though, why this method of getting a delay is used so often. IMO in most places one could use udelay(1) instead, with much less risk of doing wrong.

udelay(1) I don't believe is enough. Unfortunately I can't find my documentation on the ISA bus which covers the timeout for acknowledging an address cycle. Otherwise for tsc capable boxes I agree entirely.

#6 lore raw

Re: [PATCH] Cleanup port 0x80 use (was: Re: IO delay ...)

In reply to Martin Wilck
Followup to:  <[email protected]>
By author:    Alan Cox <[email protected]>
In newsgroup: linux.dev.kernel
Quoted 9 lines
Quoted 4 lines

I am still wondering, though, why this method of getting a delay is used so often. IMO in most places one could use udelay(1) instead, with much less risk of doing wrong.

udelay(1) I don't believe is enough. Unfortunately I can't find my documentation on the ISA bus which covers the timeout for acknowledging an address cycle. Otherwise for tsc capable boxes I agree entirely.

The ISA bus doesn't time out; a cycle on the ISA bus just happens, and the fact that noone is there to listen doesn't seem to matter.

The delay is something like 8 cycles @ 8.3 MHz or around 1 ms. However, an important thing to note is that this delay applies *at the southbridge*. An OUT is a fully synchronizing operation, so it doesn't just give a 1 ms delay due to the ISA bus cycle, but it also makes sure everything else in the system is completed before the timing counter even starts to tick.

Of course, if all you're doing is IOIO (on an x86!) it doesn't matter -- IOIO is fully synchronizing anyway.

-hpa

Signature · 3 lines
<[email protected]> at work, <[email protected]> in private!
"Unix gives you enough rope to shoot yourself in the foot."
http://www.zytor.com/~hpa/puzzle.txt	<[email protected]>
#7 lore raw

Re: [PATCH] Cleanup port 0x80 use (was: Re: IO delay ...)

Quoted 5 lines
Quoted 3 lines

documentation on the ISA bus which covers the timeout for acknowledging an address cycle. Otherwise for tsc capable boxes I agree entirely.

The ISA bus doesn't time out; a cycle on the ISA bus just happens, and the fact that noone is there to listen doesn't seem to matter.

Not so simple. I found my IEEE draft 8)

The address out comes from the chipset (southbridge now days). The sequence is

BALE high
Output address
BALE low
Set IORC/IOWC etc

Wait for NOWS while watching IOCHRDY

NOWS low says - card now ready
IOCHRDY high suppresses the wait state timer count

The default timeout is 4 wait states, which is 6 bus clocks for a failure Maybe 7 - Im not clear if the final cycle to recover and start again is always there.

Quoted 1 line

The delay is something like 8 cycles @ 8.3 MHz or around 1 ms.

1uS ?

Alan

#8 lore raw

Re: [PATCH] Cleanup port 0x80 use (was: Re: IO delay ...)

Quoted 5 lines · Alan Cox
Quoted 2 lines

The delay is something like 8 cycles @ 8.3 MHz or around 1 ms.

1uS ?

1 µs, right :-/

-hpa

#9 lore raw

Re: [PATCH] Cleanup port 0x80 use (was: Re: IO delay ...)

In reply to Martin Wilck

In article <[email protected]>,

Quoted 3 lines · H. Peter Anvin

The ISA bus doesn't time out; a cycle on the ISA bus just happens, and the fact that noone is there to listen doesn't seem to matter.

The ISA bus doesn't time out, but the PCI access before it gets forwarded to the ISA bus _does_, if the ISA bus is decoded using nagative decoding.

This is why it's important that there not be a motherboard PCI device that can decode the port - because if there is, the access is potentially a much faster PCI-only decode.

Note that this really only matters on low-end machines anyway, as the whole "inb_p()" thing tends to be used only for old ISA devices. If you have a new machine that is all PCI, I doubt that port 80h access matters not at all.

(Another way of saying it: if you have a machine with a PCI POST card, none of this will matter)

Linus

#10 lore raw

Re: [PATCH] Cleanup port 0x80 use (was: Re: IO delay ...)

In reply to Andi Kleen

Review

Quoted 2 lines · Martin Wilck
(quoted diff) +2 -0
+#define __SLOW_DOWN_IO_PORT 0x80
+#define __SLOW_DOWN_IO "\noutb %%al,$0x80"

You may want to change the above to:
#define __SLOW_DOWN_IO_ASM "\noutb %%al,$__SLOW_DOWN_IO_PORT"

Review

Quoted 1 line
(quoted diff) +1 -0
+	outb(3, __SLOW_DOWN_IO_PORT);

You may also want to replace the above entirely with a macro, like:
#define __SLOW_DOWN_IO outb(3, __SLOW_DOWN_IO_PORT)

so that on architectures that don't need/have this ISA nonsense can just replace __SLOW_DOWN_IO with something else like udelay.

arch/i386/boot/setup.S line 72

Quoted 10 lines
arch/i386/boot/setup.S renamed from arch/i386/boot/setup.S.orig +1 -0
@@ -65,6 +66,7 @@
 				# ... and the former contents of CS
 
 DELTA_INITSEG = SETUPSEG - INITSEG	# 0x0020
+DELAY_PORT = __SLOW_DOWN_IO_PORT	# port for IO delay (0x80)
 
 .code16
 .globl begtext, begdata, begbss, endtext, enddata, endbss

May as well just stick with a single define here (i.e. remove DELAY_PORT).

arch/i386/boot/setup.S line 1007

Quoted 7 lines
arch/i386/boot/setup.S renamed from arch/i386/boot/setup.S.orig +1 -1
@@ -1001,7 +1003,7 @@
 
 # Delay is needed after doing I/O
 delay:
-	outb	%al,$0x80
+	outb    %al,$DELAY_PORT
 	ret

And use __SLOW_DOWN_IO_ASM here.

Cheers, Andreas
--
Andreas Dilger \ "If a man ate a pound of pasta and a pound of antipasto,
\ would they cancel out, leaving him still hungry?"
http://www-mddsp.enel.ucalgary.ca/People/adilger/ -- Dogbert

#11 lore raw

Re: [PATCH] Cleanup port 0x80 use (was: Re: IO delay ...)

Quoted 5 lines · Andreas Dilger

Review

Quoted 2 lines
(quoted diff) +2 -0
+#define __SLOW_DOWN_IO_PORT 0x80
+#define __SLOW_DOWN_IO "\noutb %%al,$0x80"

You may want to change the above to:
#define __SLOW_DOWN_IO_ASM "\noutb %%al,$__SLOW_DOWN_IO_PORT"

Won't work, cpp doesn't substitute between double quotes. (at least the one I'm using). Or am I gettimng something wrong here??

Quoted 5 lines

You may also want to replace the above entirely with a macro, like:
#define __SLOW_DOWN_IO outb(3, __SLOW_DOWN_IO_PORT)

so that on architectures that don't need/have this ISA nonsense can just replace __SLOW_DOWN_IO with something else like udelay.

I wanted to change as little as possible, generated code was intended to be binary-identical with old code if the port is set to 0x80.

Currently source files can #define "SLOW_IO_BY_JUMPING" to avoid writing to the dummy port. Perhaps someone should introduce SLOW_IO_BY_UDELAY or so.

Quoted 1 line

May as well just stick with a single define here (i.e. remove DELAY_PORT).

OK.

Please take a look at the new version below.
(Changed only setup.S code, and some comments).

Martin

Signature · 202 lines
Martin Wilck                Phone: +49 5251 8 15113
Fujitsu Siemens Computers   Fax:   +49 5251 8 20409
Heinz-Nixdorf-Ring 1	    mailto:[email protected]
D-33106 Paderborn           http://www.fujitsu-siemens.com/primergy


--- ./include/asm-i386/io.h.orig	Fri Mar 15 17:23:15 2002
+++ ./include/asm-i386/io.h	Fri Mar 15 18:30:03 2002
@@ -221,17 +221,9 @@

 #endif /* __KERNEL__ */

-#ifdef SLOW_IO_BY_JUMPING
-#define __SLOW_DOWN_IO "\njmp 1f\n1:\tjmp 1f\n1:"
-#else
-#define __SLOW_DOWN_IO "\noutb %%al,$0x80"
-#endif
-
-#ifdef REALLY_SLOW_IO
-#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO
-#else
-#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO
-#endif
+/* Moved the __SLOW_DOWN_IO macros to a separate file
+ * that can be included by setup.S */
+#include <asm/iodelay.h>

 #ifdef CONFIG_MULTIQUAD
 extern void *xquad_portio;    /* Where the IO area was mapped */
--- ./include/asm-i386/floppy.h.orig	Fri Mar 15 17:23:15 2002
+++ ./include/asm-i386/floppy.h	Fri Mar 15 17:55:04 2002
@@ -89,8 +89,7 @@
 	jmp 5f
 4:     	movb (%2),%0
 	outb %b0,%w4
-5:	decw %w4
-	outb %0,$0x80
+5:	decw %w4" __SLOW_DOWN_IO "
 	decl %1
 	incl %2
 	testl %1,%1
--- ./include/asm-i386/iodelay.h.orig	Fri Mar 15 18:31:01 2002
+++ ./include/asm-i386/iodelay.h	Fri Mar 15 21:14:17 2002
@@ -0,0 +1,28 @@
+#ifndef _ASM_IODELAY_H
+#define _ASM_IODELAY_H
+
+/* File suitable for inclusion by setup.S, normally included via <asm/io.h> */
+
+#ifdef SLOW_IO_BY_JUMPING
+#define __SLOW_DOWN_IO "\njmp 1f\n1:\tjmp 1f\n1:"
+#else
+
+/*
+ * The dummy IO port to use for delays.
+ * Change only if you really know what you're doing
+ * Default value: 0x80
+ * Other values that have been suggested: 0x19, 0x42, 0xe2, 0xed
+ * Both macros must be changed to modify all IO delays in the kernel.
+ */
+
+#define __SLOW_DOWN_IO_PORT 0x80
+#define __SLOW_DOWN_IO "\noutb %%al,$0x80"
+#endif
+
+#ifdef REALLY_SLOW_IO
+#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO
+#else
+#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO
+#endif
+
+#endif
--- ./drivers/char/serial.c.orig	Fri Mar 15 17:23:15 2002
+++ ./drivers/char/serial.c	Fri Mar 15 17:24:13 2002
@@ -3661,12 +3661,12 @@
 		scratch = serial_inp(info, UART_IER);
 		serial_outp(info, UART_IER, 0);
 #ifdef __i386__
-		outb(0xff, 0x080);
+		outb(0xff,__SLOW_DOWN_IO_PORT);
 #endif
 		scratch2 = serial_inp(info, UART_IER);
 		serial_outp(info, UART_IER, 0x0F);
 #ifdef __i386__
-		outb(0, 0x080);
+		outb(0xff,__SLOW_DOWN_IO_PORT);
 #endif
 		scratch3 = serial_inp(info, UART_IER);
 		serial_outp(info, UART_IER, scratch);
--- ./drivers/char/riscom8.c.orig	Fri Mar 15 17:23:15 2002
+++ ./drivers/char/riscom8.c	Fri Mar 15 17:24:13 2002
@@ -278,10 +278,10 @@

 	/* Are the I/O ports here ? */
 	rc_out(bp, CD180_PPRL, 0x5a);
-	outb(0xff, 0x80);
+	outb(0xff, __SLOW_DOWN_IO_PORT);
 	val1 = rc_in(bp, CD180_PPRL);
 	rc_out(bp, CD180_PPRL, 0xa5);
-	outb(0x00, 0x80);
+	outb(0x00, __SLOW_DOWN_IO_PORT);
 	val2 = rc_in(bp, CD180_PPRL);

 	if ((val1 != 0x5a) || (val2 != 0xa5))  {
--- ./drivers/scsi/atp870u.c.orig	Fri Mar 15 17:23:15 2002
+++ ./drivers/scsi/atp870u.c	Fri Mar 15 17:24:13 2002
@@ -1042,7 +1042,7 @@
 	tmport = dev->ioport + 0x1b;
 	outb(0x02, tmport);

-	outb(0, 0x80);
+	outb(0, __SLOW_DOWN_IO_PORT);

 	val = 0x0080;		/* bsy	*/
 	tmport = dev->ioport + 0x1c;
@@ -1051,7 +1051,7 @@
 	outw(val, tmport);
 	val |= 0x0004;		/* msg	*/
 	outw(val, tmport);
-	inb(0x80);		/* 2 deskew delay(45ns*2=90ns) */
+	inb(__SLOW_DOWN_IO_PORT);  /* 2 deskew delay(45ns*2=90ns) */
 	val &= 0x007f;		/* no bsy  */
 	outw(val, tmport);
 	mydlyu(0xffff); 	/* recommanded SCAM selection response time */
@@ -1062,7 +1062,7 @@
 	if ((inb(tmport) & 0x04) != 0) {
 		goto wait_nomsg;
 	}
-	outb(1, 0x80);
+	outb(1, __SLOW_DOWN_IO_PORT);
 	mydlyu(100);
 	for (n = 0; n < 0x30000; n++) {
 		if ((inb(tmport) & 0x80) != 0) {	/* bsy ? */
@@ -1078,13 +1078,13 @@
 	}
 	goto TCM_SYNC;
 wait_io1:
-	inb(0x80);
+	inb(__SLOW_DOWN_IO_PORT);
 	val |= 0x8003;		/* io,cd,db7  */
 	outw(val, tmport);
-	inb(0x80);
+	inb(__SLOW_DOWN_IO_PORT);
 	val &= 0x00bf;		/* no sel     */
 	outw(val, tmport);
-	outb(2, 0x80);
+	outb(2, __SLOW_DOWN_IO_PORT);
 TCM_SYNC:
 	mydlyu(0x800);
 	if ((inb(tmport) & 0x80) == 0x00) {	/* bsy ? */
@@ -1103,18 +1103,18 @@
 	val &= 0x00ff;		/* synchronization  */
 	val |= 0x3f00;
 	fun_scam(dev, &val);
-	outb(3, 0x80);
+	outb(3, __SLOW_DOWN_IO_PORT);
 	val &= 0x00ff;		/* isolation	    */
 	val |= 0x2000;
 	fun_scam(dev, &val);
-	outb(4, 0x80);
+	outb(4, __SLOW_DOWN_IO_PORT);
 	i = 8;
 	j = 0;
 TCM_ID:
 	if ((inw(tmport) & 0x2000) == 0) {
 		goto TCM_ID;
 	}
-	outb(5, 0x80);
+	outb(5, __SLOW_DOWN_IO_PORT);
 	val &= 0x00ff;		/* get ID_STRING */
 	val |= 0x2000;
 	k = fun_scam(dev, &val);
--- ./drivers/video/sis/sis_main.c.orig	Fri Mar 15 17:23:15 2002
+++ ./drivers/video/sis/sis_main.c	Fri Mar 15 17:27:16 2002
@@ -2308,7 +2308,7 @@
 	u8 reg;
 	int nRes;

-	outb (0x77, 0x80);
+	outb (0x77, __SLOW_DOWN_IO_PORT);

 	if (sisfb_off)
 		return -ENXIO;
--- ./arch/i386/boot/setup.S.orig	Fri Mar 15 17:23:15 2002
+++ ./arch/i386/boot/setup.S	Fri Mar 15 20:50:13 2002
@@ -54,6 +54,7 @@
 #include <asm/boot.h>
 #include <asm/e820.h>
 #include <asm/page.h>
+#include <asm/iodelay.h>

 /* Signature words to ensure LILO loaded us right */
 #define SIG1	0xAA55
@@ -1001,7 +1002,7 @@

 # Delay is needed after doing I/O
 delay:
-	outb	%al,$0x80
+	outb    %al,$__SLOW_DOWN_IO_PORT
 	ret

 # Descriptor tables
#12 lore raw

Re: [PATCH] Cleanup port 0x80 use (was: Re: IO delay ...)

In reply to Andreas Dilger
Quoted 8 lines · Martin Wilck
Quoted 5 lines

Review

Quoted 2 lines
(quoted diff) +2 -0
+#define __SLOW_DOWN_IO_PORT 0x80
+#define __SLOW_DOWN_IO "\noutb %%al,$0x80"

You may want to change the above to:
#define __SLOW_DOWN_IO_ASM "\noutb %%al,$__SLOW_DOWN_IO_PORT"

Won't work, cpp doesn't substitute between double quotes. (at least the one I'm using). Or am I gettimng something wrong here??

As long as __SLOW_DOWN_IO_PORT is a simple constant, you can just use this instead:

    #define __SLOW_DOWN_IO_ASM	"\noutb %%al,$" #__SLOW_DOWN_IO_PORT

-- Jamie

#13 lore raw

Re: [PATCH] Cleanup port 0x80 use (was: Re: IO delay ...)

Quoted 4 lines · Jamie Lokier

As long as __SLOW_DOWN_IO_PORT is a simple constant, you can just use this instead:

    #define __SLOW_DOWN_IO_ASM	"\noutb %%al,$" #__SLOW_DOWN_IO_PORT

What cpp are you guys using? Mine does stringification (#s) only with arguments of function-like macros. However

#define __SLOW_DOWN_IO_P(p) "\noutb %%al,%" #p #define __SLOW_DOWN_IO __SLOW_DOWN_IO(__SLOW_DOWN_IO_PORT)

won't work, either, because cpp does not recursively substitute macros for stringification, so in the above _SLOW_DOWN_IO wuold evaluate as "\noutb %%al,$__SLOW_DOWN_IO_PORT" - bad.

I have tried a number of things to make this a single cpp line, but they all don't work. The only way would be to change the way the inb_p ... macros are coded.

It is possible to write
#define __SLOW_DOWN_IO __asm__ ("outb %%al, %0" : : "i" (__SLOW_DOWN_IO_PORT));

but only if one modifies the definitions of inb_p etc which are so complex that I don't dare touch them now.

Please note that, as an intermediate solution, my patch reduces explicit usage of the constant 0x80 from ~20 in 8 different source files to 2 immediately following each other in 1 source file.

Martin

Signature · 4 lines
Martin Wilck                Phone: +49 5251 8 15113
Fujitsu Siemens Computers   Fax:   +49 5251 8 20409
Heinz-Nixdorf-Ring 1	    mailto:[email protected]
D-33106 Paderborn           http://www.fujitsu-siemens.com/primergy
#14 lore raw

Re: [PATCH] Cleanup port 0x80 use (was: Re: IO delay ...)

Quoted 9 lines · Martin Wilck
Quoted 4 lines · Jamie Lokier

As long as __SLOW_DOWN_IO_PORT is a simple constant, you can just use this instead:

    #define __SLOW_DOWN_IO_ASM	"\noutb %%al,$" #__SLOW_DOWN_IO_PORT

What cpp are you guys using? Mine does stringification (#s) only with arguments of function-like macros. However

Recent 2.4 and 2.5 kernels have include/linux/stringify.h. This should work.

#define __SLOW_DOWN_IO_ASM "\noutb %%al,$" __stringify(__SLOW_DOWN_IO_PORT)

#15 lore raw

Re: [PATCH] Cleanup port 0x80 use (was: Re: IO delay ...)

Quoted 2 lines · Keith Owens

Recent 2.4 and 2.5 kernels have include/linux/stringify.h. This should work.

OK, that's it. Thanks a lot Keith!

Please find the new patch below.
Martin

Signature · 199 lines
Martin Wilck                Phone: +49 5251 8 15113
Fujitsu Siemens Computers   Fax:   +49 5251 8 20409
Heinz-Nixdorf-Ring 1	    mailto:[email protected]
D-33106 Paderborn           http://www.fujitsu-siemens.com/primergy


--- ./include/asm-i386/io.h.orig	Fri Mar 15 17:23:15 2002
+++ ./include/asm-i386/io.h	Fri Mar 15 18:30:03 2002
@@ -221,17 +221,9 @@

 #endif /* __KERNEL__ */

-#ifdef SLOW_IO_BY_JUMPING
-#define __SLOW_DOWN_IO "\njmp 1f\n1:\tjmp 1f\n1:"
-#else
-#define __SLOW_DOWN_IO "\noutb %%al,$0x80"
-#endif
-
-#ifdef REALLY_SLOW_IO
-#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO
-#else
-#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO
-#endif
+/* Moved the __SLOW_DOWN_IO macros to a separate file
+ * that can be included by setup.S */
+#include <asm/iodelay.h>

 #ifdef CONFIG_MULTIQUAD
 extern void *xquad_portio;    /* Where the IO area was mapped */
--- ./include/asm-i386/floppy.h.orig	Fri Mar 15 17:23:15 2002
+++ ./include/asm-i386/floppy.h	Fri Mar 15 17:55:04 2002
@@ -89,8 +89,7 @@
 	jmp 5f
 4:     	movb (%2),%0
 	outb %b0,%w4
-5:	decw %w4
-	outb %0,$0x80
+5:	decw %w4" __SLOW_DOWN_IO "
 	decl %1
 	incl %2
 	testl %1,%1
--- ./include/asm-i386/iodelay.h.orig	Fri Mar 15 18:31:01 2002
+++ ./include/asm-i386/iodelay.h	Mon Mar 18 12:17:20 2002
@@ -0,0 +1,25 @@
+#ifndef _ASM_IODELAY_H
+#define _ASM_IODELAY_H
+
+/*
+ * The dummy IO port to use for delays.
+ * Change only if you really know what you're doing !!
+ * Default value: 0x80.
+ * Other values that have been suggested: 0x19, 0x42, 0xe2, 0xed.
+ */
+#define __SLOW_DOWN_IO_PORT 0x80
+
+#ifdef SLOW_IO_BY_JUMPING
+#define __SLOW_DOWN_IO "\njmp 1f\n1:\tjmp 1f\n1:"
+#else
+#include <linux/stringify.h>
+#define __SLOW_DOWN_IO "\noutb %%al,$" __stringify(__SLOW_DOWN_IO_PORT)
+#endif
+
+#ifdef REALLY_SLOW_IO
+#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO
+#else
+#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO
+#endif
+
+#endif
--- ./drivers/char/serial.c.orig	Fri Mar 15 17:23:15 2002
+++ ./drivers/char/serial.c	Fri Mar 15 17:24:13 2002
@@ -3661,12 +3661,12 @@
 		scratch = serial_inp(info, UART_IER);
 		serial_outp(info, UART_IER, 0);
 #ifdef __i386__
-		outb(0xff, 0x080);
+		outb(0xff,__SLOW_DOWN_IO_PORT);
 #endif
 		scratch2 = serial_inp(info, UART_IER);
 		serial_outp(info, UART_IER, 0x0F);
 #ifdef __i386__
-		outb(0, 0x080);
+		outb(0xff,__SLOW_DOWN_IO_PORT);
 #endif
 		scratch3 = serial_inp(info, UART_IER);
 		serial_outp(info, UART_IER, scratch);
--- ./drivers/char/riscom8.c.orig	Fri Mar 15 17:23:15 2002
+++ ./drivers/char/riscom8.c	Fri Mar 15 17:24:13 2002
@@ -278,10 +278,10 @@

 	/* Are the I/O ports here ? */
 	rc_out(bp, CD180_PPRL, 0x5a);
-	outb(0xff, 0x80);
+	outb(0xff, __SLOW_DOWN_IO_PORT);
 	val1 = rc_in(bp, CD180_PPRL);
 	rc_out(bp, CD180_PPRL, 0xa5);
-	outb(0x00, 0x80);
+	outb(0x00, __SLOW_DOWN_IO_PORT);
 	val2 = rc_in(bp, CD180_PPRL);

 	if ((val1 != 0x5a) || (val2 != 0xa5))  {
--- ./drivers/scsi/atp870u.c.orig	Fri Mar 15 17:23:15 2002
+++ ./drivers/scsi/atp870u.c	Fri Mar 15 17:24:13 2002
@@ -1042,7 +1042,7 @@
 	tmport = dev->ioport + 0x1b;
 	outb(0x02, tmport);

-	outb(0, 0x80);
+	outb(0, __SLOW_DOWN_IO_PORT);

 	val = 0x0080;		/* bsy	*/
 	tmport = dev->ioport + 0x1c;
@@ -1051,7 +1051,7 @@
 	outw(val, tmport);
 	val |= 0x0004;		/* msg	*/
 	outw(val, tmport);
-	inb(0x80);		/* 2 deskew delay(45ns*2=90ns) */
+	inb(__SLOW_DOWN_IO_PORT);  /* 2 deskew delay(45ns*2=90ns) */
 	val &= 0x007f;		/* no bsy  */
 	outw(val, tmport);
 	mydlyu(0xffff); 	/* recommanded SCAM selection response time */
@@ -1062,7 +1062,7 @@
 	if ((inb(tmport) & 0x04) != 0) {
 		goto wait_nomsg;
 	}
-	outb(1, 0x80);
+	outb(1, __SLOW_DOWN_IO_PORT);
 	mydlyu(100);
 	for (n = 0; n < 0x30000; n++) {
 		if ((inb(tmport) & 0x80) != 0) {	/* bsy ? */
@@ -1078,13 +1078,13 @@
 	}
 	goto TCM_SYNC;
 wait_io1:
-	inb(0x80);
+	inb(__SLOW_DOWN_IO_PORT);
 	val |= 0x8003;		/* io,cd,db7  */
 	outw(val, tmport);
-	inb(0x80);
+	inb(__SLOW_DOWN_IO_PORT);
 	val &= 0x00bf;		/* no sel     */
 	outw(val, tmport);
-	outb(2, 0x80);
+	outb(2, __SLOW_DOWN_IO_PORT);
 TCM_SYNC:
 	mydlyu(0x800);
 	if ((inb(tmport) & 0x80) == 0x00) {	/* bsy ? */
@@ -1103,18 +1103,18 @@
 	val &= 0x00ff;		/* synchronization  */
 	val |= 0x3f00;
 	fun_scam(dev, &val);
-	outb(3, 0x80);
+	outb(3, __SLOW_DOWN_IO_PORT);
 	val &= 0x00ff;		/* isolation	    */
 	val |= 0x2000;
 	fun_scam(dev, &val);
-	outb(4, 0x80);
+	outb(4, __SLOW_DOWN_IO_PORT);
 	i = 8;
 	j = 0;
 TCM_ID:
 	if ((inw(tmport) & 0x2000) == 0) {
 		goto TCM_ID;
 	}
-	outb(5, 0x80);
+	outb(5, __SLOW_DOWN_IO_PORT);
 	val &= 0x00ff;		/* get ID_STRING */
 	val |= 0x2000;
 	k = fun_scam(dev, &val);
--- ./drivers/video/sis/sis_main.c.orig	Fri Mar 15 17:23:15 2002
+++ ./drivers/video/sis/sis_main.c	Fri Mar 15 17:27:16 2002
@@ -2308,7 +2308,7 @@
 	u8 reg;
 	int nRes;

-	outb (0x77, 0x80);
+	outb (0x77, __SLOW_DOWN_IO_PORT);

 	if (sisfb_off)
 		return -ENXIO;
--- ./arch/i386/boot/setup.S.orig	Fri Mar 15 17:23:15 2002
+++ ./arch/i386/boot/setup.S	Fri Mar 15 20:50:13 2002
@@ -54,6 +54,7 @@
 #include <asm/boot.h>
 #include <asm/e820.h>
 #include <asm/page.h>
+#include <asm/iodelay.h>

 /* Signature words to ensure LILO loaded us right */
 #define SIG1	0xAA55
@@ -1001,7 +1002,7 @@

 # Delay is needed after doing I/O
 delay:
-	outb	%al,$0x80
+	outb    %al,$__SLOW_DOWN_IO_PORT
 	ret

 # Descriptor tables
#16 lore raw

Re: [PATCH] Cleanup port 0x80 use (was: Re: IO delay ...)

In reply to Jamie Lokier
Quoted 7 lines · Martin Wilck
Quoted 4 lines

As long as __SLOW_DOWN_IO_PORT is a simple constant, you can just use this instead:

    #define __SLOW_DOWN_IO_ASM	"\noutb %%al,$" #__SLOW_DOWN_IO_PORT

What cpp are you guys using? Mine does stringification (#s) only with arguments of function-like macros.

You're right, my error. You need to use an argument, as has already been pointed out -- <linux/stringify.h>.

-- Jamie