1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2012 Robert N. M. Watson 5 * All rights reserved. 6 * 7 * This software was developed by SRI International and the University of 8 * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) 9 * ("CTSRD"), as part of the DARPA CRASH research programme. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 __FBSDID("$FreeBSD$"); 35 36 #include <sys/param.h> 37 #include <sys/bus.h> 38 #include <sys/condvar.h> 39 #include <sys/conf.h> 40 #include <sys/bio.h> 41 #include <sys/kernel.h> 42 #include <sys/lock.h> 43 #include <sys/malloc.h> 44 #include <sys/module.h> 45 #include <sys/mutex.h> 46 #include <sys/rman.h> 47 #include <sys/systm.h> 48 #include <sys/taskqueue.h> 49 50 #include <machine/bus.h> 51 #include <machine/resource.h> 52 53 #include <geom/geom_disk.h> 54 55 #include <dev/altera/sdcard/altera_sdcard.h> 56 57 static int 58 altera_sdcard_disk_dump(void *arg, void *virtual, vm_offset_t physical, 59 off_t offset, size_t length) 60 { 61 62 panic("%s: not yet", __func__); 63 } 64 65 static int 66 altera_sdcard_disk_ioctl(struct disk *disk, u_long cmd, void *data, int fflag, 67 struct thread *td) 68 { 69 70 /* XXXRW: more here? */ 71 return (EINVAL); 72 } 73 74 static void 75 altera_sdcard_disk_strategy(struct bio *bp) 76 { 77 struct altera_sdcard_softc *sc; 78 79 /* 80 * Although the SD Card doesn't need sorting, we don't want to 81 * introduce barriers, so use bioq_disksort(). 82 */ 83 sc = bp->bio_disk->d_drv1; 84 ALTERA_SDCARD_LOCK(sc); 85 switch (sc->as_state) { 86 case ALTERA_SDCARD_STATE_NOCARD: 87 device_printf(sc->as_dev, "%s: unexpected I/O on NOCARD", 88 __func__); 89 biofinish(bp, NULL, ENXIO); 90 break; 91 92 case ALTERA_SDCARD_STATE_BADCARD: 93 device_printf(sc->as_dev, "%s: unexpected I/O on BADCARD", 94 __func__); 95 biofinish(bp, NULL, ENXIO); 96 break; 97 98 case ALTERA_SDCARD_STATE_DETACHED: 99 device_printf(sc->as_dev, "%s: unexpected I/O on DETACHED", 100 __func__); 101 biofinish(bp, NULL, ENXIO); 102 103 case ALTERA_SDCARD_STATE_IDLE: 104 bioq_disksort(&sc->as_bioq, bp); 105 altera_sdcard_start(sc); 106 break; 107 108 case ALTERA_SDCARD_STATE_IO: 109 bioq_disksort(&sc->as_bioq, bp); 110 break; 111 112 default: 113 panic("%s: invalid state %d", __func__, sc->as_state); 114 } 115 ALTERA_SDCARD_UNLOCK(sc); 116 } 117 118 void 119 altera_sdcard_disk_insert(struct altera_sdcard_softc *sc) 120 { 121 struct disk *disk; 122 uint64_t size; 123 124 ALTERA_SDCARD_LOCK_ASSERT(sc); 125 126 /* 127 * Because the disk insertion routine occupies the driver instance's 128 * task queue thread, and the disk(9) instance isn't hooked up yet by 129 * definition, the only other source of events of concern is a thread 130 * initiating driver detach. That thread has to issue a detach 131 * request and await an ACK from the taskqueue thread. It is 132 * therefore safe to drop the lock here. 133 */ 134 ALTERA_SDCARD_UNLOCK(sc); 135 disk = disk_alloc(); 136 disk->d_drv1 = sc; 137 disk->d_name = "altera_sdcard"; 138 disk->d_unit = sc->as_unit; 139 disk->d_strategy = altera_sdcard_disk_strategy; 140 disk->d_dump = altera_sdcard_disk_dump; 141 disk->d_ioctl = altera_sdcard_disk_ioctl; 142 disk->d_sectorsize = ALTERA_SDCARD_SECTORSIZE; 143 disk->d_mediasize = sc->as_mediasize; 144 disk->d_maxsize = ALTERA_SDCARD_SECTORSIZE; 145 sc->as_disk = disk; 146 disk_create(disk, DISK_VERSION); 147 ALTERA_SDCARD_LOCK(sc); 148 149 /* 150 * Print a pretty-ish card insertion string. We could stand to 151 * decorate this further, e.g., with card vendor information. 152 */ 153 size = sc->as_mediasize / (1000 * 1000); 154 device_printf(sc->as_dev, "%juM SD Card inserted\n", (uintmax_t)size); 155 } 156 157 void 158 altera_sdcard_disk_remove(struct altera_sdcard_softc *sc) 159 { 160 struct disk *disk; 161 162 ALTERA_SDCARD_LOCK_ASSERT(sc); 163 KASSERT(sc->as_disk != NULL, ("%s: as_disk NULL", __func__)); 164 165 /* 166 * sc->as_state will be updated by the caller. 167 * 168 * XXXRW: Is it OK to call disk_destroy() under the mutex, or should 169 * we be deferring that to the calling context once it is released? 170 */ 171 disk = sc->as_disk; 172 disk_gone(disk); 173 disk_destroy(disk); 174 sc->as_disk = NULL; 175 176 /* 177 * Cancel all outstanding I/O on the SD Card. 178 */ 179 if (sc->as_currentbio != NULL) { 180 device_printf(sc->as_dev, "%s: SD Card removed during I/O", 181 __func__); 182 biofinish(sc->as_currentbio, NULL, ENXIO); 183 sc->as_currentbio = NULL; 184 } 185 bioq_flush(&sc->as_bioq, NULL, ENXIO); 186 device_printf(sc->as_dev, "SD Card removed\n"); 187 } 188