kjh@pollux.usc.edu (Kenneth J. Hendrickson) (07/27/90)
I have made the following changes/improvements/bug fixes to Minix:
Bug Fixes:
+ Corrected handling of colour, bold, underlined, blinking,
and reverse video Screen Attributes (console.c).
I hope these make it into the next release of Minix.
Improvements:
+ Separate bootblok.s files for each drive type.
Now booting up won't beat your drive to death, trying to
accommodate all drive types. Booting is also faster.
+ Put the screen into 43-line mode if EGA (or VGA) (start.x)
I really liked the 43-line mode under DOS, and I like it under
Minix also. Don't forget to modify your /etc/termcap file.
+ Put the screen into green/black if colour (start.x & console.s)
If green/black isn't your favourite colours, then you can change
the VIDATT parameter. Documentation is included.
I hope these make it into the next release of Minix.
Changes:
+ Use ^C for the SIGINT character instead of DEL
+ Use ^U for the SIGKILL character instead of @
+ Erase the line on SIGKILL character, like on BSD
This is more of a "religious" issue, like Andy says in his
book. Still, I hope the SIGKILL stuff makes it into the next
release.
Ken Hendrickson N8DGN/6 kjh@usc.edu ...!uunet!usc!pollux!kjh
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..
# Wrapped by kjh@pollux.usc.edu on Fri Jul 27 03:57:21 1990
echo x - /usr/src/local/kernel/Makefile.cdif
sed '/^X/s///' > /usr/src/local/kernel/Makefile.cdif << '/'
X*** /usr/src/minix/kernel/Makefile Fri Jul 20 01:19:10 1990
X--- Makefile Fri Jul 27 02:38:16 1990
X***************
X*** 3,13 ****
X # The following nonstandard flags are used:
X # -F: run cpp and cem sequentially (used when memory is tight)
X # -T.: put temporaries in working directory (when RAM disk is small)
X! BIN =.
X! CC =cc
X! CFLAGS =-F -T.
X! CPP =/usr/lib/cpp
X! CPPFLAGS =-DASLD -P
X END =/usr/lib/end.s
X LD =asld
X LDFLAGS =-i
X--- 3,14 ----
X # The following nonstandard flags are used:
X # -F: run cpp and cem sequentially (used when memory is tight)
X # -T.: put temporaries in working directory (when RAM disk is small)
X! # -DEGA43 use 43-line mode on EGA (and VGA) displays
X! BIN =.
X! CC =cc
X! CFLAGS =-F -T. -DEGA43
X! CPP =/usr/lib/cpp
X! CPPFLAGS =-DASLD -P -DEGA43
X END =/usr/lib/end.s
X LD =asld
X LDFLAGS =-i
/
echo x - /usr/src/local/kernel/console.c.cdif
sed '/^X/s///' > /usr/src/local/kernel/console.c.cdif << '/'
X*** /usr/src/minix/kernel/console.c Fri Jul 20 01:19:12 1990
X--- console.c Thu Jul 26 22:12:50 1990
X***************
X*** 12,20 ****
X #define M_VID_MASK 0x0FFF /* mask for 4K video RAM */
X #define C_RETRACE 0x0300 /* how many characters to display at once */
X #define M_RETRACE 0x7000 /* how many characters to display at once */
X! #define BLANK 0x0700 /* determines cursor color on blank screen */
X! #define LINE_WIDTH 80 /* # characters on a line */
X! #define SCR_LINES 25 /* # lines on the screen */
X #define SCR_BYTES 8000 /* size video RAM. multiple of 2*LINE_WIDTH */
X #define GO_FORWARD 0 /* scroll forward */
X #define GO_BACKWARD 1 /* scroll backward */
X--- 12,37 ----
X #define M_VID_MASK 0x0FFF /* mask for 4K video RAM */
X #define C_RETRACE 0x0300 /* how many characters to display at once */
X #define M_RETRACE 0x7000 /* how many characters to display at once */
X!
X! #define BLANK 0x0200 /* determines cursor color on blank screen */
X! /* Bit 14 (0x400) is for background Red
X! * Bit 13 (0x200) is for background Green
X! * Bit 12 (0x100) is for background Blue
X! * Bit 10 (0x400) is for foreground Red
X! * Bit 9 (0x200) is for foreground Green
X! * Bit 8 (0x100) is for foreground Blue
X! * It is probably unwise to set bits 15 or 11 of BLANK.
X! * Bit 15 (0x8000) is for foreground blinking
X! * Bit 11 (0x0800) is for foreground intensity
X! */
X!
X! #define LINE_WIDTH 80 /* # characters on a line */
X! #ifdef EGA43
X! #define SCR_LINES 43 /* # lines on the screen */
X! #else
X! #define SCR_LINES 25 /* # lines on the screen */
X! #endif
X!
X #define SCR_BYTES 8000 /* size video RAM. multiple of 2*LINE_WIDTH */
X #define GO_FORWARD 0 /* scroll forward */
X #define GO_BACKWARD 1 /* scroll backward */
X***************
X*** 36,42 ****
X /* Global variables used by the console driver. */
X PUBLIC int vid_mask; /* 037777 for color (16K) or 07777 for mono */
X PUBLIC int vid_port; /* I/O port for accessing 6845 */
X! PUBLIC int blank_color = 0x0700; /* display code for blank */
X
X /* Private variables used by the console driver. */
X PRIVATE vid_retrace; /* how many characters to display per burst */
X--- 53,59 ----
X /* Global variables used by the console driver. */
X PUBLIC int vid_mask; /* 037777 for color (16K) or 07777 for mono */
X PUBLIC int vid_port; /* I/O port for accessing 6845 */
X! PUBLIC int blank_color = BLANK; /* display code for blank */
X
X /* Private variables used by the console driver. */
X PRIVATE vid_retrace; /* how many characters to display per burst */
X***************
X*** 348,354 ****
X * ESC [nM deletes n lines at cursor
X * ESC [nP deletes n chars at cursor
X * ESC [n@ inserts n chars at cursor
X! * ESC [nm enables rendition n (0=normal, 4=bold, 5=blinking, 7=reverse)
X * ESC M scrolls the screen backwards if the cursor is on the top line
X */
X
X--- 365,372 ----
X * ESC [nM deletes n lines at cursor
X * ESC [nP deletes n chars at cursor
X * ESC [n@ inserts n chars at cursor
X! * ESC [nm enables rendition n
X! (0=normal, 1=bold, 4=underlined, 5=blinking, 7=reverse)
X * ESC M scrolls the screen backwards if the cursor is on the top line
X */
X
X***************
X*** 529,564 ****
X case 'm': /* ESC [nm enables rendition n */
X switch (value) {
X case 1: /* BOLD */
X! if (color)
X! one_con_attribute = /* red fg */
X! (attr & 0xf0ff) | 0x0400;
X! else
X! one_con_attribute |= 0x0800; /* inten*/
X break;
X
X case 4: /* UNDERLINE */
X if (color)
X! one_con_attribute = /* blue fg */
X! (attr & 0xf0ff) | 0x0100;
X else
X one_con_attribute = /* ul */
X (attr & 0x8900);
X break;
X
X case 5: /* BLINKING */
X! if (color) /* can't blink color */
X! one_con_attribute = /* magenta fg */
X! (attr & 0xf0ff) | 0x0500;
X! else
X! one_con_attribute |= /* blink */
X! 0x8000;
X break;
X
X case 7: /* REVERSE (black on light grey) */
X if (color)
X one_con_attribute =
X! ((attr & 0xf000) >> 4) |
X! ((attr & 0x0f00) << 4);
X else if ((attr & 0x7000) == 0)
X one_con_attribute =
X (attr & 0x8800) | 0x7000;
X--- 547,584 ----
X case 'm': /* ESC [nm enables rendition n */
X switch (value) {
X case 1: /* BOLD */
X! one_con_attribute |= 0x0800; /* inten */
X break;
X
X case 4: /* UNDERLINE */
X if (color)
X! if ((attr & 0x6000) == 0)
X! /* cyan on [black|blue] bg
X! * This is not standard,
X! * but it is easier to see.
X! */
X! one_con_attribute =
X! (attr & 0xf8ff) | 0x0300;
X! else
X! /* blue on other bg */
X! one_con_attribute =
X! (attr & 0xf8ff) | 0x0100;
X else
X one_con_attribute = /* ul */
X (attr & 0x8900);
X break;
X
X case 5: /* BLINKING */
X! /* EGA, CGA, and MONO can all blink */
X! one_con_attribute |= 0x8000; /* blink */
X break;
X
X case 7: /* REVERSE (black on light grey) */
X if (color)
X one_con_attribute =
X! ((attr & 0x7000) >> 4) |
X! ((attr & 0x0700) << 4) |
X! (attr & 0x8800);
X else if ((attr & 0x7000) == 0)
X one_con_attribute =
X (attr & 0x8800) | 0x7000;
X***************
X*** 569,585 ****
X
X default: if (value >= 30 && value <= 37) {
X one_con_attribute =
X! (attr & 0xf0ff) |
X! (ansi_colors[(value - 30)] << 8);
X! blank_color =
X! (blank_color & 0xf0ff) |
X (ansi_colors[(value - 30)] << 8);
X } else if (value >= 40 && value <= 47) {
X one_con_attribute =
X! (attr & 0x0fff) |
X! (ansi_colors[(value - 40)] << 12);
X! blank_color =
X! (blank_color & 0x0fff) |
X (ansi_colors[(value - 40)] << 12);
X } else
X one_con_attribute = blank_color;
X--- 589,605 ----
X
X default: if (value >= 30 && value <= 37) {
X one_con_attribute =
X! (attr & 0xf8ff) |
X! (ansi_colors[(value - 30)] << 8);
X! blank_color =
X! (blank_color & 0xf8ff) |
X (ansi_colors[(value - 30)] << 8);
X } else if (value >= 40 && value <= 47) {
X one_con_attribute =
X! (attr & 0x8fff) |
X! (ansi_colors[(value - 40)] << 12);
X! blank_color =
X! (blank_color & 0x8fff) |
X (ansi_colors[(value - 40)] << 12);
X } else
X one_con_attribute = blank_color;
X***************
X*** 768,774 ****
X vid_retrace = C_VID_MASK + 1;
X }
X
X! set_6845(CUR_SIZE, CURSOR_SHAPE); /* set cursor shape */
X set_6845(VID_ORG, 0); /* use page 0 of video ram */
X move_to(&tty_struct[0], 0, SCR_LINES-1); /* move cursor to lower left */
X }
X--- 788,796 ----
X vid_retrace = C_VID_MASK + 1;
X }
X
X! #ifndef LINE_CURSOR
X! set_6845(CUR_SIZE, CURSOR_SHAPE); /* set cursor shape (block) */
X! #endif
X set_6845(VID_ORG, 0); /* use page 0 of video ram */
X move_to(&tty_struct[0], 0, SCR_LINES-1); /* move cursor to lower left */
X }
/
echo x - /usr/src/local/kernel/start.x.cdif
sed '/^X/s///' > /usr/src/local/kernel/start.x.cdif << '/'
X*** /usr/src/minix/kernel/start.x Fri Jul 20 01:19:24 1990
X--- start.x Thu Jul 26 06:24:56 1990
X***************
X*** 50,57 ****
X #define SET_PROTECT_VEC 0x15 /* set protected mode */
X # define SET_PROTECT_FUNC 0x89
X #define VIDEO 0x10
X! # define ALTERNATE_SELECT 0x12
X! # define A_S_INFO 0x10
X
X .text
X |*===========================================================================*
X--- 50,75 ----
X #define SET_PROTECT_VEC 0x15 /* set protected mode */
X # define SET_PROTECT_FUNC 0x89
X #define VIDEO 0x10
X! # define ALTERNATE_SELECT 0x12 /* alternate select (Prt-Sc) */
X! # define A_S_INFO 0x10
X! # define SET_VID_MOD 0x00 /* set video mode function */
X! # define TEXT80 0x03 /* 80x25 16-colour text mode */
X! # define CHAR_GEN 0x11 /* character generator interface */
X! # define LOAD_8x8 0x12 /* load the ROM BIOS 8x8 char set */
X! # define CRTC_PORT 0x3d4 /* CRTC address for colour (EGA) */
X! # define CUR_SVAL 0x06 /* cursor start value (underscore) */
X! # define CUR_EVAL 0x00 /* cursor end value (underscore) */
X! # define CUR_SREG 0x0a /* cursor start register number */
X! # define CUR_EREG 0x0b /* cursor end register number */
X! # define PRT_SC 0x20 /* select alternate Prt-Sc routine */
X! # define SCRL_WINUP 0x06 /* scroll window up function */
X! # define VIDATT 0x02 /* video attributes green/black */
X! # define LINE_WIDTH 80 /* number of characters per line */
X! # ifdef EGA43
X! # define SCR_LINES 43 /* number of lines on the screen */
X! # else
X! # define SCR_LINES 25 /* number of lines on the screen */
X! # endif
X
X .text
X |*===========================================================================*
X***************
X*** 174,179 ****
X--- 192,243 ----
X movb al,bl | success is determined by knowing
X movb ah,#0 | a successful call will change bl
X sub ax,#A_S_INFO | nonzero means it is EGA
X+ push ax | save correct return value
X+
X+ #ifdef EGA43
X+ jz no_43 | non-EGA can't do 43-line mode
X+
X+ | If the display is an EGA (or VGA),
X+ | Then establish 43-line mode.
X+ | We have to do this now, as we can't do it in protected mode.
X+
X+ movb ah,#SET_VID_MOD | set video mode function
X+ movb al,#TEXT80 | 80x25 16-colour text mode
X+ int VIDEO
X+
X+ movb ah,#CHAR_GEN | character generator interface function
X+ movb al,#LOAD_8x8 | load the ROM BIOS 8x8 character set
X+ movb bl,#0 | bl = block to load
X+ int VIDEO | load 8x8 characters into RAM
X+
X+ | set up for underscore cursor
X+ | console.c code will change to block cursor
X+ | unless disabled by compiling with
X+ | -DLINE_CURSOR
X+ mov dx,#CRTC_PORT | CRTC address port for colour
X+ movb ah,#CUR_SVAL | cursor start value
X+ movb al,#CUR_SREG | cursor start register number
X+ outw | update CRTC Cursor Start register
X+ movb ah,#CUR_EVAL | cursor end value
X+ movb al,#CUR_EREG | cursor end register number
X+ outw | update CRTC Cursor End register
X+
X+ movb ah,#ALTERNATE_SELECT | alternate select function
X+ movb bl,#PRT_SC | use alternate video BIOS Prt-Sc routine
X+ int VIDEO | update INT 5 vector (print screen)
X+ #endif
X+
X+ no_43:
X+ | Use scroll window to clear screen
X+ movb ah,#SCRL_WINUP | scroll window up
X+ movb al,#0 | number of lines to scroll
X+ movb bh,#VIDATT | and set the video attributes
X+ xor cx,cx
X+ movb dh,#SCR_LINES-1 | number of lines on the screen
X+ movb dl,#LINE_WIDTH-1 | number of characters per line
X+ int VIDEO
X+
X+ pop ax | pass correct return value
X ret
X
X
/
echo x - /usr/src/local/kernel/tty.c.cdif
sed '/^X/s///' > /usr/src/local/kernel/tty.c.cdif << '/'
X*** /usr/src/minix/kernel/tty.c Fri Jul 20 01:19:27 1990
X--- tty.c Mon Jul 23 03:52:35 1990
X***************
X*** 281,289 ****
X
X /* Now do kill processing (remove current line). */
X if (ch == tp->tty_kill && tp->tty_escaped == NOT_ESCAPED) {
X! while(chuck(tp) == OK) /* keep looping */ ;
X! echo(tp, tp->tty_kill);
X! echo(tp, '\n');
X return;
X }
X
X--- 281,291 ----
X
X /* Now do kill processing (remove current line). */
X if (ch == tp->tty_kill && tp->tty_escaped == NOT_ESCAPED) {
X! while(chuck(tp) == OK)
X! /* keep looping */
X! back_over(tp);
X! /* echo(tp, tp->tty_kill); */
X! /* echo(tp, '\n'); */
X return;
X }
X
/
echo x - /usr/src/local/kernel/tty.h.cdif
sed '/^X/s///' > /usr/src/local/kernel/tty.h.cdif << '/'
X*** /usr/src/minix/kernel/tty.h Fri Jul 20 01:19:27 1990
X--- tty.h Mon Jul 23 03:43:20 1990
X***************
X*** 9,17 ****
X #define MAX_ESC_PARMS 2 /* number of escape sequence params allowed */
X
X #define ERASE_CHAR '\b' /* default erase character */
X! #define KILL_CHAR '@' /* default kill character */
X! #define INTR_CHAR (char)0177 /* default interrupt character */
X! #define QUIT_CHAR (char) 034 /* default quit character */
X #define XOFF_CHAR (char) 023 /* default x-off character (CTRL-S) */
X #define XON_CHAR (char) 021 /* default x-on character (CTRL-Q) */
X #define EOT_CHAR (char) 004 /* CTRL-D */
X--- 9,17 ----
X #define MAX_ESC_PARMS 2 /* number of escape sequence params allowed */
X
X #define ERASE_CHAR '\b' /* default erase character */
X! #define KILL_CHAR 025 /* default kill character ^U (was '@') */
X! #define INTR_CHAR 003 /* default interrupt character ^C (was 0177) */
X! #define QUIT_CHAR (char) 034 /* default quit character ^\ */
X #define XOFF_CHAR (char) 023 /* default x-off character (CTRL-S) */
X #define XON_CHAR (char) 021 /* default x-on character (CTRL-Q) */
X #define EOT_CHAR (char) 004 /* CTRL-D */
X***************
X*** 75,82 ****
X
X /* User settable characters: erase, kill, interrupt, quit, x-on; x-off. */
X char tty_erase; /* char used to erase 1 char (init ^H) */
X! char tty_kill; /* char used to erase a line (init @) */
X! char tty_intr; /* char used to send SIGINT (init DEL) */
X char tty_quit; /* char used for core dump (init CTRL-\) */
X char tty_xon; /* char used to start output (init CTRL-Q)*/
X char tty_xoff; /* char used to stop output (init CTRL-S) */
X--- 75,82 ----
X
X /* User settable characters: erase, kill, interrupt, quit, x-on; x-off. */
X char tty_erase; /* char used to erase 1 char (init ^H) */
X! char tty_kill; /* char used to erase a line (init ^U was @) */
X! char tty_intr; /* char used to send SIGINT (init ^C was DEL) */
X char tty_quit; /* char used for core dump (init CTRL-\) */
X char tty_xon; /* char used to start output (init CTRL-Q)*/
X char tty_xoff; /* char used to stop output (init CTRL-S) */
/
echo x - /usr/src/local/commands/stty.c.cdif
sed '/^X/s///' > /usr/src/local/commands/stty.c.cdif << '/'
X*** /usr/src/minix/commands/stty.c Fri Jul 20 00:15:35 1990
X--- stty.c Mon Jul 23 03:17:56 1990
X***************
X*** 12,18 ****
X #define STOPC 023 /* CTRL-S */
X #define QUITC 034 /* CTRL-\ */
X #define EOFC 004 /* CTRL-D */
X! #define DELC 0177 /* DEL */
X #define BYTE 0377
X #define FD 0 /* which file descriptor to use */
X
X--- 12,19 ----
X #define STOPC 023 /* CTRL-S */
X #define QUITC 034 /* CTRL-\ */
X #define EOFC 004 /* CTRL-D */
X! #define DELC 003 /* CTRL-C */ /* 0177 DEL */
X! #define KILLC 025 /* CTRL-U */ /* '@' */
X #define BYTE 0377
X #define FD 0 /* which file descriptor to use */
X
X***************
X*** 262,268 ****
X args.sg_flags = ECHO | CRMOD | XTABS | BITS8;
X args.sg_ispeed = B1200;
X args.sg_ospeed = B1200;
X! args.sg_kill = '@';
X args.sg_erase = '\b';
X tch.t_intrc = DELC;
X tch.t_quitc = QUITC;
X--- 263,269 ----
X args.sg_flags = ECHO | CRMOD | XTABS | BITS8;
X args.sg_ispeed = B1200;
X args.sg_ospeed = B1200;
X! args.sg_kill = KILLC;
X args.sg_erase = '\b';
X tch.t_intrc = DELC;
X tch.t_quitc = QUITC;
/
echo x - /usr/src/local/tools/bootblok1200.s
sed '/^X/s///' > /usr/src/local/tools/bootblok1200.s << '/'
X| When the PC is powered on, it reads the first block from the floppy
X| disk into address 0x7C00 and jumps to it. This boot block must contain
X| the boot program in this file. The boot program first copies itself to
X| address 256K - 1536 (to get itself out of the way). Then it loads the
X| operating system from the boot diskette into memory, and then jumps to menu.
X| Loading is not trivial because the PC is unable to read a track into
X| memory across a 64K boundary, so the positioning of everything is critical.
X| The number of sectors to load is contained at address 504 of this block.
X| The value is put there by the build program after it has discovered how
X| big the operating system is. When the bootblok program is finished loading,
X| it jumps indirectly to the program (menu) which address is given by the
X| last two words in the boot block.
X|
X| Summary of the words patched into the boot block by build:
X| Word at 504: # sectors to load
X| Word at 506: # DS value for menu
X| Word at 508: # PC value for menu
X| Word at 510: # CS value for menu
X|
X| This version of the boot block must be assembled without separate I & D
X| space.
X
X LOADSEG = 0x0060 | here the boot block will start loading
X BIOSSEG = 0x07C0 | here the boot block itself is loaded
X BOOTSEG = 0x3FA0 | here it will copy itself (256K-1.5K)
X DSKBASE = 120 | 120 = 4 * 0x1E = ptr to disk parameters
X
Xfinal = 504
Xmenu_ds = 506
Xmenu_pc = 508
Xmenu_cs = 510
X
X
X.globl begtext, begdata, begbss, endtext, enddata, endbss | asld needs these
X.text
Xbegtext:
X.data
Xbegdata:
X.bss
Xbegbss:
X.text
X
X| copy bootblock to bootseg
X mov ax,#BIOSSEG
X mov ds,ax
X xor si,si | ds:si - original block
X mov ax,#BOOTSEG
X mov es,ax
X xor di,di | es:di - new block
X mov cx,#256 | # words to move
X rep
X movw | copy loop
X
X
X| start boot procedure
X jmpi start, BOOTSEG | set cs to BOOTSEG
X
Xstart:
X mov dx,cs
X mov ds,dx | set ds to cs
X xor ax,ax
X mov es,ax | set es to 0
X mov ss,dx | set ss to cs i.e., stack in high core
X mov sp,#1536 | initialize sp to high core
X
X| print greeting
X mov ax,#2 | reset video
X int 0x10
X
X mov ax,#0x0200 | BIOS call in put cursor in ul corner
X xor bx,bx
X xor dx,dx
X int 0x10
X mov bx,#greet
X call print
X
X| Set up for 1.2M disk.
X
X xor ax,ax
X mov es,ax
X mov dx,ds
X mov ax,#atpar
X seg es
X mov DSKBASE,ax
X seg es
X mov DSKBASE+2,dx
X
X xor ax,ax | reset drive
X int 0x13
X
X| Load the operating system from diskette.
Xload:
X call setreg | set up ah, cx, dx
X mov bx,disksec | bx = number of next sector to read
X add bx,#2 | diskette sector 1 goes at 1536 ("sector" 3)
X shl bx,#1 | multiply sector number by 32
X shl bx,#1 | ditto
X shl bx,#1 | ditto
X shl bx,#1 | ditto
X shl bx,#1 | ditto
X mov es,bx | core address is es:bx (with bx = 0)
X xor bx,bx | see above
X add disksec,ax | ax tells how many sectors to read
X movb ah,#2 | opcode for read
X int 0x13 | call the BIOS for a read
X jb error | jump on diskette error
X mov ax,disksec | see if we are done loading
X cmp ax,final | ditto
X jb load | jump if there is more to load
X
X| Loading done. Finish up.
X mov dx,#0x03F2 | kill the motor
X mov ax,#0x000C
X out
X cli
X mov bx,tracksiz | menu expects # sectors/track in bx
X mov ax,menu_ds | set segment registers
X mov ds,ax | when sep I&D DS != CS
X mov es,ax | otherwise they are the same.
X mov ss,ax | words 504 - 510 are patched by build
X
X seg cs
X jmpi @menu_pc | jmp to menu
X
X| Given the number of the next disk block to read, disksec, compute the
X| cylinder, sector, head, and number of sectors to read as follows:
X| ah = # sectors to read; cl = sector #; ch = cyl; dh = head; dl = 0
Xsetreg:
X mov si,tracksiz | 9 (PC) or 15 (AT) sectors per track
X mov ax,disksec | ax = next sector to read
X xor dx,dx | dx:ax = 32-bit dividend
X div si | divide sector # by track size
X mov cx,ax | cx = track #; dx = sector (0-origin)
X mov bx,dx | bx = sector number (0-origin)
X mov ax,disksec | ax = next sector to read
X add ax,si | ax = last sector to read + 1
X dec ax | ax = last sector to read
X xor dx,dx | dx:ax = 32-bit dividend
X div tracksiz | divide last sector by track size
X cmpb al,cl | is starting track = ending track
X je set1 | jump if whole read on 1 cylinder
X sub si,dx | compute lower sector count
X dec si | si = # sectors to read
X
X| Check to see if this read crosses a 64K boundary (128 sectors).
X| Such calls must be avoided. The BIOS gets them wrong.
Xset1: mov ax,disksec | ax = next sector to read
X add ax,#2 | disk sector 1 goes in core sector 3
X mov dx,ax | dx = next sector to read
X add dx,si | dx = one sector beyond end of read
X dec dx | dx = last sector to read
X shl ax,#1 | ah = which 64K bank does read start at
X shl dx,#1 | dh = which 64K bank foes read end in
X cmpb ah,dh | ah != dh means read crosses 64K boundary
X je set2 | jump if no boundary crossed
X shrb dl,#1 | dl = excess beyond 64K boundary
X xorb dh,dh | dx = excess beyond 64K boundary
X sub si,dx | adjust si
X dec si | si = number of sectors to read
X
Xset2: mov ax,si | ax = number of sectors to read
X xor dx,dx | dh = head, dl = drive
X movb dh,cl | dh = track
X andb dh,#0x01 | dh = head
X movb ch,cl | ch = track to read
X shrb ch,#1 | ch = cylinder
X movb cl,bl | cl = sector number (0-origin)
X incb cl | cl = sector number (1-origin)
X xorb dl,dl | dl = drive number (0)
X ret | return values in ax, cx, dx
X
X
X|-------------------------------+
X| error & print routines |
X|-------------------------------+
X
Xerror:
X push ax
X mov bx,#fderr
X call print | print msg
X xor cx,cx
Xerr1: mul 0 | delay
X loop err1
X int 0x19
X
X
Xprint: | print string (bx)
X movb al,(bx) | al contains char to be printed
X testb al,al | null char?
X jne prt1 | no
X ret | else return
Xprt1: movb ah,#14 | 14 = print char
X inc bx | increment string pointer
X push bx | save bx
X movb bl,#1 | foreground color
X xorb bh,bh | page 0
X int 0x10 | call BIOS VIDEO_IO
X pop bx | restore bx
X jmp print | next character
X
X
Xdisksec:.word 1
Xpcpar: .byte 0xDF, 0x02, 25, 2, 9, 0x2A, 0xFF, 0x50, 0xF6, 1, 3 | for pc
Xatpar: .byte 0xDF, 0x02, 25, 2,15, 0x1B, 0xFF, 0x54, 0xF6, 1, 8 | for at
X
Xfderr: .asciz "Read error. Automatic reboot.\r\n"
Xgreet: .asciz "\rBooting MINIX 1.5. Copyright 1991 Prentice-Hall, Inc.\r\n"
Xtracksiz:.word 15 | changed to 9 for ps and pc
X
X| Don't forget that words 504 - 510 are filled in by build. The regular
X| code had better not get that far.
X.text
Xendtext:
X.data
Xenddata:
X.bss
Xendbss:
/
echo x - /usr/src/local/tools/bootblok360.s
sed '/^X/s///' > /usr/src/local/tools/bootblok360.s << '/'
X| When the PC is powered on, it reads the first block from the floppy
X| disk into address 0x7C00 and jumps to it. This boot block must contain
X| the boot program in this file. The boot program first copies itself to
X| address 256K - 1536 (to get itself out of the way). Then it loads the
X| operating system from the boot diskette into memory, and then jumps to menu.
X| Loading is not trivial because the PC is unable to read a track into
X| memory across a 64K boundary, so the positioning of everything is critical.
X| The number of sectors to load is contained at address 504 of this block.
X| The value is put there by the build program after it has discovered how
X| big the operating system is. When the bootblok program is finished loading,
X| it jumps indirectly to the program (menu) which address is given by the
X| last two words in the boot block.
X|
X| Summary of the words patched into the boot block by build:
X| Word at 504: # sectors to load
X| Word at 506: # DS value for menu
X| Word at 508: # PC value for menu
X| Word at 510: # CS value for menu
X|
X| This version of the boot block must be assembled without separate I & D
X| space.
X
X LOADSEG = 0x0060 | here the boot block will start loading
X BIOSSEG = 0x07C0 | here the boot block itself is loaded
X BOOTSEG = 0x3FA0 | here it will copy itself (256K-1.5K)
X DSKBASE = 120 | 120 = 4 * 0x1E = ptr to disk parameters
X
Xfinal = 504
Xmenu_ds = 506
Xmenu_pc = 508
Xmenu_cs = 510
X
X
X.globl begtext, begdata, begbss, endtext, enddata, endbss | asld needs these
X.text
Xbegtext:
X.data
Xbegdata:
X.bss
Xbegbss:
X.text
X
X| copy bootblock to bootseg
X mov ax,#BIOSSEG
X mov ds,ax
X xor si,si | ds:si - original block
X mov ax,#BOOTSEG
X mov es,ax
X xor di,di | es:di - new block
X mov cx,#256 | # words to move
X rep
X movw | copy loop
X
X
X| start boot procedure
X jmpi start, BOOTSEG | set cs to BOOTSEG
X
Xstart:
X mov dx,cs
X mov ds,dx | set ds to cs
X xor ax,ax
X mov es,ax | set es to 0
X mov ss,dx | set ss to cs i.e., stack in high core
X mov sp,#1536 | initialize sp to high core
X
X| print greeting
X mov ax,#2 | reset video
X int 0x10
X
X mov ax,#0x0200 | BIOS call in put cursor in ul corner
X xor bx,bx
X xor dx,dx
X int 0x10
X mov bx,#greet
X call print
X
X| Set up for 360K disk.
X
X mov tracksiz,#9
X xor ax,ax
X mov es,ax
X mov dx,ds
X mov ax,#pcpar
X seg es
X mov DSKBASE,ax
X seg es
X mov DSKBASE+2,dx
X xor ax,ax | diskette reset
X int 0x13
X
X| Load the operating system from diskette.
Xload:
X call setreg | set up ah, cx, dx
X mov bx,disksec | bx = number of next sector to read
X add bx,#2 | diskette sector 1 goes at 1536 ("sector" 3)
X shl bx,#1 | multiply sector number by 32
X shl bx,#1 | ditto
X shl bx,#1 | ditto
X shl bx,#1 | ditto
X shl bx,#1 | ditto
X mov es,bx | core address is es:bx (with bx = 0)
X xor bx,bx | see above
X add disksec,ax | ax tells how many sectors to read
X movb ah,#2 | opcode for read
X int 0x13 | call the BIOS for a read
X jb error | jump on diskette error
X mov ax,disksec | see if we are done loading
X cmp ax,final | ditto
X jb load | jump if there is more to load
X
X| Loading done. Finish up.
X mov dx,#0x03F2 | kill the motor
X mov ax,#0x000C
X out
X cli
X mov bx,tracksiz | menu expects # sectors/track in bx
X mov ax,menu_ds | set segment registers
X mov ds,ax | when sep I&D DS != CS
X mov es,ax | otherwise they are the same.
X mov ss,ax | words 504 - 510 are patched by build
X
X seg cs
X jmpi @menu_pc | jmp to menu
X
X| Given the number of the next disk block to read, disksec, compute the
X| cylinder, sector, head, and number of sectors to read as follows:
X| ah = # sectors to read; cl = sector #; ch = cyl; dh = head; dl = 0
Xsetreg:
X mov si,tracksiz | 9 (PC) or 15 (AT) sectors per track
X mov ax,disksec | ax = next sector to read
X xor dx,dx | dx:ax = 32-bit dividend
X div si | divide sector # by track size
X mov cx,ax | cx = track #; dx = sector (0-origin)
X mov bx,dx | bx = sector number (0-origin)
X mov ax,disksec | ax = next sector to read
X add ax,si | ax = last sector to read + 1
X dec ax | ax = last sector to read
X xor dx,dx | dx:ax = 32-bit dividend
X div tracksiz | divide last sector by track size
X cmpb al,cl | is starting track = ending track
X je set1 | jump if whole read on 1 cylinder
X sub si,dx | compute lower sector count
X dec si | si = # sectors to read
X
X| Check to see if this read crosses a 64K boundary (128 sectors).
X| Such calls must be avoided. The BIOS gets them wrong.
Xset1: mov ax,disksec | ax = next sector to read
X add ax,#2 | disk sector 1 goes in core sector 3
X mov dx,ax | dx = next sector to read
X add dx,si | dx = one sector beyond end of read
X dec dx | dx = last sector to read
X shl ax,#1 | ah = which 64K bank does read start at
X shl dx,#1 | dh = which 64K bank foes read end in
X cmpb ah,dh | ah != dh means read crosses 64K boundary
X je set2 | jump if no boundary crossed
X shrb dl,#1 | dl = excess beyond 64K boundary
X xorb dh,dh | dx = excess beyond 64K boundary
X sub si,dx | adjust si
X dec si | si = number of sectors to read
X
Xset2: mov ax,si | ax = number of sectors to read
X xor dx,dx | dh = head, dl = drive
X movb dh,cl | dh = track
X andb dh,#0x01 | dh = head
X movb ch,cl | ch = track to read
X shrb ch,#1 | ch = cylinder
X movb cl,bl | cl = sector number (0-origin)
X incb cl | cl = sector number (1-origin)
X xorb dl,dl | dl = drive number (0)
X ret | return values in ax, cx, dx
X
X
X|-------------------------------+
X| error & print routines |
X|-------------------------------+
X
Xerror:
X push ax
X mov bx,#fderr
X call print | print msg
X xor cx,cx
Xerr1: mul 0 | delay
X loop err1
X int 0x19
X
X
Xprint: | print string (bx)
X movb al,(bx) | al contains char to be printed
X testb al,al | null char?
X jne prt1 | no
X ret | else return
Xprt1: movb ah,#14 | 14 = print char
X inc bx | increment string pointer
X push bx | save bx
X movb bl,#1 | foreground color
X xorb bh,bh | page 0
X int 0x10 | call BIOS VIDEO_IO
X pop bx | restore bx
X jmp print | next character
X
X
Xdisksec:.word 1
Xpcpar: .byte 0xDF, 0x02, 25, 2, 9, 0x2A, 0xFF, 0x50, 0xF6, 1, 3 | for pc
Xatpar: .byte 0xDF, 0x02, 25, 2,15, 0x1B, 0xFF, 0x54, 0xF6, 1, 8 | for at
X
Xfderr: .asciz "Read error. Automatic reboot.\r\n"
Xgreet: .asciz "\rBooting MINIX 1.5. Copyright 1991 Prentice-Hall, Inc.\r\n"
Xtracksiz:.word 15 | changed to 9 for ps and pc
X
X| Don't forget that words 504 - 510 are filled in by build. The regular
X| code had better not get that far.
X.text
Xendtext:
X.data
Xenddata:
X.bss
Xendbss:
/
echo x - /usr/src/local/tools/bootblok720.s
sed '/^X/s///' > /usr/src/local/tools/bootblok720.s << '/'
X| When the PC is powered on, it reads the first block from the floppy
X| disk into address 0x7C00 and jumps to it. This boot block must contain
X| the boot program in this file. The boot program first copies itself to
X| address 256K - 1536 (to get itself out of the way). Then it loads the
X| operating system from the boot diskette into memory, and then jumps to menu.
X| Loading is not trivial because the PC is unable to read a track into
X| memory across a 64K boundary, so the positioning of everything is critical.
X| The number of sectors to load is contained at address 504 of this block.
X| The value is put there by the build program after it has discovered how
X| big the operating system is. When the bootblok program is finished loading,
X| it jumps indirectly to the program (menu) which address is given by the
X| last two words in the boot block.
X|
X| Summary of the words patched into the boot block by build:
X| Word at 504: # sectors to load
X| Word at 506: # DS value for menu
X| Word at 508: # PC value for menu
X| Word at 510: # CS value for menu
X|
X| This version of the boot block must be assembled without separate I & D
X| space.
X
X LOADSEG = 0x0060 | here the boot block will start loading
X BIOSSEG = 0x07C0 | here the boot block itself is loaded
X BOOTSEG = 0x3FA0 | here it will copy itself (256K-1.5K)
X DSKBASE = 120 | 120 = 4 * 0x1E = ptr to disk parameters
X
Xfinal = 504
Xmenu_ds = 506
Xmenu_pc = 508
Xmenu_cs = 510
X
X
X.globl begtext, begdata, begbss, endtext, enddata, endbss | asld needs these
X.text
Xbegtext:
X.data
Xbegdata:
X.bss
Xbegbss:
X.text
X
X| copy bootblock to bootseg
X mov ax,#BIOSSEG
X mov ds,ax
X xor si,si | ds:si - original block
X mov ax,#BOOTSEG
X mov es,ax
X xor di,di | es:di - new block
X mov cx,#256 | # words to move
X rep
X movw | copy loop
X
X
X| start boot procedure
X jmpi start, BOOTSEG | set cs to BOOTSEG
X
Xstart:
X mov dx,cs
X mov ds,dx | set ds to cs
X xor ax,ax
X mov es,ax | set es to 0
X mov ss,dx | set ss to cs i.e., stack in high core
X mov sp,#1536 | initialize sp to high core
X
X| print greeting
X mov ax,#2 | reset video
X int 0x10
X
X mov ax,#0x0200 | BIOS call in put cursor in ul corner
X xor bx,bx
X xor dx,dx
X int 0x10
X mov bx,#greet
X call print
X
X| Set up for 720K disk.
X
X mov tracksiz,#9
X xor ax,ax | ps disk parameters are in ROM F01520
X mov es,ax
X mov ax,#0x1520
X seg es
X mov DSKBASE,ax
X mov ax,#0xF000
X seg es
X mov DSKBASE+2,ax
X
X xor ax,ax | diskette reset
X int 0x13
X
X| Load the operating system from diskette.
Xload:
X call setreg | set up ah, cx, dx
X mov bx,disksec | bx = number of next sector to read
X add bx,#2 | diskette sector 1 goes at 1536 ("sector" 3)
X shl bx,#1 | multiply sector number by 32
X shl bx,#1 | ditto
X shl bx,#1 | ditto
X shl bx,#1 | ditto
X shl bx,#1 | ditto
X mov es,bx | core address is es:bx (with bx = 0)
X xor bx,bx | see above
X add disksec,ax | ax tells how many sectors to read
X movb ah,#2 | opcode for read
X int 0x13 | call the BIOS for a read
X jb error | jump on diskette error
X mov ax,disksec | see if we are done loading
X cmp ax,final | ditto
X jb load | jump if there is more to load
X
X| Loading done. Finish up.
X mov dx,#0x03F2 | kill the motor
X mov ax,#0x000C
X out
X cli
X mov bx,tracksiz | menu expects # sectors/track in bx
X mov ax,menu_ds | set segment registers
X mov ds,ax | when sep I&D DS != CS
X mov es,ax | otherwise they are the same.
X mov ss,ax | words 504 - 510 are patched by build
X
X seg cs
X jmpi @menu_pc | jmp to menu
X
X| Given the number of the next disk block to read, disksec, compute the
X| cylinder, sector, head, and number of sectors to read as follows:
X| ah = # sectors to read; cl = sector #; ch = cyl; dh = head; dl = 0
Xsetreg:
X mov si,tracksiz | 9 (PC) or 15 (AT) sectors per track
X mov ax,disksec | ax = next sector to read
X xor dx,dx | dx:ax = 32-bit dividend
X div si | divide sector # by track size
X mov cx,ax | cx = track #; dx = sector (0-origin)
X mov bx,dx | bx = sector number (0-origin)
X mov ax,disksec | ax = next sector to read
X add ax,si | ax = last sector to read + 1
X dec ax | ax = last sector to read
X xor dx,dx | dx:ax = 32-bit dividend
X div tracksiz | divide last sector by track size
X cmpb al,cl | is starting track = ending track
X je set1 | jump if whole read on 1 cylinder
X sub si,dx | compute lower sector count
X dec si | si = # sectors to read
X
X| Check to see if this read crosses a 64K boundary (128 sectors).
X| Such calls must be avoided. The BIOS gets them wrong.
Xset1: mov ax,disksec | ax = next sector to read
X add ax,#2 | disk sector 1 goes in core sector 3
X mov dx,ax | dx = next sector to read
X add dx,si | dx = one sector beyond end of read
X dec dx | dx = last sector to read
X shl ax,#1 | ah = which 64K bank does read start at
X shl dx,#1 | dh = which 64K bank foes read end in
X cmpb ah,dh | ah != dh means read crosses 64K boundary
X je set2 | jump if no boundary crossed
X shrb dl,#1 | dl = excess beyond 64K boundary
X xorb dh,dh | dx = excess beyond 64K boundary
X sub si,dx | adjust si
X dec si | si = number of sectors to read
X
Xset2: mov ax,si | ax = number of sectors to read
X xor dx,dx | dh = head, dl = drive
X movb dh,cl | dh = track
X andb dh,#0x01 | dh = head
X movb ch,cl | ch = track to read
X shrb ch,#1 | ch = cylinder
X movb cl,bl | cl = sector number (0-origin)
X incb cl | cl = sector number (1-origin)
X xorb dl,dl | dl = drive number (0)
X ret | return values in ax, cx, dx
X
X
X|-------------------------------+
X| error & print routines |
X|-------------------------------+
X
Xerror:
X push ax
X mov bx,#fderr
X call print | print msg
X xor cx,cx
Xerr1: mul 0 | delay
X loop err1
X int 0x19
X
X
Xprint: | print string (bx)
X movb al,(bx) | al contains char to be printed
X testb al,al | null char?
X jne prt1 | no
X ret | else return
Xprt1: movb ah,#14 | 14 = print char
X inc bx | increment string pointer
X push bx | save bx
X movb bl,#1 | foreground color
X xorb bh,bh | page 0
X int 0x10 | call BIOS VIDEO_IO
X pop bx | restore bx
X jmp print | next character
X
X
Xdisksec:.word 1
Xpcpar: .byte 0xDF, 0x02, 25, 2, 9, 0x2A, 0xFF, 0x50, 0xF6, 1, 3 | for pc
Xatpar: .byte 0xDF, 0x02, 25, 2,15, 0x1B, 0xFF, 0x54, 0xF6, 1, 8 | for at
X
Xfderr: .asciz "Read error. Automatic reboot.\r\n"
Xgreet: .asciz "\rBooting MINIX 1.5. Copyright 1991 Prentice-Hall, Inc.\r\n"
Xtracksiz:.word 15 | changed to 9 for ps and pc
X
X| Don't forget that words 504 - 510 are filled in by build. The regular
X| code had better not get that far.
X.text
Xendtext:
X.data
Xenddata:
X.bss
Xendbss:
/
echo x - /usr/src/local/tools/config
sed '/^X/s///' > /usr/src/local/tools/config << '/'
Xprog=`basename $0`
X
Xcase $1 in
X 360) drive=360;;
X
X 720) drive=720;;
X
X 1200) drive=1200;;
X
X clean) echo "rm -f bootblok.s"
X rm -f bootblok.s
X exit 0;;
X
X *)
X echo "$prog: usage: $prog [ 360 | 720 | 1200 ]"
X exit 1;;
X
Xesac
X
Xecho "cp bootblok$drive.s bootblok.s"
Xcp bootblok$drive.s bootblok.s
X
Xecho "Now set up to build a boot image for a" $drive "k disk."
X
Xexit 0
/
Ken Hendrickson N8DGN/6 kjh@usc.edu ...!uunet!usc!pollux!kjh