This source file includes following definitions.
- rdattach
- rd_attach
- rddump
- rdsize
- rdopen
- rdclose
- rdread
- rdwrite
- rdstrategy
- rdioctl
- rdgetdisklabel
- rd_ioctl_kalloc
- rd_ioctl_server
- rd_server_loop
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 #include <sys/param.h>
50 #include <sys/kernel.h>
51 #include <sys/malloc.h>
52 #include <sys/systm.h>
53 #include <sys/buf.h>
54 #include <sys/device.h>
55 #include <sys/file.h>
56 #include <sys/disk.h>
57 #include <sys/proc.h>
58 #include <sys/conf.h>
59 #include <sys/disklabel.h>
60 #include <sys/dkio.h>
61
62 #include <uvm/uvm_extern.h>
63
64 #include <dev/ramdisk.h>
65
66
67
68
69
70 #if !defined(RAMDISK_SERVER) && !defined(SMALL_KERNEL)
71 #define RAMDISK_SERVER 1
72 #endif
73
74
75
76
77
78
79
80
81
82 #define RD_MAX_UNITS 0x10
83 #define RD_IS_CTRL(dev) (DISKPART(dev) == RAW_PART)
84
85
86
87 struct rd_softc {
88 struct device sc_dev;
89 struct disk sc_dkdev;
90 struct rd_conf sc_rd;
91 #if RAMDISK_SERVER
92 struct buf *sc_buflist;
93 #endif
94 };
95
96 #define sc_addr sc_rd.rd_addr
97 #define sc_size sc_rd.rd_size
98 #define sc_type sc_rd.rd_type
99
100 void rdattach(int);
101 void rd_attach(struct device *, struct device *, void *);
102 void rdgetdisklabel(dev_t, struct rd_softc *, struct disklabel *, int);
103
104
105
106
107
108
109
110 struct cfdriver rd_cd = {
111 NULL, "rd", DV_DULL
112 };
113
114 void rdstrategy(struct buf *bp);
115 struct dkdriver rddkdriver = { rdstrategy };
116
117 int ramdisk_ndevs;
118 void *ramdisk_devs[RD_MAX_UNITS];
119
120
121
122
123 void
124 rdattach(n)
125 int n;
126 {
127 struct rd_softc *sc;
128 int i;
129
130 #ifdef DIAGNOSTIC
131 if (ramdisk_ndevs) {
132 printf("ramdisk: multiple attach calls?\n");
133 return;
134 }
135 #endif
136
137
138 if (n <= 1)
139 n = 1;
140 if (n > RD_MAX_UNITS)
141 n = RD_MAX_UNITS;
142 ramdisk_ndevs = n;
143
144
145 rd_cd.cd_ndevs = ramdisk_ndevs;
146 rd_cd.cd_devs = ramdisk_devs;
147
148
149 for (i = 0; i < n; i++) {
150 sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK);
151 bzero((caddr_t)sc, sizeof(*sc));
152 if (snprintf(sc->sc_dev.dv_xname, sizeof(sc->sc_dev.dv_xname),
153 "rd%d", i) >= sizeof(sc->sc_dev.dv_xname)) {
154 printf("rdattach: device name too long\n");
155 free(sc, M_DEVBUF);
156 return;
157 }
158 ramdisk_devs[i] = sc;
159 sc->sc_dev.dv_unit = i;
160 rd_attach(NULL, &sc->sc_dev, NULL);
161 }
162 }
163
164 void
165 rd_attach(parent, self, aux)
166 struct device *parent, *self;
167 void *aux;
168 {
169 struct rd_softc *sc = (struct rd_softc *)self;
170
171
172 #ifdef RAMDISK_HOOKS
173
174
175
176
177
178 rd_attach_hook(sc->sc_dev.dv_unit, &sc->sc_rd);
179 #endif
180
181
182
183
184 sc->sc_dkdev.dk_driver = &rddkdriver;
185 sc->sc_dkdev.dk_name = sc->sc_dev.dv_xname;
186 disk_attach(&sc->sc_dkdev);
187 }
188
189
190
191
192
193
194
195 #if RAMDISK_SERVER
196 int rd_server_loop(struct rd_softc *sc);
197 int rd_ioctl_server(struct rd_softc *sc,
198 struct rd_conf *urd, struct proc *proc);
199 #endif
200 int rd_ioctl_kalloc(struct rd_softc *sc,
201 struct rd_conf *urd, struct proc *proc);
202
203 dev_type_open(rdopen);
204 dev_type_close(rdclose);
205 dev_type_read(rdread);
206 dev_type_write(rdwrite);
207 dev_type_ioctl(rdioctl);
208 dev_type_size(rdsize);
209 dev_type_dump(rddump);
210
211 int
212 rddump(dev, blkno, va, size)
213 dev_t dev;
214 daddr64_t blkno;
215 caddr_t va;
216 size_t size;
217 {
218 return ENODEV;
219 }
220
221 daddr64_t
222 rdsize(dev_t dev)
223 {
224 int part, unit;
225 struct rd_softc *sc;
226
227
228 unit = DISKUNIT(dev);
229 if (unit >= ramdisk_ndevs)
230 return 0;
231 sc = ramdisk_devs[unit];
232 if (sc == NULL)
233 return 0;
234
235 if (sc->sc_type == RD_UNCONFIGURED)
236 return 0;
237
238 rdgetdisklabel(dev, sc, sc->sc_dkdev.dk_label, 0);
239 part = DISKPART(dev);
240 if (part >= sc->sc_dkdev.dk_label->d_npartitions)
241 return 0;
242 else
243 return DL_GETPSIZE(&sc->sc_dkdev.dk_label->d_partitions[part]) *
244 (sc->sc_dkdev.dk_label->d_secsize / DEV_BSIZE);
245 }
246
247 int
248 rdopen(dev, flag, fmt, proc)
249 dev_t dev;
250 int flag, fmt;
251 struct proc *proc;
252 {
253 int unit;
254 struct rd_softc *sc;
255
256 unit = DISKUNIT(dev);
257 if (unit >= ramdisk_ndevs)
258 return ENXIO;
259 sc = ramdisk_devs[unit];
260 if (sc == NULL)
261 return ENXIO;
262
263
264
265
266
267 if (RD_IS_CTRL(dev))
268 return 0;
269
270 #ifdef RAMDISK_HOOKS
271
272 rd_open_hook(unit, &sc->sc_rd);
273 #endif
274
275
276
277
278
279 if (sc->sc_type == RD_UNCONFIGURED)
280 return ENXIO;
281
282 return 0;
283 }
284
285 int
286 rdclose(dev, flag, fmt, proc)
287 dev_t dev;
288 int flag, fmt;
289 struct proc *proc;
290 {
291
292 return 0;
293 }
294
295 int
296 rdread(dev, uio, flags)
297 dev_t dev;
298 struct uio *uio;
299 int flags;
300 {
301 return (physio(rdstrategy, NULL, dev, B_READ, minphys, uio));
302 }
303
304 int
305 rdwrite(dev, uio, flags)
306 dev_t dev;
307 struct uio *uio;
308 int flags;
309 {
310 return (physio(rdstrategy, NULL, dev, B_WRITE, minphys, uio));
311 }
312
313
314
315
316
317 void
318 rdstrategy(bp)
319 struct buf *bp;
320 {
321 int unit, part;
322 struct rd_softc *sc;
323 caddr_t addr;
324 size_t off, xfer;
325 int s;
326
327 unit = DISKUNIT(bp->b_dev);
328 sc = ramdisk_devs[unit];
329
330
331 if (sc == NULL || bp->b_blkno < 0 ||
332 (bp->b_bcount % sc->sc_dkdev.dk_label->d_secsize) != 0) {
333 bp->b_error = EINVAL;
334 goto bad;
335 }
336
337
338 part = DISKPART(bp->b_dev);
339 if (part != RAW_PART &&
340 bounds_check_with_label(bp, sc->sc_dkdev.dk_label, 1) <= 0)
341 goto bad;
342
343 switch (sc->sc_type) {
344 #if RAMDISK_SERVER
345 case RD_UMEM_SERVER:
346
347 bp->b_actf = sc->sc_buflist;
348 sc->sc_buflist = bp;
349 if (bp->b_actf == NULL) {
350
351 wakeup((caddr_t)sc);
352
353 }
354
355 return;
356 #endif
357
358 case RD_KMEM_FIXED:
359 case RD_KMEM_ALLOCATED:
360
361 bp->b_resid = bp->b_bcount;
362 off = (bp->b_blkno << DEV_BSHIFT);
363 xfer = bp->b_bcount;
364 if (xfer > (sc->sc_size - off))
365 xfer = (sc->sc_size - off);
366 addr = sc->sc_addr + off;
367 if (bp->b_flags & B_READ)
368 bcopy(addr, bp->b_data, xfer);
369 else
370 bcopy(bp->b_data, addr, xfer);
371 bp->b_resid -= xfer;
372 break;
373
374 default:
375 bp->b_error = EIO;
376 bad:
377 bp->b_flags |= B_ERROR;
378 bp->b_resid = bp->b_bcount;
379 break;
380 }
381
382 s = splbio();
383 biodone(bp);
384 splx(s);
385 }
386
387 int
388 rdioctl(dev, cmd, data, flag, proc)
389 dev_t dev;
390 u_long cmd;
391 int flag;
392 caddr_t data;
393 struct proc *proc;
394 {
395 int unit;
396 struct disklabel *lp;
397 struct rd_softc *sc;
398 struct rd_conf *urd;
399 int error;
400
401 unit = DISKUNIT(dev);
402 sc = ramdisk_devs[unit];
403
404 urd = (struct rd_conf *)data;
405 switch (cmd) {
406 case DIOCRLDINFO:
407 if (sc->sc_type == RD_UNCONFIGURED)
408 break;
409 lp = malloc(sizeof(*lp), M_TEMP, M_WAITOK);
410 rdgetdisklabel(dev, sc, lp, 0);
411 bcopy(lp, sc->sc_dkdev.dk_label, sizeof(*lp));
412 free(lp, M_TEMP);
413 return 0;
414
415 case DIOCGPDINFO:
416 if (sc->sc_type == RD_UNCONFIGURED)
417 break;
418 rdgetdisklabel(dev, sc, (struct disklabel *)data, 1);
419 return 0;
420
421 case DIOCGDINFO:
422 if (sc->sc_type == RD_UNCONFIGURED) {
423 break;
424 }
425 *(struct disklabel *)data = *(sc->sc_dkdev.dk_label);
426 return 0;
427
428 case DIOCGPART:
429 ((struct partinfo *)data)->disklab = sc->sc_dkdev.dk_label;
430 ((struct partinfo *)data)->part =
431 &sc->sc_dkdev.dk_label->d_partitions[DISKPART(dev)];
432 return 0;
433
434 case DIOCWDINFO:
435 case DIOCSDINFO:
436 if (sc->sc_type == RD_UNCONFIGURED) {
437 break;
438 }
439 if ((flag & FWRITE) == 0)
440 return EBADF;
441
442 error = setdisklabel(sc->sc_dkdev.dk_label,
443 (struct disklabel *)data, 0);
444 if (error == 0) {
445 if (cmd == DIOCWDINFO)
446 error = writedisklabel(DISKLABELDEV(dev),
447 rdstrategy, sc->sc_dkdev.dk_label);
448 }
449
450 return error;
451
452 case DIOCWLABEL:
453 if (sc->sc_type == RD_UNCONFIGURED) {
454 break;
455 }
456 if ((flag & FWRITE) == 0)
457 return EBADF;
458 return 0;
459
460 case RD_GETCONF:
461
462 if (RD_IS_CTRL(dev) == 0) {
463 break;
464 }
465 *urd = sc->sc_rd;
466 return 0;
467
468 case RD_SETCONF:
469
470 if (RD_IS_CTRL(dev) == 0) {
471 break;
472 }
473
474 if (sc->sc_type != RD_UNCONFIGURED) {
475 break;
476 }
477 switch (urd->rd_type) {
478 case RD_KMEM_ALLOCATED:
479 return rd_ioctl_kalloc(sc, urd, proc);
480 #if RAMDISK_SERVER
481 case RD_UMEM_SERVER:
482 return rd_ioctl_server(sc, urd, proc);
483 #endif
484 default:
485 break;
486 }
487 break;
488 }
489 return EINVAL;
490 }
491
492 void
493 rdgetdisklabel(dev_t dev, struct rd_softc *sc, struct disklabel *lp,
494 int spoofonly)
495 {
496 bzero(lp, sizeof(struct disklabel));
497
498 lp->d_secsize = DEV_BSIZE;
499 lp->d_ntracks = 1;
500 lp->d_nsectors = sc->sc_size >> DEV_BSHIFT;
501 lp->d_ncylinders = 1;
502 lp->d_secpercyl = lp->d_nsectors;
503 if (lp->d_secpercyl == 0) {
504 lp->d_secpercyl = 100;
505
506 }
507
508 strncpy(lp->d_typename, "RAM disk", sizeof(lp->d_typename));
509 lp->d_type = DTYPE_SCSI;
510 strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname));
511 DL_SETDSIZE(lp, lp->d_nsectors);
512 lp->d_rpm = 3600;
513 lp->d_interleave = 1;
514 lp->d_version = 1;
515
516 lp->d_magic = DISKMAGIC;
517 lp->d_magic2 = DISKMAGIC;
518 lp->d_checksum = dkcksum(lp);
519
520
521
522
523 readdisklabel(DISKLABELDEV(dev), rdstrategy, lp, spoofonly);
524 }
525
526
527
528
529
530 int
531 rd_ioctl_kalloc(sc, urd, proc)
532 struct rd_softc *sc;
533 struct rd_conf *urd;
534 struct proc *proc;
535 {
536 vaddr_t addr;
537 vsize_t size;
538
539
540 size = urd->rd_size;
541 addr = uvm_km_zalloc(kernel_map, size);
542 if (!addr)
543 return ENOMEM;
544
545
546 sc->sc_addr = (caddr_t)addr;
547 sc->sc_size = (size_t)size;
548 sc->sc_type = RD_KMEM_ALLOCATED;
549 return 0;
550 }
551
552 #if RAMDISK_SERVER
553
554
555
556
557
558 int
559 rd_ioctl_server(sc, urd, proc)
560 struct rd_softc *sc;
561 struct rd_conf *urd;
562 struct proc *proc;
563 {
564 vaddr_t end;
565 int error;
566
567
568 end = (vaddr_t) (urd->rd_addr + urd->rd_size);
569
570 if ((end >= VM_MAXUSER_ADDRESS) || (end < ((vaddr_t) urd->rd_addr)) )
571 return EINVAL;
572
573
574 sc->sc_addr = urd->rd_addr;
575 sc->sc_size = urd->rd_size;
576 sc->sc_type = RD_UMEM_SERVER;
577
578
579 error = rd_server_loop(sc);
580
581
582 sc->sc_type = RD_UNCONFIGURED;
583 sc->sc_addr = 0;
584 sc->sc_size = 0;
585
586 return (error);
587 }
588
589 int rd_sleep_pri = PWAIT | PCATCH;
590
591 int
592 rd_server_loop(sc)
593 struct rd_softc *sc;
594 {
595 struct buf *bp;
596 caddr_t addr;
597 size_t off;
598 size_t xfer;
599 int error;
600 int s;
601
602 for (;;) {
603
604 while (sc->sc_buflist == NULL) {
605 error = tsleep((caddr_t)sc, rd_sleep_pri, "rd_idle", 0);
606 if (error)
607 return error;
608 }
609
610
611 bp = sc->sc_buflist;
612 sc->sc_buflist = bp->b_actf;
613 bp->b_actf = NULL;
614
615
616 error = 0;
617 bp->b_resid = bp->b_bcount;
618 off = (bp->b_blkno << DEV_BSHIFT);
619 if (off >= sc->sc_size) {
620 if (bp->b_flags & B_READ)
621 goto done;
622 error = EIO;
623 goto done;
624 }
625 xfer = bp->b_resid;
626 if (xfer > (sc->sc_size - off))
627 xfer = (sc->sc_size - off);
628 addr = sc->sc_addr + off;
629 if (bp->b_flags & B_READ)
630 error = copyin(addr, bp->b_data, xfer);
631 else
632 error = copyout(bp->b_data, addr, xfer);
633 if (!error)
634 bp->b_resid -= xfer;
635
636 done:
637 if (error) {
638 bp->b_error = error;
639 bp->b_flags |= B_ERROR;
640 }
641 s = splbio();
642 biodone(bp);
643 splx(s);
644 }
645 }
646
647 #endif