[comp.os.minix] Patches to get MINIX going on a PS/2

bishop@ecsvax.UUCP (Alan Bishop) (12/23/87)

Below is a shell archive containing some quick fixes to get MINIX going on
a PS/2.  I have seen nothing that suggests trouble on my system, but
please remember that they are still being tested.

These are just enough to get anyone running.  They pretty much assume that
you are running on a PS/2 and probably will not work without small
modifications elsewhere.  However, the bios_wini.c and bios_floppy.c
routines might be useful in getting MINIX going on machines where
the standard drivers don't work.

Please let me know if you have problems.

(Also: rdavenport@gtewis.arpa - I have tried five different ways of getting
mail to you - do you have an address with something other than .arpa at the
end?)

alan - bishop@ecsvax.UUCP
-----

#! /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:
#	READ_ME
#	bios_floppy.c
#	bios_wini.c
#	bootblok.diff
#	dosread.diff
#	main.diff
# This archive created: Wed Dec 23 01:49:35 1987
export PATH; PATH=/bin:$PATH
if test -f 'READ_ME'
then
	echo shar: will not over-write existing file "'READ_ME'"
else
cat << \SHAR_EOF > 'READ_ME'
total 25
-rw-r--r--  1 bishop       8321 Dec 22 12:49 bios_floppy.c
-rw-r--r--  1 bishop      11903 Dec 22 12:49 bios_wini.c
-rw-r--r--  1 bishop        656 Dec 22 12:51 bootblok.diff
-rw-r--r--  1 bishop        903 Dec 22 17:12 dosread.diff
-rw-r--r--  1 bishop       1028 Dec 22 12:48 main.diff

Here are the hacks to get MINIX working with PS/2.  They are NOT intended
as a permanent replacement for parts of MINIX.  Most of them assume that
you are indeed running on a PS/2 and don't check for other machines.

There are still two major problems remaining: First, fsck doesn't work.  I
haven't looked at it yet.  Also, although there are hooks for multitasking
in the bios, they aren't used.  So, the system halts while floppy and wini
requests are being serviced.   This isn't too bad since most of the time
only one or two things are happening at a time anyway.

Here's what each file does:

bios_floppy.c - replacement for the floppy driver using the BIOS interface.
It only supports 720K disks, and actually limits the real size to 360K
(although this is trivial to fix).  The reason for this is that 360K disks
can be copied sector for sector over with absolutely no change.

bios_wini.c - replacement for the hard disk drivers using the BIOS
interface.  I don't know if this will work on non AT type drives, as I
don't know what the difference is between the drives.  I have been using
this driver and recompiled the entire system with no problems (and my DOS
partition is still there.)  However, you should make a backup 
before using it on anything other than a Model 60 with 44meg hard 
disk (and probably even on that.)

bootblok.diff - the bootblok.s file needs to know about the drive
parameters for the PS/2 drive.  It assumes 9 sectors/track.

dosread.diff - it needs to know the sizes of various tables on the disk.
For some reason, the same byte is used to specify an AT high-density drive
and the 720K 3.5" mode.  This version won't work with an AT high-density
drive.

main.diff (for kernel/main.c) - Various interrupt vectors are no longer
pointed to surprise and trap, since the BIOS needs them.  In addition,
the MINIX timer is patched in through the user-timer interrupt, and the
main system timer interrupt is fed to the BIOS (this way the floppy turns
itself off.)

If you have any problems, please let me know.
I have had no problems that I can attribute to these things.  If you use
these on anything other than a PS/2, let me know how it works.

alan
(bishop@ecsvax.UUCP)
SHAR_EOF
fi # end of overwriting check
if test -f 'bios_floppy.c'
then
	echo shar: will not over-write existing file "'bios_floppy.c'"
else
cat << \SHAR_EOF > 'bios_floppy.c'
/* This file contains a driver for a Floppy Disk Controller (FDC) using the
 * BIOS.  It does not support the BIOS busy wait convention.
 * 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:
 *
 *   floppy_task:	main entry when system is brought up
 *
 *  Changes:
 *	27 october 1986 by Jakob Schripsema: fdc_results fixed for 8 MHz
 *	17 december 1986 by Alan Bishop: ripped out everything that
 *			accessed the hardware directly.
 */

