1 /* $NetBSD: bugdev.c,v 1.12 2008/04/28 20:23:29 martin Exp $ */ 2 3 /*- 4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Paul Kranenburg. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/param.h> 33 #include <sys/disklabel.h> 34 #include <machine/prom.h> 35 36 #include <lib/libsa/stand.h> 37 #include "libsa.h" 38 39 void cputobsdlabel(struct disklabel *lp, struct cpu_disklabel *clp); 40 41 int errno; 42 43 struct bugsc_softc { 44 int fd; /* Prom file descriptor */ 45 int poff; /* Partition offset */ 46 int psize; /* Partition size */ 47 short ctrl; 48 short dev; 49 } bugsc_softc[1]; 50 51 int 52 devopen(struct open_file *f, const char *fname, char **file) 53 { 54 struct bugsc_softc *pp = &bugsc_softc[0]; 55 int error, pn = 0; 56 char *dev, *cp; 57 size_t nrd; 58 static int iobuf[DEV_BSIZE / sizeof(int)]; 59 struct disklabel sdlabel; 60 61 dev = bugargs.arg_start; 62 63 /* 64 * Extract partition # from boot device string. 65 * The Bug command line format of this is: 66 * 67 * 147-Bug> bo [drive],,[<d>:][kernel_name] [options] 68 * 69 * Where: 70 * [drive] The bug LUN number, eg. 0 71 * [<d>:] <d> is partition # ('a' to 'h') 72 * [kernel_name] Eg. netbsd or /netbsd 73 * [options] Eg. -s 74 * 75 * At this time, all we need do is scan for a ':', and assume the 76 * preceding letter is a partition id. 77 */ 78 for (cp = dev + 1; *cp && cp <= bugargs.arg_end; cp++) { 79 if ( *cp == ':' ) { 80 pn = *(cp - 1) - 'a'; 81 break; 82 } 83 } 84 85 if ( pn < 0 || pn >= MAXPARTITIONS ) { 86 printf("Invalid partition number; defaulting to 'a'\n"); 87 pn = 0; 88 } 89 90 pp->fd = bugscopen(f); 91 92 if (pp->fd < 0) { 93 printf("Can't open device `%s'\n", dev); 94 return ENXIO; 95 } 96 error = bugscstrategy(pp, F_READ, LABELSECTOR, DEV_BSIZE, iobuf, &nrd); 97 if (error) 98 return error; 99 if (nrd != DEV_BSIZE) 100 return EINVAL; 101 102 /*LINTED*/ 103 cputobsdlabel(&sdlabel, (struct cpu_disklabel *)&(iobuf[0])); 104 pp->poff = sdlabel.d_partitions[pn].p_offset; 105 pp->psize = sdlabel.d_partitions[pn].p_size; 106 107 f->f_dev = devsw; 108 f->f_devdata = (void *)pp; 109 /*LINTED*/ 110 *file = (char *)fname; 111 return 0; 112 } 113 114 /* silly block scale factor */ 115 #define BUG_BLOCK_SIZE 256 116 #define BUG_SCALE (512/BUG_BLOCK_SIZE) 117 /*ARGSUSED*/ 118 int 119 bugscstrategy(void *devdata, int func, daddr_t dblk, size_t size, void *buf, 120 size_t *rsize) 121 { 122 struct mvmeprom_dskio dio; 123 struct bugsc_softc *pp = (struct bugsc_softc *)devdata; 124 daddr_t blk = dblk + pp->poff; 125 126 twiddle(); 127 128 dio.ctrl_lun = pp->ctrl; 129 dio.dev_lun = pp->dev; 130 dio.status = 0; 131 dio.pbuffer = buf; 132 dio.blk_num = blk * BUG_SCALE; 133 dio.blk_cnt = size / BUG_BLOCK_SIZE; /* assumed size in bytes */ 134 dio.flag = 0; 135 dio.addr_mod = 0; 136 #ifdef DEBUG 137 printf("bugscstrategy: size=%d blk=%d buf=%x\n", size, blk, buf); 138 printf("ctrl %d dev %d\n", dio.ctrl_lun, dio.dev_lun); 139 #endif 140 mvmeprom_diskrd(&dio); 141 142 *rsize = dio.blk_cnt * BUG_BLOCK_SIZE; 143 #ifdef DEBUG 144 printf("rsize %d status %x\n", *rsize, dio.status); 145 #endif 146 147 if (dio.status) 148 return EIO; 149 return 0; 150 } 151 152 int 153 bugscopen(struct open_file *f, ...) 154 { 155 156 #ifdef DEBUG 157 printf("bugscopen:\n"); 158 #endif 159 160 f->f_devdata = (void *)bugsc_softc; 161 bugsc_softc[0].ctrl = (short)bugargs.ctrl_lun; 162 bugsc_softc[0].dev = (short)bugargs.dev_lun; 163 #ifdef DEBUG 164 printf("using mvmebug ctrl %d dev %d\n", 165 bugsc_softc[0].ctrl, bugsc_softc[0].dev); 166 #endif 167 return 0; 168 } 169 170 /*ARGSUSED*/ 171 int 172 bugscclose(struct open_file *f) 173 { 174 175 return EIO; 176 } 177 178 /*ARGSUSED*/ 179 int 180 bugscioctl(struct open_file *f, u_long cmd, void *data) 181 { 182 183 return EIO; 184 } 185 186 void 187 cputobsdlabel(struct disklabel *lp, struct cpu_disklabel *clp) 188 { 189 int i; 190 191 lp->d_magic = (uint32_t)clp->magic1; 192 lp->d_type = (uint16_t)clp->type; 193 lp->d_subtype = (uint16_t)clp->subtype; 194 195 memcpy(lp->d_typename, clp->vid_vd, 16); 196 memcpy(lp->d_packname, clp->packname, 16); 197 198 lp->d_secsize = (uint32_t)clp->cfg_psm; 199 lp->d_nsectors = (uint32_t)clp->cfg_spt; 200 lp->d_ncylinders = (uint32_t)clp->cfg_trk; /* trk is num of cyl! */ 201 lp->d_ntracks = (uint32_t)clp->cfg_hds; 202 lp->d_secpercyl = (uint32_t)clp->secpercyl; 203 lp->d_secperunit = (uint32_t)clp->secperunit; 204 lp->d_sparespertrack = (uint16_t)clp->sparespertrack; 205 lp->d_sparespercyl = (uint16_t)clp->sparespercyl; 206 lp->d_acylinders = (uint32_t)clp->acylinders; 207 lp->d_rpm = (uint16_t)clp->rpm; 208 lp->d_interleave = (uint16_t)clp->cfg_ilv; 209 lp->d_trackskew = (uint16_t)clp->cfg_sof; 210 lp->d_cylskew = (uint16_t)clp->cylskew; 211 lp->d_headswitch = (uint32_t)clp->headswitch; 212 213 /* this silly table is for winchester drives */ 214 switch (clp->cfg_ssr) { 215 case 0: 216 lp->d_trkseek = 0; 217 break; 218 case 1: 219 lp->d_trkseek = 6; 220 break; 221 case 2: 222 lp->d_trkseek = 10; 223 break; 224 case 3: 225 lp->d_trkseek = 15; 226 break; 227 case 4: 228 lp->d_trkseek = 20; 229 break; 230 default: 231 lp->d_trkseek = 0; 232 break; 233 } 234 lp->d_flags = (uint32_t)clp->flags; 235 236 for (i = 0; i < NDDATA; i++) 237 lp->d_drivedata[i] = (uint32_t)clp->drivedata[i]; 238 239 for (i = 0; i < NSPARE; i++) 240 lp->d_spare[i] = (uint32_t)clp->spare[i]; 241 242 lp->d_magic2 = (uint32_t)clp->magic2; 243 lp->d_checksum = (uint16_t)clp->checksum; 244 lp->d_npartitions = (uint16_t)clp->partitions; 245 lp->d_bbsize = (uint32_t)clp->bbsize; 246 lp->d_sbsize = (uint32_t)clp->sbsize; 247 248 memcpy(&(lp->d_partitions[0]), clp->vid_4, 249 sizeof(struct partition) * 4); 250 251 /* CONSTCOND */ 252 memcpy(&(lp->d_partitions[4]), clp->cfg_4, sizeof(struct partition) 253 * ((MAXPARTITIONS < 16) ? (MAXPARTITIONS - 4) : 12)); 254 } 255