📄 pciba.c
字号:
if (GRAPH_SUCCESS != (ret = hwgraph_edge_add(conv, vhdl, uname0))) printk("unable to create %v/%s (ret=%d)\n", conn, uname0, vhdl, ret); else SHOWREF(vhdl, hwgraph_edge_add); if (GRAPH_SUCCESS != (ret = hwgraph_vertex_unref(vhdl))) printk("unable to unref %v\n", vhdl); else SHOWREF(vhdl, hwgraph_vertex_unref); } if (GRAPH_SUCCESS != (ret = hwgraph_vertex_unref(conn))) printk("unable to unref %v\n", conn); else SHOWREF(conn, hwgraph_vertex_unref); } if (GRAPH_SUCCESS != (ret = hwgraph_traverse(hwgraph_root, cpath1, &conn))) printk("\tunable to find %s (ret=%d)\n", cpath1, ret); else { SHOWREF(conn, hwgraph_traverse); if (GRAPH_SUCCESS != (ret = hwgraph_char_device_add(conn, dname, "pciba_", &vhdl))) printk("unable to create %v/%s (ret=%d)\n", conn, dname, ret); else { SHOWREF(vhdl, hwgraph_char_device_add); hwgraph_chmod(vhdl, 0666); SHOWREF(vhdl, hwgraph_chmod); if (GRAPH_SUCCESS != (ret = hwgraph_edge_add(conv, vhdl, uname1))) printk("unable to create %v/%s (ret=%d)\n", conn, uname1, vhdl, ret); else SHOWREF(vhdl, hwgraph_edge_add); if (GRAPH_SUCCESS != (ret = hwgraph_vertex_unref(vhdl))) printk("unable to unref %v\n", vhdl); else SHOWREF(vhdl, hwgraph_vertex_unref); } if (GRAPH_SUCCESS != (ret = hwgraph_vertex_unref(conn))) printk("unable to unref %v\n", conn); else SHOWREF(conn, hwgraph_vertex_unref); } if (GRAPH_SUCCESS != (ret = hwgraph_traverse(hwgraph_root, cpath0, &conn))) printk("\tunable to find %s (ret=%d)\n", cpath0, ret); else { SHOWREF(conn, hwgraph_traverse); if (GRAPH_SUCCESS != (ret = hwgraph_traverse(conn, dname, &vhdl))) printk("\tunable to find %v/%s (ret=%d)\n", conn, dname, ret); else { SHOWREF(vhdl, hwgraph_traverse); if (GRAPH_SUCCESS != (ret = hwgraph_edge_remove(conv, uname0, NULL))) printk("\tunable to remove edge %v/%s (ret=%d)\n", conv, uname0, ret); else SHOWREF(vhdl, hwgraph_edge_remove); if (GRAPH_SUCCESS != (ret = hwgraph_edge_remove(conn, dname, NULL))) printk("\tunable to remove edge %v/%s (ret=%d)\n", conn, dname, ret); else SHOWREF(vhdl, hwgraph_edge_remove); if (GRAPH_SUCCESS != (ret = hwgraph_vertex_unref(vhdl))) printk("unable to unref %v\n", vhdl); else SHOWREF(vhdl, hwgraph_vertex_unref); if (GRAPH_SUCCESS == (ret = hwgraph_vertex_destroy(vhdl))) printk("\tvertex %d destroyed OK\n", vhdl); else SHOWREF(vhdl, hwgraph_vertex_destroy); } if (GRAPH_SUCCESS != (ret = hwgraph_vertex_unref(conn))) printk("unable to unref %v\n", conn); else SHOWREF(conn, hwgraph_vertex_unref); } if (GRAPH_SUCCESS != (ret = hwgraph_traverse(hwgraph_root, cpath1, &conn))) printk("\tunable to find %s (ret=%d)\n", cpath1, ret); else { SHOWREF(conn, hwgraph_traverse); if (GRAPH_SUCCESS != (ret = hwgraph_traverse(conn, dname, &vhdl))) printk("\tunable to find %v/%s (ret=%d)\n", conn, dname, ret); else { SHOWREF(vhdl, hwgraph_traverse); if (GRAPH_SUCCESS != (ret = hwgraph_edge_remove(conv, uname1, NULL))) printk("\tunable to remove edge %v/%s (ret=%d)\n", conv, uname1, ret); else SHOWREF(vhdl, hwgraph_edge_remove); if (GRAPH_SUCCESS != (ret = hwgraph_edge_remove(conn, dname, NULL))) printk("\tunable to remove edge %v/%s (ret=%d)\n", conn, dname, ret); else SHOWREF(vhdl, hwgraph_edge_remove); if (GRAPH_SUCCESS != (ret = hwgraph_vertex_unref(vhdl))) printk("unable to unref %v\n", vhdl); else SHOWREF(vhdl, hwgraph_vertex_unref); if (GRAPH_SUCCESS == (ret = hwgraph_vertex_destroy(vhdl))) printk("\tvertex %d destroyed OK\n", vhdl); else SHOWREF(vhdl, hwgraph_vertex_destroy); } if (GRAPH_SUCCESS != (ret = hwgraph_vertex_unref(conn))) printk("unable to unref %v\n", conn); else SHOWREF(conn, hwgraph_vertex_unref); } if (GRAPH_SUCCESS != (ret = hwgraph_edge_remove(hwgraph_root, cname, NULL))) printk("\tunable to remove edge %v/%s (ret=%d)\n", hwgraph_root, cname, ret); else SHOWREF(conv, hwgraph_edge_remove); if (GRAPH_SUCCESS != (ret = hwgraph_vertex_unref(conv))) printk("unable to unref %v\n", conv); else SHOWREF(conv, hwgraph_vertex_unref); if (GRAPH_SUCCESS == (ret = hwgraph_vertex_destroy(conv))) printk("\tvertex %d destroyed OK\n", conv); else SHOWREF(conv, hwgraph_vertex_destroy); } }#endif return 0;}#endifintpciba_attach(devfs_handle_t hconn){#if defined(PCIIO_SLOT_NONE) pciio_info_t info = pciio_info_get(hconn); pciio_slot_t slot = pciio_info_slot_get(info);#endif pciba_comm_t comm; pciba_bus_t bus; int ht; devfs_handle_t hbase; devfs_handle_t gconn; devfs_handle_t gbase; int win; int wins; pciio_space_t space; pciaddr_t base; int iwins; int mwins;#if DEBUG_PCIBA printk("pciba_attach(%p)\n", hconn);#endif /* Pick up "dualslot guest" vertex, * which gets all functionality except * config space access. */ if ((GRAPH_SUCCESS != hwgraph_traverse(hconn, ".guest", &gconn)) || (hconn == gconn)) gconn = GRAPH_VERTEX_NONE; bus = pciba_find_bus(hconn, 1); bus->refct ++; /* set up data common to all pciba openables * on this connection point. */ NEW(comm); comm->conn = hconn; comm->bus = bus; comm->refct = 0; sema_init(&comm->lock, 1);#if !defined(PCIIO_SLOT_NONE) if (bus->refct == 1)#else if (slot == PCIIO_SLOT_NONE)#endif { pciio_info_t pciio_info; devfs_handle_t master; pciio_info = pciio_info_get(hconn); master = pciio_info_master_get(pciio_info); pciba_sub_attach(comm, PCIIO_SPACE_IO, PCIIO_SPACE_IO, 0, master, master, PCIBA_EDGE_LBL_IO); pciba_sub_attach(comm, PCIIO_SPACE_MEM, PCIIO_SPACE_MEM, 0, master, master, PCIBA_EDGE_LBL_MEM);#if defined(PCIIO_SLOT_NONE) return 0;#endif } ht = 0x7F & pciio_config_get(hconn, PCI_CFG_HEADER_TYPE, 1); wins = ((ht == 0x00) ? 6 : (ht == 0x01) ? 2 : 0); mwins = iwins = 0; hbase = GRAPH_VERTEX_NONE; gbase = GRAPH_VERTEX_NONE; for (win = 0; win < wins; win++) { base = pciio_config_get(hconn, PCI_CFG_BASE_ADDR(win), 4); if (base & 1) { space = PCIIO_SPACE_IO; base &= 0xFFFFFFFC; } else if ((base & 7) == 4) { space = PCIIO_SPACE_MEM; base &= 0xFFFFFFF0; base |= ((pciaddr_t) pciio_config_get(hconn, PCI_CFG_BASE_ADDR(win + 1), 4)) << 32; } else { space = PCIIO_SPACE_MEM; base &= 0xFFFFFFF0; } if (!base) break;#if PCIBA_ALIGN_CHECK if (base & (_PAGESZ - 1)) {#if DEBUG_PCIBA PRINT_WARNING("%p pciba: BASE%d not page aligned!\n" "\tmmap this window at offset 0x%x via \".../pci/%s\"\n", hconn, win, base, (space == PCIIO_SPACE_IO) ? "io" : "mem");#endif continue; /* next window */ }#endif if ((hbase == GRAPH_VERTEX_NONE) && ((GRAPH_SUCCESS != hwgraph_path_add(hconn, PCIBA_EDGE_LBL_BASE, &hbase)) || (hbase == GRAPH_VERTEX_NONE))) break; /* no base vertex, no more windows. */ if ((gconn != GRAPH_VERTEX_NONE) && (gbase == GRAPH_VERTEX_NONE) && ((GRAPH_SUCCESS != hwgraph_path_add(gconn, PCIBA_EDGE_LBL_BASE, &gbase)) || (gbase == GRAPH_VERTEX_NONE))) break; /* no base vertex, no more windows. */ pciba_sub_attach(comm, PCIIO_SPACE_WIN(win), space, base, hbase, gbase, PCIBA_EDGE_LBL_WIN(win)); if (space == PCIIO_SPACE_IO) { if (!iwins++) { pciba_sub_attach(comm, PCIIO_SPACE_WIN(win), space, base, hconn, gconn, PCIBA_EDGE_LBL_IO); } } else { if (!mwins++) { pciba_sub_attach(comm, PCIIO_SPACE_WIN(win), space, base, hconn, gconn, PCIBA_EDGE_LBL_MEM); } } if ((base & 7) == 4) win++; } pciba_sub_attach(comm, PCIIO_SPACE_CFG, PCIIO_SPACE_NONE, 0, hconn, gconn, PCIBA_EDGE_LBL_CFG); pciba_sub_attach(comm, PCIBA_SPACE_UDMA, PCIIO_SPACE_NONE, 0, hconn, gconn, PCIBA_EDGE_LBL_DMA);#if ULI pciba_sub_attach(comm, PCIIO_SPACE_NONE, PCIIO_SPACE_NONE, 0, hconn, gconn, PCIBA_EDGE_LBL_INTR);#endif /* XXX should ignore if device is an IOC3 */ if (ht == 0x01) base = pciio_config_get(hconn, PCI_EXPANSION_ROM+8, 4); else base = pciio_config_get(hconn, PCI_EXPANSION_ROM, 4); base &= 0xFFFFF000; if (base) { if (base & (_PAGESZ - 1))#if defined(SUPPORT_PRINTING_V_FORMAT) PRINT_WARNING("%v pciba: ROM is 0x%x\n" "\tnot page aligned, mmap will be difficult\n", hconn, base);#else PRINT_WARNING("0x%x pciba: ROM is 0x%x\n" "\tnot page aligned, mmap will be difficult\n", hconn, base);#endif pciba_sub_attach(comm, PCIIO_SPACE_ROM, PCIIO_SPACE_MEM, base, hconn, gconn, PCIBA_EDGE_LBL_ROM); }#if !FICUS /* FICUS shorts the refct by one on path_add */ if (hbase != GRAPH_VERTEX_NONE) hwgraph_vertex_unref(hbase); if (gbase != GRAPH_VERTEX_NONE) hwgraph_vertex_unref(gbase);#endif return 0;}static voidpciba_sub_attach2(pciba_comm_t comm, pciio_space_t space, pciio_space_t iomem, pciaddr_t base, devfs_handle_t from, char *name, char *suf, unsigned bigend){ char nbuf[128]; pciba_soft_t soft; devfs_handle_t handle = NULL; if (suf && *suf) { strcpy(nbuf, name); name = nbuf; strcat(name, suf); }#if DEBUG_PCIBA printk("pciba_sub_attach2 %p/%s %p at %p[%x]\n", from, name, space, space_desc, iomem, space_desc, base, from, name);#endif if (space < TRACKED_SPACES) if ((soft = comm->soft[space][bigend]) != NULL) { soft->refct ++; hwgraph_edge_add(from, soft->vhdl, name); return; } NEW(soft); if (!soft) return; soft->comm = comm; soft->space = space; soft->size = 0; soft->iomem = iomem; soft->base = base; soft->refct = 1; if (space == PCIIO_SPACE_NONE) soft->flags = 0; else if (bigend) soft->flags = PCIIO_BYTE_STREAM; else soft->flags = PCIIO_WORD_VALUES; handle = hwgraph_register(from, name, 0, DEVFS_FL_AUTO_DEVNUM, 0, 0, S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0, &pciba_fops, NULL); soft->vhdl = handle; pciba_soft_set(soft->vhdl, soft); if (space < TRACKED_SPACES) comm->soft[space][bigend] = soft; comm->refct ++;}static voidpciba_sub_attach1(pciba_comm_t comm, pciio_space_t space, pciio_space_t iomem, pciaddr_t base, devfs_handle_t hfrom, devfs_handle_t gfrom, char *name, char *suf, unsigned bigend){ pciba_sub_attach2(comm, space, iomem, base, hfrom, name, suf, bigend); if ((gfrom != GRAPH_VERTEX_NONE) && (gfrom != hfrom)) pciba_sub_attach2(comm, space, iomem, base, gfrom, name, suf, bigend);}static voidpciba_sub_attach(pciba_comm_t comm, pciio_space_t space, pciio_space_t iomem, pciaddr_t base, devfs_handle_t hfrom, devfs_handle_t gfrom, char *name){ pciba_sub_attach1(comm, space, iomem, base, hfrom, gfrom, name, NULL, 0); if (iomem != PCIIO_SPACE_NONE) { pciba_sub_attach1(comm, space, iomem, base, hfrom, gfrom, name, "_le", 0); pciba_sub_attach1(comm, space, iomem, base, hfrom, gfrom, name, "_be", 1); }}#ifdef LATERstatic voidpciba_reload_me(devfs_handle_t pconn_vhdl){ devfs_handle_t vhdl;#if DEBUG_PCIBA printf("pciba_reload_me(%v)\n", pconn_vhdl);#endif if (GRAPH_SUCCESS != hwgraph_traverse(pconn_vhdl, PCIBA_EDGE_LBL_CFG, &vhdl)) return; hwgraph_vertex_unref(vhdl);}#endif /* LATER */static pciba_bus_tpciba_find_bus(devfs_handle_t pconn, int cflag){ pciio_info_t pciio_info; devfs_handle_t master; arbitrary_info_t ainfo; pciba_bus_t bus; pciio_info = pciio_info_get(pconn); master = pciio_info_master_get(pciio_info); if (GRAPH_SUCCESS == hwgraph_info_get_LBL(master, PCIBA_INFO_LBL_BUS, &ainfo)) return (pciba_bus_t) ainfo; if (!cflag) return 0; NEW(bus); if (!bus) return 0; sema_init(&bus->lock, 1); ainfo = (arbitrary_info_t) bus; hwgraph_info_add_LBL(master, PCIBA_INFO_LBL_BUS, ainfo); hwgraph_info_get_LBL(master, PCIBA_INFO_LBL_BUS, &ainfo); if ((pciba_bus_t) ainfo != bus) DEL(bus);#if DEBUG_PCIBA else printk("pcbia_find_bus: new bus at %p\n", master);#endif return (pciba_bus_t) ainfo;}#ifdef LATERstatic voidpciba_map_push(pciba_bus_t bus, pciba_map_t map){#if DEBUG_PCIBA printk("pciba_map_push(bus=0x%x, map=0x%x, hdl=0x%x\n", bus, map, map->handle);#endif pciba_bus_lock(bus); map->next = bus->maps; bus->maps = map;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -