16265f26aSHidetoshi Shimokawa /*
26265f26aSHidetoshi Shimokawa * Copyright (C) 2003
36265f26aSHidetoshi Shimokawa * Hidetoshi Shimokawa. All rights reserved.
46265f26aSHidetoshi Shimokawa *
56265f26aSHidetoshi Shimokawa * Redistribution and use in source and binary forms, with or without
66265f26aSHidetoshi Shimokawa * modification, are permitted provided that the following conditions
76265f26aSHidetoshi Shimokawa * are met:
86265f26aSHidetoshi Shimokawa * 1. Redistributions of source code must retain the above copyright
96265f26aSHidetoshi Shimokawa * notice, this list of conditions and the following disclaimer.
106265f26aSHidetoshi Shimokawa * 2. Redistributions in binary form must reproduce the above copyright
116265f26aSHidetoshi Shimokawa * notice, this list of conditions and the following disclaimer in the
126265f26aSHidetoshi Shimokawa * documentation and/or other materials provided with the distribution.
136265f26aSHidetoshi Shimokawa * 3. All advertising materials mentioning features or use of this software
146265f26aSHidetoshi Shimokawa * must display the following acknowledgement:
156265f26aSHidetoshi Shimokawa *
166265f26aSHidetoshi Shimokawa * This product includes software developed by Hidetoshi Shimokawa.
176265f26aSHidetoshi Shimokawa *
186265f26aSHidetoshi Shimokawa * 4. Neither the name of the author nor the names of its contributors
196265f26aSHidetoshi Shimokawa * may be used to endorse or promote products derived from this software
206265f26aSHidetoshi Shimokawa * without specific prior written permission.
216265f26aSHidetoshi Shimokawa *
226265f26aSHidetoshi Shimokawa * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
236265f26aSHidetoshi Shimokawa * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
246265f26aSHidetoshi Shimokawa * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
256265f26aSHidetoshi Shimokawa * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
266265f26aSHidetoshi Shimokawa * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
276265f26aSHidetoshi Shimokawa * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
286265f26aSHidetoshi Shimokawa * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
296265f26aSHidetoshi Shimokawa * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
306265f26aSHidetoshi Shimokawa * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
316265f26aSHidetoshi Shimokawa * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
326265f26aSHidetoshi Shimokawa * SUCH DAMAGE.
336265f26aSHidetoshi Shimokawa *
346265f26aSHidetoshi Shimokawa * $Id: dcons_crom.c,v 1.8 2003/10/23 15:47:21 simokawa Exp $
35d8d65ecaSHidetoshi Shimokawa * $FreeBSD: src/sys/dev/dcons/dcons_crom.c,v 1.5 2004/10/13 05:38:42 simokawa Exp $
366265f26aSHidetoshi Shimokawa */
376265f26aSHidetoshi Shimokawa
386265f26aSHidetoshi Shimokawa #include <sys/param.h>
396265f26aSHidetoshi Shimokawa #include <sys/kernel.h>
406265f26aSHidetoshi Shimokawa #include <sys/module.h>
416265f26aSHidetoshi Shimokawa #include <sys/systm.h>
426265f26aSHidetoshi Shimokawa #include <sys/types.h>
436265f26aSHidetoshi Shimokawa #include <sys/conf.h>
446265f26aSHidetoshi Shimokawa #include <sys/malloc.h>
456265f26aSHidetoshi Shimokawa #include <sys/bus.h>
466265f26aSHidetoshi Shimokawa
476265f26aSHidetoshi Shimokawa #ifdef __DragonFly__
486265f26aSHidetoshi Shimokawa #include <bus/firewire/firewire.h>
496265f26aSHidetoshi Shimokawa #include <bus/firewire/firewirereg.h>
506265f26aSHidetoshi Shimokawa #include <bus/firewire/iec13213.h>
516265f26aSHidetoshi Shimokawa #include "dcons.h"
52d8d65ecaSHidetoshi Shimokawa #include "dcons_os.h"
536265f26aSHidetoshi Shimokawa #else
546265f26aSHidetoshi Shimokawa #include <dev/firewire/firewire.h>
556265f26aSHidetoshi Shimokawa #include <dev/firewire/firewirereg.h>
566265f26aSHidetoshi Shimokawa #include <dev/firewire/iec13213.h>
576265f26aSHidetoshi Shimokawa #include <dev/dcons/dcons.h>
58d8d65ecaSHidetoshi Shimokawa #include <dev/dcons/dcons_os.h>
596265f26aSHidetoshi Shimokawa #endif
606265f26aSHidetoshi Shimokawa
616265f26aSHidetoshi Shimokawa #include <sys/cons.h>
626265f26aSHidetoshi Shimokawa
636265f26aSHidetoshi Shimokawa static bus_addr_t dcons_paddr;
646265f26aSHidetoshi Shimokawa
65*20d3070bSSascha Wildner #if 0 /* XXX __FreeBSD_version >= 500000 */
666265f26aSHidetoshi Shimokawa static int force_console = 1;
676265f26aSHidetoshi Shimokawa TUNABLE_INT("hw.firewire.dcons_crom.force_console", &force_console);
686265f26aSHidetoshi Shimokawa #endif
696265f26aSHidetoshi Shimokawa
706265f26aSHidetoshi Shimokawa #ifndef CSRVAL_VENDOR_PRIVATE
716265f26aSHidetoshi Shimokawa #define NEED_NEW_DRIVER
726265f26aSHidetoshi Shimokawa #endif
736265f26aSHidetoshi Shimokawa
746265f26aSHidetoshi Shimokawa #define ADDR_HI(x) (((x) >> 24) & 0xffffff)
756265f26aSHidetoshi Shimokawa #define ADDR_LO(x) ((x) & 0xffffff)
766265f26aSHidetoshi Shimokawa
776265f26aSHidetoshi Shimokawa struct dcons_crom_softc {
786265f26aSHidetoshi Shimokawa struct firewire_dev_comm fd;
796265f26aSHidetoshi Shimokawa struct crom_chunk unit;
806265f26aSHidetoshi Shimokawa struct crom_chunk spec;
816265f26aSHidetoshi Shimokawa struct crom_chunk ver;
826265f26aSHidetoshi Shimokawa bus_dma_tag_t dma_tag;
836265f26aSHidetoshi Shimokawa bus_dmamap_t dma_map;
846265f26aSHidetoshi Shimokawa bus_addr_t bus_addr;
856265f26aSHidetoshi Shimokawa };
866265f26aSHidetoshi Shimokawa
876265f26aSHidetoshi Shimokawa static int
dcons_crom_probe(device_t dev)886265f26aSHidetoshi Shimokawa dcons_crom_probe(device_t dev)
896265f26aSHidetoshi Shimokawa {
906265f26aSHidetoshi Shimokawa device_t pa;
916265f26aSHidetoshi Shimokawa
926265f26aSHidetoshi Shimokawa pa = device_get_parent(dev);
936265f26aSHidetoshi Shimokawa if(device_get_unit(dev) != device_get_unit(pa)){
946265f26aSHidetoshi Shimokawa return(ENXIO);
956265f26aSHidetoshi Shimokawa }
966265f26aSHidetoshi Shimokawa
976265f26aSHidetoshi Shimokawa device_set_desc(dev, "dcons configuration ROM");
986265f26aSHidetoshi Shimokawa return (0);
996265f26aSHidetoshi Shimokawa }
1006265f26aSHidetoshi Shimokawa
1016265f26aSHidetoshi Shimokawa #ifndef NEED_NEW_DRIVER
1026265f26aSHidetoshi Shimokawa static void
dcons_crom_post_busreset(void * arg)1036265f26aSHidetoshi Shimokawa dcons_crom_post_busreset(void *arg)
1046265f26aSHidetoshi Shimokawa {
1056265f26aSHidetoshi Shimokawa struct dcons_crom_softc *sc;
1066265f26aSHidetoshi Shimokawa struct crom_src *src;
1076265f26aSHidetoshi Shimokawa struct crom_chunk *root;
1086265f26aSHidetoshi Shimokawa
1096265f26aSHidetoshi Shimokawa sc = (struct dcons_crom_softc *) arg;
1106265f26aSHidetoshi Shimokawa src = sc->fd.fc->crom_src;
1116265f26aSHidetoshi Shimokawa root = sc->fd.fc->crom_root;
1126265f26aSHidetoshi Shimokawa
1136265f26aSHidetoshi Shimokawa bzero(&sc->unit, sizeof(struct crom_chunk));
1146265f26aSHidetoshi Shimokawa
1156265f26aSHidetoshi Shimokawa crom_add_chunk(src, root, &sc->unit, CROM_UDIR);
1166265f26aSHidetoshi Shimokawa crom_add_entry(&sc->unit, CSRKEY_SPEC, CSRVAL_VENDOR_PRIVATE);
1176265f26aSHidetoshi Shimokawa crom_add_simple_text(src, &sc->unit, &sc->spec, "FreeBSD");
1186265f26aSHidetoshi Shimokawa crom_add_entry(&sc->unit, CSRKEY_VER, DCONS_CSR_VAL_VER);
1196265f26aSHidetoshi Shimokawa crom_add_simple_text(src, &sc->unit, &sc->ver, "dcons");
1206265f26aSHidetoshi Shimokawa crom_add_entry(&sc->unit, DCONS_CSR_KEY_HI, ADDR_HI(dcons_paddr));
1216265f26aSHidetoshi Shimokawa crom_add_entry(&sc->unit, DCONS_CSR_KEY_LO, ADDR_LO(dcons_paddr));
1226265f26aSHidetoshi Shimokawa }
1236265f26aSHidetoshi Shimokawa #endif
1246265f26aSHidetoshi Shimokawa
1256265f26aSHidetoshi Shimokawa static void
dmamap_cb(void * arg,bus_dma_segment_t * segments,int seg,int error)1266265f26aSHidetoshi Shimokawa dmamap_cb(void *arg, bus_dma_segment_t *segments, int seg, int error)
1276265f26aSHidetoshi Shimokawa {
1286265f26aSHidetoshi Shimokawa struct dcons_crom_softc *sc;
1296265f26aSHidetoshi Shimokawa
1306265f26aSHidetoshi Shimokawa if (error)
131e3869ec7SSascha Wildner kprintf("dcons_dmamap_cb: error=%d\n", error);
1326265f26aSHidetoshi Shimokawa
1336265f26aSHidetoshi Shimokawa sc = (struct dcons_crom_softc *)arg;
1346265f26aSHidetoshi Shimokawa sc->bus_addr = segments[0].ds_addr;
1356265f26aSHidetoshi Shimokawa
1366265f26aSHidetoshi Shimokawa bus_dmamap_sync(sc->dma_tag, sc->dma_map, BUS_DMASYNC_PREWRITE);
137bfc09ba0SMatthew Dillon device_printf(sc->fd.dev, "bus_addr 0x%jx\n",
138bfc09ba0SMatthew Dillon (uintmax_t)sc->bus_addr);
1396265f26aSHidetoshi Shimokawa if (dcons_paddr != 0) {
1406265f26aSHidetoshi Shimokawa /* XXX */
1416265f26aSHidetoshi Shimokawa device_printf(sc->fd.dev, "dcons_paddr is already set\n");
1426265f26aSHidetoshi Shimokawa return;
1436265f26aSHidetoshi Shimokawa }
1446265f26aSHidetoshi Shimokawa dcons_conf->dma_tag = sc->dma_tag;
1456265f26aSHidetoshi Shimokawa dcons_conf->dma_map = sc->dma_map;
1466265f26aSHidetoshi Shimokawa dcons_paddr = sc->bus_addr;
1476265f26aSHidetoshi Shimokawa
148*20d3070bSSascha Wildner #if 0 /* XXX __FreeBSD_version >= 500000 */
1496265f26aSHidetoshi Shimokawa /* Force to be the high-level console */
1506265f26aSHidetoshi Shimokawa if (force_console)
1516265f26aSHidetoshi Shimokawa cnselect(dcons_conf->cdev);
1526265f26aSHidetoshi Shimokawa #endif
1536265f26aSHidetoshi Shimokawa }
1546265f26aSHidetoshi Shimokawa
1556265f26aSHidetoshi Shimokawa static int
dcons_crom_attach(device_t dev)1566265f26aSHidetoshi Shimokawa dcons_crom_attach(device_t dev)
1576265f26aSHidetoshi Shimokawa {
1586265f26aSHidetoshi Shimokawa #ifdef NEED_NEW_DRIVER
159e3869ec7SSascha Wildner kprintf("dcons_crom: you need newer firewire driver\n");
1606265f26aSHidetoshi Shimokawa return (-1);
1616265f26aSHidetoshi Shimokawa #else
1626265f26aSHidetoshi Shimokawa struct dcons_crom_softc *sc;
1636265f26aSHidetoshi Shimokawa
1646265f26aSHidetoshi Shimokawa sc = (struct dcons_crom_softc *) device_get_softc(dev);
1656265f26aSHidetoshi Shimokawa sc->fd.fc = device_get_ivars(dev);
1666265f26aSHidetoshi Shimokawa sc->fd.dev = dev;
1676265f26aSHidetoshi Shimokawa sc->fd.post_explore = NULL;
1686265f26aSHidetoshi Shimokawa sc->fd.post_busreset = (void *) dcons_crom_post_busreset;
1696265f26aSHidetoshi Shimokawa
1706265f26aSHidetoshi Shimokawa /* map dcons buffer */
1716265f26aSHidetoshi Shimokawa bus_dma_tag_create(
1726265f26aSHidetoshi Shimokawa /*parent*/ sc->fd.fc->dmat,
1736265f26aSHidetoshi Shimokawa /*alignment*/ sizeof(u_int32_t),
1746265f26aSHidetoshi Shimokawa /*boundary*/ 0,
1756265f26aSHidetoshi Shimokawa /*lowaddr*/ BUS_SPACE_MAXADDR,
1766265f26aSHidetoshi Shimokawa /*highaddr*/ BUS_SPACE_MAXADDR,
1776265f26aSHidetoshi Shimokawa /*maxsize*/ dcons_conf->size,
1786265f26aSHidetoshi Shimokawa /*nsegments*/ 1,
1796265f26aSHidetoshi Shimokawa /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT,
1806265f26aSHidetoshi Shimokawa /*flags*/ BUS_DMA_ALLOCNOW,
1816265f26aSHidetoshi Shimokawa &sc->dma_tag);
1826265f26aSHidetoshi Shimokawa bus_dmamap_create(sc->dma_tag, 0, &sc->dma_map);
1836265f26aSHidetoshi Shimokawa bus_dmamap_load(sc->dma_tag, sc->dma_map,
1846265f26aSHidetoshi Shimokawa (void *)dcons_conf->buf, dcons_conf->size,
1856265f26aSHidetoshi Shimokawa dmamap_cb, sc, 0);
1866265f26aSHidetoshi Shimokawa return (0);
1876265f26aSHidetoshi Shimokawa #endif
1886265f26aSHidetoshi Shimokawa }
1896265f26aSHidetoshi Shimokawa
1906265f26aSHidetoshi Shimokawa static int
dcons_crom_detach(device_t dev)1916265f26aSHidetoshi Shimokawa dcons_crom_detach(device_t dev)
1926265f26aSHidetoshi Shimokawa {
1936265f26aSHidetoshi Shimokawa struct dcons_crom_softc *sc;
1946265f26aSHidetoshi Shimokawa
1956265f26aSHidetoshi Shimokawa sc = (struct dcons_crom_softc *) device_get_softc(dev);
1966265f26aSHidetoshi Shimokawa sc->fd.post_busreset = NULL;
1976265f26aSHidetoshi Shimokawa
1986265f26aSHidetoshi Shimokawa /* XXX */
1996265f26aSHidetoshi Shimokawa if (dcons_conf->dma_tag == sc->dma_tag)
2006265f26aSHidetoshi Shimokawa dcons_conf->dma_tag = NULL;
2016265f26aSHidetoshi Shimokawa
2026265f26aSHidetoshi Shimokawa bus_dmamap_unload(sc->dma_tag, sc->dma_map);
2036265f26aSHidetoshi Shimokawa bus_dmamap_destroy(sc->dma_tag, sc->dma_map);
2046265f26aSHidetoshi Shimokawa bus_dma_tag_destroy(sc->dma_tag);
2056265f26aSHidetoshi Shimokawa
2066265f26aSHidetoshi Shimokawa return 0;
2076265f26aSHidetoshi Shimokawa }
2086265f26aSHidetoshi Shimokawa
20939b5d600SMatthew Dillon /*
21039b5d600SMatthew Dillon * Because dcons_crom is a static device that always exists under any attached
21139b5d600SMatthew Dillon * firewire device, and not scanned by the firewire device, we need an
21239b5d600SMatthew Dillon * identify function to install the device. For our sanity we want
21339b5d600SMatthew Dillon * the sbp device to have the same unit number as the fireweire device.
21439b5d600SMatthew Dillon */
2156265f26aSHidetoshi Shimokawa static devclass_t dcons_crom_devclass;
2166265f26aSHidetoshi Shimokawa
2176265f26aSHidetoshi Shimokawa static device_method_t dcons_crom_methods[] = {
2186265f26aSHidetoshi Shimokawa /* device interface */
21939b5d600SMatthew Dillon DEVMETHOD(device_identify, bus_generic_identify_sameunit),
2206265f26aSHidetoshi Shimokawa DEVMETHOD(device_probe, dcons_crom_probe),
2216265f26aSHidetoshi Shimokawa DEVMETHOD(device_attach, dcons_crom_attach),
2226265f26aSHidetoshi Shimokawa DEVMETHOD(device_detach, dcons_crom_detach),
223d3c9c58eSSascha Wildner DEVMETHOD_END
2246265f26aSHidetoshi Shimokawa };
2256265f26aSHidetoshi Shimokawa
2266265f26aSHidetoshi Shimokawa static driver_t dcons_crom_driver = {
2276265f26aSHidetoshi Shimokawa "dcons_crom",
2286265f26aSHidetoshi Shimokawa dcons_crom_methods,
2296265f26aSHidetoshi Shimokawa sizeof(struct dcons_crom_softc),
2306265f26aSHidetoshi Shimokawa };
2316265f26aSHidetoshi Shimokawa
2326265f26aSHidetoshi Shimokawa DRIVER_MODULE(dcons_crom, firewire, dcons_crom_driver,
233aa6ac96eSSascha Wildner dcons_crom_devclass, NULL, NULL);
2346265f26aSHidetoshi Shimokawa MODULE_VERSION(dcons_crom, 1);
2356265f26aSHidetoshi Shimokawa MODULE_DEPEND(dcons_crom, dcons,
2366265f26aSHidetoshi Shimokawa DCONS_VERSION, DCONS_VERSION, DCONS_VERSION);
2376265f26aSHidetoshi Shimokawa MODULE_DEPEND(dcons_crom, firewire, 1, 1, 1);
238