[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)
{