2 * Copyright (c) 2004 Hidetoshi Shimokawa <simokawa@FreeBSD.ORG>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
31 * FireWire disk device handling.
37 #include <machine/bootinfo.h>
41 #include <bootstrap.h>
44 #include <dev/firewire/firewire.h>
46 #include <dev/dcons/dcons.h>
49 #define BIT4x2(x,y) uint8_t y:4, x:4
50 #define BIT16x2(x,y) uint32_t y:16, x:16
52 #include <dev/firewire/iec13213.h>
54 extern uint32_t dcons_paddr;
55 extern struct console dconsole;
59 struct crom_chunk root;
60 struct crom_chunk vendor;
63 struct crom_chunk unit;
64 struct crom_chunk spec;
65 struct crom_chunk ver;
68 static int fw_init(void);
69 static int fw_strategy(void *devdata, int flag, daddr_t dblk,
70 size_t size, char *buf, size_t *rsize);
71 static int fw_open(struct open_file *f, ...);
72 static int fw_close(struct open_file *f);
73 static int fw_print(int verbose);
74 static void fw_cleanup(void);
78 struct devsw fwohci = {
79 "FW1394", /* 7 chars at most */
90 static struct fwohci_softc fwinfo[MAX_OHCI];
91 static int fw_initialized = 0;
94 fw_probe(int index, struct fwohci_softc *sc)
98 sc->state = FWOHCI_STATE_INIT;
99 err = biospci_find_devclass(
100 0x0c0010 /* Serial:FireWire:OHCI */,
105 sc->state = FWOHCI_STATE_DEAD;
109 biospci_write_config(sc->locator,
112 0x6 /* enable bus master and memory mapped I/O */);
114 biospci_read_config(sc->locator, 0x00 /*devid*/, BIOSPCI_32BITS,
116 biospci_read_config(sc->locator, 0x10 /*base_addr*/, BIOSPCI_32BITS,
119 sc->handle = (uint32_t)PTOV(sc->base_addr);
120 sc->bus_id = OREAD(sc, OHCI_BUS_ID);
129 struct fwohci_softc *sc;
135 for (i = 0; i < MAX_OHCI; i ++) {
138 if (sc->state == FWOHCI_STATE_DEAD)
150 * Print information about OHCI chips
153 fw_print(int verbose)
157 struct fwohci_softc *sc;
159 printf("%s devices:", fwohci.dv_name);
160 if ((ret = pager_output("\n")) != 0)
163 for (i = 0; i < MAX_OHCI; i ++) {
165 if (sc->state == FWOHCI_STATE_DEAD)
167 snprintf(line, sizeof(line), "%d: locator=0x%04x devid=0x%08x"
168 " base_addr=0x%08x handle=0x%08x bus_id=0x%08x\n",
169 i, sc->locator, sc->devid,
170 sc->base_addr, sc->handle, sc->bus_id);
171 ret = pager_output(line);
179 fw_open(struct open_file *f, ...)
183 struct i386_devdesc *dev;
184 struct open_disk *od;
188 dev = va_arg(ap, struct i386_devdesc *);
196 fw_close(struct open_file *f)
204 struct dcons_buf *db;
206 /* invalidate dcons buffer */
208 db = (struct dcons_buf *)PTOV(dcons_paddr);
214 fw_strategy(void *devdata, int rw, daddr_t dblk, size_t size,
215 char *buf, size_t *rsize)
221 fw_init_crom(struct fwohci_softc *sc)
223 struct crom_src *src;
225 printf("fw_init_crom\n");
226 sc->crom_src_buf = (struct crom_src_buf *)
227 malloc(sizeof(struct crom_src_buf));
228 if (sc->crom_src_buf == NULL)
231 src = &sc->crom_src_buf->src;
232 bzero(src, sizeof(struct crom_src));
234 /* BUS info sample */
235 src->hdr.info_len = 4;
237 src->businfo.bus_name = CSR_BUS_NAME_IEEE1394;
239 src->businfo.irmc = 1;
240 src->businfo.cmc = 1;
241 src->businfo.isc = 1;
242 src->businfo.bmc = 1;
243 src->businfo.pmc = 0;
244 src->businfo.cyc_clk_acc = 100;
245 src->businfo.max_rec = sc->maxrec;
246 src->businfo.max_rom = MAXROM_4;
247 #define FW_GENERATION_CHANGEABLE 2
248 src->businfo.generation = FW_GENERATION_CHANGEABLE;
249 src->businfo.link_spd = sc->speed;
251 src->businfo.eui64.hi = sc->eui.hi;
252 src->businfo.eui64.lo = sc->eui.lo;
254 STAILQ_INIT(&src->chunk_list);
257 sc->crom_root = &sc->crom_src_buf->root;
261 fw_reset_crom(struct fwohci_softc *sc)
263 struct crom_src_buf *buf;
264 struct crom_src *src;
265 struct crom_chunk *root;
267 printf("fw_reset\n");
268 if (sc->crom_src_buf == NULL)
271 buf = sc->crom_src_buf;
273 root = sc->crom_root;
275 STAILQ_INIT(&src->chunk_list);
277 bzero(root, sizeof(struct crom_chunk));
278 crom_add_chunk(src, NULL, root, 0);
279 crom_add_entry(root, CSRKEY_NCAP, 0x0083c0); /* XXX */
280 /* private company_id */
281 crom_add_entry(root, CSRKEY_VENDOR, CSRVAL_VENDOR_PRIVATE);
283 crom_add_simple_text(src, root, &buf->vendor, "DragonFly Project");
285 crom_add_simple_text(src, root, &buf->vendor, "FreeBSD Project");
290 #define ADDR_HI(x) (((x) >> 24) & 0xffffff)
291 #define ADDR_LO(x) ((x) & 0xffffff)
294 dcons_crom(struct fwohci_softc *sc)
296 struct crom_src_buf *buf;
297 struct crom_src *src;
298 struct crom_chunk *root;
300 buf = sc->crom_src_buf;
302 root = sc->crom_root;
304 bzero(&buf->unit, sizeof(struct crom_chunk));
306 crom_add_chunk(src, root, &buf->unit, CROM_UDIR);
307 crom_add_entry(&buf->unit, CSRKEY_SPEC, CSRVAL_VENDOR_PRIVATE);
308 crom_add_simple_text(src, &buf->unit, &buf->spec, "FreeBSD");
309 crom_add_entry(&buf->unit, CSRKEY_VER, DCONS_CSR_VAL_VER);
310 crom_add_simple_text(src, &buf->unit, &buf->ver, "dcons");
311 crom_add_entry(&buf->unit, DCONS_CSR_KEY_HI, ADDR_HI(dcons_paddr));
312 crom_add_entry(&buf->unit, DCONS_CSR_KEY_LO, ADDR_LO(dcons_paddr));
316 fw_crom(struct fwohci_softc *sc)
318 struct crom_src *src;
324 newrom = malloc(CROMSIZE);
325 src = &sc->crom_src_buf->src;
326 crom_load(src, (uint32_t *)newrom, CROMSIZE);
327 if (bcmp(newrom, sc->config_rom, CROMSIZE) != 0) {
328 /* Bump generation and reload. */
329 src->businfo.generation++;
331 /* Handle generation count wraps. */
332 if (src->businfo.generation < 2)
333 src->businfo.generation = 2;
335 /* Recalculate CRC to account for generation change. */
336 crom_load(src, (uint32_t *)newrom, CROMSIZE);
337 bcopy(newrom, (void *)sc->config_rom, CROMSIZE);
343 fw_busreset(struct fwohci_softc *sc)
347 if (sc->state < FWOHCI_STATE_ENABLED) {
348 printf("fwohci not enabled\n");
354 while (sc->state< FWOHCI_STATE_NORMAL) {
358 printf("give up to wait bus initialize\n");
362 printf("poll count = %d\n", count);
369 struct fwohci_softc *sc;
372 if (fw_initialized == 0)
375 for (i = 0; i < MAX_OHCI; i ++) {
377 if (sc->state != FWOHCI_STATE_INIT)
380 sc->config_rom = (uint32_t *)
381 (((uint32_t)sc->config_rom_buf
382 + (CROMSIZE - 1)) & ~(CROMSIZE - 1));
384 printf("configrom: %08p %08p\n",
385 sc->config_rom_buf, sc->config_rom);
387 if (fwohci_init(sc, 0) == 0) {
388 sc->state = FWOHCI_STATE_ENABLED;
391 sc->state = FWOHCI_STATE_DEAD;
398 struct fwohci_softc *sc;
401 if (fw_initialized == 0)
404 for (i = 0; i < MAX_OHCI; i ++) {
406 if (sc->state < FWOHCI_STATE_ENABLED)
412 #if 0 /* for debug */
414 fw_busreset_cmd(int argc, char *argv[])
416 struct fwohci_softc *sc;
419 for (i = 0; i < MAX_OHCI; i ++) {
421 if (sc->state < FWOHCI_STATE_INIT)
429 fw_poll_cmd(int argc, char *argv[])
436 fw_enable_cmd(int argc, char *argv[])
445 dcons_enable(int argc, char *argv[])
449 dconsole.c_flags |= C_ACTIVEIN | C_ACTIVEOUT;
454 dcons_read(int argc, char *argv[])
457 while (dconsole.c_ready()) {
466 dcons_write(int argc, char *argv[])
472 len = strlen(argv[1]);
473 for (i = 0; i < len; i ++)
474 dconsole.c_out(argv[1][i]);
475 dconsole.c_out('\r');
476 dconsole.c_out('\n');
479 COMMAND_SET(firewire, "firewire", "enable firewire", fw_enable_cmd);
480 COMMAND_SET(fwbusreset, "fwbusreset", "firewire busreset", fw_busreset_cmd);
481 COMMAND_SET(fwpoll, "fwpoll", "firewire poll", fw_poll_cmd);
482 COMMAND_SET(dcons, "dcons", "enable dcons", dcons_enable);
483 COMMAND_SET(dread, "dread", "read from dcons", dcons_read);
484 COMMAND_SET(dwrite, "dwrite", "write to dcons", dcons_write);