Home | History | Annotate | Line # | Download | only in lib
biosdisk_ll.c revision 1.1
      1 /*	$NetBSD: biosdisk_ll.c,v 1.1 1997/03/14 02:40:32 perry Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1996
      5  * 	Matthias Drochner.  All rights reserved.
      6  * Copyright (c) 1996
      7  * 	Perry E. Metzger.  All rights reserved.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  * 3. All advertising materials mentioning features or use of this software
     18  *    must display the following acknowledgements:
     19  *	This product includes software developed for the NetBSD Project
     20  *	by Matthias Drochner.
     21  *	This product includes software developed for the NetBSD Project
     22  *	by Perry E. Metzger.
     23  * 4. The names of the authors may not be used to endorse or promote products
     24  *    derived from this software without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     27  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     28  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     29  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     30  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     31  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     32  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     33  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     34  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     35  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     36  *
     37  */
     38 
     39 /* shared by bootsector startup (bootsectmain)
     40  and biosdisk.c
     41  needs lowlevel parts from bios_disk.S
     42 */
     43 
     44 #include <lib/libsa/stand.h>
     45 
     46 #include "biosdisk_ll.h"
     47 #include "diskbuf.h"
     48 
     49 extern int get_diskinfo __P((int));
     50 extern int biosread __P((int, int, int, int, int, char*));
     51 
     52 #define	SPT(di)		((di)&0xff)
     53 #define	HEADS(di)	((((di)>>8)&0xff)+1)
     54 
     55 int set_geometry(d)
     56 struct biosdisk_ll *d;
     57 {
     58   int diskinfo;
     59 
     60   diskinfo = get_diskinfo(d->dev);
     61 
     62   d->spc = (d->spt = SPT(diskinfo)) * HEADS(diskinfo);
     63 
     64   /* get_diskinfo assumes floppy if BIOS call
     65    fails. Check at least "valid" geometry. */
     66   return(!d->spc || !d->spt);
     67 }
     68 
     69 /* Global shared "diskbuf" is used as read ahead buffer.  For
     70  * reading from floppies, the bootstrap has to be loaded on a 64K boundary
     71  * to ensure that this buffer doesn't cross a 64K DMA boundary.
     72  */
     73 #define RA_SECTORS      (DISKBUFSIZE / BIOSDISK_SECSIZE)
     74 static int ra_dev;
     75 static int ra_end;
     76 static int ra_first;
     77 
     78 int readsects(d, dblk, num, buf, cold)	/* reads ahead if (!cold) */
     79 struct biosdisk_ll *d;
     80 int dblk, num;
     81 char *buf;
     82 int cold; /* don't use data segment or bss, don't call library functions */
     83 {
     84     while(num) {
     85 	int nsec;
     86 
     87 	/* check for usable data in read-ahead buffer */
     88 	if (cold || diskbuf_user != &ra_dev || d->dev != ra_dev
     89 	    || dblk < ra_first || dblk >= ra_end) {
     90 
     91 	    /* no, read from disk */
     92 	    int cyl, head, sec;
     93 	    char *trbuf;
     94 
     95 	    cyl = dblk / d->spc;
     96 	    head = (dblk % d->spc) / d->spt;
     97 	    sec = dblk % d->spt;
     98 	    nsec = d->spt - sec;
     99 
    100 	    if(cold) {
    101 		/* transfer directly to buffer */
    102 		trbuf = buf;
    103 		if (nsec > num)
    104 		    nsec = num;
    105 	    } else {
    106 		/* fill read-ahead buffer */
    107 		trbuf = diskbuf;
    108 		if (nsec > RA_SECTORS)
    109 		    nsec = RA_SECTORS;
    110 
    111 		ra_dev = d->dev;
    112 		ra_first = dblk;
    113 		ra_end = dblk + nsec;
    114 		diskbuf_user = &ra_dev;
    115 	    }
    116 
    117 	    if (biosread(d->dev, cyl, head, sec, nsec, trbuf)) {
    118 		if(!cold) diskbuf_user = 0; /* mark invalid */
    119 		return(-1); /* XXX cannot output here if (cold) */
    120 	    }
    121 
    122 	} else /* can take blocks from end of read-ahead buffer */
    123 	    nsec = ra_end - dblk;
    124 
    125 	if(!cold) {
    126 	    /* copy data from read-ahead to user buffer */
    127 	    if(nsec > num) nsec = num;
    128 	    bcopy(diskbuf + (dblk - ra_first) * BIOSDISK_SECSIZE, buf,
    129 		  nsec * BIOSDISK_SECSIZE);
    130 	}
    131 
    132 	buf += nsec * BIOSDISK_SECSIZE;
    133 	num -= nsec;
    134 	dblk += nsec;
    135     }
    136 
    137     return(0);
    138 }
    139