[PATCH] Fixes to console drivers

Juan Perez-Sanchez <[email protected]>
Newsgroups org.kernel.vger.linux-8086
Message-ID <CAD6VGubXUAyxgnmGPgHgvTrzvBkwEkXaBzd0rr1Kw9ip-VDPtQ@mail.gmail.com>
Hi,

   The attached patch fixes some issues with console drivers, as well
as access to bios disk.

Greetings,

Juan


PREVIOUS OPERATION AND BUGS

1. File "arch/i86/drivers/char/bell.c" rings the bell on PC compatible
machines. Function sound(), written mostly in assembler, programs the
hardware to produce the audio output at frequency from parameter
"freq". It creates a stack frame and accesses the parameter with
offset 4. However, by then, the compiler already created its own stack
frame and the parameter is no longer at offset 4. The previous
implementation takes as "freq" the return address of the function.

2. In console output drivers, expansion of '\n' to the sequence '\r',
'\n' was done at several places (i.e. the tty layer, when writing to
video memory, at printk, etc.) resulting in the processing of several
'\r' codes every time.

3. In file "arch/i86/drivers/char/dircon.c", some functions move the
cursor on every write to video memory. It is more efficient to move
the cursor only at the end of a group of writes.

4. In function "arch/i86/kernel/bios16.c", parameters to bios calls
are passed in cpu registers, including the register DS. To recover the
DS register after the bios call, its contents are saved in the
variable "our_ds" placed in the code segment. But this is precisely
the purpose of variable "stashed_ds" used in the interrupt code.

NEW OPERATION

1. In bell.c, does not create another stack frame. Uses the offset for
parameter "freq" as calculated by the compiler.

2. Removed the expansion of newlines except at the tty layer and the
"con_charout()" function (because this last function bypasses the tty
layer). Made this correction to console devices: direct-console,
bios-console and sibo-console.

3. In file "arch/i86/drivers/char/dircon.c", the cursor is moved only
when necessary.

4. In file "arch/i86/drivers/char/ntty.c", functions "determine_tty()"
and "tty_write()" were rewritten to make them faster and smaller.

5. Variable "our_ds" was removed and "stashed_ds" used in its place.
There is no need to save the contents of DS before the bios call, only
to recover the kernel data segment from "stashed_ds". With this
change, variable "stashed_ds" is now the only and absolutely necessary
variable placed in the code segment, from the ~9 existing seven months
ago.

OTHER CHANGES

   Code size reduced by 80 bytes.

 The Image builded without errors. The kernel was tested with QEMU and
dioscuri emulators. Also in a PPro pc booting from floppy.
elksM.patch (application/octet-stream, 5.9 KB)
diff -Nurb elks.orig/arch/i86/drivers/char/bell.c elks/arch/i86/drivers/char/bell.c
--- elks.orig/arch/i86/drivers/char/bell.c	2012-05-11 13:26:27.000000000 -0500
+++ elks/arch/i86/drivers/char/bell.c	2012-07-16 18:50:52.000000000 -0500
@@ -13,11 +13,10 @@
  */
 static void sound(unsigned freq)
 {
+    int es;
 #ifndef S_SPLINT_S
 #asm
-	push	bp
-	mov	bp,sp
-	mov	bx, [bp+4]		! frequency
+	mov	bx, [bp+.sound.freq]	! frequency
 	mov	ax, #$34dd
 	mov	dx, #$0012
 	cmp	dx, bx
@@ -29,17 +28,16 @@
 	jne	j1
 	or	al, #3
 	out	$61, al
-	mov	al, #$b6
-	out	$43, al
 
 j1:
+	mov	al, #$b6
+	out	$43, al
 	mov	al, bl
 	out	$42, al
 	mov	al, bh
 	out	$42, al
 
 none:
-	pop	bp
 
 #endasm
 #endif
diff -Nurb elks.orig/arch/i86/drivers/char/console.c elks/arch/i86/drivers/char/console.c
--- elks.orig/arch/i86/drivers/char/console.c	2012-05-11 13:26:27.000000000 -0500
+++ elks/arch/i86/drivers/char/console.c	2012-07-16 18:50:25.000000000 -0500
@@ -162,6 +162,8 @@
 
 void con_charout(char Ch)
 {
+    if (Ch == '\n')
+	WriteChar(Visible, '\r');
     WriteChar(Visible, Ch);
 }
 
diff -Nurb elks.orig/arch/i86/drivers/char/dircon.c elks/arch/i86/drivers/char/dircon.c
--- elks.orig/arch/i86/drivers/char/dircon.c	2012-05-11 13:26:27.000000000 -0500
+++ elks/arch/i86/drivers/char/dircon.c	2012-07-16 18:50:25.000000000 -0500
@@ -192,19 +192,17 @@
 	    --C->cx;
 	    WriteChar(C, ' ');
 	    --C->cx;
-	    PositionCursor(C);
 	}
 	return;
     case NL:
 	++C->cy;
