biosdisk.c revision 1.1 1 /* $NetBSD: biosdisk.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 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed for the NetBSD Project
18 * by Matthias Drochner.
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 */
34
35 /* raw BIOS disk device for libsa.
36 needs lowlevel parts from bios_disk.S and biosdisk_ll.c
37 partly from netbsd:sys/arch/i386/boot/disk.c
38 no bad144 handling!
39
40 */
41
42 /*
43 * Ported to boot 386BSD by Julian Elischer (julian (at) tfs.com) Sept 1992
44 *
45 * Mach Operating System
46 * Copyright (c) 1992, 1991 Carnegie Mellon University
47 * All Rights Reserved.
48 *
49 * Permission to use, copy, modify and distribute this software and its
50 * documentation is hereby granted, provided that both the copyright
51 * notice and this permission notice appear in all copies of the
52 * software, derivative works or modified versions, and any portions
53 * thereof, and that both notices appear in supporting documentation.
54 *
55 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
56 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
57 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
58 *
59 * Carnegie Mellon requests users of this software to return to
60 *
61 * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU
62 * School of Computer Science
63 * Carnegie Mellon University
64 * Pittsburgh PA 15213-3890
65 *
66 * any improvements or extensions that they make and grant Carnegie Mellon
67 * the rights to redistribute these changes.
68 */
69
70 #include <sys/types.h>
71 #include <sys/disklabel.h>
72
73 #include <lib/libsa/stand.h>
74 #include <lib/libsa/saerrno.h>
75
76 #include "libi386.h"
77 #include "biosdisk_ll.h"
78 /* XXX don't include biosdisk.h for now - vararg prototype */
79
80 #define BUFSIZE (1 * BIOSDISK_SECSIZE)
81
82 struct biosdisk {
83 struct biosdisk_ll ll;
84 #ifdef COMPAT_OLDBOOT
85 int disktype;
86 #endif
87 int boff;
88 char buf[BUFSIZE];
89 };
90
91 int biosdiskstrategy(devdata, flag, dblk, size, buf, rsize)
92 void *devdata;
93 int flag;
94 daddr_t dblk;
95 size_t size;
96 void *buf;
97 size_t *rsize;
98 {
99 struct biosdisk *d;
100 int blks, frag;
101
102 if(flag != F_READ) return(EROFS);
103
104 d = (struct biosdisk*)devdata;
105
106 dblk += d->boff;
107
108 blks = size / BIOSDISK_SECSIZE;
109 if(blks && readsects(&d->ll, dblk, blks, buf, 0)){
110 if(rsize) *rsize = 0;
111 return(EIO);
112 }
113
114 /* do we really need this? */
115 frag = size % BIOSDISK_SECSIZE;
116 if(frag) {
117 if(readsects(&d->ll, dblk + blks, 1, d->buf, 0)){
118 if(rsize) *rsize = blks * BIOSDISK_SECSIZE;
119 return(EIO);
120 }
121 bcopy(d->buf, buf + blks * BIOSDISK_SECSIZE, frag);
122 }
123
124 if(rsize) *rsize = size;
125 return(0);
126 }
127
128 #ifdef COMPAT_OLDBOOT
129 int biosdisk_gettype(f)
130 struct open_file *f;
131 {
132 struct biosdisk *d = f->f_devdata;
133 return(d->disktype);
134 }
135 #endif
136
137 int biosdiskopen(f, biosdev, partition)
138 struct open_file *f;
139 int biosdev;
140 unsigned int partition;
141 {
142 struct biosdisk *d;
143 struct dos_partition *dptr;
144 int sector;
145 int error = 0, i;
146 #ifndef NO_DISKLABEL
147 struct disklabel *lp;
148 #endif
149
150 d = (struct biosdisk*)alloc(sizeof(struct biosdisk));
151 if(!d) {
152 #ifdef DEBUG
153 printf("biosdiskopen: no memory\n");
154 #endif
155 return(ENOMEM);
156 }
157
158 d->ll.dev = biosdev;
159 if(set_geometry(&d->ll)) {
160 #ifdef DISK_DEBUG
161 printf("no geometry information\n");
162 #endif
163 error = ENXIO;
164 goto out;
165 }
166
167 /* find NetBSD Partition in DOS partition table
168 XXX check magic??? */
169 if(readsects(&d->ll, 0, 1, d->buf, 0)){
170 #ifdef DISK_DEBUG
171 printf("error reading mbr\n");
172 #endif
173 error = EIO;
174 goto out;
175 }
176 dptr = (struct dos_partition *)&d->buf[DOSPARTOFF];
177 sector = -1;
178 for (i = 0; i < NDOSPART; i++, dptr++)
179 if (dptr->dp_typ == DOSPTYP_NETBSD) {
180 sector = dptr->dp_start;
181 break;
182 }
183 if(sector == -1){
184 #ifdef DISK_DEBUG
185 printf("no BSD partition\n");
186 #endif
187 error = EUNLAB; /* ??? */
188 goto out;
189 }
190
191 #ifdef NO_DISKLABEL
192 d->boff = sector;
193 #else
194 /* find partition in NetBSD disklabel */
195 if(readsects(&d->ll, sector + LABELSECTOR, 1, d->buf, 0)){
196 #ifdef DISK_DEBUG
197 printf("Error reading disklabel\n");
198 #endif
199 error = EIO;
200 goto out;
201 }
202 lp = (struct disklabel *)(d->buf + LABELOFFSET);
203 if(lp->d_magic != DISKMAGIC) {
204 #ifdef DISK_DEBUG
205 printf("warning: no disklabel\n");
206 #endif
207 d->boff = sector;
208 } else if(partition >= lp->d_npartitions ||
209 lp->d_partitions[partition].p_fstype == FS_UNUSED) {
210 #ifdef DISK_DEBUG
211 printf("illegal partition\n");
212 #endif
213 error = EPART;
214 goto out;
215 } else {
216 d->boff = lp->d_partitions[partition].p_offset;
217 #ifdef COMPAT_OLDBOOT
218 d->disktype = lp->d_type;
219 #endif
220 }
221 #endif /* NO_DISKLABEL */
222
223 #ifdef DISK_DEBUG
224 printf("partition @%d\n", d->boff);
225 #endif
226
227 f->f_devdata = d;
228 out:
229 if(error)
230 free(d, sizeof(struct biosdisk));
231 return(error);
232 }
233
234 int biosdiskclose(f)
235 struct open_file *f;
236 {
237 struct biosdisk *d = f->f_devdata;
238
239 if(!(d->ll.dev & 0x80)) /* let the floppy drive go off */
240 delay(3000000); /* 2s is enough on all PCs I found */
241
242 free(d, sizeof(struct biosdisk));
243 f->f_devdata = NULL;
244 return(0);
245 }
246
247 int biosdiskioctl(f, cmd, arg)
248 struct open_file *f;
249 u_long cmd;
250 void *arg;
251 {
252 return EIO;
253 }
254
255
256