1 /* $NetBSD: md_root.c,v 1.37 2026/05/30 10:10:11 thorpej 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 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __KERNEL_RCSID(0, "$NetBSD: md_root.c,v 1.37 2026/05/30 10:10:11 thorpej Exp $"); 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/kernel.h> 34 #include <sys/kmem.h> 35 #include <sys/buf.h> 36 #include <sys/proc.h> 37 #include <sys/device.h> 38 #include <sys/ioctl.h> 39 #include <sys/fcntl.h> 40 #include <sys/conf.h> 41 #include <sys/disklabel.h> 42 #include <sys/disk.h> 43 44 #include <dev/cons.h> 45 #include <dev/md.h> 46 47 #include <atari/atari/device.h> 48 49 /* 50 * Misc. defines: 51 */ 52 #define RAMD_CHUNK (9 * 512) /* Chunk-size for auto-load */ 53 #define RAMD_NDEV 3 /* 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, 2), /* 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, 2), /* XXX: This is crap! (720Kb flop) */ 77 }, 78 { 79 1474560, /* 1.44Mb in 2880 sectors */ 80 RAMD_LOAD, /* auto-load this device */ 81 MAKEDISKDEV(2, 0, 3), /* XXX: This is crap! (1.44Mb flop) */ 82 } 83 }; 84 85 struct read_info { 86 struct buf *bp; /* buffer for strategy function */ 87 long nbytes; /* total number of bytes to read */ 88 long offset; /* offset in input medium */ 89 char *bufp; /* current output buffer */ 90 char *ebufp; /* absolute maximum for bufp */ 91 int chunk; /* chunk size on input medium */ 92 int media_sz; /* size of input medium */ 93 void (*strat)(struct buf *); /* strategy function for read */ 94 }; 95 96 97 static int loaddisk(struct md_conf *, dev_t ld_dev, struct lwp *); 98 static int ramd_norm_read(struct read_info *); 99 100 #ifdef support_compression 101 static int cpy_uncompressed(void *, int, struct read_info *); 102 static int md_compressed(void *, int, struct read_info *); 103 #endif 104 105 /* 106 * This is called during autoconfig. 107 */ 108 void 109 md_attach_hook(int unit, struct md_conf *md) 110 { 111 112 if (atari_realconfig && (unit < RAMD_NDEV) && rd_info[unit].ramd_flag) { 113 printf ("md%d: %sauto-load on open. Size %ld bytes.\n", unit, 114 rd_info[unit].ramd_flag & RAMD_LCOMP ? "decompress/" : "", 115 rd_info[unit].ramd_size); 116 md->md_type = MD_UNCONFIGURED; /* Paranoia... */ 117 } 118 } 119 120 void 121 md_open_hook(int unit, struct md_conf *md) 122 { 123 struct ramd_info *ri; 124 125 if (unit >= RAMD_NDEV) 126 return; 127 128 ri = &rd_info[unit]; 129 if (md->md_type != MD_UNCONFIGURED) 130 return; /* Only configure once */ 131 md->md_addr = kmem_alloc(ri->ramd_size, KM_SLEEP); 132 md->md_size = ri->ramd_size; 133 if (md->md_addr == NULL) 134 return; 135 if (ri->ramd_flag & RAMD_LOAD) { 136 if (loaddisk(md, ri->ramd_dev, curlwp)) { 137 kmem_free(md->md_addr, ri->ramd_size); 138 md->md_addr = NULL; 139 return; 140 } 141 } 142 md->md_type = MD_KMEM_ALLOCATED; 143 } 144 145 static int 146 loaddisk(struct md_conf *md, dev_t ld_dev, struct lwp *lwp) 147 { 148 struct buf *buf; 149 int error; 150 const struct bdevsw *bdp; 151 struct disklabel dl; 152 struct read_info rs; 153 154 bdp = bdevsw_lookup(ld_dev); 155 if (bdp == NULL) 156 return ENXIO; 157 158 /* 159 * Initialize our buffer header: 160 */ 161 buf = getiobuf(NULL, false); 162 buf->b_cflags = BC_BUSY; 163 buf->b_dev = ld_dev; 164 buf->b_error = 0; 165 buf->b_proc = lwp->l_proc; 166 167 /* 168 * Setup read_info: 169 */ 170 rs.bp = buf; 171 rs.nbytes = md->md_size; 172 rs.offset = 0; 173 rs.bufp = md->md_addr; 174 rs.ebufp = (char *)md->md_addr + md->md_size; 175 rs.chunk = RAMD_CHUNK; 176 rs.media_sz = md->md_size; 177 rs.strat = bdp->d_strategy; 178 179 /* 180 * Open device and try to get some statistics. 181 */ 182 if ((error = bdp->d_open(ld_dev, FREAD | FNONBLOCK, 0, lwp)) != 0) { 183 putiobuf(buf); 184 return error; 185 } 186 if (bdp->d_ioctl(ld_dev, DIOCGDINFO, (void *)&dl, FREAD, lwp) == 0) { 187 /* Read on a cylinder basis */ 188 rs.chunk = dl.d_secsize * dl.d_secpercyl; 189 rs.media_sz = dl.d_secperunit * dl.d_secsize; 190 } 191 192 #ifdef support_compression 193 if (ri->ramd_flag & RAMD_LCOMP) 194 error = decompress(cpy_uncompressed, md_compressed, &rs); 195 else 196 #endif /* support_compression */ 197 error = ramd_norm_read(&rs); 198 199 bdp->d_close(ld_dev, FREAD | FNONBLOCK, 0, lwp); 200 putiobuf(buf); 201 return error; 202 } 203 204 static int 205 ramd_norm_read(struct read_info *rsp) 206 { 207 long bytes_left; 208 int done, error; 209 struct buf *bp; 210 int dotc = 0; 211 212 bytes_left = rsp->nbytes; 213 bp = rsp->bp; 214 error = 0; 215 216 while (bytes_left > 0) { 217 bp->b_cflags = BC_BUSY; 218 bp->b_flags = B_PHYS | B_READ; 219 bp->b_oflags &= ~BO_DONE; 220 bp->b_blkno = btodb(rsp->offset); 221 bp->b_bcount = uimin(rsp->chunk, bytes_left); 222 bp->b_data = rsp->bufp; 223 bp->b_error = 0; 224 225 /* Initiate read */ 226 (*rsp->strat)(bp); 227 228 /* Wait for results */ 229 biowait(bp); 230 error = bp->b_error; 231 232 /* Dot counter */ 233 printf("."); 234 if (!(++dotc % 40)) 235 printf("\n"); 236 237 done = bp->b_bcount - bp->b_resid; 238 239 bytes_left -= done; 240 rsp->offset += done; 241 rsp->bufp += done; 242 243 if (error || !done) 244 break; 245 246 if ((rsp->offset == rsp->media_sz) && (bytes_left != 0)) { 247 printf("\nInsert next media and hit any key..."); 248 cngetc(); 249 printf("\n"); 250 rsp->offset = 0; 251 } 252 } 253 printf("\n"); 254 return error; 255 } 256 257 #ifdef support_compression 258 /* 259 * Functions supporting uncompression: 260 */ 261 /* 262 * Copy from the uncompression buffer to the ramdisk 263 */ 264 static int 265 cpy_uncompressed(void * buf, int nbyte, struct read_info *rsp) 266 { 267 268 if ((rsp->bufp + nbyte) >= rsp->ebufp) 269 return 0; 270 memcpy(rsp->bufp, buf, nbyte); 271 rsp->bufp += nbyte; 272 return 0; 273 } 274 275 /* 276 * Read a maximum of 'nbyte' bytes into 'buf'. 277 */ 278 static int 279 md_compressed(void * buf, int nbyte, struct read_info *rsp) 280 { 281 static int dotc = 0; 282 struct buf *bp; 283 int nread = 0; 284 int done, error; 285 286 287 error = 0; 288 bp = rsp->bp; 289 nbyte &= ~(DEV_BSIZE - 1); 290 291 while (nbyte > 0) { 292 bp->b_cflags = BC_BUSY; 293 bp->b_flags = B_PHYS | B_READ; 294 bp->b_oflags &= ~BO_DONE; 295 bp->b_blkno = btodb(rsp->offset); 296 bp->b_bcount = uimin(rsp->chunk, nbyte); 297 bp->b_data = buf; 298 bp->b_error = 0; 299 300 /* Initiate read */ 301 (*rsp->strat)(bp); 302 303 /* Wait for results */ 304 biowait(bp); 305 error = bp->b_error; 306 307 /* Dot counter */ 308 printf("."); 309 if (!(++dotc % 40)) 310 printf("\n"); 311 312 done = bp->b_bcount - bp->b_resid; 313 314 nbyte -= done; 315 nread += done; 316 rsp->offset += done; 317 318 if (error || !done) 319 break; 320 321 if ((rsp->offset == rsp->media_sz) && (nbyte != 0)) { 322 printf("\nInsert next media and hit any key..."); 323 if (cngetc() != '\n') 324 printf("\n"); 325 rsp->offset = 0; 326 } 327 } 328 return nread; 329 } 330 #endif /* support_compression */ 331