-	/* fall thru for now: fixme when ONLCR complete */
+	break;
     case CR:
 	C->cx = 0;
 	break;
     default:
 	offset = ((unsigned int) (C->cx + C->cy * Width)) << 1;
-	pokeb((__u16) C->vseg, (__u16) offset++, (__u8) c);
-	pokeb((__u16) C->vseg, (__u16) offset, C->attr);
+	pokew((__u16) C->vseg, (__u16) offset, ((__u16)C->attr << 8) | ((__u16)c));
 	C->cx++;
     }
 
@@ -221,6 +219,8 @@
 
 void con_charout(char Ch)
 {
+    if (Ch == '\n')
+	WriteChar(Visible, '\r');
     WriteChar(Visible, Ch);
     PositionCursor(Visible);
 }
@@ -526,7 +526,6 @@
 	register char *yp = (char *)y;
 	C->cy = ((((int) yp) >= MaxRow) ? MaxRow : ((((int)yp) < 0) ? 0 : (int)y));
     }
-    PositionCursor(C);
 }
 
 #endif
@@ -572,12 +571,6 @@
 
     while (tty->outq.len != 0) {
 	chq_getch(&tty->outq, &ch, 0);
-
-#if 0
-	if (ch == '\n')
-	    WriteChar(C, '\r');
-#endif
-
 	WriteChar(C, (char) ch);
 	cnt++;
     }
diff -Nurb elks.orig/arch/i86/drivers/char/ntty.c elks/arch/i86/drivers/char/ntty.c
--- elks.orig/arch/i86/drivers/char/ntty.c	2012-05-11 13:26:27.000000000 -0500
+++ elks/arch/i86/drivers/char/ntty.c	2012-07-16 18:50:25.000000000 -0500
@@ -68,16 +68,13 @@
 
 struct tty *determine_tty(dev_t dev)
 {
-    register struct tty *ttyp;
-    register char *pi = 0;
-    unsigned short int minor = MINOR(dev);
+    register struct tty *ttyp = &ttys[0];
+    register char *minor = (char *)MINOR(dev);
 
     do {
-	ttyp = &ttys[(int)pi];
-	if (ttyp->minor == minor)
+	if (ttyp->minor == (unsigned short int)minor)
 	    return ttyp;
-	++pi;
-    } while (((int) pi) < MAX_TTYS);
+    } while (++ttyp < &ttys[MAX_TTYS]);
 
     return 0;
 }
@@ -151,7 +148,7 @@
 	break;
     case '\n':
 	if (tty->termios.c_oflag & ONLCR)
-	    tty_charout(tty, '\r');
+	    tty_charout_raw(tty, '\r');
     }
     tty_charout_raw(tty, ch);
 }
@@ -174,16 +171,14 @@
 #if 0
     int blocking = (file->f_flags & O_NONBLOCK) ? 0 : 1;
 #endif