#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 "glo.h"
#include "proc.h"


/* Parameters for the disk drive. */
#define SECTOR_SIZE	 512	/* physical sector size in bytes */
#define HC_SIZE 	 720	/* max sectors handled */
#define NR_HEADS	0x02	/* two heads (i.e., two tracks/cylinder) */
#define NT		   1	/* number of diskette/drive combinations */

/* Error codes */
#define ERR_SEEK	  -1	/* bad seek */
#define ERR_TRANSFER	  -2	/* bad transfer */
#define ERR_STATUS	  -3	/* something wrong when getting status */
#define ERR_RECALIBRATE   -4	/* recalibrate didn't work properly */
#define ERR_WR_PROTECT	  -5	/* diskette is write protected */
#define ERR_DRIVE	  -6	/* something wrong with a drive */

/* Miscellaneous. */
#define MAX_ERRORS	  20	/* how often to try rd/wt before quitting */
#define NR_DRIVES	   2	/* maximum number of drives */

/* Variables. */
PRIVATE struct floppy { 	/* main drive struct, one entry per drive */
  int fl_opcode;		/* DISK_READ or DISK_WRITE */
  int fl_curcyl;		/* current cylinder */
  int fl_procnr;		/* which proc wanted this operation? */
  int fl_drive; 		/* drive number addressed */
  int fl_cylinder;		/* cylinder number addressed */
  int fl_sector;		/* sector addressed */
  int fl_head;			/* head number addressed */
  int fl_count; 		/* byte count */
  char fl_density;		/* disk type - only zero in this version */
  vir_bytes fl_address; 	/* user virtual address */
} floppy[NR_DRIVES];

PRIVATE int nr_sectors[NT] =
	{9};   /* sectors/track */
PRIVATE int nr_blocks[NT] =
	{720}; /* sectors/diskette*/

PRIVATE int need_reset; 	/* set to 1 when controller must be reset */
PRIVATE message mess;		/* message buffer for in and out */
PRIVATE int d;			/* density */
PRIVATE int initialized;	/* set to 1 after first use */

PRIVATE char interleave[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};

PRIVATE char pc_table[] = {0xDF, 0x02, 25, 2, 9, 0x2A, 0xFF, 0x50,
	0xF6, 1, 3}; /* IBM PC 5.25 360K drive */
PRIVATE char at_table[] = {0xDF, 0x02, 25, 2, 15, 0x1B, 0xFF, 0x54,
	0xF6, 1, 8}; /* IBM AT 5.25 1.44M drive */
PUBLIC char disk_table[] = {0xAF, 0x02, 0x25, 2, 9, 0x1B, 0xFF, 0x6C,
	0xF6, 0xF, 8}; /* IBM PS2 3.5 720K drive */


/*===========================================================================*
 *				floppy_task				     *
 *===========================================================================*/
PUBLIC floppy_task()
{
/* Main program of the floppy disk driver task. */

  int r, caller, proc_nr;

  /* 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, &mess);	/* get a request to do some work */
	if (mess.m_source < 0)
		panic("disk task got message from ", mess.m_source);
	caller = mess.m_source;
	proc_nr = mess.PROC_NR;

	/* Now carry out the work. */
	switch(mess.m_type) {
	    case DISK_READ:	r = do_rdwt(&mess);	break;
	    case DISK_WRITE:	r = do_rdwt(&mess);	break;
	    default:		r = EINVAL;		break;
	}

	/* Finally, prepare and send the reply message. */
	mess.m_type = TASK_REPLY;
	mess.REP_PROC_NR = proc_nr;
	mess.REP_STATUS = r;	/* # of bytes transferred or error code */
	send(caller, &mess);	/* send reply to caller */
  }
}


/*===========================================================================*
 *				do_rdwt 				     *
 *===========================================================================*/
