| 
						 
							
							
							
						 
					 | 
				
			
			 | 
			 | 
			
				@ -1,527 +0,0 @@
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/* This file contains the "device dependent" part of a hard disk driver that
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * uses the ROM BIOS.  It makes a call and just waits for the transfer to
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * happen.  It is not interrupt driven and thus will (*) have poor performance.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * The advantage is that it should work on virtually any PC, XT, 386, PS/2
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * or clone.  The demo disk uses this driver.  It is suggested that all
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * MINIX users try the other drivers, and use this one only as a last resort,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * if all else fails.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * (*) The performance is within 10% of the AT driver for reads on any disk
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *     and writes on a 2:1 interleaved disk, it will be DMA_BUF_SIZE bytes
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *     per revolution for a minimum of 60 kb/s for writes to 1:1 disks.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * The file contains one entry point:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *	 bios_winchester_task:	main entry when system is brought up
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * Changes:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *	30 Apr 1992 by Kees J. Bot: device dependent/independent split.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *	14 May 2000 by Kees J. Bot: d-d/i rewrite.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#include <minix/drivers.h>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#include <minix/blockdriver.h>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#include <minix/drvlib.h>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#include <minix/sysutil.h>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#include <minix/safecopies.h>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#include <sys/ioc_disk.h>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#include <machine/int86.h>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#include <assert.h>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/* Parameters for the disk drive. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#define MAX_DRIVES         8	/* this driver supports 8 drives (d0 - d7)*/
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#define NR_MINORS      (MAX_DRIVES * DEV_PER_DRIVE)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#define SUB_PER_DRIVE	(NR_PARTITIONS * NR_PARTITIONS)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#define NR_SUBDEVS	(MAX_DRIVES * SUB_PER_DRIVE)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/* Variables. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static struct wini {		/* main drive struct, one entry per drive */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  unsigned cylinders;		/* number of cylinders */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  unsigned heads;		/* number of heads */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  unsigned sectors;		/* number of sectors per track */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  unsigned open_ct;		/* in-use count */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  int drive_id;			/* Drive ID at BIOS level */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  int present;			/* Valid drive */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  int int13ext;			/* IBM/MS INT 13 extensions supported? */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  struct device part[DEV_PER_DRIVE];	/* disks and partitions */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  struct device subpart[SUB_PER_DRIVE]; /* subpartitions */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				} wini[MAX_DRIVES], *w_wn;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static int w_drive;			/* selected drive */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static struct device *w_dv;		/* device's base and size */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static char *bios_buf_v;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static phys_bytes bios_buf_phys;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static int remap_first = 0;		/* Remap drives for CD HD emulation */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#define BIOSBUF 16384
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				int main(void);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static struct device *w_prepare(dev_t device);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static struct device *w_part(dev_t minor);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static ssize_t w_transfer(dev_t minor, int do_write, u64_t position,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					endpoint_t endpt, iovec_t *iov, unsigned int nr_req, int flags);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static int w_do_open(dev_t minor, int access);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static int w_do_close(dev_t minor);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void w_init(void);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void w_geometry(dev_t minor, struct partition *entry);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static int w_ioctl(dev_t minor, unsigned int request, endpoint_t endpt,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					cp_grant_id_t grant);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/* Entry points to this driver. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static struct blockdriver w_dtab = {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  BLOCKDRIVER_TYPE_DISK,	/* handle partition requests */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  w_do_open,	/* open or mount request, initialize device */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  w_do_close,	/* release device */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  w_transfer,	/* do the I/O */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  w_ioctl,	/* I/O control */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  NULL,		/* no cleanup needed */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  w_part,	/* return partition information structure */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  w_geometry,	/* tell the geometry of the disk */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  NULL,		/* leftover hardware interrupts */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  NULL,		/* ignore leftover alarms */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  NULL,		/* catch-all for unrecognized commands */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  NULL		/* no threading support */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				};
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/* SEF functions and variables. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void sef_local_startup(void);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static int sef_cb_init_fresh(int type, sef_init_info_t *info);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/*===========================================================================*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *				bios_winchester_task			     *
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *===========================================================================*/
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				int main(void)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  /* SEF local startup. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  sef_local_startup();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  /* Call the generic receive loop. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  blockdriver_task(&w_dtab);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  return(OK);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/*===========================================================================*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *			       sef_local_startup			     *
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *===========================================================================*/
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void sef_local_startup(void)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  /* Register init callbacks. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  sef_setcb_init_fresh(sef_cb_init_fresh);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  sef_setcb_init_lu(sef_cb_init_fresh);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  /* Register live update callbacks. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_standard);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  /* Let SEF perform startup. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  sef_startup();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/*===========================================================================*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *		            sef_cb_init_fresh                                *
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *===========================================================================*/
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/* Initialize the bios_wini driver. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  long v;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  v = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  env_parse("bios_remap_first", "d", 0, &v, 0, 1);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  remap_first = v;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  /* Announce we are up! */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  blockdriver_announce(type);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  return(OK);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/*===========================================================================*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *				w_prepare				     *
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *===========================================================================*/
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static struct device *w_prepare(dev_t device)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/* Prepare for I/O on a device. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  if (device < NR_MINORS) {			/* d0, d0p[0-3], d1, ... */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					w_drive = device / DEV_PER_DRIVE;	/* save drive number */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					w_wn = &wini[w_drive];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					w_dv = &w_wn->part[device % DEV_PER_DRIVE];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  } else
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  if ((unsigned) (device -= MINOR_d0p0s0) < NR_SUBDEVS) {/*d[0-7]p[0-3]s[0-3]*/
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					w_drive = device / SUB_PER_DRIVE;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					w_wn = &wini[w_drive];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					w_dv = &w_wn->subpart[device % SUB_PER_DRIVE];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  } else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return(NULL);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  if (w_drive >= MAX_DRIVES || !w_wn->present)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  	return NULL;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  return(w_dv);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/*===========================================================================*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *				w_part					     *
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *===========================================================================*/
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static struct device *w_part(dev_t minor)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/* Return a pointer to the partition information of the given minor device. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  return w_prepare(minor);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/*===========================================================================*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *				w_transfer				     *
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *===========================================================================*/
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static ssize_t w_transfer(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  dev_t minor,			/* minor device number */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  int do_write,			/* read or write? */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  u64_t pos64,			/* offset on device to read or write */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  endpoint_t proc_nr,		/* process doing the request */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  iovec_t *iov,			/* pointer to read or write request vector */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  unsigned int nr_req,		/* length of request vector */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  int UNUSED(flags)		/* transfer flags */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  struct wini *wn;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  iovec_t *iop, *iov_end = iov + nr_req;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  int r, errors;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  unsigned count;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  vir_bytes chunk, nbytes;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  unsigned long block;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  vir_bytes i13e_rw_off, rem_buf_size;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  unsigned secspcyl;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  struct int13ext_rw {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					u8_t	len;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					u8_t	res1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					u16_t	count;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					u16_t	addr[2];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					u32_t	block[2];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  } *i13e_rw;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  struct reg86u reg86;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  u32_t lopos;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  ssize_t total;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  if (w_prepare(minor) == NULL) return(ENXIO);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  wn = w_wn;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  secspcyl = wn->heads * wn->sectors;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  lopos= ex64lo(pos64);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  /* Check disk address. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  if ((lopos & SECTOR_MASK) != 0) return(EINVAL);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  total = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  errors = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  i13e_rw_off= BIOSBUF-sizeof(*i13e_rw);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  rem_buf_size= (i13e_rw_off & ~SECTOR_MASK);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  i13e_rw = (struct int13ext_rw *) (bios_buf_v + i13e_rw_off);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  assert(rem_buf_size != 0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  while (nr_req > 0) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					/* How many bytes to transfer? */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					nbytes = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					for (iop = iov; iop < iov_end; iop++) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (nbytes + iop->iov_size > rem_buf_size) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							/* Don't do half a segment if you can avoid it. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (nbytes == 0) nbytes = rem_buf_size;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						nbytes += iop->iov_size;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if ((nbytes & SECTOR_MASK) != 0) return(EINVAL);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					/* Which block on disk and how close to EOF? */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (cmp64(pos64, w_dv->dv_size) >= 0) return(total);	/* At EOF */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (cmp64(add64u(pos64, nbytes), w_dv->dv_size) > 0) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						u64_t n;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						n = sub64(w_dv->dv_size, pos64);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						assert(ex64hi(n) == 0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						nbytes = ex64lo(n);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					block = div64u(add64(w_dv->dv_base, pos64), SECTOR_SIZE);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					/* Degrade to per-sector mode if there were errors. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (errors > 0) nbytes = SECTOR_SIZE;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (do_write) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						/* Copy from user space to the DMA buffer. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						count = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						for (iop = iov; count < nbytes; iop++) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							chunk = iop->iov_size;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (count + chunk > nbytes) chunk = nbytes - count;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							assert(chunk <= rem_buf_size);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if(proc_nr != SELF) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							   	r=sys_safecopyfrom(proc_nr,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									(cp_grant_id_t) iop->iov_addr,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						       			0, (vir_bytes) (bios_buf_v+count),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									chunk, D);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								if (r != OK)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									panic("copy failed: %d", r);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							} else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								memcpy(bios_buf_v+count,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									(char *) iop->iov_addr, chunk);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							count += chunk;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					/* Do the transfer */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (wn->int13ext) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						i13e_rw->len = 0x10;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						i13e_rw->res1 = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						i13e_rw->count = nbytes >> SECTOR_SHIFT;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						i13e_rw->addr[0] = bios_buf_phys % HCLICK_SIZE;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						i13e_rw->addr[1] = bios_buf_phys / HCLICK_SIZE;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						i13e_rw->block[0] = block;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						i13e_rw->block[1] = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						/* Set up an extended read or write BIOS call. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						reg86.u.b.intno = 0x13;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						reg86.u.w.ax = do_write ? 0x4300 : 0x4200;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						reg86.u.b.dl = wn->drive_id;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						reg86.u.w.si = (bios_buf_phys + i13e_rw_off) % HCLICK_SIZE;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						reg86.u.w.ds = (bios_buf_phys + i13e_rw_off) / HCLICK_SIZE;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					} else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						/* Set up an ordinary read or write BIOS call. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						unsigned cylinder = block / secspcyl;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						unsigned sector = (block % wn->sectors) + 1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						unsigned head = (block % secspcyl) / wn->sectors;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						reg86.u.b.intno = 0x13;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						reg86.u.b.ah = do_write ? 0x03 : 0x02;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						reg86.u.b.al = nbytes >> SECTOR_SHIFT;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						reg86.u.w.bx = bios_buf_phys % HCLICK_SIZE;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						reg86.u.w.es = bios_buf_phys / HCLICK_SIZE;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						reg86.u.b.ch = cylinder & 0xFF;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						reg86.u.b.cl = sector | ((cylinder & 0x300) >> 2);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						reg86.u.b.dh = head;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						reg86.u.b.dl = wn->drive_id;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					r= sys_int86(®86);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (r != OK)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						panic("BIOS call failed: %d", r);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (reg86.u.w.f & 0x0001) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						/* An error occurred, try again sector by sector unless */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (++errors == 2) return(EIO);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						continue;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (!do_write) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						/* Copy from the DMA buffer to user space. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						count = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						for (iop = iov; count < nbytes; iop++) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							chunk = iop->iov_size;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (count + chunk > nbytes) chunk = nbytes - count;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							assert(chunk <= rem_buf_size);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if(proc_nr != SELF) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							   	r=sys_safecopyto(proc_nr, iop->iov_addr, 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								       	0, (vir_bytes) (bios_buf_v+count),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								       	chunk, D);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								if (r != OK)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									panic("sys_safecopy failed: %d", r);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							} else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								memcpy((char *) iop->iov_addr,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									bios_buf_v+count, chunk);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							count += chunk;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					/* Book the bytes successfully transferred. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					pos64 = add64ul(pos64, nbytes);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					total += nbytes;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					while (nbytes > 0) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (nbytes < iov->iov_size) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							/* Not done with this one yet. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							iov->iov_size -= nbytes;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						nbytes -= iov->iov_size;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						iov->iov_size = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						iov++;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						nr_req--;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  return(total);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/*============================================================================*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *				w_do_open				      *
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *============================================================================*/
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static int w_do_open(dev_t minor, int UNUSED(access))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/* Device open: Initialize the controller and read the partition table. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  static int init_done = FALSE;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  if (!init_done) { w_init(); init_done = TRUE; }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  if (w_prepare(minor) == NULL) return(ENXIO);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  if (w_wn->open_ct++ == 0) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					/* Partition the disk. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					partition(&w_dtab, w_drive * DEV_PER_DRIVE, P_PRIMARY, 0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  return(OK);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/*============================================================================*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *				w_do_close				      *
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *============================================================================*/
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static int w_do_close(dev_t minor)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/* Device close: Release a device. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  if (w_prepare(minor) == NULL) return(ENXIO);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  w_wn->open_ct--;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  return(OK);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/*===========================================================================*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *				w_init					     *
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *===========================================================================*/
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void w_init(void)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/* This routine is called at startup to initialize the drive parameters. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  int r, drive, drive_id, nr_drives;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  struct wini *wn;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  unsigned long capacity;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  struct int13ext_params {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					u16_t	len;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					u16_t	flags;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					u32_t	cylinders;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					u32_t	heads;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					u32_t	sectors;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					u32_t	capacity[2];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					u16_t	bts_per_sec;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					u16_t	config[2];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  } *i13e_par;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  struct reg86u reg86;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  /* Ask the system task for a suitable buffer */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  if(!(bios_buf_v = alloc_contig(BIOSBUF, AC_LOWER1M, &bios_buf_phys))) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  	panic("allocating bios buffer failed: %d", ENOMEM);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  if (bios_buf_phys+BIOSBUF > 0x100000)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  	panic("bad BIOS buffer / phys: %d", bios_buf_phys);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#if 0
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  printf("bios_wini: got buffer size %d, virtual 0x%x, phys 0x%x\n",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  		BIOSBUF, bios_buf_v, bios_buf_phys);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#endif
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  i13e_par = (struct int13ext_params *) bios_buf_v;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  /* Get the geometry of the drives */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  for (drive = 0; drive < MAX_DRIVES; drive++) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  	if (remap_first)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  	{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  		if (drive == 7)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							drive_id= 0x80;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						else
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							drive_id= 0x80 + drive + 1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  	}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  	else
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						drive_id= 0x80 + drive;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					(void) w_prepare(drive * DEV_PER_DRIVE);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					wn = w_wn;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					wn->drive_id= drive_id;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					reg86.u.b.intno = 0x13;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					reg86.u.b.ah = 0x08;	/* Get drive parameters. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					reg86.u.b.dl = drive_id;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					r= sys_int86(®86);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (r != OK)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						panic("BIOS call failed: %d", r);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					nr_drives = !(reg86.u.w.f & 0x0001) ? reg86.u.b.dl : drive;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (drive_id >= 0x80 + nr_drives) continue;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					wn->present= 1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					wn->heads = reg86.u.b.dh + 1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					wn->sectors = reg86.u.b.cl & 0x3F;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					wn->cylinders = (reg86.u.b.ch | ((reg86.u.b.cl & 0xC0) << 2)) + 1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					capacity = (unsigned long) wn->cylinders * wn->heads * wn->sectors;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					reg86.u.b.intno = 0x13;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					reg86.u.b.ah = 0x41;	/* INT 13 Extensions - Installation check */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					reg86.u.w.bx = 0x55AA;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					reg86.u.b.dl = drive_id;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					r= sys_int86(®86);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (r != OK)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					    panic("BIOS call failed: %d", r);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (!(reg86.u.w.f & 0x0001) && reg86.u.w.bx == 0xAA55
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								&& (reg86.u.w.cx & 0x0001)) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						/* INT 13 Extensions available. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						i13e_par->len = 0x001E;	/* Input size of parameter packet */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						reg86.u.b.intno = 0x13;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						reg86.u.b.ah = 0x48;	/* Ext. Get drive parameters. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						reg86.u.b.dl = drive_id;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						reg86.u.w.si = bios_buf_phys % HCLICK_SIZE;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						reg86.u.w.ds = bios_buf_phys / HCLICK_SIZE;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						r= sys_int86(®86);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (r != OK)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							panic("BIOS call failed: %d", r);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (!(reg86.u.w.f & 0x0001)) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							wn->int13ext = 1;	/* Extensions can be used. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							capacity = i13e_par->capacity[0];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (i13e_par->capacity[1] != 0) capacity = 0xFFFFFFFF;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (wn->int13ext) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						printf("bios-d%u: %lu sectors\n", w_drive, capacity);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					} else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						printf("bios-d%u: %d cylinders, %d heads, "
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							"%d sectors per track\n",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							w_drive, wn->cylinders, wn->heads, wn->sectors);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					wn->part[0].dv_size = mul64u(capacity, SECTOR_SIZE);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/*============================================================================*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *				w_geometry				      *
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *============================================================================*/
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void w_geometry(dev_t minor, struct partition *entry)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  if (w_prepare(minor) == NULL) return;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  entry->cylinders = w_wn->cylinders;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  entry->heads = w_wn->heads;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  entry->sectors = w_wn->sectors;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/*============================================================================*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *				w_ioctl					      *
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *============================================================================*/
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static int w_ioctl(dev_t minor, unsigned int request, endpoint_t endpt,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					cp_grant_id_t grant)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					int count;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (w_prepare(minor) == NULL) return ENXIO;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (request == DIOCOPENCT) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						count = w_wn->open_ct;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return sys_safecopyto(endpt, grant, 0, (vir_bytes)&count,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							sizeof(count), D);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return EINVAL;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 |