-    __u16 tmp;
 
-    pi = 0;
-    while (((int)pi) < len) {
-	tmp = peekb(current->t_regs.ds, (__u16) (data + ((int)pi)));
-	tty_charout(tty, (unsigned char) tmp /* , blocking */ );
-	++pi;
+    pi = (char *)len;
+    while ((int)(pi--)) {
+	tty_charout(tty,
+	   (unsigned char) peekb(current->t_regs.ds, (__u16)(data++))
+	   /* , blocking */ );
     }
-    tty->ops->write(tty);
-    return (int)pi;
+    return len;
 }
 
 int tty_read(struct inode *inode, struct file *file, char *data, int len)
diff -Nurb elks.orig/arch/i86/drivers/char/sibo_con.c elks/arch/i86/drivers/char/sibo_con.c
--- elks.orig/arch/i86/drivers/char/sibo_con.c	2012-05-11 13:26:27.000000000 -0500
+++ elks/arch/i86/drivers/char/sibo_con.c	2012-07-16 18:50:25.000000000 -0500
@@ -210,6 +210,8 @@
 
 void con_charout(char Ch)
 {
+    if (Ch == '\n')
+	WriteChar(Visible, '\r');
     WriteChar(Visible, Ch);
 }
 
diff -Nurb elks.orig/arch/i86/kernel/bios16.c elks/arch/i86/kernel/bios16.c
--- elks.orig/arch/i86/kernel/bios16.c	2012-06-27 17:52:16.000000000 -0500
+++ elks/arch/i86/kernel/bios16.c	2012-07-16 18:50:25.000000000 -0500
@@ -28,7 +28,7 @@
 #asm
 	.text
 /*
- *	our_ds lives in the kernel cs or we can never recover it...
+ *	stashed_ds lives in the kernel cs or we can never recover it...
  */
 
 /* In ROM we cant store anything! The space for the extrasegment
@@ -36,12 +36,10 @@
  * ChM 10/99
  */
 
-#ifndef CONFIG_ROMCODE
-cseg_our_ds: 
-	.word	0
-   #define our_ds    cseg_our_ds
+#ifdef CONFIG_ROMCODE
+ #define stashed_ds	[0]
 #else 
-   #define our_ds    [18]
+    .extern    stashed_ds
 #endif	
 	
 	.globl  _call_bios
@@ -56,17 +54,7 @@
 	push si
 	push di
 
-! We have to save DS carefully.	
-
-#ifdef CONFIG_ROMCODE
-        mov bx,#CONFIG_ROM_IRQ_DATA
-        mov es,bx       ;es is already stored
-        seg es
-#else
-   ! We can find our DS from CS now.
-	seg cs		
-#endif
-	mov our_ds, ds
+! DS already saved in stashed_ds
 
 	mov bx, _bios_data_table
 
@@ -110,10 +98,9 @@
         mov bx,#CONFIG_ROM_IRQ_DATA
         mov ds,bx       ;we can use ds for one fetch
 #else
-   ! We can find our DS from CS now.
 	seg cs		
 #endif
- 	mov  ds, our_ds
+        mov ds,stashed_ds  ! the org DS of kernel
 
 ! ***** We can now use the bios data table again *****
 
diff -Nurb elks.orig/kernel/printk.c elks/kernel/printk.c
--- elks.orig/kernel/printk.c	2012-07-07 10:05:25.000000000 -0500
+++ elks/kernel/printk.c	2012-07-16 18:50:25.000000000 -0500
@@ -35,12 +35,7 @@
  */
 extern void con_charout(char);
 
-static void kputchar(register char ch)
-{
-    if (ch == '\n')
-	con_charout('\r');
-    con_charout(ch);
-}
+#define kputchar(ch) con_charout(ch)
 
 static void kputs(register char *buf)
 {
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.