PRIVATE int do_rdwt(m_ptr)
message *m_ptr; 		/* pointer to read or write message */
{
/* Carry out a read or write request from the disk. */
  register struct floppy *fp;
  int r, drive, errors;
  long block;

  /* Decode the message parameters. */
  drive = m_ptr->DEVICE;
  if (drive < 0 || drive >= NR_DRIVES) return(EIO);
  fp = &floppy[drive];		/* 'fp' points to entry for this drive */
  fp->fl_drive = drive; 	/* save drive number explicitly */
  fp->fl_opcode = m_ptr->m_type;	/* DISK_READ or DISK_WRITE */
  if (m_ptr->POSITION % BLOCK_SIZE != 0) return(EINVAL);
  block = m_ptr->POSITION/SECTOR_SIZE;
  if (block >= HC_SIZE) return(EOF);	/* sector is beyond end of 1.2M disk */
  d = fp->fl_density;		/* diskette/drive combination */
  fp->fl_cylinder = (int) (block / (NR_HEADS * nr_sectors[d]));
  fp->fl_sector = (int) interleave[block % nr_sectors[d]];
  fp->fl_head = (int) (block % (NR_HEADS*nr_sectors[d]) )/nr_sectors[d];
  fp->fl_count = m_ptr->COUNT;
  fp->fl_address = (vir_bytes) m_ptr->ADDRESS;
  fp->fl_procnr = m_ptr->PROC_NR;
  if (fp->fl_count != BLOCK_SIZE) return(EINVAL);

  errors = 0;

  /* This loop allows a failed operation to be repeated. */
  while (errors <= MAX_ERRORS) {

	/* If a lot of errors occur when 'initialized' is 0, it probably
	 * means that we are trying at the wrong density.  Try another one.
	 * Increment 'errors' here since loop is aborted on error.
	 */
	errors++;		/* increment count once per loop cycle */
	if (errors % (MAX_ERRORS/NT) == 0) {
		d = (d + 1) % NT;	/* try next density */
		fp->fl_density = d;
		need_reset = 1;
	}
	if (block >= nr_blocks[d]) continue;

	/* First check to see if a reset is needed. */
	if (need_reset) reset(fp);

	/* Perform the transfer. */
	r = transfer(fp);
	if (r == OK) break;	/* if successful, exit loop */
	if (r == ERR_WR_PROTECT) break; /* retries won't help */

  }

  if (r == OK && fp->fl_cylinder > 0) initialized = 1;	/* seek works */
  return(r == OK ? BLOCK_SIZE : EIO);
}



/*===========================================================================*
 *				transfer				     *
 *===========================================================================*/
PRIVATE int transfer(fp)
register struct floppy *fp;	/* pointer to the drive struct */
{
/* Read or write one block based on the head, track, sector, and
   drive information we have. */

   unsigned int ax, bx, cx, dx, es;
   int result;
   vir_bytes vir, ct;
   phys_bytes user_phys;
   extern phys_bytes umap();

/* AH = 2 (read) or 3 (write).	AL = 2 (for one sector) */
   ax = ((fp->fl_opcode == DISK_READ ? 2 : 3) << 8) + 2;
   cx = (fp->fl_cylinder << 8) + fp->fl_sector;
   dx = (fp->fl_head << 8) + fp->fl_drive;

   vir = (vir_bytes) fp->fl_address;
   ct = (vir_bytes) fp->fl_count;
   user_phys = umap(proc_addr(fp->fl_procnr), D, vir, ct);
#ifdef DEBUG
   printf("Trying to load at address %X\n", (long int) user_phys);
#endif

   bx = (unsigned int) (user_phys & 0xF);
   es = (unsigned int) (user_phys >> 4);

#ifdef DEBUG
     printf("diskint called with AX=%x BX=%x CX=%x DX=%x ES=%x\n", ax, 
	bx, cx, dx, es);
#endif
     result = diskint(ax, bx, cx, dx, es);
#ifdef DEBUG
     printf("diskint returned %d\n", result);
#endif
     switch (result) {
	case 0: return(OK);
	case 9:	panic("BIOS DMA crossed 64K boundary", (int) vir);
	case 3: need_reset = 1;
		return(ERR_WR_PROTECT);
	default:need_reset = 1;
		return(ERR_DRIVE);
   }
}



/*===========================================================================*
 *				reset					     *
 *===========================================================================*/
PRIVATE reset(fp)
struct floppy *fp;
/* Issue a reset to the diskette system. */

