/* Copyright 1999, Be Incorporated. All Rights Reserved. This file may be used under the terms of the Be Sample Code License. */ #include "cm_private.h" #include #if !defined(_KERNEL_EXPORT_H) #include #endif /* _KERNEL_EXPORT_H */ static status_t mux_open(const char *name, uint32 flags, void **cookie); static status_t mux_close(void *cookie); static status_t mux_free(void *cookie); static status_t mux_control(void *cookie, uint32 op, void *data, size_t len); static status_t mux_read(void *cookie, off_t pos, void *data, size_t *len); static status_t mux_write(void *cookie, off_t pos, const void *data, size_t *len); device_hooks mux_hooks = { &mux_open, &mux_close, &mux_free, &mux_control, &mux_read, &mux_write, NULL, /* select */ NULL, /* deselect */ NULL, /* readv */ NULL /* writev */ }; typedef struct { int port_l; int port_r; int minval; int maxval; int leftshift; int mask; char name[B_OS_NAME_LENGTH]; } mux_info; const mux_info the_muxes[] = { { 0, 1, 1, 7, 5, 0xe0, "Sampling Input" }, { 0, -1, 0, 1, 4, 0x10, "Mic +20dB Selection" }, { 0x2a, -1, 0, 1, 0, 0x01, "MIDI Output To Synth" }, { 0x2a, -1, 0, 1, 1, 0x02, "MIDI Input To Synth" }, { 0x2a, -1, 0, 1, 2, 0x04, "MIDI Output To Port" }, }; static const uchar unmap_input[] = { 0, CMEDIA_PCI_INPUT_CD, CMEDIA_PCI_INPUT_DAC, CMEDIA_PCI_INPUT_AUX2, CMEDIA_PCI_INPUT_LINE, CMEDIA_PCI_INPUT_AUX1, CMEDIA_PCI_INPUT_MIC, CMEDIA_PCI_INPUT_MIX_OUT }; static uchar map_input(uchar val) { int i; for (i = 0; i < 8; i++) if (unmap_input[i] == val) return i; return 0; } static status_t mux_open( const char * name, uint32 flags, void ** cookie) { int ix; /* mux_dev * plex = NULL; */ ddprintf(("cmedia_pci: mux_open()\n")); *cookie = NULL; for (ix=0; ixopen_count, -1); return B_OK; } static status_t mux_free( void * cookie) { ddprintf(("cmedia_pci: mux_free()\n")); if (((mux_dev *)cookie)->open_count != 0) { dprintf("cmedia_pci: mux open_count is bad in mux_free()!\n"); } return B_OK; /* already done in close */ } static int get_mux_value( cmedia_pci_dev * card, int ix) { uchar val; if (ix < 0) { return -1; } if (ix > 4) { return -1; } val = get_indirect(card, the_muxes[ix].port_l); val &= the_muxes[ix].mask; val >>= the_muxes[ix].leftshift; if (ix == CMEDIA_PCI_INPUT_MUX) return unmap_input[val]; return val; } static int gather_info( mux_dev * mux, cmedia_pci_routing * data, int count) { int ix; cpu_status cp; cp = disable_interrupts(); acquire_spinlock(&mux->card->hardware); for (ix=0; ixcard, data[ix].selector); if (data[ix].value < 0) { break; } } release_spinlock(&mux->card->hardware); restore_interrupts(cp); return ix; } static status_t set_mux_value( cmedia_pci_dev * card, int selector, int value) { ddprintf(("set_mux_value(%d,%d)\n", selector, value)); if (selector < 0 || selector > 4) { ddprintf(("selector EINVAL\n")); return EINVAL; } if (selector == CMEDIA_PCI_INPUT_MUX) value = map_input(value); if (value < the_muxes[selector].minval || value > the_muxes[selector].maxval) { ddprintf(("value EINVAL\n")); return EINVAL; } set_indirect(card, the_muxes[selector].port_l, (value << the_muxes[selector].leftshift), the_muxes[selector].mask); if (the_muxes[selector].port_r > -1) { set_indirect(card, the_muxes[selector].port_r, (value << the_muxes[selector].leftshift), the_muxes[selector].mask); } return B_OK; } static int disperse_info( mux_dev * mux, cmedia_pci_routing * data, int count) { int ix; cpu_status cp; cp = disable_interrupts(); acquire_spinlock(&mux->card->hardware); for (ix=0; ixcard, data[ix].selector, data[ix].value) < B_OK) { break; } } release_spinlock(&mux->card->hardware); restore_interrupts(cp); return ix; } static status_t mux_control( void * cookie, uint32 iop, void * data, size_t len) { mux_dev * plex = (mux_dev *)cookie; status_t err = B_OK; ddprintf(("cmedia_pci: mux_control()\n")); /* slow printing */ switch (iop) { case B_ROUTING_GET_VALUES: ((cmedia_pci_routing_cmd *)data)->count = gather_info(plex, ((cmedia_pci_routing_cmd *)data)->data, ((cmedia_pci_routing_cmd *)data)->count); break; case B_ROUTING_SET_VALUES: ((cmedia_pci_routing_cmd *)data)->count = disperse_info(plex, ((cmedia_pci_routing_cmd *)data)->data, ((cmedia_pci_routing_cmd *)data)->count); break; default: err = B_BAD_VALUE; break; } return err; } static status_t mux_read( void * cookie, off_t pos, void * data, size_t * nread) { return EPERM; } static status_t mux_write( void * cookie, off_t pos, const void * data, size_t * nwritten) { return EPERM; }