md_root.c revision 1.1 1 /* $NetBSD: md_root.c,v 1.1 1996/03/14 21:41:51 leo Exp $ */
2
3 /*
4 * Copyright (c) 1996 Leo Weppelman.
5 * 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 by Leo Weppelman.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/malloc.h>
37 #include <sys/buf.h>
38 #include <sys/proc.h>
39 #include <sys/device.h>
40 #include <sys/ioctl.h>
41 #include <sys/fcntl.h>
42 #include <sys/conf.h>
43 #include <sys/disklabel.h>
44 #include <sys/disk.h>
45 #include <sys/dkbad.h>
46
47 #include <dev/ramdisk.h>
48
49 /*
50 * Misc. defines:
51 */
52 #define RAMD_CHUNK (9 * 512) /* Chunk-size for auto-load */
53 #define RAMD_NDEV 2 /* Number of devices configured */
54
55 struct ramd_info {
56 u_long ramd_size; /* Size of disk in bytes */
57 u_long ramd_flag; /* see defs below */
58 dev_t ramd_dev; /* device to load from */
59 };
60
61 /*
62 * ramd_flag:
63 */
64 #define RAMD_LOAD 0x01 /* Auto load when first opened */
65 #define RAMD_LCOMP 0x02 /* Input is compressed */
66
67 struct ramd_info rd_info[RAMD_NDEV] = {
68 {
69 1105920, /* 1Mb in 2160 sectors */
70 RAMD_LOAD, /* auto-load this device */
71 MAKEDISKDEV(2, 0, 1), /* XXX: This is crap! (720Kb flop) */
72 },
73 {
74 1474560, /* 1.44Mb in 2880 sectors */
75 RAMD_LOAD, /* auto-load this device */
76 MAKEDISKDEV(2, 0, 1), /* XXX: This is crap! (720Kb flop) */
77 }
78 };
79
80 struct read_info {
81 struct buf *bp; /* buffer for strategy function */
82 long nbytes; /* total number of bytes to read */
83 long offset; /* offset in input medium */
84 caddr_t bufp; /* current output buffer */
85 caddr_t ebufp; /* absolute maximum for bufp */
86 int chunk; /* chunk size on input medium */
87 int media_sz; /* size of input medium */
88 void (*strat)(struct buf *); /* strategy function for read */
89 };
90
91
92 static int loaddisk __P((struct rd_conf *, dev_t ld_dev, struct proc *));
93 static int ramd_norm_read __P((struct read_info *));
94 static int cpy_uncompressed __P((caddr_t, int, struct read_info *));
95 static int rd_compressed __P((caddr_t, int, struct read_info *));
96
97 /*
98 * This is called during autoconfig.
99 */
100 int
101 rd_match_hook(parent, self, aux)
102 struct device *parent;
103 void *self;
104 void *aux;
105 {
106 if(strcmp("rd", aux) && strcmp("*", aux))
107 return(0);
108 return(1);
109 }
110
111 void
112 rd_attach_hook(unit, rd)
113 int unit;
114 struct rd_conf *rd;
115 {
116 extern int atari_realconfig;
117
118 if (atari_realconfig && (unit < RAMD_NDEV) && rd_info[unit].ramd_flag) {
119 printf (":%sauto-load on open. Size %d bytes.",
120 rd_info[unit].ramd_flag & RAMD_LCOMP ? " decompress/" : "",
121 rd_info[unit].ramd_size);
122 rd->rd_type = RD_UNCONFIGURED; /* Paranoia... */
123 }
124 }
125
126 void
127 rd_open_hook(unit, rd)
128 int unit;
129 struct rd_conf *rd;
130 {
131 struct ramd_info *ri;
132 int s;
133 int error = 0;
134
135 if(unit >= RAMD_NDEV)
136 return;
137
138 ri = &rd_info[unit];
139 if (rd->rd_type != RD_UNCONFIGURED)
140 return; /* Only configure once */
141 rd->rd_addr = malloc(ri->ramd_size, M_DEVBUF, M_WAITOK);
142 rd->rd_size = ri->ramd_size;
143 if(rd->rd_addr == NULL)
144 return;
145 if(ri->ramd_flag & RAMD_LOAD) {
146 if (loaddisk(rd, ri->ramd_dev, curproc)) {
147 free(rd->rd_addr, M_DEVBUF);
148 rd->rd_addr = NULL;
149 return;
150 }
151 }
152 rd->rd_type = RD_KMEM_ALLOCATED;
153 }
154
155 static int
156 loaddisk(rd, ld_dev, proc)
157 struct rd_conf *rd;
158 dev_t ld_dev;
159 struct proc *proc;
160 {
161 struct buf buf;
162 int error;
163 struct bdevsw *bdp = &bdevsw[major(ld_dev)];
164 struct disklabel dl;
165 struct read_info rs;
166
167 /*
168 * Initialize our buffer header:
169 */
170 buf.b_actf = NULL;
171 buf.b_rcred = buf.b_wcred = proc->p_ucred;
172 buf.b_vnbufs.le_next = NOLIST;
173 buf.b_flags = B_BUSY;
174 buf.b_dev = ld_dev;
175 buf.b_error = 0;
176 buf.b_proc = proc;
177
178 /*
179 * Setup read_info:
180 */
181 rs.bp = &buf;
182 rs.nbytes = rd->rd_size;
183 rs.offset = 0;
184 rs.bufp = rd->rd_addr;
185 rs.ebufp = rd->rd_addr + rd->rd_size;
186 rs.chunk = RAMD_CHUNK;
187 rs.media_sz = rd->rd_size;
188 rs.strat = bdp->d_strategy;
189
190 /*
191 * Open device and try to get some statistics.
192 */
193 if(error = bdp->d_open(ld_dev, FREAD | FNONBLOCK, 0, proc))
194 return(error);
195 if(bdp->d_ioctl(ld_dev, DIOCGDINFO, (caddr_t)&dl, FREAD, proc) == 0) {
196 /* Read on a cylinder basis */
197 rs.chunk = dl.d_secsize * dl.d_secpercyl;
198 rs.media_sz = dl.d_secperunit * dl.d_secsize;
199 }
200
201 #ifdef support_compression
202 if(ri->ramd_flag & RAMD_LCOMP)
203 error = decompress(cpy_uncompressed, rd_compressed, &rs);
204 else
205 #endif /* support_compression */
206 error = ramd_norm_read(&rs);
207
208 bdp->d_close(ld_dev,FREAD | FNONBLOCK, 0, proc);
209 return(error);
210 }
211
212 static int
213 ramd_norm_read(rsp)
214 struct read_info *rsp;
215 {
216 long bytes_left;
217 int done, error;
218 struct buf *bp;
219 int s;
220 int dotc = 0;
221
222 bytes_left = rsp->nbytes;
223 bp = rsp->bp;
224 error = 0;
225
226 while(bytes_left > 0) {
227 s = splbio();
228 bp->b_flags = B_BUSY | B_PHYS | B_READ;
229 splx(s);
230 bp->b_blkno = btodb(rsp->offset);
231 bp->b_bcount = rsp->chunk;
232 bp->b_data = rsp->bufp;
233
234 /* Initiate read */
235 (*rsp->strat)(bp);
236
237 /* Wait for results */
238 s = splbio();
239 while ((bp->b_flags & B_DONE) == 0)
240 tsleep((caddr_t) bp, PRIBIO + 1, "ramd_norm_read", 0);
241 if (bp->b_flags & B_ERROR)
242 error = (bp->b_error ? bp->b_error : EIO);
243 splx(s);
244
245 /* Dot counter */
246 printf(".");
247 if(!(++dotc % 40))
248 printf("\n");
249
250 done = bp->b_bcount - bp->b_resid;
251 bytes_left -= done;
252 rsp->offset += done;
253 rsp->bufp += done;
254
255 if(error || !done)
256 break;
257
258 if((rsp->offset == rsp->media_sz) && (bytes_left != 0)) {
259 printf("\nInsert next media and hit any key...");
260 cngetc();
261 printf("\n");
262 rsp->offset = 0;
263 }
264 }
265 printf("\n");
266 return(error);
267 }
268
269 #ifdef support_compression
270 /*
271 * Functions supporting uncompression:
272 */
273 /*
274 * Copy from the uncompression buffer to the ramdisk
275 */
276 static int
277 cpy_uncompressed(buf, nbyte, rsp)
278 caddr_t buf;
279 struct read_info *rsp;
280 int nbyte;
281 {
282 if((rsp->bufp + nbyte) >= rsp->ebufp)
283 return(0);
284 bcopy(buf, rsp->bufp, nbyte);
285 rsp->bufp += nbyte;
286 return(0);
287 }
288
289 /*
290 * Read a maximum of 'nbyte' bytes into 'buf'.
291 */
292 static int
293 rd_compressed(buf, nbyte, rsp)
294 caddr_t buf;
295 struct read_info *rsp;
296 int nbyte;
297 {
298 static int dotc = 0;
299 struct buf *bp;
300 int nread = 0;
301 int s;
302 int done, error;
303
304
305 error = 0;
306 bp = rsp->bp;
307 nbyte &= ~(DEV_BSIZE - 1);
308
309 while(nbyte > 0) {
310 s = splbio();
311 bp->b_flags = B_BUSY | B_PHYS | B_READ;
312 splx(s);
313 bp->b_blkno = btodb(rsp->offset);
314 bp->b_bcount = min(rsp->chunk, nbyte);
315 bp->b_data = buf;
316
317 /* Initiate read */
318 (*rsp->strat)(bp);
319
320 /* Wait for results */
321 s = splbio();
322 while ((bp->b_flags & B_DONE) == 0)
323 tsleep((caddr_t) bp, PRIBIO + 1, "ramd_norm_read", 0);
324 if (bp->b_flags & B_ERROR)
325 error = (bp->b_error ? bp->b_error : EIO);
326 splx(s);
327
328 /* Dot counter */
329 printf(".");
330 if(!(++dotc % 40))
331 printf("\n");
332
333 done = bp->b_bcount - bp->b_resid;
334 nbyte -= done;
335 nread += done;
336 rsp->offset += done;
337
338 if(error || !done)
339 break;
340
341 if((rsp->offset == rsp->media_sz) && (nbyte != 0)) {
342 if(rsp->offset == rsp->media_sz) {
343 printf("\nInsert next media and hit any key...");
344 if(cngetc() != '\n')
345 printf("\n");
346 rsp->offset = 0;
347 }
348 }
349 s = splbio();
350 splx(s);
351 return(nread);
352 }
353 #endif /* support_compression */
354