Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!uunet!pilchuck!amc!ipmoea!ericr From: ericr@ipmoea.UUCP (Eric Roskos) Newsgroups: comp.os.minix Subject: Changes to compile Minix with MSC (kernel.shar: 7 of 12) Message-ID: <29@ipmoea.UUCP> Date: Sat, 22-Aug-87 01:45:21 EDT Article-I.D.: ipmoea.29 Posted: Sat Aug 22 01:45:21 1987 Date-Received: Sun, 23-Aug-87 16:01:15 EDT Reply-To: ericr@ipmoea.UUCP (Eric Roskos) Organization: Redmond, WA Lines: 505 #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # kernel/gn_wini.c # kernel/kernel # kernel/linklist # kernel/_link.bat # This archive created: Sat Aug 1 14:02:09 1987 export PATH; PATH=/bin:$PATH echo shar: extracting "'gn_wini.c'" '(11852 characters)' if test -f 'gn_wini.c' then echo shar: will not over-write existing file "'gn_wini.c'" else cat << \SHAR_EOF > 'gn_wini.c' /* This file contains a driver for "Generic" winchester disks; it uses * the ROM BIOS winchester disk routines. * * It was written by Eric Roskos, based on Adri Koppes's XT_WINI driver. * * If you use this driver, you have to define GENERIC_FDISK and recompile * main.c and klib88.asm, since those files have ifdef's in them for this * driver: main.c is changed to not overwrite the BIOS reserved vectors * and int 13H, and klib88.asm has C call interfaces to the BIOS. * * The driver supports two operations: read a block and * write a block. It accepts two messages, one for reading and one for * writing, both using message format m2 and with the same parameters: * * m_type DEVICE PROC_NR COUNT POSITION ADRRESS * ---------------------------------------------------------------- * | DISK_READ | device | proc nr | bytes | offset | buf ptr | * |------------+---------+---------+---------+---------+---------| * | DISK_WRITE | device | proc nr | bytes | offset | buf ptr | * ---------------------------------------------------------------- * * The file contains one entry point: * * winchester_task: main entry when system is brought up * */ #include "../h/const.h" #include "../h/type.h" #include "../h/callnr.h" #include "../h/com.h" #include "../h/error.h" #include "const.h" #include "type.h" #include "proc.h" /* * define WN_SAFETY to cause the driver to panic if you try to access any * sectors below the start of partition 2 -- this is supposed to prevent an * errant program from causing the DOS partition to be overwritten. It * assumes your DOS partition is partition 1 (the first one). */ #define WN_SAFETY /* */ /* Parameters for the disk drive. */ #define SECTOR_SIZE 512 /* physical sector size in bytes */ #define NR_SECTORS 0x11 /* number of sectors per track */ /* Error codes */ #define ERR -1 /* general error */ /* Miscellaneous. */ #define MAX_ERRORS 4 /* how often to try rd/wt before quitting */ #define MAX_RESULTS 4 /* max number of bytes controller returns */ #define NR_DEVICES 10 /* maximum number of drives */ #define MAX_WIN_RETRY 10000 /* max # times to try to output to WIN */ #define PART_TABLE 0x1C6 /* IBM partition table starts here in sect 0 */ #define DEV_PER_DRIVE 5 /* hd0 + hd1 + hd2 + hd3 + hd4 = 5 */ #define SAFETY_CONST 0xAAAAAAAAL /* table integrity check */ /* Variables. */ PRIVATE struct wini { /* main drive struct, one entry per drive */ int wn_opcode; /* DISK_READ or DISK_WRITE */ int wn_procnr; /* which proc wanted this operation? */ int wn_drive; /* drive number addressed */ int wn_cylinder; /* cylinder number addressed */ int wn_sector; /* sector addressed */ int wn_head; /* head number addressed */ int wn_heads; /* maximum number of heads */ long wn_low; /* lowest cylinder of partition */ long wn_size; /* size of partition in blocks */ int wn_trksize; /* size of track on this drive */ int wn_count; /* byte count */ vir_bytes wn_address; /* user virtual address */ char wn_results[MAX_RESULTS]; /* the controller can give lots of output */ } wini[NR_DEVICES]; PRIVATE int w_need_reset = FALSE; /* set to 1 when controller must be reset */ PRIVATE int nr_drives; /* Number of drives */ PRIVATE message w_mess; /* message buffer for in and out */ /* this buffer is sort of a waste of space, I think? */ PRIVATE unsigned char buf[BLOCK_SIZE]; /* Buffer used by the startup routine */ PRIVATE struct param { int nr_cyl; /* Number of cylinders */ int nr_heads; /* Number of heads */ int nr_drives; /* Number of drives on this drive's ctroller */ int nr_sectors; /* number of sectors per track */ } param0, param1; /*===========================================================================* * winchester_task * *===========================================================================*/ PUBLIC winchester_task() { /* Main program of the winchester disk driver task. */ int r, caller, proc_nr; #ifdef DEBUG printf("Winchester task has started\n"); #endif /* First initialize the controller */ init_params(); /* Here is the main loop of the disk task. It waits for a message, carries * it out, and sends a reply. */ while (TRUE) { /* First wait for a request to read or write a disk block. */ receive(ANY, &w_mess); /* get a request to do some work */ if (w_mess.m_source < 0) { printf("winchester task got message from %d ", w_mess.m_source); continue; } caller = w_mess.m_source; proc_nr = w_mess.PROC_NR; /* Now carry out the work. */ switch(w_mess.m_type) { case DISK_READ: case DISK_WRITE: r = w_do_rdwt(&w_mess); break; default: r = EINVAL; break; } /* Finally, prepare and send the reply message. */ w_mess.m_type = TASK_REPLY; w_mess.REP_PROC_NR = proc_nr; w_mess.REP_STATUS = r; /* # of bytes transferred or error code */ send(caller, &w_mess); /* send reply to caller */ } } /*===========================================================================* * w_do_rdwt * *===========================================================================*/ PRIVATE int w_do_rdwt(m_ptr) message *m_ptr; /* pointer to read or write w_message */ { /* Carry out a read or write request from the disk. */ register struct wini *wn; int r, device, errors = 0; long sector; phys_bytes user_phys; int sb, ib; int fRW; int csectors; int nr_sectors; extern phys_bytes umap(); #ifdef WN_SAFETY extern long wn_low_safety, wn_low_xor; #endif /* Decode the w_message parameters. */ device = m_ptr->DEVICE; if (device < 0 || device >= NR_DEVICES) return(EIO); if (m_ptr->COUNT != BLOCK_SIZE) return(EINVAL); wn = &wini[device]; /* 'wn' points to entry for this drive */ wn->wn_drive = device/DEV_PER_DRIVE; /* save drive number */ if (wn->wn_drive >= nr_drives) return(EIO); wn->wn_opcode = m_ptr->m_type; /* DISK_READ or DISK_WRITE */ if (m_ptr->POSITION % BLOCK_SIZE != 0) return(EINVAL); sector = m_ptr->POSITION/SECTOR_SIZE; if ((sector+BLOCK_SIZE/SECTOR_SIZE) > wn->wn_size) return(EOF); sector += wn->wn_low; nr_sectors = wn->wn_trksize; #ifdef WN_SAFETY /* try to insure errant program can't destroy another partition */ if (wn->wn_opcode != DISK_READ) /* allow reads of DOS partition */ { if ((wn_low_safety^SAFETY_CONST) != wn_low_xor) { printf("safety: %X xor: %X computed xor: %X\n", wn_low_safety, wn_low_xor, wn_low_safety^SAFETY_CONST); printf("winchester: driver tables appear overwritten\n"); return(EIO); } if (sector < wn_low_safety) { printf("winchester: tried to write sector below safety boundary\n", sector); return(EIO); } } #endif wn->wn_cylinder = sector / (wn->wn_heads * nr_sectors); wn->wn_sector = (sector % nr_sectors); wn->wn_head = (sector % (wn->wn_heads * nr_sectors) )/nr_sectors; wn->wn_count = m_ptr->COUNT; wn->wn_address = (vir_bytes) m_ptr->ADDRESS; wn->wn_procnr = m_ptr->PROC_NR; /* here we compute the values we pass the BIOS */ user_phys = umap(proc_addr(wn->wn_procnr), D, wn->wn_address, (vir_bytes)wn->wn_count); sb = (user_phys >> 4) & 0xffff; ib = user_phys & 0xf; fRW = (wn->wn_opcode==DISK_READ)? 0 : 1; csectors = wn->wn_count / SECTOR_SIZE; /* This loop allows a failed operation to be repeated. */ while (errors <= MAX_ERRORS) { errors++; /* increment count once per loop cycle */ if (errors >= MAX_ERRORS) return(EIO); /* First check to see if a reset is needed. */ if (w_need_reset) w_reset(); /* Perform the transfer. */ #ifdef DEBUG printf("diskio(%d,%x,%x,%x,%x,%x,%x,%x,%x)\n", fRW, wn->wn_cylinder, wn->wn_sector, wn->wn_head, csectors, wn->wn_drive, sb, ib, wn->wn_trksize); #endif r = diskio(fRW, wn->wn_cylinder, wn->wn_sector, wn->wn_head, csectors, wn->wn_drive, sb, ib, wn->wn_trksize); if (r == OK) break; /* if successful, exit loop */ } if (r!=OK) { printf("\ngn_wini: hardware error, BIOS code %02x\n", r); w_need_reset = TRUE; } return(r == OK ? BLOCK_SIZE : EIO); } #ifdef DEBUG /* debug code */ diskdebug(ax,bx,cx,dx) int ax,bx,cx,dx; { printf("BIOS call would have: ax=%04x, bx=%04x, cx=%04x, dx=%04x\n", ax,bx,cx,dx); return(0); } #endif /*===========================================================================* * w_reset * *===========================================================================*/ PRIVATE w_reset() { /* Issue a reset to the controller. This is done after any catastrophe, * like the controller refusing to respond. */ return(win_init()); } /*============================================================================* * init_params * *============================================================================*/ PRIVATE init_params() { /* This routine is called at startup to initialize the partition table, * the number of drives and the controller */ unsigned int i, segment, offset; phys_bytes address; extern phys_bytes umap(); extern int vec_table[]; /* * Be sure BIOS is all set up before we ask for parameters. This * may not really be necessary; we do it again below. */ win_init(); /* Copy the parameters to the structures */ hdisk_params(0, ¶m0); hdisk_params(1, ¶m1); /* Get the number of drives */ nr_drives = param0.nr_drives; /* Set the parameters in the drive structure */ for (i=0; i<5; i++) { wini[i].wn_heads = param0.nr_heads; wini[i].wn_trksize = param0.nr_sectors; } wini[0].wn_low = wini[5].wn_low = 0L; wini[0].wn_size = (long)((long)param0.nr_cyl * (long)param0.nr_heads * (long)NR_SECTORS); for (i=5; i<10; i++) { wini[i].wn_heads = param1.nr_heads; wini[i].wn_trksize = param1.nr_sectors; } wini[5].wn_size = (long)((long)param1.nr_cyl * (long)param1.nr_heads * (long)NR_SECTORS); /* Initialize the controller */ if ((nr_drives > 0) && (win_init() != OK)) nr_drives = 0; /* Read the partition table for each drive and save them */ for (i = 0; i < nr_drives; i++) { w_mess.DEVICE = i * 5; w_mess.POSITION = 0L; w_mess.COUNT = BLOCK_SIZE; w_mess.ADDRESS = (char *) buf; w_mess.PROC_NR = WINCHESTER; w_mess.m_type = DISK_READ; if (w_do_rdwt(&w_mess) != BLOCK_SIZE) panic("Can't read partition table of winchester ", i); copy_prt(i * 5); } } /*============================================================================* * copy_prt * *============================================================================*/ PRIVATE copy_prt(drive) int drive; { /* This routine copies the partition table for the selected drive to * the variables wn_low and wn_size */ register int i, offset; struct wini *wn; long adjust; #ifdef WN_SAFETY extern long wn_low_safety, wn_low_xor; #endif for (i=0; i<4; i++) { adjust = 0; wn = &wini[i + drive + 1]; offset = PART_TABLE + i * 0x10; wn->wn_low = *(long *)&buf[offset]; if ((wn->wn_low % (BLOCK_SIZE/SECTOR_SIZE)) != 0) { adjust = wn->wn_low; wn->wn_low = (wn->wn_low/(BLOCK_SIZE/SECTOR_SIZE)+1)*(BLOCK_SIZE/SECTOR_SIZE); adjust = wn->wn_low - adjust; } wn->wn_size = *(long *)&buf[offset + sizeof(long)] - adjust; } sort(&wini[drive + 1]); #ifdef WN_SAFETY wn_low_safety = wini[2].wn_low; wn_low_xor = wn_low_safety ^ SAFETY_CONST; #endif } PRIVATE sort(wn) register struct wini *wn; { register int i,j; for (i=0; i<4; i++) for (j=0; j<3; j++) if ((wn[j].wn_low == 0) && (wn[j+1].wn_low != 0)) swap(&wn[j], &wn[j+1]); else if (wn[j].wn_low > wn[j+1].wn_low && wn[j+1].wn_low != 0) swap(&wn[j], &wn[j+1]); } PRIVATE swap(first, second) register struct wini *first, *second; { register struct wini tmp; tmp = *first; *first = *second; *second = tmp; } SHAR_EOF if test 11852 -ne "`wc -c < 'gn_wini.c'`" then echo shar: error transmitting "'gn_wini.c'" '(should have been 11852 characters)' fi fi # end of overwriting check echo shar: extracting "'kernel'" '(657 characters)' if test -f 'kernel' then echo shar: will not over-write existing file "'kernel'" else cat << \SHAR_EOF > 'kernel' OBJ = at_wini.obj clock.obj dmp.obj floppy.obj klib88.obj main.obj \ memory.obj mpx88.obj printer.obj proc.obj system.obj table.obj \ tty.obj wini.obj xt_wini.obj gn_wini.obj .c.obj: cl -Di8088 -DGENERIC_FDISK -X -I..\include -Osal -Gs -c $*.c .asm.obj: masm /DGENERIC_FDISK $*,$*,$*; at_wini.obj: at_wini.c clock.obj: clock.c dmp.obj: dmp.c floppy.obj: floppy.c gn_wini.obj: gn_wini.c main.obj: main.c memory.obj: memory.c printer.obj: printer.c proc.obj: proc.c system.obj: system.c table.obj: table.c tty.obj: tty.c wini.obj: wini.c xt_wini.obj: xt_wini.c klib88.obj: klib88.asm mpx88.obj: mpx88.asm kernel.exe: $(OBJ) _link SHAR_EOF if test 657 -ne "`wc -c < 'kernel'`" then echo shar: error transmitting "'kernel'" '(should have been 657 characters)' fi fi # end of overwriting check echo shar: extracting "'linklist'" '(112 characters)' if test -f 'linklist' then echo shar: will not over-write existing file "'linklist'" else cat << \SHAR_EOF > 'linklist' main+proc+system+clock+memory+floppy+ gn_wini+tty+printer+table+klib88+dmp kernel kernel ..\lib\minix \lib\libh SHAR_EOF if test 112 -ne "`wc -c < 'linklist'`" then echo shar: error transmitting "'linklist'" '(should have been 112 characters)' fi fi # end of overwriting check echo shar: extracting "'_link.bat'" '(105 characters)' if test -f '_link.bat' then echo shar: will not over-write existing file "'_link.bat'" else cat << \SHAR_EOF > '_link.bat' echo/ echo Linking kernel link/m/nod mpx88+ < linklist >kernel.lst ..\dos2out -p kernel >> kernel.lst SHAR_EOF if test 105 -ne "`wc -c < '_link.bat'`" then echo shar: error transmitting "'_link.bat'" '(should have been 105 characters)' fi fi # end of overwriting check # End of shell archive exit 0