{
#ifdef DEBUG
	printf("Issuing reset\n");
#endif
	diskint(0, 0, 0, fp->fl_drive, 0);
	need_reset = 0;
}
SHAR_EOF
fi # end of overwriting check
if test -f 'bios_wini.c'
then
	echo shar: will not over-write existing file "'bios_wini.c'"
else
cat << \SHAR_EOF > 'bios_wini.c'
/* This file contains a driver for the IBM-AT winchester controller.
 * It was written by Adri Koppes.
 * It has been highly hacked by Alan Bishop (12/18/87) to strip
 *	out all the device dependent guts.
 *
 * 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"


/* Parameters for the disk drive. */
#define SECTOR_SIZE	 512	/* physical sector size in bytes */

/* Error codes */
#define ERR		  -1	/* general error */

/* Miscellaneous. */
#define MAX_ERRORS	   4	/* how often to try rd/wt before quitting */
#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 */

/* 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 */
  int wn_maxsec;		/* maximum number of sectors per track */
  long wn_low;			/* lowest cylinder of partition */
  long wn_size; 		/* size of partition in blocks */
  int wn_count; 		/* byte count */
  vir_bytes wn_address; 	/* user virtual address */
} wini[NR_DEVICES];

PRIVATE int w_need_reset = TRUE;	 /* 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 */

PRIVATE unsigned char buf[BLOCK_SIZE]; /* Buffer used by the startup routine */

/*===========================================================================*
 *				winchester_task 			     *
 *===========================================================================*/
PUBLIC winchester_task()
{
/* Main program of the winchester disk driver task. */

  int r, caller, proc_nr;

  /* First initialize the controller */
  init_param();

  /* 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;

  /* 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;
  wn->wn_cylinder = sector / (wn->wn_heads * wn->wn_maxsec);
  wn->wn_sector =  (sector % wn->wn_maxsec) + 1;
  wn->wn_head = (sector % (wn->wn_heads * wn->wn_maxsec) )/wn->wn_maxsec;
  wn->wn_count = m_ptr->COUNT;
  wn->wn_address = (vir_bytes) m_ptr->ADDRESS;
  wn->wn_procnr = m_ptr->PROC_NR;
#ifdef DEBUG
  printf("cylinder=%d sector=%d head=%d\n", wn->wn_cylinder, 
	wn->wn_sector, wn->wn_head);
#endif
  /* 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. */
	r = w_transfer(wn);
	if (r == OK) break;	/* if successful, exit loop */
#ifdef DEBUG
	printf("Transfer failed.  Returned %d.  errors=%d\n", r, errors);
#endif

  }

  return(r == OK ? BLOCK_SIZE : EIO);
}

/*===========================================================================*
 *				w_transfer				     *
 *===========================================================================*/
PRIVATE int w_transfer(wn)
register struct wini *wn;	/* pointer to the drive struct */
{
/* Read or write one block based on the head, track, sector, and
   drive information we have. */

	unsigned int ax, bx, cx, dx, es;
	int result;
	vir_bytes vir, ct;
	phys_bytes user_phys;
	extern phys_bytes umap();

/* AH = 2 (read) or 3 (write).	AL = 2 (for two sectors) */
	ax = ((wn->wn_opcode == DISK_READ ? 2 : 3) << 8) + 2;

/* Load the low 8 bits of the 10 bit cylinder into CH, the sector
	into the low 6 bits of CL, and the high 2 bits of the
	cylinder into the high 2 bits of CL.
*/
	cx = ((wn->wn_cylinder & BYTE) << 8) + (wn->wn_sector & 0x3F) +
		((wn->wn_cylinder >> 2) & 0xC0);
	dx = (wn->wn_head << 8) + (wn->wn_drive | 0x80);

#ifdef DEBUG
        printf("xfer to (local) %x\n", (int) wn->wn_address);
#endif
	vir = (vir_bytes) wn->wn_address;
	ct = (vir_bytes) wn->wn_count;
	user_phys = umap(proc_addr(wn->wn_procnr), D, vir, ct);

#ifdef DEBUG
	printf("xfer to (global) %X\n", (long int) user_phys);
#endif
	bx = (unsigned int) (user_phys & 0xF);
	es = (unsigned int) (user_phys >> 4);
#ifdef DEBUG
	printf("Calling diskint with AX=%x BX=%x CX=%x DX=%x ES=%x\n", ax, 
	bx, cx, dx, es);
#endif
	result = diskint(ax, bx, cx, dx, es);
#ifdef DEBUG
	printf("diskint returned %d\n", result);
#endif
	switch (result) {
		case 0	: return(OK);
		case 9	: panic("BIOS DMA crossed 64K boundary", (int) vir);
	       default	: w_need_reset = TRUE;
			  return(ERR);
	}
}


