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