ast@cs.vu.nl (Andy Tanenbaum) (09/28/88)
: This is a shar archive. Extract with sh, not csh. : This archive ends with exit, so do not worry about trailing junk. : --------------------------- cut here -------------------------- PATH=/bin:/usr/bin:/usr/ucb echo Extracting 'floppy.c.cdif' sed 's/^X//' > 'floppy.c.cdif' << '+ END-OF-FILE ''floppy.c.cdif' X*** /local/ast/minix/tape3b/kernel/floppy.c Wed Jul 13 16:59:18 1988 X--- floppy.c Mon Sep 26 23:34:08 1988 X*************** X*** 120,126 **** X vir_bytes fl_address; /* user virtual address */ X char fl_results[MAX_RESULTS]; /* the controller can give lots of output */ X char fl_calibration; /* CALIBRATED or UNCALIBRATED */ X! char fl_density; /* 0 = 360K/360K; 1 = 360K/1.2M; 2= 1.2M/1.2M */ X } floppy[NR_DRIVES]; X X #define UNCALIBRATED 0 /* drive needs to be calibrated at next use */ X--- 120,126 ---- X vir_bytes fl_address; /* user virtual address */ X char fl_results[MAX_RESULTS]; /* the controller can give lots of output */ X char fl_calibration; /* CALIBRATED or UNCALIBRATED */ X! char fl_density; /* 0 = 360K/360K; 1 = 360K/1.2M; 2= 1.2M/1.2M*/ X } floppy[NR_DRIVES]; X X #define UNCALIBRATED 0 /* drive needs to be calibrated at next use */ X*************** X*** 158,164 **** X PRIVATE int steps_per_cyl[NT] = X {1, 1, 2, 1, 2, 1}; /* 2 = dbl step */ X PRIVATE int mtr_setup[NT] = X! {HZ/4,3*HZ/4,HZ/4,HZ/4,3*HZ/4,3*HZ/4};/* in ticks */ X X /*===========================================================================* X * floppy_task * X--- 158,164 ---- X PRIVATE int steps_per_cyl[NT] = X {1, 1, 2, 1, 2, 1}; /* 2 = dbl step */ X PRIVATE int mtr_setup[NT] = X! {HZ/4,3*HZ/4,HZ/4,2*HZ/4,3*HZ/4,3*HZ/4};/* in ticks */ X X /*===========================================================================* X * floppy_task * X*************** X*** 204,210 **** X { X /* Carry out a read or write request from the disk. */ X register struct floppy *fp; X! int r, drive, errors, stop_motor(); X long block; X X /* Decode the message parameters. */ X--- 204,210 ---- X { X /* Carry out a read or write request from the disk. */ X register struct floppy *fp; X! int r, sectors, drive, errors, stop_motor(); X long block; X X /* Decode the message parameters. */ X*************** X*** 238,243 **** X--- 238,247 ---- X if (errors % (MAX_ERRORS/NT) == 0) { X d = (d + 1) % NT; /* try next density */ X fp->fl_density = d; X+ sectors = nr_sectors[d]; X+ fp->fl_cylinder = (int) (block / (NR_HEADS * sectors)); X+ fp->fl_sector = (int) interleave[(int)(block % sectors)]; X+ fp->fl_head = (int)(block%(NR_HEADS*sectors)) / sectors; X need_reset = 1; X } X if (block >= nr_blocks[d]) continue; X*************** X*** 259,265 **** X r = transfer(fp); X if (r == OK) break; /* if successful, exit loop */ X if (r == ERR_WR_PROTECT) break; /* retries won't help */ X- X } X X /* Start watch_dog timer to turn motor off in a few seconds */ X--- 263,268 ---- X*************** X*** 385,391 **** X * positioned on the correct cylinder. X */ X X! int r; X X /* Are we already on the correct cylinder? */ X if (fp->fl_calibration == UNCALIBRATED) X--- 388,394 ---- X * positioned on the correct cylinder. X */ X X! int r, send_mess(); X X /* Are we already on the correct cylinder? */ X if (fp->fl_calibration == UNCALIBRATED) X*************** X*** 407,412 **** X--- 410,419 ---- X if (r != OK) X if (recalibrate(fp) != OK) return(ERR_SEEK); X fp->fl_curcyl = (r == OK ? fp->fl_cylinder : -1); X+ if (r == OK && ps) { /* give head time to settle on PS/2 */ X+ clock_mess(2, send_mess); X+ receive(CLOCK, &mess); X+ } X return(r); X } X X*************** X*** 567,572 **** X--- 574,583 ---- X } else { X /* Recalibration succeeded. */ X fp->fl_calibration = CALIBRATED; X+ if (ps) { /* give head time to settle on PS/2 */ X+ clock_mess(2, send_mess); X+ receive(CLOCK, &mess); X+ } X return(OK); X } X } X*************** X*** 621,627 **** X X mess.m_type = SET_ALARM; X mess.CLOCK_PROC_NR = FLOPPY; X! mess.DELTA_TICKS = ticks; X mess.FUNC_TO_CALL = func; X sendrec(CLOCK, &mess); X } X--- 632,638 ---- X X mess.m_type = SET_ALARM; X mess.CLOCK_PROC_NR = FLOPPY; X! mess.DELTA_TICKS = (long) ticks; X mess.FUNC_TO_CALL = func; X sendrec(CLOCK, &mess); X } X*************** X*** 634,639 **** X { X /* This routine is called when the clock task has timed out on motor startup.*/ X X- mess.m_type = MOTOR_RUNNING; X send(FLOPPY, &mess); X } X--- 645,649 ---- + END-OF-FILE floppy.c.cdif chmod 'u=rw,g=r,o=r' 'floppy.c.cdif' set `wc -c 'floppy.c.cdif'` count=$1 case $count in 4225) :;; *) echo 'Bad character count in ''floppy.c.cdif' >&2 echo 'Count should be 4225' >&2 esac echo Extracting 'glo.h.cdif' sed 's/^X//' > 'glo.h.cdif' << '+ END-OF-FILE ''glo.h.cdif' X*** /local/ast/minix/tape3b/kernel/glo.h Fri Jul 15 20:26:02 1988 X--- glo.h Mon Sep 26 23:34:09 1988 X*************** X*** 11,15 **** X EXTERN message int_mess; /* interrupt routines build message here */ X X /* CPU type. */ X! EXTERN int olivetti; /* TRUE for Olivetti-style keyboard */ X! EXTERN int pc_at; /* PC-AT type diskette drives (360K/1.2M) ? */ X--- 11,22 ---- X EXTERN message int_mess; /* interrupt routines build message here */ X X /* CPU type. */ X! EXTERN int pc_at; /* PC-AT type diskette drives (360K/1.2M) ? */ X! EXTERN int ps; /* are we dealing with a ps? */ X! EXTERN int port_65; /* saved contents of Planar Control Register */ X! X! /* Video cards and keyboard types. */ X! EXTERN int color; /* 1 if console is color, 0 if it is mono */ X! EXTERN int ega; /* 1 if console is EGA, 0 if not */ X! EXTERN int need_ega_int; /* ask clock for ega interrupt */ X! EXTERN int scan_code; /* scan code of key pressed to start minix */ + END-OF-FILE glo.h.cdif chmod 'u=rw,g=r,o=r' 'glo.h.cdif' set `wc -c 'glo.h.cdif'` count=$1 case $count in 951) :;; *) echo 'Bad character count in ''glo.h.cdif' >&2 echo 'Count should be 951' >&2 esac echo Extracting 'klib88.s.cdif' sed 's/^X//' > 'klib88.s.cdif' << '+ END-OF-FILE ''klib88.s.cdif' X*** /local/ast/minix/tape3b/kernel/klib88.s Thu Jul 21 22:08:49 1988 X--- klib88.s Mon Sep 26 23:40:35 1988 X*************** X*** 3,16 **** X | X | phys_copy: copies data from anywhere to anywhere in memory X | cp_mess: copies messages from source to destination X- | port_out: outputs data on an I/O port X- | port_in: inputs data from an I/O port X | lock: disable interrupts X | restore: restore interrupts (enable/disabled) as they were before lock() X | build_sig: build 4 word structure pushed onto stack for signals X | csv: procedure prolog to save the registers X | cret: procedure epilog to restore the registers X | get_chrome: returns 0 if display is monochrome, 1 if it is color X | vid_copy: copy data to video ram (on color display during retrace only) X | scr_up: scroll screen a line up (in software, by copying) X | scr_down: scroll screen a line down (in software, by copying) X--- 3,15 ---- X | X | phys_copy: copies data from anywhere to anywhere in memory X | cp_mess: copies messages from source to destination X | lock: disable interrupts X | restore: restore interrupts (enable/disabled) as they were before lock() X | build_sig: build 4 word structure pushed onto stack for signals X | csv: procedure prolog to save the registers X | cret: procedure epilog to restore the registers X | get_chrome: returns 0 if display is monochrome, 1 if it is color X+ | get_ega: returns 1 if display is EGA, 0 otherwise X | vid_copy: copy data to video ram (on color display during retrace only) X | scr_up: scroll screen a line up (in software, by copying) X | scr_down: scroll screen a line down (in software, by copying) X*************** X*** 20,38 **** X | dma_read: transfer data between HD controller and memory X | dma_write: transfer data between memory and HD controller X | em_xfer: read or write AT extended memory using the BIOS X X | The following procedures are defined in this file and called from outside it. X! .globl _phys_copy, _cp_mess, _port_out, _port_in, _lock, _restore X .globl _build_sig, csv, cret, _get_chrome, _vid_copy, _get_byte, _reboot X .globl _wreboot, _dma_read, _dma_write, _em_xfer, _scr_up, _scr_down X X! | The following external procedure is called in this file. X .globl _panic X X | Variables and data structures X! .globl _color, _cur_proc, _proc_ptr, splimit, _vec_table, _vid_mask X X- X |*===========================================================================* X |* phys_copy * X |*===========================================================================* X--- 19,43 ---- X | dma_read: transfer data between HD controller and memory X | dma_write: transfer data between memory and HD controller X | em_xfer: read or write AT extended memory using the BIOS X+ | wait_retrace: waits for retrace interval, and returns int disabled X+ | wait_no_retrace: waits for not retrace interval, and returns int disabled X+ | ack_char: acknowledge character from keyboard X+ | save_tty_vec: save tty interrupt vector 0x71 for PS/2 X X | The following procedures are defined in this file and called from outside it. X! .globl _phys_copy, _cp_mess, _lock, _restore X .globl _build_sig, csv, cret, _get_chrome, _vid_copy, _get_byte, _reboot X .globl _wreboot, _dma_read, _dma_write, _em_xfer, _scr_up, _scr_down X+ .globl _ack_char, _save_tty_vec, _get_ega, _wait_retrace, _wait_no_retrace X X! X! | The following external procedures are called in this file. X .globl _panic X X | Variables and data structures X! .globl _color, _cur_proc, _proc_ptr, splimit X! .globl _port_65, _ps, _vec_table, _vid_mask, _vid_port X X |*===========================================================================* X |* phys_copy * X |*===========================================================================* X*************** X*** 41,47 **** X X _phys_copy: X pushf | save flags X! cli | disable interrupts X cld | clear direction flag X push bp | save the registers X push ax | save ax X--- 46,52 ---- X X _phys_copy: X pushf | save flags X! | cli | disable interrupts X cld | clear direction flag X push bp | save the registers X push ax | save ax X*************** X*** 130,136 **** X |*===========================================================================* X |* cp_mess * X |*===========================================================================* X! | This routine makes a fast copy of a message from anywhere in the address X | space to anywhere else. It also copies the source address provided as a X | parameter to the call into the first word of the destination message. X | It is called by: X--- 135,141 ---- X |*===========================================================================* X |* cp_mess * X |*===========================================================================* X! | This routine is makes a fast copy of a message from anywhere in the address X | space to anywhere else. It also copies the source address provided as a X | parameter to the call into the first word of the destination message. X | It is called by: X*************** X*** 138,223 **** X | where all 5 parameters are shorts (16-bits). X | X | Note that the message size, 'Msize' is in WORDS (not bytes) and must be set X! | correctly. Changing the definition of message in type file and not changing X | it here will lead to total disaster. X! | This routine destroys ax. It preserves the other registers. X X Msize = 12 | size of a message in 16-bit words X _cp_mess: X- push bp | save bp X push es | save es X push ds | save ds X! mov bp,sp | index off bp because machine can't use sp X pushf | save flags X cli | disable interrupts X- cld | clear direction flag X- push cx | save cx X push si | save si X push di | save di X! X! mov ax,8(bp) | ax = process number of sender X! mov di,16(bp) | di = offset of destination buffer X! mov es,14(bp) | es = clicks of destination X! mov si,12(bp) | si = offset of source message X! mov ds,10(bp) | ds = clicks of source message X seg es | segment override prefix X mov (di),ax | copy sender's process number to dest message X add si,*2 | don't copy first word X add di,*2 | don't copy first word X mov cx,*Msize-1 | remember, first word doesn't count X rep | iterate cx times to copy 11 words X movw | copy the message X- X pop di | restore di X pop si | restore si X! pop cx | restore cs X! popf | restore flags X pop ds | restore ds X! pop es | restore es X! pop bp | restore bp X ret | that's all folks! X X X |*===========================================================================* X- |* port_out * X- |*===========================================================================* X- | port_out(port, value) writes 'value' on the I/O port 'port'. X- X- _port_out: X- push bx | save bx X- mov bx,sp | index off bx X- push ax | save ax X- push dx | save dx X- mov dx,4(bx) | dx = port X- mov ax,6(bx) | ax = value X- out | output 1 byte X- pop dx | restore dx X- pop ax | restore ax X- pop bx | restore bx X- ret | return to caller X- X- X- |*===========================================================================* X- |* port_in * X- |*===========================================================================* X- | port_in(port, &value) reads from port 'port' and puts the result in 'value'. X- _port_in: X- push bx | save bx X- mov bx,sp | index off bx X- push ax | save ax X- push dx | save dx X- mov dx,4(bx) | dx = port X- in | input 1 byte X- xorb ah,ah | clear ah X- mov bx,6(bx) | fetch address where byte is to go X- mov (bx),ax | return byte to caller in param X- pop dx | restore dx X- pop ax | restore ax X- pop bx | restore bx X- ret | return to caller X- X- X- |*===========================================================================* X |* lock * X |*===========================================================================* X | Disable CPU interrupts. Return old psw as function value. X--- 143,187 ---- X | where all 5 parameters are shorts (16-bits). X | X | Note that the message size, 'Msize' is in WORDS (not bytes) and must be set X! | correctly. Changing the definition of message the type file and not changing X | it here will lead to total disaster. X! | X! | This routine only preserves the registers the 'C' compiler X! | expects to be preserved (es, ds, si, di, sp, bp). X X Msize = 12 | size of a message in 16-bit words X _cp_mess: X push es | save es X push ds | save ds X! mov bx,sp | index off bx because machine can't use sp X pushf | save flags X cli | disable interrupts X push si | save si X push di | save di X! mov di,14(bx) | di = offset of destination buffer X! les si,10(bx) | use 32 bit load(ds is our base) X! | si = offset of source message X! | es = clicks of destination X! lds ax,6(bx) | use 32 bit load .... X! | ax = process number of sender X! | ds = clicks of source message X seg es | segment override prefix X mov (di),ax | copy sender's process number to dest message X add si,*2 | don't copy first word X add di,*2 | don't copy first word X mov cx,*Msize-1 | remember, first word doesn't count X+ cld | clear direction flag X rep | iterate cx times to copy 11 words X movw | copy the message X pop di | restore di X pop si | restore si X! popf | restore flags (resets interrupts to old state) X pop ds | restore ds X! pop es | restore es X ret | that's all folks! X X X |*===========================================================================* X |* lock * X |*===========================================================================* X | Disable CPU interrupts. Return old psw as function value. X*************** X*** 332,337 **** X--- 296,318 ---- X ret | monochrome return X X |*===========================================================================* X+ |* get_ega * X+ |*===========================================================================* X+ | This routine calls the BIOS to find out if the display is ega. This X+ | is needed because scrolling is different. X+ _get_ega: X+ movb bl,*0x10 X+ movb ah,*0x12 X+ int 0x10 | call the BIOS to get equipment type X+ X+ cmpb bl,*0x10 | if reg is unchanged, it failed X+ je notega X+ mov ax,#1 | color = 1 X+ ret | color return X+ notega: xor ax,ax | mono = 0 X+ ret | monochrome return X+ X+ |*===========================================================================* X |* dma_read * X |*===========================================================================* X _dma_read: X*************** X*** 392,401 **** X | 'videobase' is 0xB800 for color and 0xB000 for monochrome displays X | 'offset' tells where within video ram to copy the data X | 'words' tells how many words to copy X! | if buffer is zero, the fill char (BLANK) is used X X- BLANK = 0x0700 | controls color of cursor on blank screen X- X _vid_copy: X push bp | we need bp to access the parameters X mov bp,sp | set bp to sp for indexing X--- 373,380 ---- X | 'videobase' is 0xB800 for color and 0xB000 for monochrome displays X | 'offset' tells where within video ram to copy the data X | 'words' tells how many words to copy X! | if buffer is zero, the fill char (blank_color) is used X X _vid_copy: X push bp | we need bp to access the parameters X mov bp,sp | set bp to sp for indexing X*************** X*** 423,428 **** X--- 402,409 ---- X X vid.1: test _color,*1 | skip vertical retrace test if display is mono X jz vid.4 | if monochrome then go to vid.2 X+ test _ega,*1 | if ega also don't need to wait X+ jnz vid.4 X X |vid.2: in | with a color display, you can only copy to X | test al,*010 | the video ram during vertical retrace, so X*************** X*** 432,438 **** X jz vid.3 | until it comes on (start of retrace) X X vid.4: pushf | copying may now start; save flags X! cli | interrupts just get in the way: disable them X cld | clear direction flag X mov es,6(bp) | load es now: int routines may ruin it X X--- 413,419 ---- X jz vid.3 | until it comes on (start of retrace) X X vid.4: pushf | copying may now start; save flags X! | cli | interrupts just get in the way: disable them X cld | clear direction flag X mov es,6(bp) | load es now: int routines may ruin it X X*************** X*** 464,481 **** X pop bp | restore bp X ret | return to caller X X! vid.7: mov ax,#BLANK | ax = blanking character X rep | copy loop X stow | blank screen X jmp vid.5 | done X X |*===========================================================================* X |* scr_up * X |*===========================================================================* X | This routine scrolls the screen up one line on an EGA display X | X | The call is: X! | scr_up(org) X | where X | 'org' is the video segment origin of the desired page X X--- 445,506 ---- X pop bp | restore bp X ret | return to caller X X! vid.7: mov ax,_blank_color | ax = blanking character X rep | copy loop X stow | blank screen X jmp vid.5 | done X X |*===========================================================================* X+ |* wait_retrace * X+ |*===========================================================================* X+ | Wait until we're in the retrace interval. Return locked (ints off). X+ | But enable them during the wait. X+ X+ _wait_ret: push dx X+ pushf X+ mov dx,_vid_port X+ or dx,#0x000A X+ wtre.3: sti X+ nop X+ nop X+ cli X+ in | 0x3DA bit 3 is set during retrace. X+ testb al,*010 | Wait until it is on. X+ jz wtre.3 X+ X+ pop ax | return flags for restoration later X+ pop dx X+ ret | return to caller X+ X+ |*===========================================================================* X+ |* wait_no_retrace * X+ |*===========================================================================* X+ | Wait until we're not in the retrace interval. Return locked (ints off). X+ | But enable then during the wait. X+ X+ _wait_no_ret: push dx X+ pushf X+ mov dx,_vid_port X+ or dx,#0x000A X+ wtnre: sti X+ nop X+ nop X+ cli X+ in | 0x3DA bit 3 is set during retrace. X+ testb al,*010 | Wait until it is off. X+ jnz wtnre X+ X+ pop ax | return flags for restoration later X+ pop dx X+ ret | return to caller X+ X+ |*===========================================================================* X |* scr_up * X |*===========================================================================* X | This routine scrolls the screen up one line on an EGA display X | X | The call is: X! | scr_up(org,source,dest,count) X | where X | 'org' is the video segment origin of the desired page X X*************** X*** 487,498 **** X push cx | save cx X push es | save es X push ds | save ds X! mov si,#160 | si = pointer to data to be copied X! mov di,#0 | di = offset within video ram X! mov cx,#1920 | cx = word count for copy loop X X pushf | copying may now start; save flags X! cli | interrupts just get in the way: disable them X cld | clear diretion flag X mov ax,4(bp) X mov es,ax | load es now: int routines may ruin it X--- 512,523 ---- X push cx | save cx X push es | save es X push ds | save ds X! mov si,6(bp) | si = pointer to data to be copied X! mov di,8(bp) | di = offset within video ram X! mov cx,10(bp) | cx = word count for copy loop X X pushf | copying may now start; save flags X! | cli | interrupts just get in the way: disable them X cld | clear diretion flag X mov ax,4(bp) X mov es,ax | load es now: int routines may ruin it X*************** X*** 528,539 **** X push cx | save cx X push es | save es X push ds | save ds X! mov si,#3838 | si = pointer to data to be copied X! mov di,#3998 | di = offset within video ram X! mov cx,#1920 | cx = word count for copy loop X X pushf | copying may now start; save flags X! cli | interrupts just get in the way: disable them X mov ax,4(bp) X mov es,ax | load es now: int routines may ruin it X mov ds,ax X--- 553,564 ---- X push cx | save cx X push es | save es X push ds | save ds X! mov si,6(bp) | si = pointer to data to be copied X! mov di,8(bp) | di = offset within video ram X! mov cx,10(bp) | cx = word count for copy loop X X pushf | copying may now start; save flags X! | cli | interrupts just get in the way: disable them X mov ax,4(bp) X mov es,ax | load es now: int routines may ruin it X mov ds,ax X*************** X*** 704,712 **** X--- 729,785 ---- X pop bp X ret X X+ |*=========================================================================== X+ |* ack_char X+ |*=========================================================================== X+ | Acknowledge character from keyboard for PS/2 X X+ _ack_char: X+ push dx X+ mov dx,#0x69 X+ in X+ xor ax,#0x10 X+ out X+ xor ax,#0x10 X+ out X X+ mov dx,#0x66 X+ movb ah,#0x10 X+ in X+ notb ah X+ andb al,ah X+ out X+ jmp frw1 X+ frw1: notb ah X+ orb al,ah X+ out X+ jmp frw2 X+ frw2: notb ah X+ andb al,ah X+ out X+ X+ pop dx X+ ret X+ X+ X |*===========================================================================* X+ |* save_tty_vec * X+ |*===========================================================================* X+ | Save the tty vector 0x71 (PS/2) X+ _save_tty_vec: X+ push es X+ xor ax,ax X+ mov es,ax X+ seg es X+ mov ax,452 X+ mov tty_vec1,ax X+ seg es X+ mov ax,454 X+ mov tty_vec2,ax X+ pop es X+ ret X+ X+ |*===========================================================================* X |* reboot & wreboot * X |*===========================================================================* X | This code reboots the PC X*************** X*** 718,726 **** X--- 791,803 ---- X call _eth_stp | stop the ethernet chip X call resvec | restore the vectors in low core X mov ax,#0x40 X+ push ds X mov ds,ax X mov ax,#0x1234 X mov 0x72,ax X+ pop ds X+ test _ps,#0xFFFF X+ jnz r.1 X mov ax,#0xFFFF X mov ds,ax X mov ax,3 X*************** X*** 728,733 **** X--- 805,819 ---- X mov ax,1 X push ax X reti X+ r.1: X+ mov ax,_port_65 | restore port 0x65 X+ mov dx,#0x65 X+ out X+ mov dx,#0x21 | restore interrupt mask port X+ mov ax,#0xBC X+ out X+ sti | enable interrupts X+ int 0x19 | for PS/2 call bios to reboot X X _wreboot: X cli | disable interrupts X*************** X*** 738,746 **** X--- 824,836 ---- X xor ax,ax | wait for character before continuing X int 0x16 | get char X mov ax,#0x40 X+ push ds X mov ds,ax X mov ax,#0x1234 X mov 0x72,ax X+ pop ds X+ test _ps,#0xFFFF X+ jnz wr.1 X mov ax,#0xFFFF X mov ds,ax X mov ax,3 X*************** X*** 748,753 **** X--- 838,853 ---- X mov ax,1 X push ax X reti X+ wr.1: X+ mov ax,_port_65 | restore port 0x65 X+ mov dx,#0x65 X+ out X+ mov dx,#0x21 | restore interrupt mask port X+ mov ax,#0xBC X+ out X+ sti | enable interrupts X+ int 0x19 | for PS/2 call bios to reboot X+ X X | Restore the interrupt vectors in low core. X resvec: cld X*************** X*** 757,762 **** X--- 857,870 ---- X mov es,di X rep X movw X+ X+ mov ax,tty_vec1 | Restore keyboard interrupt vector for PS/2 X+ seg es X+ mov 452,ax X+ mov ax,tty_vec2 X+ seg es X+ mov 454,ax X+ X ret X X | Some library routines use exit, so this label is needed. X*************** X*** 771,773 **** X--- 879,883 ---- X tmp: .word 0 | count of bytes already copied X stkoverrun: .asciz "Kernel stack overrun, task = " X _vec_table: .zerow 142 | storage for interrupt vectors X+ tty_vec1: .word 0 | sorage for vector 0x71 (offset) X+ tty_vec2: .word 0 | sorage for vector 0x71 (segment) + END-OF-FILE klib88.s.cdif chmod 'u=rw,g=r,o=r' 'klib88.s.cdif' set `wc -c 'klib88.s.cdif'` count=$1 case $count in 19718) :;; *) echo 'Bad character count in ''klib88.s.cdif' >&2 echo 'Count should be 19718' >&2 esac echo Extracting 'main.c.cdif' sed 's/^X//' > 'main.c.cdif' << '+ END-OF-FILE ''main.c.cdif' X*** /local/ast/minix/tape3b/kernel/main.c Wed Jul 13 16:59:19 1988 X--- main.c Tue Sep 27 08:51:13 1988 X*************** X*** 28,34 **** X--- 28,39 ---- X #define CPU_TY1 0xFFFF /* BIOS segment that tells CPU type */ X #define CPU_TY2 0x000E /* BIOS offset that tells CPU type */ X #define PC_AT 0xFC /* IBM code for PC-AT (in BIOS at 0xFFFFE) */ X+ #define PS 0xFA /* IBM code for PS/2 (in BIOS at 0xFFFFE) */ X #define EM_VEC 0x15 /* vector for extended memory BIOS calls */ X+ #define CMASK1 0x00 /* interrupt mask: ptr, dsk, keybd, clk, PIC */ X+ #define CMASK2 0xBF /* interrupt mask for secondary PIC */ X+ #define CMASK3 0x3C /* interrupt mask for PS/2 */ X+ #define CMASK4 0x9E /* Planar Control Register */ X #define HIGH_INT 16 /* limit of the interrupt vectors */ X X extern int int00(), int01(), int02(), int03(), int04(), int05(), int06(), X*************** X*** 54,60 **** X int stack_size; X int * ktsb; /* kernel task stack base */ X extern unsigned sizes[8]; /* table filled in by build */ X! extern int color, vec_table[], get_chrome(); X extern int s_call(), disk_int(), tty_int(), clock_int(), disk_int(); X extern int wini_int(), lpr_int(), trp(), rs232_int(), secondary_int(); X extern phys_bytes umap(); X--- 59,65 ---- X int stack_size; X int * ktsb; /* kernel task stack base */ X extern unsigned sizes[8]; /* table filled in by build */ X! extern int port_65, ega, color, vec_table[], get_chrome(); X extern int s_call(), disk_int(), tty_int(), clock_int(), disk_int(); X extern int wini_int(), lpr_int(), trp(), rs232_int(), secondary_int(); X extern phys_bytes umap(); X*************** X*** 84,98 **** X for (ktsb = t_stack, t = -NR_TASKS, rp = &proc[0]; X rp <= &proc[NR_TASKS+LOW_USER]; rp++, t++) { X for (i = 0; i < NR_REGS; i++) rp->p_reg[i] = 0100 * i; /* debugging */ X! if (t < 0) X! { X stack_size = tasktab[t+NR_TASKS].stksize; X ktsb += stack_size / sizeof (int); X rp->p_sp = ktsb; X rp->p_splimit = ktsb - (stack_size - SAFETY) / sizeof(int); X! } X! else X! { X rp->p_sp = INIT_SP; X rp->p_splimit = rp->p_sp; X } X--- 89,100 ---- X for (ktsb = t_stack, t = -NR_TASKS, rp = &proc[0]; X rp <= &proc[NR_TASKS+LOW_USER]; rp++, t++) { X for (i = 0; i < NR_REGS; i++) rp->p_reg[i] = 0100 * i; /* debugging */ X! if (t < 0) { X stack_size = tasktab[t+NR_TASKS].stksize; X ktsb += stack_size / sizeof (int); X rp->p_sp = ktsb; X rp->p_splimit = ktsb - (stack_size - SAFETY) / sizeof(int); X! } else { X rp->p_sp = INIT_SP; X rp->p_splimit = rp->p_sp; X } X*************** X*** 141,156 **** X--- 143,162 ---- X X /* Determine if display is color or monochrome and CPU type (from BIOS). */ X color = get_chrome(); /* 0 = mono, 1 = color */ X+ ega = get_ega(); X t = (int)get_byte(CPU_TY1, CPU_TY2) & 0xFF; /* is this PC, XT, AT ... ? */ X if (t == PC_AT) pc_at = TRUE; X+ else if (t == PS) ps = TRUE; X X /* Save the old interrupt vectors. */ X phys_b = umap(proc_addr(HARDWARE), D, (vir_bytes) vec_table, VECTOR_BYTES); X phys_copy(0L, phys_b, (long) VECTOR_BYTES); /* save all the vectors */ X+ if (ps) save_tty_vec(); /* save tty vector 0x71 for reboot() */ X X /* Set up the new interrupt vectors. */ X for (t = 0; t < HIGH_INT; t++) set_vec(t, int_vec[t], base_click); X for (t = HIGH_INT; t < 256; t++) set_vec(t, trp, base_click); X+ X set_vec(SYS_VECTOR, s_call, base_click); X set_vec(CLOCK_VECTOR, clock_int, base_click); X set_vec(KEYBOARD_VECTOR, tty_int, base_click); X*************** X*** 166,184 **** X if (pc_at) { X set_vec(AT_WINI_VECTOR, wini_int, base_click); X phys_copy(phys_b + 4L*EM_VEC, 4L*EM_VEC, 4L); /* extended mem vec */ X! } else { X set_vec(XT_WINI_VECTOR, wini_int, base_click); X- } X X /* Put a ptr to proc table in a known place so it can be found in /dev/mem */ X set_vec( (BASE - 4)/4, proc, (phys_clicks) 0); X X bill_ptr = proc_addr(HARDWARE); /* it has to point somewhere */ X pick_proc(); X X /* Now go to the assembly code to start running the current process. */ X- port_out(INT_CTLMASK, 0); /* do not mask out any interrupts in 8259A */ X- port_out(INT2_MASK, 0); /* same for second interrupt controller */ X restart(); X } X X--- 172,200 ---- X if (pc_at) { X set_vec(AT_WINI_VECTOR, wini_int, base_click); X phys_copy(phys_b + 4L*EM_VEC, 4L*EM_VEC, 4L); /* extended mem vec */ X! } else X set_vec(XT_WINI_VECTOR, wini_int, base_click); X X+ if (ps) /* PS/2 */ X+ set_vec(PS_KEYB_VECTOR, tty_int, base_click); X+ X /* Put a ptr to proc table in a known place so it can be found in /dev/mem */ X set_vec( (BASE - 4)/4, proc, (phys_clicks) 0); X X bill_ptr = proc_addr(HARDWARE); /* it has to point somewhere */ X pick_proc(); X X+ /* Mask out interupts except ptr, disk, clock, keyboard, PIC */ X+ if (ps) { X+ port_in(PCR, &port_65); /* save Planar Control Register */ X+ port_out(0x65, CMASK4); /* set Planar Control Register */ X+ port_out(INT_CTLMASK, CMASK3); X+ } else { X+ port_out(INT_CTLMASK, CMASK1); /* mask out unwanted 8259 interrupts */ X+ port_out(INT2_MASK, CMASK2); /* same for second intr controller */ X+ } X+ X /* Now go to the assembly code to start running the current process. */ X restart(); X } X X*************** X*** 268,274 **** X phys_copy(phys_b, (phys_bytes) vec_nr*4, (phys_bytes) 4); X } X #endif X- X X /*===========================================================================* X * networking * X--- 284,289 ---- + END-OF-FILE main.c.cdif chmod 'u=rw,g=r,o=r' 'main.c.cdif' set `wc -c 'main.c.cdif'` count=$1 case $count in 5620) :;; *) echo 'Bad character count in ''main.c.cdif' >&2 echo 'Count should be 5620' >&2 esac echo Extracting 'makefile.cdif' sed 's/^X//' > 'makefile.cdif' << '+ END-OF-FILE ''makefile.cdif' X*** /local/ast/minix/tape3b/kernel/makefile Wed Jul 13 16:59:14 1988 X--- makefile Tue Sep 27 08:51:14 1988 X*************** X*** 6,35 **** X # This is because they have to be in /lib on a PC; the diskette is too small X # for them to be in /usr/lib. You can change this by editing commands/cc.c. X # X! # Normally, MINIX scrolls the screen using the 6845's registers. However, X! # on some EGA cards (those that are not IBM compatible), the 6845 is not X! # properly emulated. On these machines, it is necessary to scroll in X! # software by copying. This is much slower, but it works. The CFLAGS flags are: X! # X # -Di8088 - required on an 8088/80286/80386 CPU; forbidden on a 68000 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 # X! # In the standard distribution, the following defaults are set X! # PC: CFLAGS = -Di8088 -F -T. X! # AT: CFLAGS = -Di8088 -F X! # X! CFLAGS= -Di8088 -F X h=../h X! l=/usr/lib X X obj = mpx88.s main.s tty.s floppy.s wini.s system.s proc.s clock.s memory.s \ X! printer.s table.s klib88.s dmp.s X X cobjs = main.s tty.s floppy.s wini.s system.s proc.s clock.s memory.s \ X! printer.s table.s dmp.s X X- X kernel: makefile $(obj) $l/libc.a X @echo "Start linking Kernel." X @asld -o kernel $(obj) $l/libc.a $l/end.s X--- 6,26 ---- X # This is because they have to be in /lib on a PC; the diskette is too small X # for them to be in /usr/lib. You can change this by editing commands/cc.c. X # X! # The CFLAGS values are: X # -Di8088 - required on an 8088/80286/80386 CPU; forbidden on a 68000 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 # X! CFLAGS= -Di8088 -F X h=../h X! l=/lib X X obj = mpx88.s main.s tty.s floppy.s wini.s system.s proc.s clock.s memory.s \ X! console.s rs232.s printer.s table.s klib88.s dmp.s X X cobjs = main.s tty.s floppy.s wini.s system.s proc.s clock.s memory.s \ X! console.s rs232.s printer.s table.s dmp.s X X kernel: makefile $(obj) $l/libc.a X @echo "Start linking Kernel." X @asld -o kernel $(obj) $l/libc.a $l/end.s X*************** X*** 46,51 **** X--- 37,53 ---- X clock.s: glo.h X clock.s: proc.h X X+ console.s: const.h type.h $h/const.h $h/type.h X+ console.s: $h/callnr.h X+ console.s: $h/com.h X+ console.s: $h/error.h X+ console.s: $h/sgtty.h X+ console.s: $h/signal.h X+ console.s: glo.h X+ console.s: proc.h X+ console.s: tty.h X+ console.s: ttymaps.h X+ X floppy.s: const.h type.h $h/const.h $h/type.h X floppy.s: $h/callnr.h X floppy.s: $h/com.h X*************** X*** 99,104 **** X--- 101,107 ---- X table.s: const.h type.h $h/const.h $h/type.h $h/com.h X table.s: glo.h X table.s: proc.h X+ table.s: tty.h X X tty.s: const.h type.h $h/const.h $h/type.h X tty.s: $h/callnr.h X*************** X*** 108,113 **** X--- 111,120 ---- X tty.s: $h/signal.h X tty.s: glo.h X tty.s: proc.h X+ tty.s: tty.h X+ tty.s: ttymaps.h X+ tty.s: tty.h X+ tty.s: ttymaps.h X X wini.s: const.h type.h $h/const.h $h/type.h X wini.s: $h/callnr.h + END-OF-FILE makefile.cdif chmod 'u=rw,g=r,o=r' 'makefile.cdif' set `wc -c 'makefile.cdif'` count=$1 case $count in 3083) :;; *) echo 'Bad character count in ''makefile.cdif' >&2 echo 'Count should be 3083' >&2 esac echo Extracting 'memory.c.cdif' sed 's/^X//' > 'memory.c.cdif' << '+ END-OF-FILE ''memory.c.cdif' X*** /local/ast/minix/tape3b/kernel/memory.c Wed Jul 13 16:59:19 1988 X--- memory.c Tue Sep 27 08:51:14 1988 X*************** X*** 99,110 **** X /* Get minor device number and check for /dev/null. */ X device = m_ptr->DEVICE; X if (device < 0 || device >= NR_RAMS) return(ENXIO); /* bad minor device */ X! if (device==NULL_DEV) return(m_ptr->m_type == DISK_READ ? EOF : m_ptr->COUNT); X X /* Set up 'mem_phys' for /dev/mem, /dev/kmem, or /dev/ram. */ X if (m_ptr->POSITION < 0) return(ENXIO); X mem_phys = ram_origin[device] + m_ptr->POSITION; X! if (mem_phys >= ram_limit[device]) return(EOF); X count = m_ptr->COUNT; X if(mem_phys + count > ram_limit[device]) count = ram_limit[device] - mem_phys; X X--- 99,110 ---- X /* Get minor device number and check for /dev/null. */ X device = m_ptr->DEVICE; X if (device < 0 || device >= NR_RAMS) return(ENXIO); /* bad minor device */ X! if (device==NULL_DEV) return(m_ptr->m_type == DISK_READ ? 0 : m_ptr->COUNT); X X /* Set up 'mem_phys' for /dev/mem, /dev/kmem, or /dev/ram. */ X if (m_ptr->POSITION < 0) return(ENXIO); X mem_phys = ram_origin[device] + m_ptr->POSITION; X! if (mem_phys >= ram_limit[device]) return(device == RAM_DEV ? EOF : 0); X count = m_ptr->COUNT; X if(mem_phys + count > ram_limit[device]) count = ram_limit[device] - mem_phys; X + END-OF-FILE memory.c.cdif chmod 'u=rw,g=r,o=r' 'memory.c.cdif' set `wc -c 'memory.c.cdif'` count=$1 case $count in 1335) :;; *) echo 'Bad character count in ''memory.c.cdif' >&2 echo 'Count should be 1335' >&2 esac echo Extracting 'mpx88.s.cdif' sed 's/^X//' > 'mpx88.s.cdif' << '+ END-OF-FILE ''mpx88.s.cdif' X*** /local/ast/minix/tape3b/kernel/mpx88.s Thu Jul 21 22:08:49 1988 X--- mpx88.s Tue Sep 27 08:51:15 1988 X*************** X*** 70,76 **** X mov ax,4 | build has loaded this word with ds value X mov ds,ax | ds now contains proper value X mov ss,ax | ss now contains proper value X! mov _scan_code,bx | save scan code for '=' key from bootstrap X mov sp,#_k_stack | set sp to point to the top of the X add sp,#K_STACK_BYTES | kernel stack X X--- 70,76 ---- X mov ax,4 | build has loaded this word with ds value X mov ds,ax | ds now contains proper value X mov ss,ax | ss now contains proper value X! mov _scan_code,bx | save scan code from bootstrap X mov sp,#_k_stack | set sp to point to the top of the X add sp,#K_STACK_BYTES | kernel stack X X*************** X*** 269,274 **** X--- 269,275 ---- X |* save * X |*===========================================================================* X save: | save the machine state in the proc table. X+ cld | set direction flag to a known value X push ds | stack: psw/cs/pc/ret addr/ds X push cs | prepare to restore ds X pop ds | ds has now been set to cs X*************** X*** 300,305 **** X--- 301,307 ---- X add sp,#K_STACK_BYTES | set sp to top of temporary stack X mov splimit,#_k_stack | limit for temporary stack X add splimit,#8 | splimit checks for stack overflow X+ cld X mov ax,ret_save | ax = address to return to X jmp (ax) | return to caller; Note: sp points to saved ax X + END-OF-FILE mpx88.s.cdif chmod 'u=rw,g=r,o=r' 'mpx88.s.cdif' set `wc -c 'mpx88.s.cdif'` count=$1 case $count in 1482) :;; *) echo 'Bad character count in ''mpx88.s.cdif' >&2 echo 'Count should be 1482' >&2 esac echo Extracting 'printer.c.cdif' sed 's/^X//' > 'printer.c.cdif' << '+ END-OF-FILE ''printer.c.cdif' X*** /local/ast/minix/tape3b/kernel/printer.c Wed Jul 13 16:59:19 1988 X--- printer.c Tue Sep 27 08:51:16 1988 X*************** X*** 134,139 **** X--- 134,140 ---- X break; X } X } X+ restore(old_state); X } X X /* Reply to FS, no matter what happened. */ + END-OF-FILE printer.c.cdif chmod 'u=rw,g=r,o=r' 'printer.c.cdif' set `wc -c 'printer.c.cdif'` count=$1 case $count in 263) :;; *) echo 'Bad character count in ''printer.c.cdif' >&2 echo 'Count should be 263' >&2 esac echo Extracting 'proc.c.cdif' sed 's/^X//' > 'proc.c.cdif' << '+ END-OF-FILE ''proc.c.cdif' X*** /local/ast/minix/tape3b/kernel/proc.c Wed Jul 13 16:59:20 1988 X--- proc.c Tue Sep 27 08:51:16 1988 X*************** X*** 36,41 **** X--- 36,43 ---- X X #ifdef i8088 X /* Re-enable the 8259A interrupt controller. */ X+ if (ps && task==FLOPPY)port_out(0x3C, ENABLE);/* Nonspecific End-Of-Int ps */ X+ X port_out(INT_CTL, ENABLE); /* this re-enables the 8259A controller chip */ X if (pc_at && task == WINCHESTER) X /* this re-enables the second controller chip */ + END-OF-FILE proc.c.cdif chmod 'u=rw,g=r,o=r' 'proc.c.cdif' set `wc -c 'proc.c.cdif'` count=$1 case $count in 474) :;; *) echo 'Bad character count in ''proc.c.cdif' >&2 echo 'Count should be 474' >&2 esac echo Extracting 'ps_wini.c.new' sed 's/^X//' > 'ps_wini.c.new' << '+ END-OF-FILE ''ps_wini.c.new' X/* This file contains a driver for the IBM-PS/2 winchester controller. X * It was written by Wim van Leersum. X * X * The driver supports two operations: read a block and X * write a block. It accepts two messages, one for reading and one for X * writing, both using message format m2 and with the same parameters: X * X * m_type DEVICE PROC_NR COUNT POSITION ADRRESS X * ---------------------------------------------------------------- X * | DISK_READ | device | proc nr | bytes | offset | buf ptr | X * |------------+---------+---------+---------+---------+---------| X * | DISK_WRITE | device | proc nr | bytes | offset | buf ptr | X * ---------------------------------------------------------------- X * X * The file contains one entry point: X * X * winchester_task: main entry when system is brought up X * X */ X X#include "../h/const.h" X#include "../h/type.h" X#include "../h/callnr.h" X#include "../h/com.h" X#include "../h/error.h" X#include "const.h" X#include "type.h" X#include "proc.h" X X/* I/O Ports used by winchester disk controller. */ X#define DATA 0x320 /* data register */ X#define ASR 0x322 /* Attachment Status Register */ X#define ATT_REG 0x324 /* Attention register */ X#define ISR 0x324 /* Interrupt status register */ X#define ACR 0x322 /* Attachment control register */ X X/* Winchester disk controller status bits. */ X#define BUSY 0x04 /* controler busy? */ X#define DATA_REQUEST 0x10 /* controler asking for data */ X#define IR 0x02 /* Interrupt Request */ X X/* Winchester disk controller command bytes. */ X#define CSB0 0x03 /* Command Specify Block byte 0 */ X#define CSB 0x40 /* Get controlers attention for a CSB */ X#define DR 0x10 /* Get controlers attention for data transfer */ X#define CCB 0x80 /* same for command control block */ X#define WIN_READ (char)0x15 /* command for the drive to read */ X#define WIN_WRITE (char)0x95 /* command for the drive to write */ X X/* Miscellaneous. */ X#define SECTOR_SIZE 512 /* physical sector size in bytes */ X#define ERR -1 /* general error */ X#define MAX_ERRORS 4 /* how often to try rd/wt before quitting */ X#define NR_DEVICES 10 /* maximum number of drives */ X#define MAX_WIN_RETRY 10000 /* max # times to try to input from WIN */ X#define PART_TABLE 0x1C6 /* IBM partition table starts here in sect 0 */ X#define DEV_PER_DRIVE 5 /* hd0 + hd1 + hd2 + hd3 + hd4 = 5 */ X X#define DMA_READ 0x47 /* DMA read opcode */ X#define DMA_WRITE 0x4B /* DMA write opcode */ X#define DMA_ADDR 0x006 /* port for low 16 bits of DMA address */ X#define DMA_TOP 0x082 /* port for top 4 bits of 20-bit DMA addr */ X#define DMA_COUNT 0x007 /* port for DMA count (count = bytes - 1) */ X#define DMA_M2 0x00C /* DMA status port */ X#define DMA_M1 0x00B /* DMA status port */ X#define DMA_INIT 0x00A /* DMA init port */ X X/* Variables. */ XPRIVATE struct wini { /* main drive struct, one entry per drive */ X int wn_heads; /* maximum number of heads */ X int wn_maxsec; /* maximum number of sectors per track */ X long wn_low; /* lowest cylinder of partition */ X long wn_size; /* size of partition in blocks */ X} wini[NR_DEVICES]; X XPRIVATE int w_need_reset = FALSE; /* set to 1 when controller must be reset */ XPRIVATE int nr_drives; /* Number of drives */ X XPRIVATE message w_mess; /* message buffer for in and out */ X XPRIVATE char command[14]; /* Common command block */ X XPRIVATE unsigned char buf[BLOCK_SIZE]; /* Buffer used by the startup routine */ X X/*===========================================================================* X * winchester_task * X *===========================================================================*/ XPUBLIC winchester_task() X{ X/* Main program of the winchester disk driver task. */ X Xint r, caller, proc_nr; X X /* First initialize the controller */ X init_params(); X X /* Here is the main loop of the disk task. It waits for a message, carries X * it out, and sends a reply. X */ X X while (TRUE) { X /* First wait for a request to read or write a disk block. */ X receive(ANY, &w_mess); /* get a request to do some work */ X if (w_mess.m_source < 0) { X printf("winchester task got message from %d ", w_mess.m_source); X continue; X } X caller = w_mess.m_source; X proc_nr = w_mess.PROC_NR; X X /* Now carry out the work. */ X switch(w_mess.m_type) { X case DISK_READ: X case DISK_WRITE: r = w_do_rdwt(&w_mess); break; X default: r = EINVAL; break; X } X X /* Finally, prepare and send the reply message. */ X w_mess.m_type = TASK_REPLY; X w_mess.REP_PROC_NR = proc_nr; X X w_mess.REP_STATUS = r; /* # of bytes transferred or error code */ X send(caller, &w_mess); /* send reply to caller */ X } X} X X X/*===========================================================================* X * w_do_rdwt * X *===========================================================================*/ XPRIVATE int w_do_rdwt(m_ptr) Xmessage *m_ptr; /* pointer to read or write w_message */ X{ X/* Carry out a read or write request from the disk. */ Xregister struct wini *wn; Xint r, drive, device, errors = 0; Xlong sector; X X /* Decode the w_message parameters. */ X device = m_ptr->DEVICE; X if (device < 0 || device >= NR_DEVICES) X return(EIO); X if (m_ptr->COUNT != BLOCK_SIZE) X return(EINVAL); X wn = &wini[device]; /* 'wn' points to entry for this drive */ X drive = device/DEV_PER_DRIVE; /* save drive number */ X if (drive >= nr_drives) X return(EIO); X if (m_ptr->POSITION % BLOCK_SIZE != 0) X return(EINVAL); X sector = m_ptr->POSITION/SECTOR_SIZE; X if ((sector+BLOCK_SIZE/SECTOR_SIZE) > wn->wn_size) X return(EOF); X X ch_select(); /* Select fixed disk chip */ X X /* This loop allows a failed operation to be repeated. */ X while (errors <= MAX_ERRORS) { X r = OK; X errors++; /* increment count once per loop cycle */ X if (errors > MAX_ERRORS) { X ch_unselect(); X return(EIO); X } X X /* First check to see if a reset is needed. */ X if (w_need_reset) r = w_reset(); X X if (r != OK) break; X X r = w_transfer(wn); /* Perform the transfer. */ X if (r == OK) break; /* if successful, exit loop */ X } X X ch_unselect(); /* Do not select fixed disk chip anymore */ X X return(r == OK ? BLOCK_SIZE : EIO); X} X X X/*===========================================================================* X * ch_select * X *==========================================================================*/ XPRIVATE ch_select() X{ X/* select fixed disk chip */ Xint i; X X port_in(PCR, &i); X port_out(PCR, i | 1); /* bit 1 of Planar Control Reg selects hard disk chip*/ X} X X/*===========================================================================* X * ch_unselect * X *==========================================================================*/ XPRIVATE ch_unselect() X{ Xint i; X X port_in(PCR, &i); X port_out(PCR, i&0xFE); /*bit 1 of Planar Control Reg selects hard disk chip*/ X} X X/*===========================================================================* X * w_dma_setup * X *==========================================================================*/ XPRIVATE w_dma_setup() X{ X/* The IBM PC can perform DMA operations by using the DMA chip. To use it, X * the DMA (Direct Memory Access) chip is loaded with the 20-bit memory address X * to by read from or written to, the byte count minus 1, and a read or write X * opcode. This routine sets up the DMA chip. Note that the chip is not X * capable of doing a DMA across a 64K boundary (e.g., you can't read a X * 512-byte block starting at physical address 65520). X */ X X int lock_var, mode, low_addr, high_addr, top_addr, low_ct, high_ct, top_end; X vir_bytes vir, ct; X phys_bytes user_phys; X extern phys_bytes umap(); X X mode = (w_mess.m_type == DISK_READ ? DMA_READ : DMA_WRITE); X vir = (vir_bytes) w_mess.ADDRESS; X ct = (vir_bytes) BLOCK_SIZE; X user_phys = umap(proc_addr(w_mess.PROC_NR), D, vir, BLOCK_SIZE); X X low_addr = (int) user_phys & BYTE; X high_addr = (int) (user_phys >> 8) & BYTE; X top_addr = (int) (user_phys >> 16) & BYTE; X low_ct = (int) (ct - 1) & BYTE; X high_ct = (int) ( (ct - 1) >> 8) & BYTE; X X /* Check to see if the transfer will require the DMA address counter to X * go from one 64K segment to another. If so, do not even start it, since X * the hardware does not carry from bit 15 to bit 16 of the DMA address. X * Also check for bad buffer address. These errors mean FS contains a bug. X */ X if (user_phys == 0) X panic("FS gave winchester disk driver bad addr", (int) vir); X top_end = (int) (((user_phys + ct - 1) >> 16) & BYTE); X if (top_end != top_addr) panic("Trying to DMA across 64K boundary", top_addr); X X /* Now set up the DMA registers. */ X lock_var = lock(); X port_out(DMA_M2, mode); /* set the DMA mode */ X port_out(DMA_M1, mode); /* set it again */ X port_out(DMA_ADDR, low_addr); /* output low-order 8 bits */ X port_out(DMA_ADDR, high_addr);/* output next 8 bits */ X port_out(DMA_TOP, top_addr); /* output highest 4 bits */ X port_out(DMA_COUNT, low_ct); /* output low 8 bits of count - 1 */ X port_out(DMA_COUNT, high_ct); /* output high 8 bits of count - 1 */ X restore(lock_var); X} X X/*===========================================================================* X * w_transfer * X *===========================================================================*/ XPRIVATE int w_transfer(wn) Xstruct wini *wn; /* pointer to the drive struct */ X{ Xextern phys_bytes umap(); Xregister int i, old_state; Xint r; Xmessage dummy; X X if (w_mess.m_type == DISK_READ) X set_command(WIN_READ, wn); /* build command table */ X else X set_command(WIN_WRITE, wn); X X if (com_out(6, CCB) != OK) return(ERR); /* output command table */ X X for (i = 0; i < MAX_WIN_RETRY; i++) { X port_in(ASR, &r); X if (r & IR) break; /* interrupt request */ X delay(); X } X X if (i == MAX_WIN_RETRY) { X w_need_reset = TRUE; X return(ERR); X } X X if (win_results() != OK) { X w_need_reset = TRUE; X return(ERR); X } X X w_dma_setup(); /* set up dma controler */ X X port_out(ACR, 3); /* enable interrupts and dma */ X port_out(DMA_INIT, 3); /* initialize DMA */ X X port_in(INT_CTLMASK, &r); /* do not mask out fixed disk interrupt */ X port_out(INT_CTLMASK, r & 0xDF); X X if (com_out(0, DR) != OK) return(ERR); /* ask for data transfer */ X X receive(HARDWARE, &dummy); X port_out(INT_CTLMASK, r); /* mask out fixed disk interrupt */ X port_out(ACR, 0); /* disable interrupt and dma */ X X if (win_results() != OK) { X w_need_reset = TRUE; X return(ERR); X } X X return(OK); X} X X/*===========================================================================* X * w_reset * X *===========================================================================*/ XPRIVATE w_reset() X{ X/* Issue a reset to the controller. This is done after any catastrophe, X * like the controller refusing to respond. X */ X X int i; X message dummy; X X port_out(ACR, 0x80); /* Strobe reset bit high. */ X port_out(ACR, 0); /* Strobe reset bit low. */ X X for (i = 0; i < MAX_WIN_RETRY; i++) { X if((status() & IR) == IR) break; X delay(); X } X if (i == MAX_WIN_RETRY) { X printf("Winchester won't reset\n"); X return(ERR); X } X X /* Reset succeeded. Tell WIN drive parameters. */ X if (win_init() != OK) { /* Initialize the controler */ X printf("Winchester wouldn't accept parameters\n"); X return(ERR); X } X X w_need_reset = FALSE; X return(OK); X} X X/*===========================================================================* X * win_init * X *===========================================================================*/ XPRIVATE win_init() X{ X/* Routine to initialize the drive parameters after boot or reset */ X Xregister int i; Xmessage dummy; X X command[0] = CSB0; /* set command bytes */ X for (i = 1; i < 14; i++) X command[i] = 0; X X if (com_out(14, CSB) != OK) { /* Output command block */ X printf("Can't output command block to winchester controler\n"); X return(ERR); X } X X port_out(ACR, 0); /* no interrupts and no dma */ X return(OK); X} X X/*============================================================================* X * win_results * X *============================================================================*/ XPRIVATE win_results() X{ X/* Routine to check if controller has done the operation succesfully */ X int r; X X port_in(ISR, &r); X if ((r & 0xFD) != 0) return(ERR); X return(OK); X} X X/*============================================================================* X * set_command * X *============================================================================*/ XPRIVATE set_command(r_w, wn) Xchar r_w; Xregister struct wini *wn; X{ X/* Set command block to read or write */ Xlong sector; Xunsigned rw_sector, cylinder, head; X X sector = w_mess.POSITION/SECTOR_SIZE; X sector += wn->wn_low; X cylinder = sector / (wn->wn_heads * wn->wn_maxsec); X rw_sector = (sector % wn->wn_maxsec) + 1; X head = (sector % (wn->wn_heads * wn->wn_maxsec) )/wn->wn_maxsec; X X command[0] = r_w; /* WIN_READ or WIN_WRITE */ X command[1] = ((head << 4) & 0xF0) | ((cylinder >> 8) & 0x03); X command[2] = cylinder; X command[3] = rw_sector; X command[4] = 2; X command[5] = BLOCK_SIZE/SECTOR_SIZE; /* Number of sectors */ X} X X/*============================================================================* X * com_out * X *============================================================================*/ XPRIVATE com_out(nr_bytes, attention) Xint nr_bytes; Xint attention; X{ X X/* Output the command block to the winchester controller and return status */ X Xregister int i, j; Xint r; Xmessage dummy; X X port_out(ATT_REG, attention); /* get controler's attention */ X X if (nr_bytes == 0) return(OK); X X for (i = 0; i < nr_bytes; i++) { /* output command block */ X for (j = 0; j < MAX_WIN_RETRY; j++) /* wait for data request */ X if (status() & DATA_REQUEST) break; X X if (j == MAX_WIN_RETRY) { X w_need_reset = TRUE; X return(ERR); X } X port_out(DATA, (int) command[i]); X } X X for (i = 0; i < MAX_WIN_RETRY; i++) { X if ((status() & BUSY) != BUSY) break; X delay(); X } X if (i == MAX_WIN_RETRY) { X w_need_reset = TRUE; X return(ERR); X } X X return(OK); X} X X/*============================================================================* X * status * X *============================================================================*/ XPRIVATE int status() X{ X/* Get status of the controler */ Xint r; X X port_in(ASR, &r); X return r; X} X X/*============================================================================* X * init_params * X *============================================================================*/ XPRIVATE init_params() X{ X/* This routine is called at startup to initialize the partition table, X * the number of drives and the controller X*/ Xunsigned int i, j, segment, offset; Xphys_bytes address; Xextern phys_bytes umap(); Xextern int vec_table[]; X X /* Copy the parameter vector from the saved vector table */ X offset = vec_table[2 * 0x41]; X segment = vec_table[2 * 0x41 + 1]; X X /* Calculate the address off the parameters and copy them to buf */ X address = ((long)segment << 4) + offset; X phys_copy(address, umap(proc_addr(WINCHESTER), D, (vir_bytes)buf, 16), 16L); X X /* Copy the parameters to the structures */ X copy_params(buf, &wini[0]); X X /* Copy the parameter vector from the saved vector table */ X offset = vec_table[2 * 0x46]; X segment = vec_table[2 * 0x46 + 1]; X X /* Calculate the address off the parameters and copy them to buf */ X address = ((long)segment << 4) + offset; X phys_copy(address, umap(proc_addr(WINCHESTER), D, (vir_bytes)buf, 16), 16L); X X /* Copy the parameters to the structures */ X copy_params(buf, &wini[5]); X X /* Get the nummer of drives from the bios */ X phys_copy(0x475L, umap(proc_addr(WINCHESTER), D, (vir_bytes)buf, 1), 1L); X nr_drives = (int) *buf; X X if (nr_drives > 1) nr_drives = 1; /* Only one supported */ X X /* Set the parameters in the drive structure */ X wini[0].wn_low = wini[5].wn_low = 0L; X X ch_select(); /* select fixed disk chip */ X win_init(); /* output parameters to controler */ X ch_unselect(); X X /* Read the partition table for each drive and save them */ X for (i = 0; i < nr_drives; i++) { X w_mess.DEVICE = i * 5; X w_mess.POSITION = 0L; X w_mess.COUNT = BLOCK_SIZE; X w_mess.ADDRESS = (char *) buf; X w_mess.PROC_NR = WINCHESTER; X w_mess.m_type = DISK_READ; X if (w_do_rdwt(&w_mess) != BLOCK_SIZE) { X printf("Can't read partition table on winchester %d\n",i); X for (j = 0; j < 1000; j++) delay(); X continue; X } X if (buf[510] != 0x55 || buf[511] != 0xAA) { X printf("Invalid partition table on winchester %d\n",i); X for (j = 0; j < 1000; j++) delay(); X continue; X } X copy_prt((int)i*5); X } X} X X/*============================================================================* X * copy_params * X *============================================================================*/ XPRIVATE copy_params(src, dest) Xregister unsigned char *src; Xregister struct wini *dest; X{ X/* This routine copies the parameters from src to dest X * and sets the parameters for partition 0 and 5 X*/ X register int i; X long cyl, heads, sectors; X X for (i=0; i<5; i++) { X dest[i].wn_heads = (int)src[2]; X dest[i].wn_maxsec = (int)src[14]; X } X cyl = (long)(*(int *)src); X heads = (long)dest[0].wn_heads; X sectors = (long)dest[0].wn_maxsec; X dest[0].wn_size = cyl * heads * sectors; X} X X/*============================================================================* X * copy_prt * X *============================================================================*/ XPRIVATE copy_prt(drive) Xint drive; X{ X/* This routine copies the partition table for the selected drive to X * the variables wn_low and wn_size X */ X X register int i, offset; X struct wini *wn; X long adjust; X X for (i=0; i<4; i++) { X adjust = 0; X wn = &wini[i + drive + 1]; X offset = PART_TABLE + i * 0x10; X wn->wn_low = *(long *)&buf[offset]; X if ((wn->wn_low % (BLOCK_SIZE/SECTOR_SIZE)) != 0) { X adjust = wn->wn_low; X wn->wn_low = (wn->wn_low/(BLOCK_SIZE/SECTOR_SIZE)+1)*(BLOCK_SIZE/SECTOR_SIZE); X adjust = wn->wn_low - adjust; X } X wn->wn_size = *(long *)&buf[offset + sizeof(long)] - adjust; X } X sort(&wini[drive + 1]); X} X X/*============================================================================* X * sort * X *============================================================================*/ XPRIVATE sort(wn) Xregister struct wini wn[]; X{ X register int i,j; X struct wini tmp; X X for (i=0; i<4; i++) X for (j=0; j<3; j++) X if ((wn[j].wn_low == 0 && wn[j+1].wn_low != 0) || X (wn[j].wn_low > wn[j+1].wn_low && wn[j+1].wn_low != 0)) { X tmp = wn[j]; X wn[j] = wn[j+1]; X wn[j+1] = tmp; X } X} X X/*============================================================================* X * delay * X *============================================================================*/ XPRIVATE delay() X{ X int i; X X for (i = 0; i < 1000; i++) X ; X} + END-OF-FILE ps_wini.c.new chmod 'u=rw,g=r,o=r' 'ps_wini.c.new' set `wc -c 'ps_wini.c.new'` count=$1 case $count in 18813) :;; *) echo 'Bad character count in ''ps_wini.c.new' >&2 echo 'Count should be 18813' >&2 esac exit 0