/*===========================================================================*
 *				w_reset 				     *
 *===========================================================================*/
PRIVATE w_reset(wn)
struct wini *wn;
{
/* Issue a reset to the controller.  This is done after any catastrophe,
 * like the controller refusing to respond.
 */

   w_need_reset = FALSE;

   diskint(0, 0, 0, wn->wn_drive | 0x80, 0);
   return(OK);
}


/*============================================================================*
 *				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[];

  /* Copy the parameter vector from the saved vector table */
  offset = vec_table[2 * 0x41];
  segment = vec_table[2 * 0x41 + 1];

  /* Calculate the address off the parameters and copy them to buf */
  address = ((long)segment << 4) + offset;
  phys_copy(address, umap(proc_addr(WINCHESTER), D, buf, 16), 16L);

  /* Copy the parameters to the structures */
  copy_param(buf, &wini[0]);

  /* Copy the parameter vector from the saved vector table */
  offset = vec_table[2 * 0x46];
  segment = vec_table[2 * 0x46 + 1];

  /* Calculate the address off the parameters and copy them to buf */
  address = ((long)segment << 4) + offset;
  phys_copy(address, umap(proc_addr(WINCHESTER), D, buf, 16), 16L);

  /* Copy the parameters to the structures */
  copy_param(buf, &wini[5]);

  /* Get the nummer of drives from the bios */
  phys_copy(0x475L, umap(proc_addr(WINCHESTER), D, buf, 1), 1L);
  nr_drives = (int) *buf;
#ifdef DEBUG
  printf("BIOS says we have %d drives.\n", nr_drives);
#endif

  /* Set the parameters in the drive structure */
  wini[0].wn_low = wini[5].wn_low = 0L;

  /* 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);
	if (buf[510] != 0x55 || buf[511] != 0xAA) {
		printf("Invalid partition table\n");
#ifdef DEBUG
		printf("buf[510]=%x, buf[511]=%x\n", buf[510], buf[511]);
#endif
		continue;
	}
	copy_prt(i*5);
  }
}

/*============================================================================*
 *				copy_params				      *
 *============================================================================*/
PRIVATE copy_params(src, dest)
register unsigned char *src;
register struct wini *dest;
{
/* This routine copies the parameters from src to dest
 * and sets the parameters for partition 0 and 5
*/
  register int i;
  long cyl, heads, sectors;

  for (i=0; i<5; i++) {
	dest[i].wn_heads = (int)src[2];
	dest[i].wn_maxsec = (int)src[14];
  }
  cyl = (long)(*(int *)src);
  heads = (long)dest[0].wn_heads;
  sectors = (long)dest[0].wn_maxsec;
  dest[0].wn_size = cyl * heads * sectors;
#ifdef DEBUG
  printf("wn_size=%d wn_heads=%d wn_maxsec=%d\n", dest[0].wn_size,
	dest[0].wn_heads, dest[0].wn_maxsec);
#endif

}

