1 1.26 mlelstv /* $NetBSD: mmemcard.c,v 1.26 2015/04/26 15:15:19 mlelstv Exp $ */ 2 1.1 itohy 3 1.1 itohy /*- 4 1.1 itohy * Copyright (c) 2002 The NetBSD Foundation, Inc. 5 1.1 itohy * All rights reserved. 6 1.1 itohy * 7 1.1 itohy * This code is derived from software contributed to The NetBSD Foundation 8 1.1 itohy * by ITOH Yasufumi. 9 1.1 itohy * 10 1.1 itohy * Redistribution and use in source and binary forms, with or without 11 1.1 itohy * modification, are permitted provided that the following conditions 12 1.1 itohy * are met: 13 1.1 itohy * 1. Redistributions of source code must retain the above copyright 14 1.1 itohy * notice, this list of conditions and the following disclaimer. 15 1.1 itohy * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 itohy * notice, this list of conditions and the following disclaimer in the 17 1.1 itohy * documentation and/or other materials provided with the distribution. 18 1.1 itohy * 19 1.1 itohy * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 itohy * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 itohy * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 itohy * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 itohy * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 itohy * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 itohy * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 itohy * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 itohy * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 itohy * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 itohy * POSSIBILITY OF SUCH DAMAGE. 30 1.1 itohy */ 31 1.3 lukem 32 1.3 lukem #include <sys/cdefs.h> 33 1.26 mlelstv __KERNEL_RCSID(0, "$NetBSD: mmemcard.c,v 1.26 2015/04/26 15:15:19 mlelstv Exp $"); 34 1.1 itohy 35 1.1 itohy #include <sys/param.h> 36 1.1 itohy #include <sys/buf.h> 37 1.4 yamt #include <sys/bufq.h> 38 1.1 itohy #include <sys/device.h> 39 1.1 itohy #include <sys/disklabel.h> 40 1.1 itohy #include <sys/disk.h> 41 1.1 itohy #include <sys/kernel.h> 42 1.1 itohy #include <sys/malloc.h> 43 1.1 itohy #include <sys/proc.h> 44 1.1 itohy #include <sys/stat.h> 45 1.1 itohy #include <sys/systm.h> 46 1.1 itohy #include <sys/vnode.h> 47 1.1 itohy #include <sys/conf.h> 48 1.1 itohy 49 1.1 itohy #include <dreamcast/dev/maple/maple.h> 50 1.1 itohy #include <dreamcast/dev/maple/mapleconf.h> 51 1.1 itohy 52 1.20 tsutsui #include "ioconf.h" 53 1.20 tsutsui 54 1.1 itohy #define MMEM_MAXACCSIZE 1012 /* (255*4) - 8 = 253*32 / 8 */ 55 1.1 itohy 56 1.1 itohy struct mmem_funcdef { /* XXX assuming little-endian structure packing */ 57 1.1 itohy unsigned unused : 8, 58 1.1 itohy ra : 4, /* number of access / read */ 59 1.1 itohy wa : 4, /* number of access / write */ 60 1.1 itohy bb : 8, /* block size / 32 - 1 */ 61 1.1 itohy pt : 8; /* number of partition - 1 */ 62 1.1 itohy }; 63 1.1 itohy 64 1.1 itohy struct mmem_request_read_data { 65 1.5 tsutsui uint32_t func_code; 66 1.5 tsutsui uint8_t pt; 67 1.5 tsutsui uint8_t phase; 68 1.5 tsutsui uint16_t block; 69 1.1 itohy }; 70 1.1 itohy 71 1.1 itohy struct mmem_response_read_data { 72 1.5 tsutsui uint32_t func_code; /* function code (big endian) */ 73 1.5 tsutsui uint32_t blkno; /* 512byte block number (big endian) */ 74 1.5 tsutsui uint8_t data[MMEM_MAXACCSIZE]; 75 1.1 itohy }; 76 1.1 itohy 77 1.1 itohy struct mmem_request_write_data { 78 1.5 tsutsui uint32_t func_code; 79 1.5 tsutsui uint8_t pt; 80 1.5 tsutsui uint8_t phase; /* 0, 1, 2, 3: for each 128 byte */ 81 1.5 tsutsui uint16_t block; 82 1.5 tsutsui uint8_t data[MMEM_MAXACCSIZE]; 83 1.1 itohy }; 84 1.1 itohy #define MMEM_SIZE_REQW(sc) ((sc)->sc_waccsz + 8) 85 1.1 itohy 86 1.1 itohy struct mmem_request_get_media_info { 87 1.5 tsutsui uint32_t func_code; 88 1.5 tsutsui uint32_t pt; /* pt (1 byte) and unused 3 bytes */ 89 1.1 itohy }; 90 1.1 itohy 91 1.1 itohy struct mmem_media_info { 92 1.5 tsutsui uint16_t maxblk, minblk; 93 1.5 tsutsui uint16_t infpos; 94 1.5 tsutsui uint16_t fatpos, fatsz; 95 1.5 tsutsui uint16_t dirpos, dirsz; 96 1.5 tsutsui uint16_t icon; 97 1.5 tsutsui uint16_t datasz; 98 1.5 tsutsui uint16_t rsvd[3]; 99 1.1 itohy }; 100 1.1 itohy 101 1.1 itohy struct mmem_response_media_info { 102 1.5 tsutsui uint32_t func_code; /* function code (big endian) */ 103 1.1 itohy struct mmem_media_info info; 104 1.1 itohy }; 105 1.1 itohy 106 1.1 itohy struct mmem_softc { 107 1.19 tsutsui device_t sc_dev; 108 1.1 itohy 109 1.19 tsutsui device_t sc_parent; 110 1.1 itohy struct maple_unit *sc_unit; 111 1.1 itohy struct maple_devinfo *sc_devinfo; 112 1.1 itohy 113 1.1 itohy enum mmem_stat { 114 1.1 itohy MMEM_INIT, /* during initialization */ 115 1.1 itohy MMEM_INIT2, /* during initialization */ 116 1.1 itohy MMEM_IDLE, /* init done, not in I/O */ 117 1.1 itohy MMEM_READ, /* in read operation */ 118 1.1 itohy MMEM_WRITE1, /* in write operation (read and compare) */ 119 1.1 itohy MMEM_WRITE2, /* in write operation (write) */ 120 1.1 itohy MMEM_DETACH /* detaching */ 121 1.1 itohy } sc_stat; 122 1.1 itohy 123 1.1 itohy int sc_npt; /* number of partitions */ 124 1.1 itohy int sc_bsize; /* block size */ 125 1.1 itohy int sc_wacc; /* number of write access per block */ 126 1.1 itohy int sc_waccsz; /* size of a write access */ 127 1.1 itohy int sc_racc; /* number of read access per block */ 128 1.1 itohy int sc_raccsz; /* size of a read access */ 129 1.1 itohy 130 1.1 itohy struct mmem_pt { 131 1.1 itohy int pt_flags; 132 1.1 itohy #define MMEM_PT_OK 1 /* partition is alive */ 133 1.1 itohy struct disk pt_dk; /* disk(9) */ 134 1.1 itohy struct mmem_media_info pt_info; /* geometry per part */ 135 1.1 itohy 136 1.2 itohy char pt_name[16 /* see device.h */ + 4 /* ".255" */]; 137 1.1 itohy } *sc_pt; 138 1.1 itohy 139 1.1 itohy /* write request buffer (only one is used at a time) */ 140 1.1 itohy union { 141 1.1 itohy struct mmem_request_read_data req_read; 142 1.1 itohy struct mmem_request_write_data req_write; 143 1.1 itohy struct mmem_request_get_media_info req_minfo; 144 1.1 itohy } sc_req; 145 1.1 itohy #define sc_reqr sc_req.req_read 146 1.1 itohy #define sc_reqw sc_req.req_write 147 1.1 itohy #define sc_reqm sc_req.req_minfo 148 1.1 itohy 149 1.1 itohy /* pending buffers */ 150 1.6 yamt struct bufq_state *sc_q; 151 1.1 itohy 152 1.1 itohy /* current I/O access */ 153 1.1 itohy struct buf *sc_bp; 154 1.1 itohy int sc_cnt; 155 1.1 itohy char *sc_iobuf; 156 1.1 itohy int sc_retry; 157 1.1 itohy #define MMEM_MAXRETRY 12 158 1.1 itohy }; 159 1.1 itohy 160 1.1 itohy /* 161 1.1 itohy * minor number layout (mmemdetach() depends on this layout): 162 1.1 itohy * 163 1.1 itohy * 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 164 1.1 itohy * |---------------------| |---------------------| |---------| 165 1.1 itohy * unit part disklabel partition 166 1.1 itohy */ 167 1.1 itohy #define MMEM_PART(diskunit) ((diskunit) & 0xff) 168 1.1 itohy #define MMEM_UNIT(diskunit) ((diskunit) >> 8) 169 1.1 itohy #define MMEM_DISKMINOR(unit, part, disklabel_partition) \ 170 1.1 itohy DISKMINOR(((unit) << 8) | (part), (disklabel_partition)) 171 1.1 itohy 172 1.19 tsutsui static int mmemmatch(device_t, cfdata_t, void *); 173 1.19 tsutsui static void mmemattach(device_t, device_t, void *); 174 1.5 tsutsui static void mmem_defaultlabel(struct mmem_softc *, struct mmem_pt *, 175 1.5 tsutsui struct disklabel *); 176 1.19 tsutsui static int mmemdetach(device_t, int); 177 1.5 tsutsui static void mmem_intr(void *, struct maple_response *, int, int); 178 1.5 tsutsui static void mmem_printerror(const char *, int, int, uint32_t); 179 1.5 tsutsui static void mmemstart(struct mmem_softc *); 180 1.5 tsutsui static void mmemstart_bp(struct mmem_softc *); 181 1.5 tsutsui static void mmemstart_write2(struct mmem_softc *); 182 1.5 tsutsui static void mmemdone(struct mmem_softc *, struct mmem_pt *, int); 183 1.1 itohy 184 1.1 itohy dev_type_open(mmemopen); 185 1.1 itohy dev_type_close(mmemclose); 186 1.1 itohy dev_type_read(mmemread); 187 1.1 itohy dev_type_write(mmemwrite); 188 1.1 itohy dev_type_ioctl(mmemioctl); 189 1.1 itohy dev_type_strategy(mmemstrategy); 190 1.1 itohy 191 1.1 itohy const struct bdevsw mmem_bdevsw = { 192 1.21 dholland .d_open = mmemopen, 193 1.21 dholland .d_close = mmemclose, 194 1.21 dholland .d_strategy = mmemstrategy, 195 1.21 dholland .d_ioctl = mmemioctl, 196 1.21 dholland .d_dump = nodump, 197 1.21 dholland .d_psize = nosize, 198 1.23 dholland .d_discard = nodiscard, 199 1.21 dholland .d_flag = D_DISK 200 1.1 itohy }; 201 1.1 itohy 202 1.1 itohy const struct cdevsw mmem_cdevsw = { 203 1.21 dholland .d_open = mmemopen, 204 1.21 dholland .d_close = mmemclose, 205 1.21 dholland .d_read = mmemread, 206 1.21 dholland .d_write = mmemwrite, 207 1.21 dholland .d_ioctl = mmemioctl, 208 1.21 dholland .d_stop = nostop, 209 1.21 dholland .d_tty = notty, 210 1.21 dholland .d_poll = nopoll, 211 1.21 dholland .d_mmap = nommap, 212 1.21 dholland .d_kqfilter = nokqfilter, 213 1.24 dholland .d_discard = nodiscard, 214 1.21 dholland .d_flag = D_DISK 215 1.1 itohy }; 216 1.1 itohy 217 1.19 tsutsui CFATTACH_DECL_NEW(mmem, sizeof(struct mmem_softc), 218 1.1 itohy mmemmatch, mmemattach, mmemdetach, NULL); 219 1.1 itohy 220 1.26 mlelstv struct dkdriver mmemdkdriver = { 221 1.26 mlelstv .d_strategy = mmemstrategy 222 1.26 mlelstv }; 223 1.1 itohy 224 1.1 itohy static int 225 1.19 tsutsui mmemmatch(device_t parent, cfdata_t cf, void *aux) 226 1.1 itohy { 227 1.1 itohy struct maple_attach_args *ma = aux; 228 1.1 itohy 229 1.5 tsutsui return ma->ma_function == MAPLE_FN_MEMCARD ? MAPLE_MATCH_FUNC : 0; 230 1.1 itohy } 231 1.1 itohy 232 1.1 itohy static void 233 1.19 tsutsui mmemattach(device_t parent, device_t self, void *aux) 234 1.1 itohy { 235 1.19 tsutsui struct mmem_softc *sc = device_private(self); 236 1.1 itohy struct maple_attach_args *ma = aux; 237 1.1 itohy int i; 238 1.1 itohy union { 239 1.5 tsutsui uint32_t v; 240 1.1 itohy struct mmem_funcdef s; 241 1.1 itohy } funcdef; 242 1.1 itohy 243 1.19 tsutsui sc->sc_dev = self; 244 1.1 itohy sc->sc_parent = parent; 245 1.1 itohy sc->sc_unit = ma->ma_unit; 246 1.1 itohy sc->sc_devinfo = ma->ma_devinfo; 247 1.1 itohy 248 1.1 itohy funcdef.v = maple_get_function_data(ma->ma_devinfo, MAPLE_FN_MEMCARD); 249 1.1 itohy printf(": Memory card\n"); 250 1.1 itohy printf("%s: %d part, %d bytes/block, ", 251 1.19 tsutsui device_xname(self), 252 1.1 itohy sc->sc_npt = funcdef.s.pt + 1, 253 1.1 itohy sc->sc_bsize = (funcdef.s.bb + 1) << 5); 254 1.1 itohy if ((sc->sc_wacc = funcdef.s.wa) == 0) 255 1.1 itohy printf("no write, "); 256 1.1 itohy else 257 1.1 itohy printf("%d acc/write, ", sc->sc_wacc); 258 1.1 itohy if ((sc->sc_racc = funcdef.s.ra) == 0) 259 1.1 itohy printf("no read\n"); 260 1.1 itohy else 261 1.1 itohy printf("%d acc/read\n", sc->sc_racc); 262 1.1 itohy 263 1.1 itohy /* 264 1.1 itohy * start init sequence 265 1.1 itohy */ 266 1.1 itohy sc->sc_stat = MMEM_INIT; 267 1.6 yamt bufq_alloc(&sc->sc_q, "disksort", BUFQ_SORT_RAWBLOCK); 268 1.1 itohy 269 1.1 itohy /* check consistency */ 270 1.1 itohy if (sc->sc_wacc != 0) { 271 1.1 itohy sc->sc_waccsz = sc->sc_bsize / sc->sc_wacc; 272 1.1 itohy if (sc->sc_bsize != sc->sc_waccsz * sc->sc_wacc) { 273 1.1 itohy printf("%s: write access isn't equally divided\n", 274 1.19 tsutsui device_xname(self)); 275 1.1 itohy sc->sc_wacc = 0; /* no write */ 276 1.1 itohy } else if (sc->sc_waccsz > MMEM_MAXACCSIZE) { 277 1.1 itohy printf("%s: write access size is too large\n", 278 1.19 tsutsui device_xname(self)); 279 1.1 itohy sc->sc_wacc = 0; /* no write */ 280 1.1 itohy } 281 1.1 itohy } 282 1.1 itohy if (sc->sc_racc != 0) { 283 1.1 itohy sc->sc_raccsz = sc->sc_bsize / sc->sc_racc; 284 1.1 itohy if (sc->sc_bsize != sc->sc_raccsz * sc->sc_racc) { 285 1.1 itohy printf("%s: read access isn't equally divided\n", 286 1.19 tsutsui device_xname(self)); 287 1.1 itohy sc->sc_racc = 0; /* no read */ 288 1.1 itohy } else if (sc->sc_raccsz > MMEM_MAXACCSIZE) { 289 1.1 itohy printf("%s: read access size is too large\n", 290 1.19 tsutsui device_xname(self)); 291 1.1 itohy sc->sc_racc = 0; /* no read */ 292 1.1 itohy } 293 1.1 itohy } 294 1.1 itohy if (sc->sc_wacc == 0 && sc->sc_racc == 0) { 295 1.1 itohy printf("%s: device doesn't support read nor write\n", 296 1.19 tsutsui device_xname(self)); 297 1.1 itohy return; 298 1.1 itohy } 299 1.1 itohy 300 1.1 itohy /* per-part structure */ 301 1.1 itohy sc->sc_pt = malloc(sizeof(struct mmem_pt) * sc->sc_npt, M_DEVBUF, 302 1.1 itohy M_WAITOK|M_ZERO); 303 1.1 itohy 304 1.1 itohy for (i = 0; i < sc->sc_npt; i++) { 305 1.22 christos snprintf(sc->sc_pt[i].pt_name, sizeof(sc->sc_pt[i].pt_name), 306 1.22 christos "%s.%d", device_xname(self), i); 307 1.1 itohy } 308 1.1 itohy 309 1.1 itohy maple_set_callback(parent, sc->sc_unit, MAPLE_FN_MEMCARD, 310 1.1 itohy mmem_intr, sc); 311 1.1 itohy 312 1.1 itohy /* 313 1.1 itohy * get capacity (start from partition 0) 314 1.1 itohy */ 315 1.5 tsutsui sc->sc_reqm.func_code = htobe32(MAPLE_FUNC(MAPLE_FN_MEMCARD)); 316 1.1 itohy sc->sc_reqm.pt = 0; 317 1.1 itohy maple_command(sc->sc_parent, sc->sc_unit, MAPLE_FN_MEMCARD, 318 1.1 itohy MAPLE_COMMAND_GETMINFO, sizeof sc->sc_reqm / 4, &sc->sc_reqm, 0); 319 1.1 itohy } 320 1.1 itohy 321 1.1 itohy static int 322 1.19 tsutsui mmemdetach(device_t self, int flags) 323 1.1 itohy { 324 1.19 tsutsui struct mmem_softc *sc = device_private(self); 325 1.1 itohy struct buf *bp; 326 1.1 itohy int i; 327 1.1 itohy int minor_l, minor_h; 328 1.1 itohy 329 1.1 itohy sc->sc_stat = MMEM_DETACH; /* just in case */ 330 1.1 itohy 331 1.1 itohy /* 332 1.1 itohy * kill pending I/O 333 1.1 itohy */ 334 1.1 itohy if ((bp = sc->sc_bp) != NULL) { 335 1.1 itohy bp->b_error = EIO; 336 1.1 itohy bp->b_resid = bp->b_bcount; 337 1.1 itohy biodone(bp); 338 1.1 itohy } 339 1.18 yamt while ((bp = bufq_get(sc->sc_q)) != NULL) { 340 1.1 itohy bp->b_error = EIO; 341 1.1 itohy bp->b_resid = bp->b_bcount; 342 1.1 itohy biodone(bp); 343 1.1 itohy } 344 1.6 yamt bufq_free(sc->sc_q); 345 1.1 itohy 346 1.1 itohy /* 347 1.1 itohy * revoke vnodes 348 1.1 itohy */ 349 1.1 itohy #ifdef __HAVE_OLD_DISKLABEL 350 1.1 itohy #error This code assumes DISKUNIT() is contiguous in minor number. 351 1.1 itohy #endif 352 1.8 thorpej minor_l = MMEM_DISKMINOR(device_unit(self), 0, 0); 353 1.8 thorpej minor_h = MMEM_DISKMINOR(device_unit(self), sc->sc_npt - 1, 354 1.1 itohy MAXPARTITIONS - 1); 355 1.1 itohy vdevgone(bdevsw_lookup_major(&mmem_bdevsw), minor_l, minor_h, VBLK); 356 1.1 itohy vdevgone(cdevsw_lookup_major(&mmem_cdevsw), minor_l, minor_h, VCHR); 357 1.1 itohy 358 1.1 itohy /* 359 1.1 itohy * free per-partition structure 360 1.1 itohy */ 361 1.1 itohy if (sc->sc_pt) { 362 1.1 itohy /* 363 1.1 itohy * detach disks 364 1.1 itohy */ 365 1.1 itohy for (i = 0; i < sc->sc_npt; i++) { 366 1.13 ad if (sc->sc_pt[i].pt_flags & MMEM_PT_OK) { 367 1.1 itohy disk_detach(&sc->sc_pt[i].pt_dk); 368 1.13 ad disk_destroy(&sc->sc_pt[i].pt_dk); 369 1.13 ad } 370 1.1 itohy } 371 1.1 itohy free(sc->sc_pt, M_DEVBUF); 372 1.1 itohy } 373 1.1 itohy 374 1.1 itohy return 0; 375 1.1 itohy } 376 1.1 itohy 377 1.1 itohy /* fake disklabel */ 378 1.1 itohy static void 379 1.5 tsutsui mmem_defaultlabel(struct mmem_softc *sc, struct mmem_pt *pt, 380 1.5 tsutsui struct disklabel *d) 381 1.1 itohy { 382 1.1 itohy 383 1.5 tsutsui memset(d, 0, sizeof *d); 384 1.1 itohy 385 1.1 itohy #if 0 386 1.25 christos d->d_type = DKTYPE_FLOPPY; /* XXX? */ 387 1.1 itohy #endif 388 1.1 itohy strncpy(d->d_typename, sc->sc_devinfo->di_product_name, 389 1.1 itohy sizeof d->d_typename); 390 1.1 itohy strcpy(d->d_packname, "fictitious"); 391 1.1 itohy d->d_secsize = sc->sc_bsize; 392 1.1 itohy d->d_ntracks = 1; /* XXX */ 393 1.1 itohy d->d_nsectors = d->d_secpercyl = 8; /* XXX */ 394 1.1 itohy d->d_secperunit = pt->pt_info.maxblk - pt->pt_info.minblk + 1; 395 1.1 itohy d->d_ncylinders = d->d_secperunit / d->d_secpercyl; 396 1.1 itohy d->d_rpm = 1; /* when 4 acc/write */ 397 1.1 itohy 398 1.1 itohy d->d_npartitions = RAW_PART + 1; 399 1.1 itohy d->d_partitions[RAW_PART].p_size = d->d_secperunit; 400 1.1 itohy 401 1.1 itohy d->d_magic = d->d_magic2 = DISKMAGIC; 402 1.1 itohy d->d_checksum = dkcksum(d); 403 1.1 itohy } 404 1.1 itohy 405 1.1 itohy /* 406 1.1 itohy * called back from maple bus driver 407 1.1 itohy */ 408 1.1 itohy static void 409 1.19 tsutsui mmem_intr(void *arg, struct maple_response *response, int sz, int flags) 410 1.1 itohy { 411 1.19 tsutsui struct mmem_softc *sc = arg; 412 1.1 itohy struct mmem_response_read_data *r = (void *) response->data; 413 1.1 itohy struct mmem_response_media_info *rm = (void *) response->data; 414 1.1 itohy struct buf *bp; 415 1.1 itohy int part; 416 1.1 itohy struct mmem_pt *pt; 417 1.1 itohy char pbuf[9]; 418 1.1 itohy int off; 419 1.1 itohy 420 1.1 itohy switch (sc->sc_stat) { 421 1.1 itohy case MMEM_INIT: 422 1.1 itohy /* checking part geometry */ 423 1.1 itohy part = sc->sc_reqm.pt; 424 1.1 itohy pt = &sc->sc_pt[part]; 425 1.1 itohy switch ((maple_response_t) response->response_code) { 426 1.1 itohy case MAPLE_RESPONSE_DATATRF: 427 1.1 itohy pt->pt_info = rm->info; 428 1.1 itohy format_bytes(pbuf, sizeof(pbuf), 429 1.5 tsutsui (uint64_t) 430 1.1 itohy ((pt->pt_info.maxblk - pt->pt_info.minblk + 1) 431 1.1 itohy * sc->sc_bsize)); 432 1.1 itohy printf("%s: %s, blk %d %d, inf %d, fat %d %d, dir %d %d, icon %d, data %d\n", 433 1.1 itohy pt->pt_name, 434 1.1 itohy pbuf, 435 1.1 itohy pt->pt_info.maxblk, pt->pt_info.minblk, 436 1.1 itohy pt->pt_info.infpos, 437 1.1 itohy pt->pt_info.fatpos, pt->pt_info.fatsz, 438 1.1 itohy pt->pt_info.dirpos, pt->pt_info.dirsz, 439 1.1 itohy pt->pt_info.icon, 440 1.1 itohy pt->pt_info.datasz); 441 1.1 itohy 442 1.13 ad disk_init(&pt->pt_dk, pt->pt_name, &mmemdkdriver); 443 1.1 itohy disk_attach(&pt->pt_dk); 444 1.1 itohy 445 1.1 itohy mmem_defaultlabel(sc, pt, pt->pt_dk.dk_label); 446 1.1 itohy 447 1.1 itohy /* this partition is active */ 448 1.1 itohy pt->pt_flags = MMEM_PT_OK; 449 1.1 itohy 450 1.1 itohy break; 451 1.1 itohy default: 452 1.1 itohy printf("%s: init: unexpected response %#x, sz %d\n", 453 1.5 tsutsui pt->pt_name, be32toh(response->response_code), sz); 454 1.1 itohy break; 455 1.1 itohy } 456 1.1 itohy if (++part == sc->sc_npt) { 457 1.1 itohy #if 1 458 1.1 itohy /* 459 1.1 itohy * XXX Read a block and discard the contents (only to 460 1.1 itohy * turn off the access indicator on Visual Memory). 461 1.1 itohy */ 462 1.1 itohy pt = &sc->sc_pt[0]; 463 1.1 itohy sc->sc_reqr.func_code = 464 1.5 tsutsui htobe32(MAPLE_FUNC(MAPLE_FN_MEMCARD)); 465 1.1 itohy sc->sc_reqr.pt = 0; 466 1.5 tsutsui sc->sc_reqr.block = htobe16(pt->pt_info.minblk); 467 1.1 itohy sc->sc_reqr.phase = 0; 468 1.1 itohy maple_command(sc->sc_parent, sc->sc_unit, 469 1.1 itohy MAPLE_FN_MEMCARD, MAPLE_COMMAND_BREAD, 470 1.1 itohy sizeof sc->sc_reqr / 4, &sc->sc_reqr, 0); 471 1.1 itohy sc->sc_stat = MMEM_INIT2; 472 1.1 itohy #else 473 1.1 itohy sc->sc_stat = MMEM_IDLE; /* init done */ 474 1.1 itohy #endif 475 1.1 itohy } else { 476 1.1 itohy sc->sc_reqm.pt = part; 477 1.1 itohy maple_command(sc->sc_parent, sc->sc_unit, 478 1.1 itohy MAPLE_FN_MEMCARD, MAPLE_COMMAND_GETMINFO, 479 1.1 itohy sizeof sc->sc_reqm / 4, &sc->sc_reqm, 0); 480 1.1 itohy } 481 1.1 itohy break; 482 1.1 itohy 483 1.1 itohy case MMEM_INIT2: 484 1.1 itohy /* XXX just discard */ 485 1.1 itohy sc->sc_stat = MMEM_IDLE; /* init done */ 486 1.1 itohy break; 487 1.1 itohy 488 1.1 itohy case MMEM_READ: 489 1.1 itohy bp = sc->sc_bp; 490 1.1 itohy 491 1.1 itohy switch ((maple_response_t) response->response_code) { 492 1.1 itohy case MAPLE_RESPONSE_DATATRF: /* read done */ 493 1.1 itohy off = sc->sc_raccsz * sc->sc_reqr.phase; 494 1.5 tsutsui memcpy(sc->sc_iobuf + off, r->data + off, 495 1.5 tsutsui sc->sc_raccsz); 496 1.1 itohy 497 1.1 itohy if (++sc->sc_reqr.phase == sc->sc_racc) { 498 1.1 itohy /* all phase done */ 499 1.1 itohy pt = &sc->sc_pt[sc->sc_reqr.pt]; 500 1.1 itohy mmemdone(sc, pt, 0); 501 1.1 itohy } else { 502 1.1 itohy /* go next phase */ 503 1.1 itohy maple_command(sc->sc_parent, sc->sc_unit, 504 1.1 itohy MAPLE_FN_MEMCARD, MAPLE_COMMAND_BREAD, 505 1.1 itohy sizeof sc->sc_reqr / 4, &sc->sc_reqr, 0); 506 1.1 itohy } 507 1.1 itohy break; 508 1.1 itohy case MAPLE_RESPONSE_FILEERR: 509 1.1 itohy mmem_printerror(sc->sc_pt[sc->sc_reqr.pt].pt_name, 510 1.1 itohy 1, bp->b_rawblkno, 511 1.1 itohy r->func_code /* XXX */); 512 1.1 itohy mmemstart_bp(sc); /* retry */ 513 1.1 itohy break; 514 1.1 itohy default: 515 1.1 itohy printf("%s: read: unexpected response %#x %#x, sz %d\n", 516 1.1 itohy sc->sc_pt[sc->sc_reqr.pt].pt_name, 517 1.5 tsutsui be32toh(response->response_code), 518 1.5 tsutsui be32toh(r->func_code), sz); 519 1.1 itohy mmemstart_bp(sc); /* retry */ 520 1.1 itohy break; 521 1.1 itohy } 522 1.1 itohy break; 523 1.1 itohy 524 1.1 itohy case MMEM_WRITE1: /* read before write / verify after write */ 525 1.1 itohy bp = sc->sc_bp; 526 1.1 itohy 527 1.1 itohy switch ((maple_response_t) response->response_code) { 528 1.1 itohy case MAPLE_RESPONSE_DATATRF: /* read done */ 529 1.1 itohy off = sc->sc_raccsz * sc->sc_reqr.phase; 530 1.5 tsutsui if (memcmp(r->data + off, sc->sc_iobuf + off, 531 1.1 itohy sc->sc_raccsz)) { 532 1.1 itohy /* 533 1.1 itohy * data differ, start writing 534 1.1 itohy */ 535 1.1 itohy mmemstart_write2(sc); 536 1.1 itohy } else if (++sc->sc_reqr.phase == sc->sc_racc) { 537 1.1 itohy /* 538 1.1 itohy * all phase done and compared equal 539 1.1 itohy */ 540 1.1 itohy pt = &sc->sc_pt[sc->sc_reqr.pt]; 541 1.1 itohy mmemdone(sc, pt, 0); 542 1.1 itohy } else { 543 1.1 itohy /* go next phase */ 544 1.1 itohy maple_command(sc->sc_parent, sc->sc_unit, 545 1.1 itohy MAPLE_FN_MEMCARD, MAPLE_COMMAND_BREAD, 546 1.1 itohy sizeof sc->sc_reqr / 4, &sc->sc_reqr, 0); 547 1.1 itohy } 548 1.1 itohy break; 549 1.1 itohy case MAPLE_RESPONSE_FILEERR: 550 1.1 itohy mmem_printerror(sc->sc_pt[sc->sc_reqr.pt].pt_name, 551 1.1 itohy 1, bp->b_rawblkno, 552 1.1 itohy r->func_code /* XXX */); 553 1.1 itohy mmemstart_write2(sc); /* start writing */ 554 1.1 itohy break; 555 1.1 itohy default: 556 1.1 itohy printf("%s: verify: unexpected response %#x %#x, sz %d\n", 557 1.1 itohy sc->sc_pt[sc->sc_reqr.pt].pt_name, 558 1.5 tsutsui be32toh(response->response_code), 559 1.5 tsutsui be32toh(r->func_code), sz); 560 1.1 itohy mmemstart_write2(sc); /* start writing */ 561 1.1 itohy break; 562 1.1 itohy } 563 1.1 itohy break; 564 1.1 itohy 565 1.1 itohy case MMEM_WRITE2: /* write */ 566 1.1 itohy bp = sc->sc_bp; 567 1.1 itohy 568 1.1 itohy switch ((maple_response_t) response->response_code) { 569 1.1 itohy case MAPLE_RESPONSE_OK: /* write done */ 570 1.1 itohy if (sc->sc_reqw.phase == sc->sc_wacc) { 571 1.1 itohy /* all phase done */ 572 1.1 itohy mmemstart_bp(sc); /* start verify */ 573 1.1 itohy } else if (++sc->sc_reqw.phase == sc->sc_wacc) { 574 1.1 itohy /* check error */ 575 1.1 itohy maple_command(sc->sc_parent, sc->sc_unit, 576 1.1 itohy MAPLE_FN_MEMCARD, MAPLE_COMMAND_GETLASTERR, 577 1.1 itohy 2 /* no data */ , &sc->sc_reqw, 578 1.1 itohy MAPLE_FLAG_CMD_PERIODIC_TIMING); 579 1.1 itohy } else { 580 1.1 itohy /* go next phase */ 581 1.5 tsutsui memcpy(sc->sc_reqw.data, sc->sc_iobuf + 582 1.5 tsutsui sc->sc_waccsz * sc->sc_reqw.phase, 583 1.5 tsutsui sc->sc_waccsz); 584 1.1 itohy maple_command(sc->sc_parent, sc->sc_unit, 585 1.1 itohy MAPLE_FN_MEMCARD, MAPLE_COMMAND_BWRITE, 586 1.1 itohy MMEM_SIZE_REQW(sc) / 4, &sc->sc_reqw, 587 1.1 itohy MAPLE_FLAG_CMD_PERIODIC_TIMING); 588 1.1 itohy } 589 1.1 itohy break; 590 1.1 itohy case MAPLE_RESPONSE_FILEERR: 591 1.1 itohy mmem_printerror(sc->sc_pt[sc->sc_reqw.pt].pt_name, 592 1.1 itohy 0, bp->b_rawblkno, 593 1.1 itohy r->func_code /* XXX */); 594 1.1 itohy mmemstart_write2(sc); /* retry writing */ 595 1.1 itohy break; 596 1.1 itohy default: 597 1.1 itohy printf("%s: write: unexpected response %#x, %#x, sz %d\n", 598 1.1 itohy sc->sc_pt[sc->sc_reqw.pt].pt_name, 599 1.5 tsutsui be32toh(response->response_code), 600 1.5 tsutsui be32toh(r->func_code), sz); 601 1.1 itohy mmemstart_write2(sc); /* retry writing */ 602 1.1 itohy break; 603 1.1 itohy } 604 1.1 itohy break; 605 1.1 itohy 606 1.1 itohy default: 607 1.1 itohy break; 608 1.1 itohy } 609 1.1 itohy } 610 1.1 itohy 611 1.1 itohy static void 612 1.5 tsutsui mmem_printerror(const char *head, int rd, int blk, uint32_t code) 613 1.1 itohy { 614 1.1 itohy 615 1.1 itohy printf("%s: error %sing blk %d:", head, rd? "read" : "writ", blk); 616 1.1 itohy NTOHL(code); 617 1.1 itohy if (code & 1) 618 1.1 itohy printf(" PT error"); 619 1.1 itohy if (code & 2) 620 1.1 itohy printf(" Phase error"); 621 1.1 itohy if (code & 4) 622 1.1 itohy printf(" Block error"); 623 1.1 itohy if (code & 010) 624 1.1 itohy printf(" Write error"); 625 1.1 itohy if (code & 020) 626 1.1 itohy printf(" Length error"); 627 1.1 itohy if (code & 040) 628 1.1 itohy printf(" CRC error"); 629 1.1 itohy if (code & ~077) 630 1.1 itohy printf(" Unknown error %#x", code & ~077); 631 1.1 itohy printf("\n"); 632 1.1 itohy } 633 1.1 itohy 634 1.1 itohy int 635 1.7 christos mmemopen(dev_t dev, int flags, int devtype, struct lwp *l) 636 1.1 itohy { 637 1.1 itohy int diskunit, unit, part, labelpart; 638 1.1 itohy struct mmem_softc *sc; 639 1.1 itohy struct mmem_pt *pt; 640 1.1 itohy 641 1.1 itohy diskunit = DISKUNIT(dev); 642 1.1 itohy unit = MMEM_UNIT(diskunit); 643 1.1 itohy part = MMEM_PART(diskunit); 644 1.1 itohy labelpart = DISKPART(dev); 645 1.16 tsutsui if ((sc = device_lookup_private(&mmem_cd, unit)) == NULL 646 1.1 itohy || sc->sc_stat == MMEM_INIT 647 1.1 itohy || sc->sc_stat == MMEM_INIT2 648 1.1 itohy || part >= sc->sc_npt || (pt = &sc->sc_pt[part])->pt_flags == 0) 649 1.1 itohy return ENXIO; 650 1.1 itohy 651 1.1 itohy switch (devtype) { 652 1.1 itohy case S_IFCHR: 653 1.1 itohy pt->pt_dk.dk_copenmask |= (1 << labelpart); 654 1.1 itohy break; 655 1.1 itohy case S_IFBLK: 656 1.1 itohy pt->pt_dk.dk_bopenmask |= (1 << labelpart); 657 1.1 itohy break; 658 1.1 itohy } 659 1.1 itohy 660 1.1 itohy return 0; 661 1.1 itohy } 662 1.1 itohy 663 1.1 itohy int 664 1.7 christos mmemclose(dev_t dev, int flags, int devtype, struct lwp *l) 665 1.1 itohy { 666 1.1 itohy int diskunit, unit, part, labelpart; 667 1.1 itohy struct mmem_softc *sc; 668 1.1 itohy struct mmem_pt *pt; 669 1.1 itohy 670 1.1 itohy diskunit = DISKUNIT(dev); 671 1.1 itohy unit = MMEM_UNIT(diskunit); 672 1.1 itohy part = MMEM_PART(diskunit); 673 1.17 tsutsui sc = device_lookup_private(&mmem_cd, unit); 674 1.1 itohy pt = &sc->sc_pt[part]; 675 1.1 itohy labelpart = DISKPART(dev); 676 1.1 itohy 677 1.1 itohy switch (devtype) { 678 1.1 itohy case S_IFCHR: 679 1.1 itohy pt->pt_dk.dk_copenmask &= ~(1 << labelpart); 680 1.1 itohy break; 681 1.1 itohy case S_IFBLK: 682 1.1 itohy pt->pt_dk.dk_bopenmask &= ~(1 << labelpart); 683 1.1 itohy break; 684 1.1 itohy } 685 1.1 itohy 686 1.1 itohy return 0; 687 1.1 itohy } 688 1.1 itohy 689 1.1 itohy void 690 1.5 tsutsui mmemstrategy(struct buf *bp) 691 1.1 itohy { 692 1.1 itohy int diskunit, unit, part, labelpart; 693 1.1 itohy struct mmem_softc *sc; 694 1.1 itohy struct mmem_pt *pt; 695 1.1 itohy daddr_t off, nblk, cnt; 696 1.1 itohy 697 1.1 itohy diskunit = DISKUNIT(bp->b_dev); 698 1.1 itohy unit = MMEM_UNIT(diskunit); 699 1.1 itohy part = MMEM_PART(diskunit); 700 1.16 tsutsui if ((sc = device_lookup_private(&mmem_cd, unit)) == NULL 701 1.2 itohy || sc->sc_stat == MMEM_INIT 702 1.2 itohy || sc->sc_stat == MMEM_INIT2 703 1.2 itohy || part >= sc->sc_npt || (pt = &sc->sc_pt[part])->pt_flags == 0) 704 1.2 itohy goto inval; 705 1.1 itohy 706 1.1 itohy #if 0 707 1.1 itohy printf("%s: mmemstrategy: blkno %d, count %ld\n", 708 1.1 itohy pt->pt_name, bp->b_blkno, bp->b_bcount); 709 1.1 itohy #endif 710 1.1 itohy 711 1.1 itohy if (bp->b_flags & B_READ) { 712 1.1 itohy if (sc->sc_racc == 0) 713 1.1 itohy goto inval; /* no read */ 714 1.1 itohy } else if (sc->sc_wacc == 0) { 715 1.1 itohy bp->b_error = EROFS; /* no write */ 716 1.11 ad goto done; 717 1.1 itohy } 718 1.1 itohy 719 1.1 itohy if (bp->b_blkno & ~(~(daddr_t)0 >> (DEV_BSHIFT + 1 /* sign bit */)) 720 1.1 itohy || (bp->b_bcount % sc->sc_bsize) != 0) 721 1.1 itohy goto inval; 722 1.1 itohy 723 1.1 itohy cnt = howmany(bp->b_bcount, sc->sc_bsize); 724 1.1 itohy if (cnt == 0) 725 1.1 itohy goto done; /* no work */ 726 1.1 itohy 727 1.1 itohy off = bp->b_blkno * DEV_BSIZE / sc->sc_bsize; 728 1.1 itohy 729 1.1 itohy /* offset to disklabel partition */ 730 1.1 itohy labelpart = DISKPART(bp->b_dev); 731 1.1 itohy if (labelpart == RAW_PART) { 732 1.1 itohy nblk = pt->pt_info.maxblk - pt->pt_info.minblk + 1; 733 1.1 itohy } else { 734 1.1 itohy off += 735 1.1 itohy nblk = pt->pt_dk.dk_label->d_partitions[labelpart].p_offset; 736 1.1 itohy nblk += pt->pt_dk.dk_label->d_partitions[labelpart].p_size; 737 1.1 itohy } 738 1.1 itohy 739 1.1 itohy /* deal with the EOF condition */ 740 1.1 itohy if (off + cnt > nblk) { 741 1.1 itohy if (off >= nblk) { 742 1.1 itohy if (off == nblk) 743 1.1 itohy goto done; 744 1.1 itohy goto inval; 745 1.1 itohy } 746 1.1 itohy cnt = nblk - off; 747 1.1 itohy bp->b_resid = bp->b_bcount - (cnt * sc->sc_bsize); 748 1.1 itohy } 749 1.1 itohy 750 1.1 itohy bp->b_rawblkno = off; 751 1.1 itohy 752 1.1 itohy /* queue this transfer */ 753 1.18 yamt bufq_put(sc->sc_q, bp); 754 1.1 itohy 755 1.1 itohy if (sc->sc_stat == MMEM_IDLE) 756 1.1 itohy mmemstart(sc); 757 1.1 itohy 758 1.1 itohy return; 759 1.1 itohy 760 1.1 itohy inval: bp->b_error = EINVAL; 761 1.1 itohy done: bp->b_resid = bp->b_bcount; 762 1.1 itohy biodone(bp); 763 1.1 itohy } 764 1.1 itohy 765 1.1 itohy /* 766 1.1 itohy * start I/O operations 767 1.1 itohy */ 768 1.1 itohy static void 769 1.5 tsutsui mmemstart(struct mmem_softc *sc) 770 1.1 itohy { 771 1.1 itohy struct buf *bp; 772 1.1 itohy struct mmem_pt *pt; 773 1.1 itohy int s; 774 1.1 itohy 775 1.18 yamt if ((bp = bufq_get(sc->sc_q)) == NULL) { 776 1.1 itohy sc->sc_stat = MMEM_IDLE; 777 1.1 itohy maple_enable_unit_ping(sc->sc_parent, sc->sc_unit, 778 1.1 itohy MAPLE_FN_MEMCARD, 1); 779 1.1 itohy return; 780 1.1 itohy } 781 1.1 itohy 782 1.1 itohy sc->sc_bp = bp; 783 1.1 itohy sc->sc_cnt = howmany(bp->b_bcount - bp->b_resid, sc->sc_bsize); 784 1.1 itohy KASSERT(sc->sc_cnt); 785 1.1 itohy sc->sc_iobuf = bp->b_data; 786 1.1 itohy sc->sc_retry = 0; 787 1.1 itohy 788 1.1 itohy pt = &sc->sc_pt[MMEM_PART(DISKUNIT(bp->b_dev))]; 789 1.1 itohy s = splbio(); 790 1.1 itohy disk_busy(&pt->pt_dk); 791 1.1 itohy splx(s); 792 1.1 itohy 793 1.1 itohy /* 794 1.1 itohy * I/O access will fail if the removal detection (by maple driver) 795 1.1 itohy * occurs before finishing the I/O, so disable it. 796 1.1 itohy * We are sending commands, and the removal detection is still alive. 797 1.1 itohy */ 798 1.1 itohy maple_enable_unit_ping(sc->sc_parent, sc->sc_unit, MAPLE_FN_MEMCARD, 0); 799 1.1 itohy 800 1.1 itohy mmemstart_bp(sc); 801 1.1 itohy } 802 1.1 itohy 803 1.1 itohy /* 804 1.1 itohy * start/retry a specified I/O operation 805 1.1 itohy */ 806 1.1 itohy static void 807 1.5 tsutsui mmemstart_bp(struct mmem_softc *sc) 808 1.1 itohy { 809 1.1 itohy struct buf *bp; 810 1.1 itohy int diskunit, part; 811 1.1 itohy struct mmem_pt *pt; 812 1.1 itohy 813 1.1 itohy bp = sc->sc_bp; 814 1.1 itohy diskunit = DISKUNIT(bp->b_dev); 815 1.1 itohy part = MMEM_PART(diskunit); 816 1.1 itohy pt = &sc->sc_pt[part]; 817 1.1 itohy 818 1.1 itohy /* handle retry */ 819 1.1 itohy if (sc->sc_retry++ > MMEM_MAXRETRY) { 820 1.1 itohy /* retry count exceeded */ 821 1.2 itohy mmemdone(sc, pt, EIO); 822 1.1 itohy return; 823 1.1 itohy } 824 1.1 itohy 825 1.1 itohy /* 826 1.1 itohy * Start the first phase (phase# = 0). 827 1.1 itohy */ 828 1.1 itohy /* start read */ 829 1.1 itohy sc->sc_stat = (bp->b_flags & B_READ) ? MMEM_READ : MMEM_WRITE1; 830 1.5 tsutsui sc->sc_reqr.func_code = htobe32(MAPLE_FUNC(MAPLE_FN_MEMCARD)); 831 1.1 itohy sc->sc_reqr.pt = part; 832 1.5 tsutsui sc->sc_reqr.block = htobe16(bp->b_rawblkno); 833 1.1 itohy sc->sc_reqr.phase = 0; /* first phase */ 834 1.1 itohy maple_command(sc->sc_parent, sc->sc_unit, MAPLE_FN_MEMCARD, 835 1.1 itohy MAPLE_COMMAND_BREAD, sizeof sc->sc_reqr / 4, &sc->sc_reqr, 0); 836 1.1 itohy } 837 1.1 itohy 838 1.1 itohy static void 839 1.5 tsutsui mmemstart_write2(struct mmem_softc *sc) 840 1.1 itohy { 841 1.1 itohy struct buf *bp; 842 1.1 itohy int diskunit, part; 843 1.1 itohy struct mmem_pt *pt; 844 1.1 itohy 845 1.1 itohy bp = sc->sc_bp; 846 1.1 itohy diskunit = DISKUNIT(bp->b_dev); 847 1.1 itohy part = MMEM_PART(diskunit); 848 1.1 itohy pt = &sc->sc_pt[part]; 849 1.1 itohy 850 1.1 itohy /* handle retry */ 851 1.1 itohy if (sc->sc_retry++ > MMEM_MAXRETRY - 2 /* spare for verify read */) { 852 1.1 itohy /* retry count exceeded */ 853 1.2 itohy mmemdone(sc, pt, EIO); 854 1.1 itohy return; 855 1.1 itohy } 856 1.1 itohy 857 1.1 itohy /* 858 1.1 itohy * Start the first phase (phase# = 0). 859 1.1 itohy */ 860 1.1 itohy /* start write */ 861 1.1 itohy sc->sc_stat = MMEM_WRITE2; 862 1.5 tsutsui sc->sc_reqw.func_code = htobe32(MAPLE_FUNC(MAPLE_FN_MEMCARD)); 863 1.1 itohy sc->sc_reqw.pt = part; 864 1.5 tsutsui sc->sc_reqw.block = htobe16(bp->b_rawblkno); 865 1.1 itohy sc->sc_reqw.phase = 0; /* first phase */ 866 1.5 tsutsui memcpy(sc->sc_reqw.data, sc->sc_iobuf /* + sc->sc_waccsz * phase */, 867 1.5 tsutsui sc->sc_waccsz); 868 1.1 itohy maple_command(sc->sc_parent, sc->sc_unit, MAPLE_FN_MEMCARD, 869 1.1 itohy MAPLE_COMMAND_BWRITE, MMEM_SIZE_REQW(sc) / 4, &sc->sc_reqw, 870 1.1 itohy MAPLE_FLAG_CMD_PERIODIC_TIMING); 871 1.1 itohy } 872 1.1 itohy 873 1.1 itohy static void 874 1.5 tsutsui mmemdone(struct mmem_softc *sc, struct mmem_pt *pt, int err) 875 1.1 itohy { 876 1.1 itohy struct buf *bp = sc->sc_bp; 877 1.1 itohy int s; 878 1.1 itohy int bcnt; 879 1.1 itohy 880 1.1 itohy KASSERT(bp); 881 1.1 itohy 882 1.1 itohy if (err) { 883 1.10 he bcnt = (char *)sc->sc_iobuf - (char *)bp->b_data; 884 1.1 itohy bp->b_resid = bp->b_bcount - bcnt; 885 1.1 itohy 886 1.1 itohy /* raise error if no block is read */ 887 1.1 itohy if (bcnt == 0) { 888 1.2 itohy bp->b_error = err; 889 1.1 itohy } 890 1.1 itohy goto term_xfer; 891 1.1 itohy } 892 1.1 itohy 893 1.1 itohy sc->sc_iobuf += sc->sc_bsize; 894 1.1 itohy if (--sc->sc_cnt == 0) { 895 1.1 itohy term_xfer: 896 1.1 itohy /* terminate current transfer */ 897 1.1 itohy sc->sc_bp = NULL; 898 1.1 itohy s = splbio(); 899 1.10 he disk_unbusy(&pt->pt_dk, 900 1.10 he (char *)sc->sc_iobuf - (char *)bp->b_data, 901 1.1 itohy sc->sc_stat == MMEM_READ); 902 1.1 itohy biodone(bp); 903 1.1 itohy splx(s); 904 1.1 itohy 905 1.1 itohy /* go next transfer */ 906 1.1 itohy mmemstart(sc); 907 1.1 itohy } else { 908 1.1 itohy /* go next block */ 909 1.1 itohy bp->b_rawblkno++; 910 1.1 itohy sc->sc_retry = 0; 911 1.1 itohy mmemstart_bp(sc); 912 1.1 itohy } 913 1.1 itohy } 914 1.1 itohy 915 1.1 itohy int 916 1.5 tsutsui mmemread(dev_t dev, struct uio *uio, int flags) 917 1.1 itohy { 918 1.1 itohy 919 1.5 tsutsui return physio(mmemstrategy, NULL, dev, B_READ, minphys, uio); 920 1.1 itohy } 921 1.1 itohy 922 1.1 itohy int 923 1.5 tsutsui mmemwrite(dev_t dev, struct uio *uio, int flags) 924 1.1 itohy { 925 1.1 itohy 926 1.5 tsutsui return physio(mmemstrategy, NULL, dev, B_WRITE, minphys, uio); 927 1.1 itohy } 928 1.1 itohy 929 1.1 itohy int 930 1.9 christos mmemioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 931 1.1 itohy { 932 1.1 itohy int diskunit, unit, part; 933 1.1 itohy struct mmem_softc *sc; 934 1.1 itohy struct mmem_pt *pt; 935 1.1 itohy 936 1.1 itohy diskunit = DISKUNIT(dev); 937 1.1 itohy unit = MMEM_UNIT(diskunit); 938 1.1 itohy part = MMEM_PART(diskunit); 939 1.17 tsutsui sc = device_lookup_private(&mmem_cd, unit); 940 1.1 itohy pt = &sc->sc_pt[part]; 941 1.1 itohy 942 1.1 itohy switch (cmd) { 943 1.1 itohy case DIOCGDINFO: 944 1.1 itohy *(struct disklabel *)data = *pt->pt_dk.dk_label; /* XXX */ 945 1.1 itohy break; 946 1.1 itohy 947 1.1 itohy default: 948 1.1 itohy /* generic maple ioctl */ 949 1.1 itohy return maple_unit_ioctl(sc->sc_parent, sc->sc_unit, cmd, data, 950 1.7 christos flag, l); 951 1.1 itohy } 952 1.1 itohy 953 1.1 itohy return 0; 954 1.1 itohy } 955