Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/bhyve/pci_hda.c
Show First 20 Lines • Show All 142 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
static inline void hda_set_reg_by_offset(struct hda_softc *sc, uint32_t offset, | static inline void hda_set_reg_by_offset(struct hda_softc *sc, uint32_t offset, | ||||
uint32_t value); | uint32_t value); | ||||
static inline uint32_t hda_get_reg_by_offset(struct hda_softc *sc, | static inline uint32_t hda_get_reg_by_offset(struct hda_softc *sc, | ||||
uint32_t offset); | uint32_t offset); | ||||
static inline void hda_set_field_by_offset(struct hda_softc *sc, | static inline void hda_set_field_by_offset(struct hda_softc *sc, | ||||
uint32_t offset, uint32_t mask, uint32_t value); | uint32_t offset, uint32_t mask, uint32_t value); | ||||
static struct hda_softc *hda_init(nvlist_t *nvl); | static struct hda_softc *hda_init(config_node_t *node); | ||||
static void hda_update_intr(struct hda_softc *sc); | static void hda_update_intr(struct hda_softc *sc); | ||||
static void hda_response_interrupt(struct hda_softc *sc); | static void hda_response_interrupt(struct hda_softc *sc); | ||||
static int hda_codec_constructor(struct hda_softc *sc, | static int hda_codec_constructor(struct hda_softc *sc, | ||||
struct hda_codec_class *codec, const char *play, const char *rec); | struct hda_codec_class *codec, const char *play, const char *rec); | ||||
static struct hda_codec_class *hda_find_codec_class(const char *name); | static struct hda_codec_class *hda_find_codec_class(const char *name); | ||||
static int hda_send_command(struct hda_softc *sc, uint32_t verb); | static int hda_send_command(struct hda_softc *sc, uint32_t verb); | ||||
static int hda_notify_codecs(struct hda_softc *sc, uint8_t run, | static int hda_notify_codecs(struct hda_softc *sc, uint8_t run, | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | static int hda_transfer(struct hda_codec_inst *hci, uint8_t stream, | ||||
uint8_t dir, void *buf, size_t count); | uint8_t dir, void *buf, size_t count); | ||||
static void hda_set_pib(struct hda_softc *sc, uint8_t stream_ind, uint32_t pib); | static void hda_set_pib(struct hda_softc *sc, uint8_t stream_ind, uint32_t pib); | ||||
static uint64_t hda_get_clock_ns(void); | static uint64_t hda_get_clock_ns(void); | ||||
/* | /* | ||||
* PCI HDA function declarations | * PCI HDA function declarations | ||||
*/ | */ | ||||
static int pci_hda_init(struct vmctx *ctx, struct pci_devinst *pi, nvlist_t *nvl); | static int pci_hda_init(struct vmctx *ctx, struct pci_devinst *pi, config_node_t *node); | ||||
static void pci_hda_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, | static void pci_hda_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, | ||||
int baridx, uint64_t offset, int size, uint64_t value); | int baridx, uint64_t offset, int size, uint64_t value); | ||||
static uint64_t pci_hda_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, | static uint64_t pci_hda_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, | ||||
int baridx, uint64_t offset, int size); | int baridx, uint64_t offset, int size); | ||||
/* | /* | ||||
* HDA global data | * HDA global data | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | hda_set_field_by_offset(struct hda_softc *sc, uint32_t offset, | ||||
reg_value &= ~mask; | reg_value &= ~mask; | ||||
reg_value |= (value & mask); | reg_value |= (value & mask); | ||||
hda_set_reg_by_offset(sc, offset, reg_value); | hda_set_reg_by_offset(sc, offset, reg_value); | ||||
} | } | ||||
static struct hda_softc * | static struct hda_softc * | ||||
hda_init(nvlist_t *nvl) | hda_init(config_node_t *node) | ||||
{ | { | ||||
struct hda_softc *sc = NULL; | struct hda_softc *sc = NULL; | ||||
struct hda_codec_class *codec = NULL; | struct hda_codec_class *codec = NULL; | ||||
const char *value; | const char *value; | ||||
char *play; | char *play; | ||||
char *rec; | char *rec; | ||||
int err; | int err; | ||||
#if DEBUG_HDA == 1 | #if DEBUG_HDA == 1 | ||||
dbg = fopen("/tmp/bhyve_hda.log", "w+"); | dbg = fopen("/tmp/bhyve_hda.log", "w+"); | ||||
#endif | #endif | ||||
sc = calloc(1, sizeof(*sc)); | sc = calloc(1, sizeof(*sc)); | ||||
if (!sc) | if (!sc) | ||||
return (NULL); | return (NULL); | ||||
hda_reset_regs(sc); | hda_reset_regs(sc); | ||||
/* | /* | ||||
* TODO search all configured codecs | * TODO search all configured codecs | ||||
* For now we play with one single codec | * For now we play with one single codec | ||||
*/ | */ | ||||
codec = hda_find_codec_class("hda_codec"); | codec = hda_find_codec_class("hda_codec"); | ||||
if (codec) { | if (codec) { | ||||
value = get_config_value_node(nvl, "play"); | value = get_config_value_node(node, "play"); | ||||
if (value == NULL) | if (value == NULL) | ||||
play = NULL; | play = NULL; | ||||
else | else | ||||
play = strdup(value); | play = strdup(value); | ||||
value = get_config_value_node(nvl, "rec"); | value = get_config_value_node(node, "rec"); | ||||
if (value == NULL) | if (value == NULL) | ||||
rec = NULL; | rec = NULL; | ||||
else | else | ||||
rec = strdup(value); | rec = strdup(value); | ||||
DPRINTF("play: %s rec: %s", play, rec); | DPRINTF("play: %s rec: %s", play, rec); | ||||
if (play != NULL || rec != NULL) { | if (play != NULL || rec != NULL) { | ||||
err = hda_codec_constructor(sc, codec, play, rec); | err = hda_codec_constructor(sc, codec, play, rec); | ||||
assert(!err); | assert(!err); | ||||
▲ Show 20 Lines • Show All 859 Lines • ▼ Show 20 Lines | static uint64_t hda_get_clock_ns(void) | ||||
return (ts.tv_sec * 1000000000LL + ts.tv_nsec); | return (ts.tv_sec * 1000000000LL + ts.tv_nsec); | ||||
} | } | ||||
/* | /* | ||||
* PCI HDA function definitions | * PCI HDA function definitions | ||||
*/ | */ | ||||
static int | static int | ||||
pci_hda_init(struct vmctx *ctx, struct pci_devinst *pi, nvlist_t *nvl) | pci_hda_init(struct vmctx *ctx, struct pci_devinst *pi, config_node_t *node) | ||||
{ | { | ||||
struct hda_softc *sc = NULL; | struct hda_softc *sc = NULL; | ||||
assert(ctx != NULL); | assert(ctx != NULL); | ||||
assert(pi != NULL); | assert(pi != NULL); | ||||
pci_set_cfgdata16(pi, PCIR_VENDOR, INTEL_VENDORID); | pci_set_cfgdata16(pi, PCIR_VENDOR, INTEL_VENDORID); | ||||
pci_set_cfgdata16(pi, PCIR_DEVICE, HDA_INTEL_82801G); | pci_set_cfgdata16(pi, PCIR_DEVICE, HDA_INTEL_82801G); | ||||
pci_set_cfgdata8(pi, PCIR_SUBCLASS, PCIS_MULTIMEDIA_HDA); | pci_set_cfgdata8(pi, PCIR_SUBCLASS, PCIS_MULTIMEDIA_HDA); | ||||
pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_MULTIMEDIA); | pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_MULTIMEDIA); | ||||
/* select the Intel HDA mode */ | /* select the Intel HDA mode */ | ||||
pci_set_cfgdata8(pi, PCIR_HDCTL, 0x01); | pci_set_cfgdata8(pi, PCIR_HDCTL, 0x01); | ||||
/* allocate one BAR register for the Memory address offsets */ | /* allocate one BAR register for the Memory address offsets */ | ||||
pci_emul_alloc_bar(pi, 0, PCIBAR_MEM32, HDA_LAST_OFFSET); | pci_emul_alloc_bar(pi, 0, PCIBAR_MEM32, HDA_LAST_OFFSET); | ||||
/* allocate an IRQ pin for our slot */ | /* allocate an IRQ pin for our slot */ | ||||
pci_lintr_request(pi); | pci_lintr_request(pi); | ||||
sc = hda_init(nvl); | sc = hda_init(node); | ||||
if (!sc) | if (!sc) | ||||
return (-1); | return (-1); | ||||
sc->pci_dev = pi; | sc->pci_dev = pi; | ||||
pi->pi_arg = sc; | pi->pi_arg = sc; | ||||
return (0); | return (0); | ||||
} | } | ||||
Show All 35 Lines |