1170101Ssimokawa/*- 2170101Ssimokawa * Copyright (c) 2004 Hidetoshi Shimokawa <simokawa@FreeBSD.ORG> 3170101Ssimokawa * All rights reserved. 4170101Ssimokawa * 5170101Ssimokawa * Redistribution and use in source and binary forms, with or without 6170101Ssimokawa * modification, are permitted provided that the following conditions 7170101Ssimokawa * are met: 8170101Ssimokawa * 1. Redistributions of source code must retain the above copyright 9170101Ssimokawa * notice, this list of conditions and the following disclaimer. 10170101Ssimokawa * 2. Redistributions in binary form must reproduce the above copyright 11170101Ssimokawa * notice, this list of conditions and the following disclaimer in the 12170101Ssimokawa * documentation and/or other materials provided with the distribution. 13170101Ssimokawa * 14170101Ssimokawa * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15170101Ssimokawa * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16170101Ssimokawa * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17170101Ssimokawa * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18170101Ssimokawa * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19170101Ssimokawa * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20170101Ssimokawa * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21170101Ssimokawa * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22170101Ssimokawa * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23170101Ssimokawa * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24170101Ssimokawa * SUCH DAMAGE. 25170101Ssimokawa */ 26170101Ssimokawa 27170101Ssimokawa#include <sys/cdefs.h> 28170101Ssimokawa__FBSDID("$FreeBSD: releng/10.2/sys/boot/i386/libfirewire/firewire.c 264816 2014-04-23 12:08:20Z brueffer $"); 29170101Ssimokawa 30170101Ssimokawa/* 31170101Ssimokawa * FireWire disk device handling. 32170101Ssimokawa * 33170101Ssimokawa */ 34170101Ssimokawa 35170101Ssimokawa#include <stand.h> 36170101Ssimokawa 37170101Ssimokawa#include <machine/bootinfo.h> 38170101Ssimokawa 39170101Ssimokawa#include <stdarg.h> 40170101Ssimokawa 41170101Ssimokawa#include <bootstrap.h> 42170101Ssimokawa#include <btxv86.h> 43170101Ssimokawa#include <libi386.h> 44170101Ssimokawa#include "fwohci.h" 45170101Ssimokawa#include <dev/dcons/dcons.h> 46170101Ssimokawa 47170101Ssimokawa/* XXX */ 48170101Ssimokawa#define BIT4x2(x,y) uint8_t y:4, x:4 49170101Ssimokawa#define BIT16x2(x,y) uint32_t y:16, x:16 50170101Ssimokawa#define _KERNEL 51170101Ssimokawa#include <dev/firewire/iec13213.h> 52170101Ssimokawa 53170101Ssimokawaextern uint32_t dcons_paddr; 54170101Ssimokawaextern struct console dconsole; 55170101Ssimokawa 56170101Ssimokawastruct crom_src_buf { 57170101Ssimokawa struct crom_src src; 58170101Ssimokawa struct crom_chunk root; 59170101Ssimokawa struct crom_chunk vendor; 60170101Ssimokawa struct crom_chunk hw; 61170101Ssimokawa /* for dcons */ 62170101Ssimokawa struct crom_chunk unit; 63170101Ssimokawa struct crom_chunk spec; 64170101Ssimokawa struct crom_chunk ver; 65170101Ssimokawa}; 66170101Ssimokawa 67170101Ssimokawastatic int fw_init(void); 68170101Ssimokawastatic int fw_strategy(void *devdata, int flag, daddr_t dblk, 69170101Ssimokawa size_t size, char *buf, size_t *rsize); 70170101Ssimokawastatic int fw_open(struct open_file *f, ...); 71170101Ssimokawastatic int fw_close(struct open_file *f); 72170101Ssimokawastatic void fw_print(int verbose); 73170101Ssimokawastatic void fw_cleanup(void); 74170101Ssimokawa 75170101Ssimokawavoid fw_enable(void); 76170101Ssimokawa 77170101Ssimokawastruct devsw fwohci = { 78170101Ssimokawa "FW1394", /* 7 chars at most */ 79170101Ssimokawa DEVT_NET, 80170101Ssimokawa fw_init, 81170101Ssimokawa fw_strategy, 82170101Ssimokawa fw_open, 83170101Ssimokawa fw_close, 84170101Ssimokawa noioctl, 85170101Ssimokawa fw_print, 86170101Ssimokawa fw_cleanup 87170101Ssimokawa}; 88170101Ssimokawa 89170101Ssimokawastatic struct fwohci_softc fwinfo[MAX_OHCI]; 90170101Ssimokawastatic int fw_initialized = 0; 91170101Ssimokawa 92170101Ssimokawastatic void 93170101Ssimokawafw_probe(int index, struct fwohci_softc *sc) 94170101Ssimokawa{ 95170101Ssimokawa int err; 96170101Ssimokawa 97170101Ssimokawa sc->state = FWOHCI_STATE_INIT; 98170101Ssimokawa err = biospci_find_devclass( 99170101Ssimokawa 0x0c0010 /* Serial:FireWire:OHCI */, 100170101Ssimokawa index /* index */, 101170101Ssimokawa &sc->locator); 102170101Ssimokawa 103170101Ssimokawa if (err != 0) { 104170101Ssimokawa sc->state = FWOHCI_STATE_DEAD; 105170101Ssimokawa return; 106170101Ssimokawa } 107170101Ssimokawa 108170101Ssimokawa biospci_write_config(sc->locator, 109170101Ssimokawa 0x4 /* command */, 110170101Ssimokawa 0x6 /* enable bus master and memory mapped I/O */, 111170101Ssimokawa 1 /* word */); 112170101Ssimokawa 113170101Ssimokawa biospci_read_config(sc->locator, 0x00 /*devid*/, 2 /*dword*/, 114170101Ssimokawa &sc->devid); 115170101Ssimokawa biospci_read_config(sc->locator, 0x10 /*base_addr*/, 2 /*dword*/, 116170101Ssimokawa &sc->base_addr); 117170101Ssimokawa 118170101Ssimokawa sc->handle = (uint32_t)PTOV(sc->base_addr); 119170101Ssimokawa sc->bus_id = OREAD(sc, OHCI_BUS_ID); 120170101Ssimokawa 121170101Ssimokawa return; 122170101Ssimokawa} 123170101Ssimokawa 124170101Ssimokawastatic int 125170101Ssimokawafw_init(void) 126170101Ssimokawa{ 127170101Ssimokawa int i, avail; 128170101Ssimokawa struct fwohci_softc *sc; 129170101Ssimokawa 130170101Ssimokawa if (fw_initialized) 131170101Ssimokawa return (0); 132170101Ssimokawa 133170101Ssimokawa avail = 0; 134170101Ssimokawa for (i = 0; i < MAX_OHCI; i ++) { 135170101Ssimokawa sc = &fwinfo[i]; 136170101Ssimokawa fw_probe(i, sc); 137170101Ssimokawa if (sc->state == FWOHCI_STATE_DEAD) 138170101Ssimokawa break; 139170101Ssimokawa avail ++; 140264816Sbrueffer break; 141170101Ssimokawa } 142170101Ssimokawa fw_initialized = 1; 143170101Ssimokawa 144170101Ssimokawa return (0); 145170101Ssimokawa} 146170101Ssimokawa 147170101Ssimokawa 148170101Ssimokawa/* 149170101Ssimokawa * Print information about OHCI chips 150170101Ssimokawa */ 151170101Ssimokawastatic void 152170101Ssimokawafw_print(int verbose) 153170101Ssimokawa{ 154170101Ssimokawa int i; 155170101Ssimokawa struct fwohci_softc *sc; 156170101Ssimokawa 157170101Ssimokawa for (i = 0; i < MAX_OHCI; i ++) { 158170101Ssimokawa sc = &fwinfo[i]; 159170101Ssimokawa if (sc->state == FWOHCI_STATE_DEAD) 160170101Ssimokawa break; 161170101Ssimokawa printf("%d: locator=0x%04x devid=0x%08x" 162170101Ssimokawa " base_addr=0x%08x handle=0x%08x bus_id=0x%08x\n", 163170101Ssimokawa i, sc->locator, sc->devid, 164170101Ssimokawa sc->base_addr, sc->handle, sc->bus_id); 165170101Ssimokawa } 166170101Ssimokawa} 167170101Ssimokawa 168170101Ssimokawastatic int 169170101Ssimokawafw_open(struct open_file *f, ...) 170170101Ssimokawa{ 171170101Ssimokawa#if 0 172170101Ssimokawa va_list ap; 173170101Ssimokawa struct i386_devdesc *dev; 174170101Ssimokawa struct open_disk *od; 175170101Ssimokawa int error; 176170101Ssimokawa 177170101Ssimokawa va_start(ap, f); 178170101Ssimokawa dev = va_arg(ap, struct i386_devdesc *); 179170101Ssimokawa va_end(ap); 180170101Ssimokawa#endif 181170101Ssimokawa 182170101Ssimokawa return (ENXIO); 183170101Ssimokawa} 184170101Ssimokawa 185170101Ssimokawastatic int 186170101Ssimokawafw_close(struct open_file *f) 187170101Ssimokawa{ 188170101Ssimokawa return (0); 189170101Ssimokawa} 190170101Ssimokawa 191170101Ssimokawastatic void 192170101Ssimokawafw_cleanup() 193170101Ssimokawa{ 194170101Ssimokawa struct dcons_buf *db; 195170101Ssimokawa 196170101Ssimokawa /* invalidate dcons buffer */ 197170101Ssimokawa if (dcons_paddr) { 198170101Ssimokawa db = (struct dcons_buf *)PTOV(dcons_paddr); 199170101Ssimokawa db->magic = 0; 200170101Ssimokawa } 201170101Ssimokawa} 202170101Ssimokawa 203170101Ssimokawastatic int 204170101Ssimokawafw_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf, size_t *rsize) 205170101Ssimokawa{ 206170101Ssimokawa return (EIO); 207170101Ssimokawa} 208170101Ssimokawa 209170101Ssimokawastatic void 210170101Ssimokawafw_init_crom(struct fwohci_softc *sc) 211170101Ssimokawa{ 212170101Ssimokawa struct crom_src *src; 213170101Ssimokawa 214170101Ssimokawa printf("fw_init_crom\n"); 215170101Ssimokawa sc->crom_src_buf = (struct crom_src_buf *) 216170101Ssimokawa malloc(sizeof(struct crom_src_buf)); 217170101Ssimokawa if (sc->crom_src_buf == NULL) 218170101Ssimokawa return; 219170101Ssimokawa 220170101Ssimokawa src = &sc->crom_src_buf->src; 221170101Ssimokawa bzero(src, sizeof(struct crom_src)); 222170101Ssimokawa 223170101Ssimokawa /* BUS info sample */ 224170101Ssimokawa src->hdr.info_len = 4; 225170101Ssimokawa 226170101Ssimokawa src->businfo.bus_name = CSR_BUS_NAME_IEEE1394; 227170101Ssimokawa 228170101Ssimokawa src->businfo.irmc = 1; 229170101Ssimokawa src->businfo.cmc = 1; 230170101Ssimokawa src->businfo.isc = 1; 231170101Ssimokawa src->businfo.bmc = 1; 232170101Ssimokawa src->businfo.pmc = 0; 233170101Ssimokawa src->businfo.cyc_clk_acc = 100; 234170101Ssimokawa src->businfo.max_rec = sc->maxrec; 235170101Ssimokawa src->businfo.max_rom = MAXROM_4; 236170101Ssimokawa src->businfo.generation = 1; 237170101Ssimokawa src->businfo.link_spd = sc->speed; 238170101Ssimokawa 239170101Ssimokawa src->businfo.eui64.hi = sc->eui.hi; 240170101Ssimokawa src->businfo.eui64.lo = sc->eui.lo; 241170101Ssimokawa 242170101Ssimokawa STAILQ_INIT(&src->chunk_list); 243170101Ssimokawa 244170101Ssimokawa sc->crom_src = src; 245170101Ssimokawa sc->crom_root = &sc->crom_src_buf->root; 246170101Ssimokawa} 247170101Ssimokawa 248170101Ssimokawastatic void 249170101Ssimokawafw_reset_crom(struct fwohci_softc *sc) 250170101Ssimokawa{ 251170101Ssimokawa struct crom_src_buf *buf; 252170101Ssimokawa struct crom_src *src; 253170101Ssimokawa struct crom_chunk *root; 254170101Ssimokawa 255170101Ssimokawa printf("fw_reset\n"); 256170101Ssimokawa if (sc->crom_src_buf == NULL) 257170101Ssimokawa fw_init_crom(sc); 258170101Ssimokawa 259170101Ssimokawa buf = sc->crom_src_buf; 260170101Ssimokawa src = sc->crom_src; 261170101Ssimokawa root = sc->crom_root; 262170101Ssimokawa 263170101Ssimokawa STAILQ_INIT(&src->chunk_list); 264170101Ssimokawa 265170101Ssimokawa bzero(root, sizeof(struct crom_chunk)); 266170101Ssimokawa crom_add_chunk(src, NULL, root, 0); 267170101Ssimokawa crom_add_entry(root, CSRKEY_NCAP, 0x0083c0); /* XXX */ 268170101Ssimokawa /* private company_id */ 269170101Ssimokawa crom_add_entry(root, CSRKEY_VENDOR, CSRVAL_VENDOR_PRIVATE); 270170101Ssimokawa#ifdef __DragonFly__ 271170101Ssimokawa crom_add_simple_text(src, root, &buf->vendor, "DragonFly Project"); 272170101Ssimokawa#else 273170101Ssimokawa crom_add_simple_text(src, root, &buf->vendor, "FreeBSD Project"); 274170101Ssimokawa#endif 275170101Ssimokawa} 276170101Ssimokawa 277170101Ssimokawa 278170101Ssimokawa#define ADDR_HI(x) (((x) >> 24) & 0xffffff) 279170101Ssimokawa#define ADDR_LO(x) ((x) & 0xffffff) 280170101Ssimokawa 281170101Ssimokawastatic void 282170101Ssimokawadcons_crom(struct fwohci_softc *sc) 283170101Ssimokawa{ 284170101Ssimokawa struct crom_src_buf *buf; 285170101Ssimokawa struct crom_src *src; 286170101Ssimokawa struct crom_chunk *root; 287170101Ssimokawa 288170101Ssimokawa buf = sc->crom_src_buf; 289170101Ssimokawa src = sc->crom_src; 290170101Ssimokawa root = sc->crom_root; 291170101Ssimokawa 292170101Ssimokawa bzero(&buf->unit, sizeof(struct crom_chunk)); 293170101Ssimokawa 294170101Ssimokawa crom_add_chunk(src, root, &buf->unit, CROM_UDIR); 295170101Ssimokawa crom_add_entry(&buf->unit, CSRKEY_SPEC, CSRVAL_VENDOR_PRIVATE); 296170101Ssimokawa crom_add_simple_text(src, &buf->unit, &buf->spec, "FreeBSD"); 297170101Ssimokawa crom_add_entry(&buf->unit, CSRKEY_VER, DCONS_CSR_VAL_VER); 298170101Ssimokawa crom_add_simple_text(src, &buf->unit, &buf->ver, "dcons"); 299170101Ssimokawa crom_add_entry(&buf->unit, DCONS_CSR_KEY_HI, ADDR_HI(dcons_paddr)); 300170101Ssimokawa crom_add_entry(&buf->unit, DCONS_CSR_KEY_LO, ADDR_LO(dcons_paddr)); 301170101Ssimokawa} 302170101Ssimokawa 303170101Ssimokawavoid 304170101Ssimokawafw_crom(struct fwohci_softc *sc) 305170101Ssimokawa{ 306170101Ssimokawa struct crom_src *src; 307170101Ssimokawa void *newrom; 308170101Ssimokawa 309170101Ssimokawa fw_reset_crom(sc); 310170101Ssimokawa dcons_crom(sc); 311170101Ssimokawa 312170101Ssimokawa newrom = malloc(CROMSIZE); 313170101Ssimokawa src = &sc->crom_src_buf->src; 314170101Ssimokawa crom_load(src, (uint32_t *)newrom, CROMSIZE); 315170101Ssimokawa if (bcmp(newrom, sc->config_rom, CROMSIZE) != 0) { 316170101Ssimokawa /* bump generation and reload */ 317170101Ssimokawa src->businfo.generation ++; 318170101Ssimokawa /* generation must be between 0x2 and 0xF */ 319170101Ssimokawa if (src->businfo.generation < 2) 320170101Ssimokawa src->businfo.generation ++; 321170101Ssimokawa crom_load(src, (uint32_t *)newrom, CROMSIZE); 322170101Ssimokawa bcopy(newrom, (void *)sc->config_rom, CROMSIZE); 323170101Ssimokawa } 324170101Ssimokawa free(newrom); 325170101Ssimokawa} 326170101Ssimokawa 327170101Ssimokawastatic int 328170101Ssimokawafw_busreset(struct fwohci_softc *sc) 329170101Ssimokawa{ 330170101Ssimokawa int count; 331170101Ssimokawa 332170101Ssimokawa if (sc->state < FWOHCI_STATE_ENABLED) { 333170101Ssimokawa printf("fwohci not enabled\n"); 334170101Ssimokawa return(CMD_OK); 335170101Ssimokawa } 336170101Ssimokawa fw_crom(sc); 337170101Ssimokawa fwohci_ibr(sc); 338170101Ssimokawa count = 0; 339170101Ssimokawa while (sc->state< FWOHCI_STATE_NORMAL) { 340170101Ssimokawa fwohci_poll(sc); 341170101Ssimokawa count ++; 342170101Ssimokawa if (count > 1000) { 343170101Ssimokawa printf("give up to wait bus initialize\n"); 344170101Ssimokawa return (-1); 345170101Ssimokawa } 346170101Ssimokawa } 347170101Ssimokawa printf("poll count = %d\n", count); 348170101Ssimokawa return (0); 349170101Ssimokawa} 350170101Ssimokawa 351170101Ssimokawavoid 352170101Ssimokawafw_enable(void) 353170101Ssimokawa{ 354170101Ssimokawa struct fwohci_softc *sc; 355170101Ssimokawa int i; 356170101Ssimokawa 357170101Ssimokawa if (fw_initialized == 0) 358170101Ssimokawa fw_init(); 359170101Ssimokawa 360170101Ssimokawa for (i = 0; i < MAX_OHCI; i ++) { 361170101Ssimokawa sc = &fwinfo[i]; 362170101Ssimokawa if (sc->state != FWOHCI_STATE_INIT) 363170101Ssimokawa break; 364170101Ssimokawa 365170101Ssimokawa sc->config_rom = (uint32_t *) 366170101Ssimokawa (((uint32_t)sc->config_rom_buf 367170101Ssimokawa + (CROMSIZE - 1)) & ~(CROMSIZE - 1)); 368170101Ssimokawa#if 0 369170101Ssimokawa printf("configrom: %08p %08p\n", 370170101Ssimokawa sc->config_rom_buf, sc->config_rom); 371170101Ssimokawa#endif 372170101Ssimokawa if (fwohci_init(sc, 0) == 0) { 373170101Ssimokawa sc->state = FWOHCI_STATE_ENABLED; 374170101Ssimokawa fw_busreset(sc); 375170101Ssimokawa } else 376170101Ssimokawa sc->state = FWOHCI_STATE_DEAD; 377170101Ssimokawa } 378170101Ssimokawa} 379170101Ssimokawa 380170101Ssimokawavoid 381170101Ssimokawafw_poll(void) 382170101Ssimokawa{ 383170101Ssimokawa struct fwohci_softc *sc; 384170101Ssimokawa int i; 385170101Ssimokawa 386170101Ssimokawa if (fw_initialized == 0) 387170101Ssimokawa return; 388170101Ssimokawa 389170101Ssimokawa for (i = 0; i < MAX_OHCI; i ++) { 390170101Ssimokawa sc = &fwinfo[i]; 391170101Ssimokawa if (sc->state < FWOHCI_STATE_ENABLED) 392170101Ssimokawa break; 393170101Ssimokawa fwohci_poll(sc); 394170101Ssimokawa } 395170101Ssimokawa} 396170101Ssimokawa 397170101Ssimokawa#if 0 /* for debug */ 398170101Ssimokawastatic int 399170101Ssimokawafw_busreset_cmd(int argc, char *argv[]) 400170101Ssimokawa{ 401170101Ssimokawa struct fwohci_softc *sc; 402170101Ssimokawa int i; 403170101Ssimokawa 404170101Ssimokawa for (i = 0; i < MAX_OHCI; i ++) { 405170101Ssimokawa sc = &fwinfo[i]; 406170101Ssimokawa if (sc->state < FWOHCI_STATE_INIT) 407170101Ssimokawa break; 408170101Ssimokawa fw_busreset(sc); 409170101Ssimokawa } 410170101Ssimokawa return(CMD_OK); 411170101Ssimokawa} 412170101Ssimokawa 413170101Ssimokawastatic int 414170101Ssimokawafw_poll_cmd(int argc, char *argv[]) 415170101Ssimokawa{ 416170101Ssimokawa fw_poll(); 417170101Ssimokawa return(CMD_OK); 418170101Ssimokawa} 419170101Ssimokawa 420170101Ssimokawastatic int 421170101Ssimokawafw_enable_cmd(int argc, char *argv[]) 422170101Ssimokawa{ 423170101Ssimokawa fw_print(0); 424170101Ssimokawa fw_enable(); 425170101Ssimokawa return(CMD_OK); 426170101Ssimokawa} 427170101Ssimokawa 428170101Ssimokawa 429170101Ssimokawastatic int 430170101Ssimokawadcons_enable(int argc, char *argv[]) 431170101Ssimokawa{ 432170101Ssimokawa dconsole.c_init(0); 433170101Ssimokawa fw_enable(); 434170101Ssimokawa dconsole.c_flags |= C_ACTIVEIN | C_ACTIVEOUT; 435170101Ssimokawa return(CMD_OK); 436170101Ssimokawa} 437170101Ssimokawa 438170101Ssimokawastatic int 439170101Ssimokawadcons_read(int argc, char *argv[]) 440170101Ssimokawa{ 441170101Ssimokawa char c; 442170101Ssimokawa while (dconsole.c_ready()) { 443170101Ssimokawa c = dconsole.c_in(); 444170101Ssimokawa printf("%c", c); 445170101Ssimokawa } 446170101Ssimokawa printf("\r\n"); 447170101Ssimokawa return(CMD_OK); 448170101Ssimokawa} 449170101Ssimokawa 450170101Ssimokawastatic int 451170101Ssimokawadcons_write(int argc, char *argv[]) 452170101Ssimokawa{ 453170101Ssimokawa int len, i; 454170101Ssimokawa if (argc < 2) 455170101Ssimokawa return(CMD_OK); 456170101Ssimokawa 457170101Ssimokawa len = strlen(argv[1]); 458170101Ssimokawa for (i = 0; i < len; i ++) 459170101Ssimokawa dconsole.c_out(argv[1][i]); 460170101Ssimokawa dconsole.c_out('\r'); 461170101Ssimokawa dconsole.c_out('\n'); 462170101Ssimokawa return(CMD_OK); 463170101Ssimokawa} 464170101SsimokawaCOMMAND_SET(firewire, "firewire", "enable firewire", fw_enable_cmd); 465170101SsimokawaCOMMAND_SET(fwbusreset, "fwbusreset", "firewire busreset", fw_busreset_cmd); 466170101SsimokawaCOMMAND_SET(fwpoll, "fwpoll", "firewire poll", fw_poll_cmd); 467170101SsimokawaCOMMAND_SET(dcons, "dcons", "enable dcons", dcons_enable); 468170101SsimokawaCOMMAND_SET(dread, "dread", "read from dcons", dcons_read); 469170101SsimokawaCOMMAND_SET(dwrite, "dwrite", "write to dcons", dcons_write); 470170101Ssimokawa#endif 471