예제 #1
0
/*
 * audioixp_attach()
 *
 * Description:
 *	Attach an instance of the audioixp driver. This routine does
 * 	the device dependent attach tasks.
 *
 * Arguments:
 *	dev_info_t	*dip	Pointer to the device's dev_info struct
 *	ddi_attach_cmd_t cmd	Attach command
 *
 * Returns:
 *	DDI_SUCCESS		The driver was initialized properly
 *	DDI_FAILURE		The driver couldn't be initialized properly
 */
static int
audioixp_attach(dev_info_t *dip)
{
	uint16_t		cmdeg;
	audioixp_state_t	*statep;
	audio_dev_t		*adev;
	uint32_t		devid;
	const char		*name;
	const char		*rev;

	/* we don't support high level interrupts in the driver */
	if (ddi_intr_hilevel(dip, 0) != 0) {
		cmn_err(CE_WARN,
		    "!%s%d: unsupported high level interrupt",
		    ddi_driver_name(dip), ddi_get_instance(dip));
		return (DDI_FAILURE);
	}

	/* allocate the soft state structure */
	statep = kmem_zalloc(sizeof (*statep), KM_SLEEP);
	statep->dip = dip;
	ddi_set_driver_private(dip, statep);

	if (ddi_get_iblock_cookie(dip, 0, &statep->iblock) != DDI_SUCCESS) {
		cmn_err(CE_WARN,
		    "!%s%d: cannot get iblock cookie",
		    ddi_driver_name(dip), ddi_get_instance(dip));
		kmem_free(statep, sizeof (*statep));
		return (DDI_FAILURE);
	}
	mutex_init(&statep->inst_lock, NULL, MUTEX_DRIVER, statep->iblock);

	/* allocate framework audio device */
	if ((adev = audio_dev_alloc(dip, 0)) == NULL) {
		cmn_err(CE_WARN, "!%s%d: unable to allocate audio dev",
		    ddi_driver_name(dip), ddi_get_instance(dip));
		goto error;
	}
	statep->adev = adev;

	/* map in the registers */
	if (audioixp_map_regs(statep) != DDI_SUCCESS) {
		audio_dev_warn(adev, "couldn't map registers");
		goto error;
	}

	/* set device information -- this could be smarter */
	devid = ((pci_config_get16(statep->pcih, PCI_CONF_VENID)) << 16) |
	    pci_config_get16(statep->pcih, PCI_CONF_DEVID);

	name = "ATI AC'97";
	switch (devid) {
	case IXP_PCI_ID_200:
		rev = "IXP150";
		break;
	case IXP_PCI_ID_300:
		rev = "SB300";
		break;
	case IXP_PCI_ID_400:
		if (pci_config_get8(statep->pcih, PCI_CONF_REVID) & 0x80) {
			rev = "SB450";
		} else {
			rev = "SB400";
		}
		break;
	case IXP_PCI_ID_SB600:
		rev = "SB600";
		break;
	default:
		rev = "Unknown";
		break;
	}
	audio_dev_set_description(adev, name);
	audio_dev_set_version(adev, rev);

	/* allocate port structures */
	if ((audioixp_alloc_port(statep, IXP_PLAY) != DDI_SUCCESS) ||
	    (audioixp_alloc_port(statep, IXP_REC) != DDI_SUCCESS)) {
		goto error;
	}

	statep->ac97 = ac97_alloc(dip, audioixp_rd97, audioixp_wr97, statep);
	if (statep->ac97 == NULL) {
		audio_dev_warn(adev, "failed to allocate ac97 handle");
		goto error;
	}

	/* set PCI command register */
	cmdeg = pci_config_get16(statep->pcih, PCI_CONF_COMM);
	pci_config_put16(statep->pcih, PCI_CONF_COMM,
	    cmdeg | PCI_COMM_IO | PCI_COMM_MAE);

	/* set up kernel statistics */
	if ((statep->ksp = kstat_create(IXP_NAME, ddi_get_instance(dip),
	    IXP_NAME, "controller", KSTAT_TYPE_INTR, 1,
	    KSTAT_FLAG_PERSISTENT)) != NULL) {
		kstat_install(statep->ksp);
	}


	if (audioixp_chip_init(statep) != DDI_SUCCESS) {
		audio_dev_warn(statep->adev, "failed to init chip");
		goto error;
	}

	/* initialize the AC'97 part */
	if (ac97_init(statep->ac97, adev) != DDI_SUCCESS) {
		audio_dev_warn(adev, "ac'97 initialization failed");
		goto error;
	}

	/* set up the interrupt handler */
	if (ddi_add_intr(dip, 0, &statep->iblock, NULL, audioixp_intr,
	    (caddr_t)statep) != DDI_SUCCESS) {
		audio_dev_warn(adev, "bad interrupt specification");
	}
	statep->intr_added = B_TRUE;

	if (audio_dev_register(adev) != DDI_SUCCESS) {
		audio_dev_warn(adev, "unable to register with framework");
		goto error;
	}

	ddi_report_dev(dip);

	return (DDI_SUCCESS);

error:
	audioixp_destroy(statep);
	return (DDI_FAILURE);
}
예제 #2
0
/*
 * audio1575_attach()
 *
 * Description:
 *	Attach an instance of the audio1575 driver. This routine does the
 * 	device dependent attach tasks. When it is completed, it registers
 *	with the audio framework.
 *
 * Arguments:
 *	dev_info_t	*dip	Pointer to the device's dev_info struct
 *
 * Returns:
 *	DDI_SUCCESS		The driver was initialized properly
 *	DDI_FAILURE		The driver couldn't be initialized properly
 */