/*============================================================================*
 *				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;

  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]);
}

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]);
}

swap(first, second)
register struct wini *first, *second;
{
  register struct wini tmp;

  tmp = *first;
  *first = *second;
  *second = tmp;
}
SHAR_EOF
fi # end of overwriting check
if test -f 'bootblok.diff'
then
	echo shar: will not over-write existing file "'bootblok.diff'"
else
cat << \SHAR_EOF > 'bootblok.diff'
66c66
< 	mov	ax,#atpar	| tenatively assume 1.2M diskette
---
> 	mov	ax,#pspar
100a101
> 	xor	ax,ax
128a130
> 
215,219c217,222
< 
< disksec:.word 1
< tracksiz:	.word 15	| changed to 9 for 360K diskettes
< pcpar:	.byte	0xDF, 0x02, 25, 2, 9, 0x2A, 0xFF, 0x50, 0xF6, 1, 3   | for PC
< atpar:	.byte	0xDF, 0x02, 25, 2,15, 0x1B, 0xFF, 0x54, 0xF6, 1, 8   | for AT
---
> disksec:.word 1
> tracksiz:	.word 9	| changed to 9 for 360K diskettes
> pcpar:	.byte	0xDF, 0x02, 25, 2, 9, 0x2A, 0xFF, 0x50, 0xF6, 1, 3   | for PC
> atpar:	.byte	0xDF, 0x02, 25, 2,15, 0x1B, 0xFF, 0x54, 0xF6, 1, 8   | for AT
> pspar:	.byte	0xAF, 0x02,0x25,2, 9, 0x1B, 0xFF, 0x6C, 0xF6,0xF,8 
> 
SHAR_EOF
fi # end of overwriting check
if test -f 'dosread.diff'
then
	echo shar: will not over-write existing file "'dosread.diff'"
else
cat << \SHAR_EOF > 'dosread.diff'
6a7,8
>  * Hacked by: Alan Bishop.  Probably won't work on anything other
>  *	than 720K 3.5" drives now.
178,183c180,192
< 		total_clusters = 2372;	/* 2400 - 14 - 7 - 7 - 1 */
< 		cluster_size = 512;	/* 1 sector per cluster */
< 		fat_size = 3584;	/* 7 sectors */
< 		data_start = 14848;	/* Starts on sector #29 */
< 		root_entries = 224;	
< 		sub_entries = 16;	/* 512 / 32 */
---
> /*		total_clusters = 2372;	/* 2400 - 14 - 7 - 7 - 1 */
> /*		cluster_size = 512;	/* 1 sector per cluster */
> /*		fat_size = 3584;	/* 7 sectors */
> /*		data_start = 14848;	/* Starts on sector #29 */
> /*		root_entries = 224;	
> /*		sub_entries = 16;	/* 512 / 32 */
> 
> 		total_clusters = 706;	/* 720 - 7 - 6 - 1 */
> 		cluster_size = 1024;	/* 2 sectors per cluster */
> 		fat_size = 1536;	/* 3 sectors */
> 		data_start = 7168;	/* Starts on sector #14 */
> 		root_entries = 112;
> 		sub_entries = 32;	/* 1024 / 32 */
SHAR_EOF
fi # end of overwriting check
if test -f 'main.diff'
then
	echo shar: will not over-write existing file "'main.diff'"
else
cat << \SHAR_EOF > 'main.diff'
47a48
>   extern char disk_table[];
120,128c121,131
<   for (t = 0; t < 16; t++) set_vec(t, surprise, base_click);
<   for (t = 16; t < 256; t++) set_vec(t, trp, base_click);
<   set_vec(DIVIDE_VECTOR, divide, base_click);
<   set_vec(SYS_VECTOR, s_call, base_click);
<   set_vec(CLOCK_VECTOR, clock_int, base_click);
<   set_vec(KEYBOARD_VECTOR, tty_int, base_click);
<   set_vec(FLOPPY_VECTOR, disk_int, base_click);
<   set_vec(PRINTER_VECTOR, lpr_int, base_click);
<   if (pc_at)
---
> /*  for (t = 0; t < 16; t++) set_vec(t, surprise, base_click); */
> /*  for (t = 16; t < 256; t++) set_vec(t, trp, base_click); */
>   set_vec(DIVIDE_VECTOR, divide, base_click);
>   set_vec(SYS_VECTOR, s_call, base_click);
> #define	CLOCK_VECTOR	0x1c
>   set_vec(CLOCK_VECTOR, clock_int, base_click);
>   set_vec(KEYBOARD_VECTOR, tty_int, base_click);
> /*  set_vec(FLOPPY_VECTOR, disk_int, base_click); */
>   set_vec(PRINTER_VECTOR, lpr_int, base_click);
>   set_vec(0x1e, disk_table, base_click);
> /*  if (pc_at)
132c135
< 
---
> */
SHAR_EOF
fi # end of overwriting check
#	End of shell archive
exit 0