1 /* 2 * Copyright (C) 2003 3 * Hidetoshi Shimokawa. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * 16 * This product includes software developed by Hidetoshi Shimokawa. 17 * 18 * 4. Neither the name of the author nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * $Id: dcons_crom.c,v 1.8 2003/10/23 15:47:21 simokawa Exp $ 35 * $FreeBSD$ 36 */ 37 38 #include <sys/param.h> 39 #include <sys/kernel.h> 40 #include <sys/module.h> 41 #include <sys/systm.h> 42 #include <sys/types.h> 43 #include <sys/conf.h> 44 #include <sys/malloc.h> 45 46 #include <sys/bus.h> 47 #include <machine/bus.h> 48 49 #include <dev/firewire/firewire.h> 50 #include <dev/firewire/firewirereg.h> 51 #include <dev/firewire/iec13213.h> 52 #include <dev/dcons/dcons.h> 53 54 #include <sys/cons.h> 55 56 static bus_addr_t dcons_paddr; 57 58 #if __FreeBSD_version >= 500000 59 static int force_console = 1; 60 TUNABLE_INT("hw.firewire.dcons_crom.force_console", &force_console); 61 #endif 62 63 #ifndef CSRVAL_VENDOR_PRIVATE 64 #define NEED_NEW_DRIVER 65 #endif 66 67 #define ADDR_HI(x) (((x) >> 24) & 0xffffff) 68 #define ADDR_LO(x) ((x) & 0xffffff) 69 70 struct dcons_crom_softc { 71 struct firewire_dev_comm fd; 72 struct crom_chunk unit; 73 struct crom_chunk spec; 74 struct crom_chunk ver; 75 bus_dma_tag_t dma_tag; 76 bus_dmamap_t dma_map; 77 bus_addr_t bus_addr; 78 }; 79 80 static void 81 dcons_crom_identify(driver_t *driver, device_t parent) 82 { 83 BUS_ADD_CHILD(parent, 0, "dcons_crom", device_get_unit(parent)); 84 } 85 86 static int 87 dcons_crom_probe(device_t dev) 88 { 89 device_t pa; 90 91 pa = device_get_parent(dev); 92 if(device_get_unit(dev) != device_get_unit(pa)){ 93 return(ENXIO); 94 } 95 96 device_set_desc(dev, "dcons configuration ROM"); 97 return (0); 98 } 99 100 #ifndef NEED_NEW_DRIVER 101 static void 102 dcons_crom_post_busreset(void *arg) 103 { 104 struct dcons_crom_softc *sc; 105 struct crom_src *src; 106 struct crom_chunk *root; 107 108 sc = (struct dcons_crom_softc *) arg; 109 src = sc->fd.fc->crom_src; 110 root = sc->fd.fc->crom_root; 111 112 bzero(&sc->unit, sizeof(struct crom_chunk)); 113 114 crom_add_chunk(src, root, &sc->unit, CROM_UDIR); 115 crom_add_entry(&sc->unit, CSRKEY_SPEC, CSRVAL_VENDOR_PRIVATE); 116 crom_add_simple_text(src, &sc->unit, &sc->spec, "FreeBSD"); 117 crom_add_entry(&sc->unit, CSRKEY_VER, DCONS_CSR_VAL_VER); 118 crom_add_simple_text(src, &sc->unit, &sc->ver, "dcons"); 119 crom_add_entry(&sc->unit, DCONS_CSR_KEY_HI, ADDR_HI(dcons_paddr)); 120 crom_add_entry(&sc->unit, DCONS_CSR_KEY_LO, ADDR_LO(dcons_paddr)); 121 } 122 #endif 123 124 static void 125 dmamap_cb(void *arg, bus_dma_segment_t *segments, int seg, int error) 126 { 127 struct dcons_crom_softc *sc; 128 129 if (error) 130 printf("dcons_dmamap_cb: error=%d\n", error); 131 132 sc = (struct dcons_crom_softc *)arg; 133 sc->bus_addr = segments[0].ds_addr; 134 135 bus_dmamap_sync(sc->dma_tag, sc->dma_map, BUS_DMASYNC_PREWRITE); 136 device_printf(sc->fd.dev, 137 #if __FreeBSD_version < 500000 138 "bus_addr 0x%x\n", sc->bus_addr); 139 #else 140 "bus_addr 0x%jx\n", (uintmax_t)sc->bus_addr); 141 #endif 142 if (dcons_paddr != 0) { 143 /* XXX */ 144 device_printf(sc->fd.dev, "dcons_paddr is already set\n"); 145 return; 146 } 147 dcons_conf->dma_tag = sc->dma_tag; 148 dcons_conf->dma_map = sc->dma_map; 149 dcons_paddr = sc->bus_addr; 150 151 #if __FreeBSD_version >= 500000 152 /* Force to be the high-level console */ 153 if (force_console) 154 cnselect(dcons_conf->cdev); 155 #endif 156 } 157 158 static int 159 dcons_crom_attach(device_t dev) 160 { 161 #ifdef NEED_NEW_DRIVER 162 printf("dcons_crom: you need newer firewire driver\n"); 163 return (-1); 164 #else 165 struct dcons_crom_softc *sc; 166 167 sc = (struct dcons_crom_softc *) device_get_softc(dev); 168 sc->fd.fc = device_get_ivars(dev); 169 sc->fd.dev = dev; 170 sc->fd.post_explore = NULL; 171 sc->fd.post_busreset = (void *) dcons_crom_post_busreset; 172 173 /* map dcons buffer */ 174 bus_dma_tag_create( 175 /*parent*/ sc->fd.fc->dmat, 176 /*alignment*/ sizeof(u_int32_t), 177 /*boundary*/ 0, 178 /*lowaddr*/ BUS_SPACE_MAXADDR, 179 /*highaddr*/ BUS_SPACE_MAXADDR, 180 /*filter*/NULL, /*filterarg*/NULL, 181 /*maxsize*/ dcons_conf->size, 182 /*nsegments*/ 1, 183 /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 184 /*flags*/ BUS_DMA_ALLOCNOW, 185 #if __FreeBSD_version >= 501102 186 /*lockfunc*/busdma_lock_mutex, 187 /*lockarg*/&Giant, 188 #endif 189 &sc->dma_tag); 190 bus_dmamap_create(sc->dma_tag, 0, &sc->dma_map); 191 bus_dmamap_load(sc->dma_tag, sc->dma_map, 192 (void *)dcons_conf->buf, dcons_conf->size, 193 dmamap_cb, sc, 0); 194 return (0); 195 #endif 196 } 197 198 static int 199 dcons_crom_detach(device_t dev) 200 { 201 struct dcons_crom_softc *sc; 202 203 sc = (struct dcons_crom_softc *) device_get_softc(dev); 204 sc->fd.post_busreset = NULL; 205 206 /* XXX */ 207 if (dcons_conf->dma_tag == sc->dma_tag) 208 dcons_conf->dma_tag = NULL; 209 210 bus_dmamap_unload(sc->dma_tag, sc->dma_map); 211 bus_dmamap_destroy(sc->dma_tag, sc->dma_map); 212 bus_dma_tag_destroy(sc->dma_tag); 213 214 return 0; 215 } 216 217 static devclass_t dcons_crom_devclass; 218 219 static device_method_t dcons_crom_methods[] = { 220 /* device interface */ 221 DEVMETHOD(device_identify, dcons_crom_identify), 222 DEVMETHOD(device_probe, dcons_crom_probe), 223 DEVMETHOD(device_attach, dcons_crom_attach), 224 DEVMETHOD(device_detach, dcons_crom_detach), 225 { 0, 0 } 226 }; 227 228 static driver_t dcons_crom_driver = { 229 "dcons_crom", 230 dcons_crom_methods, 231 sizeof(struct dcons_crom_softc), 232 }; 233 234 DRIVER_MODULE(dcons_crom, firewire, dcons_crom_driver, 235 dcons_crom_devclass, 0, 0); 236 MODULE_VERSION(dcons_crom, 1); 237 MODULE_DEPEND(dcons_crom, dcons, 238 DCONS_VERSION, DCONS_VERSION, DCONS_VERSION); 239 MODULE_DEPEND(dcons_crom, firewire, 1, 1, 1); 240