static int
audio1575_attach(dev_info_t *dip)
{
	audio1575_state_t	*statep;
	audio_dev_t		*adev;
	uint32_t		devid;
	const char		*name;
	const char		*rev;
	int			maxch;

	/* allocate the soft state structure */
	statep = kmem_zalloc(sizeof (*statep), KM_SLEEP);
	ddi_set_driver_private(dip, statep);
	statep->dip = dip;

	/*
	 * We want the micboost enabled by default as well.
	 */
	(void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, AC97_PROP_MICBOOST, 1);

	/* allocate common audio dev structure */
	adev = audio_dev_alloc(dip, 0);
	if (adev == NULL) {
		audio_dev_warn(NULL, "unable to allocate audio dev");
		goto error;
	}
	statep->adev = adev;

	/* map in the audio registers */
	if (audio1575_map_regs(statep) != DDI_SUCCESS) {
		audio_dev_warn(adev, "couldn't map registers");
		goto error;
	}

	/* Enable PCI I/O and Memory Spaces */
	audio1575_pci_enable(statep);

	devid = (pci_config_get16(statep->pcih, PCI_CONF_VENID) << 16) |
	    pci_config_get16(statep->pcih, PCI_CONF_DEVID);
	switch (devid) {
	case 0x10b95455:
		name = "Uli M1575 AC'97";
		rev = "M5455";
		break;
	default:
		name = "Uli AC'97";
		rev = "Unknown";
		break;
	}
	/* set device information -- this should check PCI config space */
	audio_dev_set_description(adev, name);
	audio_dev_set_version(adev, rev);

	statep->ac97 = ac97_alloc(dip, audio1575_read_ac97,
	    audio1575_write_ac97, statep);
	ASSERT(statep->ac97 != NULL);

	/*
	 * Override "max-channels" property to prevent configuration
	 * of 4 or 6 (or possibly even 8!) channel audio.  The default
	 * is to support as many channels as the hardware can do.
	 */
	maxch = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
	    "max-channels", ac97_num_channels(statep->ac97));
	if (maxch < 2) {
		maxch = 2;
	}

	statep->maxch = min(maxch, 6) & ~1;

	/* allocate port structures */
	if ((audio1575_alloc_port(statep, M1575_PLAY, statep->maxch) !=
	    DDI_SUCCESS) ||
	    (audio1575_alloc_port(statep, M1575_REC, 2) != DDI_SUCCESS)) {
		goto error;
	}

	if (audio1575_chip_init(statep) != DDI_SUCCESS) {
		audio_dev_warn(adev, "failed to init chip");
		goto error;
	}

	if (ac97_init(statep->ac97, adev) != DDI_SUCCESS) {
		audio_dev_warn(adev, "ac'97 initialization failed");
		goto error;
	}

	/* register with the framework */
	if (audio_dev_register(adev) != DDI_SUCCESS) {
		audio_dev_warn(adev, "unable to register with framework");
		goto error;
	}

	/* everything worked out, so report the device */
	ddi_report_dev(dip);

	return (DDI_SUCCESS);

error:
	audio1575_destroy(statep);
	return (DDI_FAILURE);
}