diff --git a/usr.sbin/bhyve/pci_passthru.h b/usr.sbin/bhyve/pci_passthru.h --- a/usr.sbin/bhyve/pci_passthru.h +++ b/usr.sbin/bhyve/pci_passthru.h @@ -53,3 +53,6 @@ struct pcisel *passthru_get_sel(struct passthru_softc *sc); int set_pcir_handler(struct passthru_softc *sc, int reg, int len, cfgread_handler rhandler, cfgwrite_handler whandler); +int passthru_set_bar_handler(struct passthru_softc *sc, int baridx, + uint64_t off, uint64_t size, passthru_read_handler rhandler, + passthru_write_handler whandler); diff --git a/usr.sbin/bhyve/pci_passthru.c b/usr.sbin/bhyve/pci_passthru.c --- a/usr.sbin/bhyve/pci_passthru.c +++ b/usr.sbin/bhyve/pci_passthru.c @@ -752,6 +752,45 @@ return (0); } +int +passthru_set_bar_handler(struct passthru_softc *sc, int baridx, uint64_t off, + uint64_t size, passthru_read_handler rhandler, + passthru_write_handler whandler) +{ + struct passthru_bar_handler *handler_new; + struct passthru_bar_handler *handler; + + assert(sc->psc_bar[baridx].type == PCIBAR_IO || + sc->psc_bar[baridx].type == PCIBAR_MEM32 || + sc->psc_bar[baridx].type == PCIBAR_MEM64); + assert(sc->psc_bar[baridx].size >= off + size); + assert(off < off + size); + + handler_new = malloc(sizeof(struct passthru_bar_handler)); + if (handler_new == NULL) { + return (ENOMEM); + } + + handler_new->off = off; + handler_new->size = size; + handler_new->read = rhandler; + handler_new->write = whandler; + + TAILQ_FOREACH(handler, &sc->psc_bar_handler[baridx], chain) { + if (handler->off < handler_new->off) { + assert(handler->off + handler->size < handler_new->off); + continue; + } + assert(handler->off > handler_new->off + handler_new->size); + TAILQ_INSERT_BEFORE(handler, handler_new, chain); + return (0); + } + + TAILQ_INSERT_TAIL(&sc->psc_bar_handler[baridx], handler_new, chain); + + return (0); +} + static int passthru_legacy_config(nvlist_t *nvl, const char *opts) {