md_root.c revision 1.3 1 /* $NetBSD: md_root.c,v 1.3 1996/04/18 08:52:09 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
95 #ifdef support_compression
96 static int cpy_uncompressed __P((caddr_t, int, struct read_info *));
97 static int rd_compressed __P((caddr_t, int, struct read_info *));
98 #endif
99
100 /*
101 * This is called during autoconfig.
102 */
103 void
104 rd_attach_hook(unit, rd)
105 int unit;
106 struct rd_conf *rd;
107 {
108 extern int atari_realconfig;
109
110 if (atari_realconfig && (unit < RAMD_NDEV) && rd_info[unit].ramd_flag) {
111 printf ("rd%d:%sauto-load on open. Size %ld bytes.\n", unit,
112 rd_info[unit].ramd_flag & RAMD_LCOMP ? " decompress/" : "",
113 rd_info[unit].ramd_size);
114 rd->rd_type = RD_UNCONFIGURED; /* Paranoia... */
115 }
116 }
117
118 void
119 rd_open_hook(unit, rd)
120 int unit;
121 struct rd_conf *rd;
122 {
123 struct ramd_info *ri;
124
125 if(unit >= RAMD_NDEV)
126 return;
127
128 ri = &rd_info[unit];
129 if (rd->rd_type != RD_UNCONFIGURED)
130 return; /* Only configure once */
131 rd->rd_addr = malloc(ri->ramd_size, M_DEVBUF, M_WAITOK);
132 rd->rd_size = ri->ramd_size;
133 if(rd->rd_addr == NULL)
134 return;
135 if(ri->ramd_flag & RAMD_LOAD) {
136 if (loaddisk(rd, ri->ramd_dev, curproc)) {
137 free(rd->rd_addr, M_DEVBUF);
138 rd->rd_addr = NULL;
139 return;
140 }
141 }
142 rd->rd_type = RD_KMEM_ALLOCATED;
143 }
144
145 static int
146 loaddisk(rd, ld_dev, proc)
147 struct rd_conf *rd;
148 dev_t ld_dev;
149 struct proc *proc;
150 {
151 struct buf buf;
152 int error;
153 struct bdevsw *bdp = &bdevsw[major(ld_dev)];
154 struct disklabel dl;
155 struct read_info rs;
156
157 /*
158 * Initialize our buffer header:
159 */
160 buf.b_actf = NULL;
161 buf.b_rcred = buf.b_wcred = proc->p_ucred;
162 buf.b_vnbufs.le_next = NOLIST;
163 buf.b_flags = B_BUSY;
164 buf.b_dev = ld_dev;
165 buf.b_error = 0;
166 buf.b_proc = proc;
167
168 /*
169 * Setup read_info:
170 */
171 rs.bp = &buf;
172 rs.nbytes = rd->rd_size;
173 rs.offset = 0;
174 rs.bufp = rd->rd_addr;
175 rs.ebufp = rd->rd_addr + rd->rd_size;
176 rs.chunk = RAMD_CHUNK;
177 rs.media_sz = rd->rd_size;
178 rs.strat = bdp->d_strategy;
179
180 /*
181 * Open device and try to get some statistics.
182 */
183 if((error = bdp->d_open(ld_dev, FREAD | FNONBLOCK, 0, proc)) != 0)
184 return(error);
185 if(bdp->d_ioctl(ld_dev, DIOCGDINFO, (caddr_t)&dl, FREAD, proc) == 0) {
186 /* Read on a cylinder basis */
187 rs.chunk = dl.d_secsize * dl.d_secpercyl;
188 rs.media_sz = dl.d_secperunit * dl.d_secsize;
189 }
190
191 #ifdef support_compression
192 if(ri->ramd_flag & RAMD_LCOMP)
193 error = decompress(cpy_uncompressed, rd_compressed, &rs);
194 else
195 #endif /* support_compression */
196 error = ramd_norm_read(&rs);
197
198 bdp->d_close(ld_dev,FREAD | FNONBLOCK, 0, proc);
199 return(error);
200 }
201
202 static int
203 ramd_norm_read(rsp)
204 struct read_info *rsp;
205 {
206 long bytes_left;
207 int done, error;
208 struct buf *bp;
209 int s;
210 int dotc = 0;
211
212 bytes_left = rsp->nbytes;
213 bp = rsp->bp;
214 error = 0;
215
216 while(bytes_left > 0) {
217 s = splbio();
218 bp->b_flags = B_BUSY | B_PHYS | B_READ;
219 splx(s);
220 bp->b_blkno = btodb(rsp->offset);
221 bp->b_bcount = rsp->chunk;
222 bp->b_data = rsp->bufp;
223
224 /* Initiate read */
225 (*rsp->strat)(bp);
226
227 /* Wait for results */
228 s = splbio();
229 while ((bp->b_flags & B_DONE) == 0)
230 tsleep((caddr_t) bp, PRIBIO + 1, "ramd_norm_read", 0);
231 if (bp->b_flags & B_ERROR)
232 error = (bp->b_error ? bp->b_error : EIO);
233 splx(s);
234
235 /* Dot counter */
236 printf(".");
237 if(!(++dotc % 40))
238 printf("\n");
239
240 done = bp->b_bcount - bp->b_resid;
241 bytes_left -= done;
242 rsp->offset += done;
243 rsp->bufp += done;
244
245 if(error || !done)
246 break;
247
248 if((rsp->offset == rsp->media_sz) && (bytes_left != 0)) {
249 printf("\nInsert next media and hit any key...");
250 cngetc();
251 printf("\n");
252 rsp->offset = 0;
253 }
254 }
255 printf("\n");
256 return(error);
257 }
258
259 #ifdef support_compression
260 /*
261 * Functions supporting uncompression:
262 */
263 /*
264 * Copy from the uncompression buffer to the ramdisk
265 */
266 static int
267 cpy_uncompressed(buf, nbyte, rsp)
268 caddr_t buf;
269 struct read_info *rsp;
270 int nbyte;
271 {
272 if((rsp->bufp + nbyte) >= rsp->ebufp)
273 return(0);
274 bcopy(buf, rsp->bufp, nbyte);
275 rsp->bufp += nbyte;
276 return(0);
277 }
278
279 /*
280 * Read a maximum of 'nbyte' bytes into 'buf'.
281 */
282 static int
283 rd_compressed(buf, nbyte, rsp)
284 caddr_t buf;
285 struct read_info *rsp;
286 int nbyte;
287 {
288 static int dotc = 0;
289 struct buf *bp;
290 int nread = 0;
291 int s;
292 int done, error;
293
294
295 error = 0;
296 bp = rsp->bp;
297 nbyte &= ~(DEV_BSIZE - 1);
298
299 while(nbyte > 0) {
300 s = splbio();
301 bp->b_flags = B_BUSY | B_PHYS | B_READ;
302 splx(s);
303 bp->b_blkno = btodb(rsp->offset);
304 bp->b_bcount = min(rsp->chunk, nbyte);
305 bp->b_data = buf;
306
307 /* Initiate read */
308 (*rsp->strat)(bp);
309
310 /* Wait for results */
311 s = splbio();
312 while ((bp->b_flags & B_DONE) == 0)
313 tsleep((caddr_t) bp, PRIBIO + 1, "ramd_norm_read", 0);
314 if (bp->b_flags & B_ERROR)
315 error = (bp->b_error ? bp->b_error : EIO);
316 splx(s);
317
318 /* Dot counter */
319 printf(".");
320 if(!(++dotc % 40))
321 printf("\n");
322
323 done = bp->b_bcount - bp->b_resid;
324 nbyte -= done;
325 nread += done;
326 rsp->offset += done;
327
328 if(error || !done)
329 break;
330
331 if((rsp->offset == rsp->media_sz) && (nbyte != 0)) {
332 if(rsp->offset == rsp->media_sz) {
333 printf("\nInsert next media and hit any key...");
334 if(cngetc() != '\n')
335 printf("\n");
336 rsp->offset = 0;
337 }
338 }
339 s = splbio();
340 splx(s);
341 return(nread);
342 }
343 #endif /* support_compression */
344