Пример #1
0
status_t
arch_smp_init(kernel_args *args)
{
	TRACE(("%s: entry\n", __func__));

	if (!apic_available()) {
		// if we don't have an apic we can't do smp
		TRACE(("%s: apic not available for smp\n", __func__));
		return B_OK;
	}

	// setup some globals
	memcpy(sCPUAPICIds, args->arch_args.cpu_apic_id, sizeof(args->arch_args.cpu_apic_id));
	memcpy(sAPICVersions, args->arch_args.cpu_apic_version, sizeof(args->arch_args.cpu_apic_version));

	// set up the local apic on the boot cpu
	arch_smp_per_cpu_init(args, 0);

	if (args->num_cpus > 1) {
		// I/O interrupts start at ARCH_INTERRUPT_BASE, so all interrupts are shifted
		reserve_io_interrupt_vectors(3, 0xfd - ARCH_INTERRUPT_BASE);
		install_io_interrupt_handler(0xfd - ARCH_INTERRUPT_BASE, &x86_ici_interrupt, NULL, B_NO_LOCK_VECTOR);
		install_io_interrupt_handler(0xfe - ARCH_INTERRUPT_BASE, &x86_smp_error_interrupt, NULL, B_NO_LOCK_VECTOR);
		install_io_interrupt_handler(0xff - ARCH_INTERRUPT_BASE, &x86_spurious_interrupt, NULL, B_NO_LOCK_VECTOR);
	}

	return B_OK;
}
void
arch_debug_install_interrupt_handlers(void)
{
    install_io_interrupt_handler(INT_PS2_KEYBOARD, &debug_keyboard_interrupt,
                                 NULL, 0);
    sKeyboardHandlerInstalled = true;
}
Пример #3
0
/**
 * Sets IRQ for VMMDev.
 *
 * @returns Haiku error code.
 * @param   pvState  Pointer to the state info structure.
 */
static int VBoxGuestHaikuAddIRQ(void *pvState)
{
    status_t err;
    struct VBoxGuestDeviceState *pState = (struct VBoxGuestDeviceState *)pvState;

    AssertReturn(pState, VERR_INVALID_PARAMETER);

    err = install_io_interrupt_handler(pState->iIrqResId, VBoxGuestHaikuISR, pState,  0);
    if (err == B_OK)
        return VINF_SUCCESS;
    return VERR_DEV_IO_ERROR;
}
Пример #4
0
int
bus_setup_intr(device_t dev, struct resource *res, int p3, interrupt_handler int_func, void *cookie, void **tag)
{
	int irq = (int)res;

	struct int_tag *int_tag = (struct int_tag *) malloc(sizeof(struct int_tag));
	int_tag->int_func = int_func;
	int_tag->cookie = cookie;
	int_tag->irq = irq;
	*tag = int_tag;

	return install_io_interrupt_handler(irq, int_func, cookie, 0);
}
Пример #5
0
static status_t
hpet_init_timer(hpet_timer_cookie* cookie)
{
	struct hpet_timer *timer = cookie->timer;

	uint32 interrupts = (uint32)HPET_GET_CAP_TIMER_ROUTE(timer);

	// TODO: Check if the interrupt is already used, and try another
	int32 interrupt = -1;	
	for (int i = 0; i < 32; i++) {
		if (interrupts & (1 << i)) {
			interrupt = i;
			break;
		}
	}

	if (interrupt == -1) {
		dprintf("hpet_init_timer(): timer can't be routed to any interrupt!");
		return B_ERROR;
	}
	// Non-periodic mode
	timer->config &= ~HPET_CONF_TIMER_TYPE;

	// level triggered
	timer->config |= HPET_CONF_TIMER_INT_TYPE;

	// Disable FSB/MSI
	timer->config &= ~HPET_CONF_TIMER_FSB_ENABLE;

#if HPET64
	//disable 32 bit mode
	timer->config &= ~HPET_CONF_TIMER_32MODE;
#else
	//enable 32 bit mode
	timer->config |= HPET_CONF_TIMER_32MODE;
#endif

	timer->config |= (interrupt << HPET_CONF_TIMER_INT_ROUTE_SHIFT)
		& HPET_CONF_TIMER_INT_ROUTE_MASK;

	cookie->irq = interrupt = HPET_GET_CONF_TIMER_INT_ROUTE(timer);
	status_t status = install_io_interrupt_handler(interrupt, &hpet_timer_interrupt, cookie, 0);
	if (status != B_OK) {
		dprintf("hpet_init_timer(): cannot install interrupt handler: %s\n", strerror(status));
		return status;
	}
#ifdef TRACE_HPET
	hpet_dump_timer(timer);
#endif
	return B_OK;
}
Пример #6
0
/**
 * Sets IRQ for VMMDev.
 *
 * @returns Haiku error code.
 * @param   pvState  Pointer to the state info structure.
 */
static int VBoxGuestHaikuAddIRQ(void *pvState)
{
    status_t status;
    struct VBoxGuestDeviceState *pState = (struct VBoxGuestDeviceState *)pvState;

    status = install_io_interrupt_handler(pState->iIrqResId, VBoxGuestHaikuISR, pState,  0);

    if (status != B_OK)
    {
        return VERR_DEV_IO_ERROR;
    }

    return VINF_SUCCESS;
}
Пример #7
0
static status_t
b57_open(const char *name, uint32 flags, void **cookie)
{
	struct be_b57_dev *pDevice = NULL;
	int i;

	*cookie = NULL;
	for (i = 0; i < cards_found; i++) {
		if (strcmp(dev_list[i],name) == 0) {
			*cookie = pDevice = &be_b57_dev_cards[i];
			break;
		}
	}

	if (*cookie == NULL)
		return B_FILE_NOT_FOUND;

	if (atomic_or(&pDevice->opened, 1)) {
		*cookie = pDevice = NULL;
		return B_BUSY;
	}

	install_io_interrupt_handler(pDevice->pci_data.u.h0.interrupt_line,
		b57_interrupt, *cookie, 0);
	if (LM_InitializeAdapter(&pDevice->lm_dev) != LM_STATUS_SUCCESS) {
		atomic_and(&pDevice->opened,0);
		remove_io_interrupt_handler(pDevice->pci_data.u.h0.interrupt_line, b57_interrupt, *cookie);
		*cookie = NULL;
		return B_ERROR;
	}

	/*QQ_InitQueue(&pDevice->rx_out_of_buf_q.Container,
        MAX_RX_PACKET_DESC_COUNT);*/

	//pDevice->lm_dev.PhyCrcCount = 0;
	LM_EnableInterrupt(&pDevice->lm_dev);

	dprintf("Broadcom 57xx adapter successfully inited at %s:\n", name);
	dprintf("MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\n",
		pDevice->lm_dev.NodeAddress[0], pDevice->lm_dev.NodeAddress[1],
		pDevice->lm_dev.NodeAddress[2], pDevice->lm_dev.NodeAddress[3],
		pDevice->lm_dev.NodeAddress[4], pDevice->lm_dev.NodeAddress[5]);
	dprintf("PCI Data: 0x%08x\n", pDevice->pci_data.u.h0.base_registers[0]);
	dprintf("IRQ: %d\n", pDevice->pci_data.u.h0.interrupt_line);

	return B_OK;
}
Пример #8
0
static void
InitInterruptHandler(DeviceInfo& di)
{
	SharedInfo& si = *(di.sharedInfo);

	TRACE("enter InitInterruptHandler()\n");

	DisableVBI();					// disable & clear any pending interrupts
	si.bInterruptAssigned = false;	// indicate interrupt not assigned yet

	// Create a semaphore for vertical blank management.
	si.vertBlankSem = create_sem(0, di.name);
	if (si.vertBlankSem < 0)
		return;

	// Change the owner of the semaphores to the calling team (usually the
	// app_server).  This is required because apps can't aquire kernel
	// semaphores.

	thread_id threadID = find_thread(NULL);
	thread_info threadInfo;
	status_t status = get_thread_info(threadID, &threadInfo);
	if (status == B_OK)
		status = set_sem_owner(si.vertBlankSem, threadInfo.team);

	// If there is a valid interrupt assigned, set up interrupts.

	if (status == B_OK && di.pciInfo.u.h0.interrupt_pin != 0x00
		&& di.pciInfo.u.h0.interrupt_line != 0xff) {
		// We have a interrupt line to use.

		status = install_io_interrupt_handler(di.pciInfo.u.h0.interrupt_line,
			InterruptHandler, (void*)(&di), 0);

		if (status == B_OK)
			si.bInterruptAssigned = true;	// we can use interrupt related functions
	}

	if (status != B_OK) {
		// Interrupt does not exist; thus delete semaphore as it won't be used.
		delete_sem(si.vertBlankSem);
		si.vertBlankSem = -1;
	}
}
Пример #9
0
OMAP3Timer::OMAP3Timer(fdt_module_info *fdtModule, fdt_device_node node)
	: HardwareTimer(fdtModule, node),
	fSystemTime(0)
{
	fRegArea = fFDT->map_reg_range(node, 0, (void**)&fRegBase);
	if (fRegArea < 0)
		panic("Cannot map OMAP3Timer registers!");

	fInterrupt = fFDT->get_interrupt(node, 0);
	if (fInterrupt < 0)
		panic("Cannot get OMAP3Timer interrupt!");

	uint32 rev = fRegBase[TIDR];
	dprintf("OMAP: Found timer @ 0x%p, IRQ %d (rev %ld.%ld)\n", fRegBase, fInterrupt, (rev >> 4) & 0xf, rev & 0xf);

	// Let the timer run (so we can use it as clocksource)
	fRegBase[TCLR] |= 1;
	fRegBase[TIER] = 2; // Enable overflow interrupt

	install_io_interrupt_handler(fInterrupt, &OMAP3Timer::_InterruptWrapper, this, 0);
}
Пример #10
0
status_t
device_open(const char *name, uint32 flags, void **cookie)
{
	struct sis_info *info;
	area_id area;
	int id;

	// verify device access (we only allow one user at a time)
	{
		char *thisName;
		int32 mask;

		// search for device name
		for (id = 0; (thisName = gDeviceNames[id]) != NULL; id++) {
			if (!strcmp(name, thisName))
				break;
		}
		if (!thisName)
			return EINVAL;
	
		// check if device is already open
		mask = 1L << id;
		if (atomic_or(&gDeviceOpenMask, mask) & mask)
			return B_BUSY;
	}

	// allocate internal device structure
	if ((area = create_area(DEVICE_NAME " private data", cookie,
							B_ANY_KERNEL_ADDRESS,
							ROUND_TO_PAGE_SIZE(sizeof(struct sis_info)),
							B_FULL_LOCK, B_READ_AREA | B_WRITE_AREA)) < B_OK) {
		gDeviceOpenMask &= ~(1L << id);
		return B_NO_MEMORY;
	}
	info = (struct sis_info *)*cookie;
	memset(info, 0, sizeof(struct sis_info));

	info->cookieMagic = SiS_COOKIE_MAGIC;
	info->thisArea = area;
	info->id = id;
	info->pciInfo = pciInfo[id];
	info->registers = (addr_t)pciInfo[id]->u.h0.base_registers[0];

	if (sis900_getMACAddress(info))
		dprintf(DEVICE_NAME ": MAC address %02x:%02x:%02x:%02x:%02x:%02x\n",
			  info->address.ebyte[0], info->address.ebyte[1], info->address.ebyte[2],
			  info->address.ebyte[3], info->address.ebyte[4], info->address.ebyte[5]);
	else
		dprintf(DEVICE_NAME ": could not get MAC address\n");

	readSettings(info);

	if (createSemaphores(info) == B_OK) {
		status_t status = sis900_initPHYs(info);
		if (status == B_OK) {
			TRACE((DEVICE_NAME ": MII status = %d\n", mdio_read(info, MII_STATUS)));

			//sis900_configFIFOs(info);
			sis900_reset(info);

			// install & enable interrupts
			install_io_interrupt_handler(info->pciInfo->u.h0.interrupt_line,
				sis900_interrupt, info, 0);
			sis900_enableInterrupts(info);

			sis900_setRxFilter(info);
			sis900_createRings(info);

			// enable receiver's state machine
			write32(info->registers + SiS900_MAC_COMMAND, SiS900_MAC_CMD_Rx_ENABLE);

			// check link mode & add timer (once every second)
			sis900_checkMode(info);
			add_timer(&info->timer, sis900_timer, 1000000LL, B_PERIODIC_TIMER);	

			return B_OK;
		}
		dprintf(DEVICE_NAME ": could not initialize MII PHY: %s\n", strerror(status));
		deleteSemaphores(info);
	} else
		dprintf(DEVICE_NAME ": could not create semaphores.\n");

	gDeviceOpenMask &= ~(1L << id);
	delete_area(area);

	return B_ERROR;
}
Пример #11
0
/* Initialize the BT-9X8 and confirm that it is operating as expected
*/
static long init_buslogic(BusLogic *bl)
{
    uchar status;
    uchar id[16];
    int i;
    char *str = bl->productname;

    d_printf("buslogic: init_buslogic()\n");

    dprintf("buslogic: reset: ");
    outb(BL_CONTROL_REG, BL_CONTROL_RHARD);
    spin(10000); /* give the controller some time to settle down from reset */

    for(i=0; i<1000; i++) {
        spin(100000);
        status = inb(BL_STATUS_REG);
        if(status & BL_STATUS_DACT) {
            dprintf(".");
            continue;
        }
        if(status & BL_STATUS_DFAIL) {
            dprintf(" FAILED\n");
            return -1;
        }
        if(status & BL_STATUS_INREQ) {
            dprintf(" OKAY\n");
            break;
        }
        if(status & BL_STATUS_HARDY) {
            dprintf(" READY\n");
            break;
        }
    }
    if(i==100) {
        dprintf(" TIMEOUT\n");
        return -1;
    }

    if(bl_execute(bl, 0x04, NULL, 0, id, 4)) {
        d_printf("buslogic: can't id?\n");
        return B_ERROR;
    }
    d_printf("buslogic: Firmware Rev %c.%c\n",id[2],id[3]);

    id[0]=14;
    id[14]=id[2];

    if(bl_execute(bl, 0x8d, id, 1, id, 14)) {
        d_printf("buslogic: cannot read extended config\n");
        return B_ERROR;
    }

    d_printf("buslogic: rev = %c.%c%c%c mb = %d, sgmax = %d, flags = 0x%02x\n",
             id[14], id[10], id[11], id[12], id[4], id[2] | (id[3]<<8), id[13]);
    if(id[13] & 0x01) bl->wide = 1;
    else bl->wide = 0;

    if(id[14] == '5') {
        *str++ = 'B';
        *str++ = 'T';
        *str++ = '-';
        *str++ = '9';
        *str++ = bl->wide ? '5' : '4';
        *str++ = '8';
        if(id[13] & 0x02) *str++ = 'D';
        *str++ = ' ';
        *str++ = 'v';
        *str++ = id[14];
        *str++ = '.';
        *str++ = id[10];
        *str++ = id[11];
        *str++ = id[12];
        *str++ = 0;
    } else {
        strcpy(str,"unknown");
    }
    if(bl_execute(bl, 0x0B, NULL, 0, id, 3)) {
        d_printf("buslogic: cannot read config\n");
        return B_ERROR;
    }
    bl->scsi_id = id[2];
    d_printf("buslogic: Adapter SCSI ID = %d\n",bl->scsi_id);

    if(install_io_interrupt_handler(bl->irq, scsi_int_dispatch, bl, 0)
            == B_ERROR) d_printf("buslogic: can't install irq handler\n");

    /* are we getting INTs? */
    bl->done = 0;
    spin(10000);
    outb(BL_COMMAND_REG, 0x00);
    spin(1000000);
    if(bl->done) {
        d_printf("buslogic: interrupt test passed\n");
    } else {
        d_printf("buslogic: interrupt test failed\n");
        return B_ERROR;
    }

    /* strict round-robin on */
    id[0] = 0;
    if(bl_execute(bl,0x8F, id, 1, NULL, 0)) {
        d_printf("buslogic: cannot enable strict round-robin mode\n");
        return B_ERROR;
    }


    id[0] = bl->box_count;
    {   int mbaddr = toLE(bl->phys_mailboxes);
        memcpy(id + 1, &(mbaddr),4);
    }
    if(bl_execute(bl, 0x81, id, 5, NULL, 0)) {
        d_printf("buslogic: cannot init mailboxes\n");
        return B_ERROR;
    }
    d_printf("buslogic: %d mailboxes @ 0x%08xv/0x%08lxp\n",
             bl->box_count, (uint) bl->out_boxes, bl->phys_mailboxes);

    return B_NO_ERROR;
}
Пример #12
0
static status_t
ice1712_setup(ice1712 *ice)
{
	int result, i;
	uint8 reg8 = 0;
	uint16 mute;

	ice->irq			= ice->info.u.h0.interrupt_line;
	ice->Controller		= ice->info.u.h0.base_registers[0];
	ice->DDMA			= ice->info.u.h0.base_registers[1];
	ice->DMA_Path		= ice->info.u.h0.base_registers[2];
	ice->Multi_Track	= ice->info.u.h0.base_registers[3];

	// Soft Reset
	write_ccs_uint8(ice, CCS_CONTROL_STATUS, 0x81);
	snooze(200000);
	write_ccs_uint8(ice, CCS_CONTROL_STATUS, 0x01);
	snooze(200000);

	result = read_eeprom(ice, ice->eeprom_data);

/*	TRACE("EEprom -> ");
	for (i = 0; i < 32; i++)
		TRACE("%x, ", eeprom_data[i]);
	TRACE("<- EEprom\n");*/

	write_ccs_uint8(ice, CCS_SERR_SHADOW, 0x01);

	//Write all configurations register from EEProm
	ice->info.device_id = ice->eeprom_data[E2PROM_MAP_SUBVENDOR_HIGH] << 8
		| ice->eeprom_data[E2PROM_MAP_SUBVENDOR_LOW];
	ice->info.vendor_id = ice->eeprom_data[E2PROM_MAP_SUBDEVICE_HIGH] << 8
		| ice->eeprom_data[E2PROM_MAP_SUBDEVICE_LOW];
	ice->product = ice->info.vendor_id << 16 | ice->info.device_id;
	TRACE("Product ID : 0x%x\n", ice->product);

	write_cci_uint8(ice, CCI_GPIO_WRITE_MASK,
		ice->eeprom_data[E2PROM_MAP_GPIOMASK]);
	write_cci_uint8(ice, CCI_GPIO_DATA,
		ice->eeprom_data[E2PROM_MAP_GPIOSTATE]);
	write_cci_uint8(ice, CCI_GPIO_DIRECTION_CONTROL,
		ice->eeprom_data[E2PROM_MAP_GPIODIR]);

	TRACE("CCI_GPIO_WRITE_MASK : 0x%x\n",
		ice->eeprom_data[E2PROM_MAP_GPIOMASK]);
	TRACE("CCI_GPIO_DATA : 0x%x\n",
		ice->eeprom_data[E2PROM_MAP_GPIOSTATE]);
	TRACE("CCI_GPIO_DIRECTION_CONTROL : 0x%x\n",
		ice->eeprom_data[E2PROM_MAP_GPIODIR]);


	//Write Configuration in the PCI configuration Register
	(pci->write_pci_config)(ice->info.bus, ice->info.device,
		ice->info.function, 0x60, 1, ice->eeprom_data[E2PROM_MAP_CONFIG]);
	(pci->write_pci_config)(ice->info.bus, ice->info.device,
		ice->info.function, 0x61, 1, ice->eeprom_data[E2PROM_MAP_ACL]);
	(pci->write_pci_config)(ice->info.bus, ice->info.device,
		ice->info.function, 0x62, 1, ice->eeprom_data[E2PROM_MAP_I2S]);
	(pci->write_pci_config)(ice->info.bus, ice->info.device,
		ice->info.function, 0x63, 1, ice->eeprom_data[E2PROM_MAP_SPDIF]);

	TRACE("E2PROM_MAP_CONFIG : 0x%x\n", ice->eeprom_data[E2PROM_MAP_CONFIG]);
	reg8 = ice->eeprom_data[E2PROM_MAP_CONFIG];
	//Bits signification for E2PROM_MAP_CONFIG Byte
	//
	// 8   7   6   5   4   3   2   1   0
	//           |-D-|-C-|---B---|---A---
	//
	// D : MPU401 number minus 1
	// C : AC'97
	// B : Stereo ADC number minus 1 (=> 1 to 4)
	// A : Stereo DAC number minus 1 (=> 1 to 4)

	ice->config.nb_DAC = ((reg8 & 0x03) + 1) * 2;
	reg8 >>= 2;
	ice->config.nb_ADC = ((reg8 & 0x03) + 1) * 2;
	reg8 >>= 2;

	if ((reg8 & 0x01) != 0) {//Consumer AC'97 Exist
		TRACE("Consumer AC'97 does exist\n");
		//For now do nothing
/*		write_ccs_uint8(ice, CCS_CONS_AC97_COMMAND_STATUS, 0x40);
		snooze(10000);
		write_ccs_uint8(ice, CCS_CONS_AC97_COMMAND_STATUS, 0x00);
		snooze(20000);
*/	} else {
		TRACE("Consumer AC'97 does NOT exist\n");
	}
	reg8 >>= 1;
	ice->config.nb_MPU401 = (reg8 & 0x1) + 1;

	if (ice->config.nb_MPU401 > 0) {
		sprintf(ice->midi_interf[0].name, "midi/ice1712/%ld/1",
			ice - cards + 1);

		(*mpu401->create_device)(ice->Controller + CCS_MIDI_1_DATA,
			&ice->midi_interf[0].mpu401device,
			0x14121712,
			ice_1712_midi_interrupt_op,
			&ice->midi_interf[0]);

		names[num_names++] = ice->midi_interf[0].name;
		ice->midi_interf[0].card = ice;
		ice->midi_interf[0].int_mask = CCS_INTERRUPT_MIDI_1;
	}

	if (ice->config.nb_MPU401 > 1) {
		sprintf(ice->midi_interf[1].name, "midi/ice1712/%ld/2",
			ice - cards + 1);

		(*mpu401->create_device)(ice->Controller + CCS_MIDI_2_DATA,
			&ice->midi_interf[1].mpu401device,
			0x14121712,
			ice_1712_midi_interrupt_op,
			&ice->midi_interf[1]);

		names[num_names++] = ice->midi_interf[1].name;
		ice->midi_interf[1].card = ice;
		ice->midi_interf[1].int_mask = CCS_INTERRUPT_MIDI_2;
	}

	TRACE("E2PROM_MAP_SPDIF : 0x%x\n", ice->eeprom_data[E2PROM_MAP_SPDIF]);
	ice->config.spdif = ice->eeprom_data[E2PROM_MAP_SPDIF];

	switch (ice->product) {
		case ICE1712_SUBDEVICE_DELTA66 :
		case ICE1712_SUBDEVICE_DELTA44 :
			ice->CommLines.clock = DELTA66_CLK;
			ice->CommLines.data_in = 0;
			ice->CommLines.data_out = DELTA66_DOUT;
			ice->CommLines.cs_mask = DELTA66_CLK | DELTA66_DOUT
				| DELTA66_CODEC_CS_0 | DELTA66_CODEC_CS_1;
			break;
		case ICE1712_SUBDEVICE_DELTA410 :
		case ICE1712_SUBDEVICE_AUDIOPHILE_2496 :
		case ICE1712_SUBDEVICE_DELTADIO2496 :
			ice->CommLines.clock = AP2496_CLK;
			ice->CommLines.data_in = AP2496_DIN;
			ice->CommLines.data_out = AP2496_DOUT;
			ice->CommLines.cs_mask = AP2496_CLK | AP2496_DIN
				| AP2496_DOUT | AP2496_SPDIF_CS | AP2496_CODEC_CS;
			break;
		case ICE1712_SUBDEVICE_DELTA1010 :
		case ICE1712_SUBDEVICE_DELTA1010LT :
			ice->CommLines.clock = DELTA1010LT_CLK;
			ice->CommLines.data_in = DELTA1010LT_DIN;
			ice->CommLines.data_out = DELTA1010LT_DOUT;
			ice->CommLines.cs_mask = DELTA1010LT_CLK | DELTA1010LT_DIN
				| DELTA1010LT_DOUT | DELTA1010LT_CS_NONE;
			break;
		case ICE1712_SUBDEVICE_VX442 :
			ice->CommLines.clock = VX442_CLK;
			ice->CommLines.data_in = VX442_DIN;
			ice->CommLines.data_out = VX442_DOUT;
			ice->CommLines.cs_mask = VX442_SPDIF_CS | VX442_CODEC_CS_0
				| VX442_CODEC_CS_1;
			break;
	}

	sprintf(ice->name, "%s/%ld", HMULTI_AUDIO_DEV_PATH, ice - cards + 1);
	names[num_names++] = ice->name;
	names[num_names] = NULL;

	ice->buffer_ready_sem = create_sem(0, "Buffer Exchange");
	if (ice->buffer_ready_sem < B_OK) {
		return ice->buffer_ready_sem;
	}

//	TRACE("installing interrupt : %0x\n", ice->irq);
	install_io_interrupt_handler(ice->irq, ice_1712_int, ice, 0);

	ice->mem_id_pb = alloc_mem(&ice->phys_addr_pb, &ice->log_addr_pb,
								PLAYBACK_BUFFER_TOTAL_SIZE,
								"playback buffer");
	if (ice->mem_id_pb < B_OK) {
		remove_io_interrupt_handler(ice->irq, ice_1712_int, ice);
		delete_sem(ice->buffer_ready_sem);
		return ice->mem_id_pb;
	}

	ice->mem_id_rec = alloc_mem(&ice->phys_addr_rec, &ice->log_addr_rec,
								RECORD_BUFFER_TOTAL_SIZE,
								"record buffer");
	if (ice->mem_id_rec < B_OK) {
		remove_io_interrupt_handler(ice->irq, ice_1712_int, ice);
		delete_sem(ice->buffer_ready_sem);
		delete_area(ice->mem_id_pb);
		return(ice->mem_id_rec);
	}

	memset(ice->log_addr_pb, 0, PLAYBACK_BUFFER_TOTAL_SIZE);
	memset(ice->log_addr_rec, 0, RECORD_BUFFER_TOTAL_SIZE);

	ice->sampling_rate = 0x08;
	ice->buffer = 0;
	ice->frames_count = 0;
	ice->buffer_size = MAX_BUFFER_FRAMES;

	ice->total_output_channels = ice->config.nb_DAC;
	if (ice->config.spdif & SPDIF_OUT_PRESENT)
		ice->total_output_channels += 2;

	ice->total_input_channels = ice->config.nb_ADC + 2;
	if (ice->config.spdif & SPDIF_IN_PRESENT)
		ice->total_input_channels += 2;

	//Write bits in the GPIO
	write_cci_uint8(ice, CCI_GPIO_WRITE_MASK, ~(ice->CommLines.cs_mask));
	//Deselect CS
	write_cci_uint8(ice, CCI_GPIO_DATA, ice->CommLines.cs_mask);

	//Set the rampe volume to a faster one
	write_mt_uint16(ice, MT_VOLUME_CONTROL_RATE, 0x01);

	//All Analog outputs from DMA
	write_mt_uint16(ice, MT_ROUTING_CONTROL_PSDOUT,	0x0000);
	//All Digital output from DMA
	write_mt_uint16(ice, MT_ROUTING_CONTROL_SPDOUT,	0x0000);

	//Just to route all input to all output
//	write_mt_uint16(ice, MT_ROUTING_CONTROL_PSDOUT,	0xAAAA);
//	write_mt_uint32(ice, MT_CAPTURED_DATA,	0x76543210);

	//Just to route SPDIF Input to DAC 0
//	write_mt_uint16(ice, MT_ROUTING_CONTROL_PSDOUT,	0xAAAF);
//	write_mt_uint32(ice, MT_CAPTURED_DATA,	0x76543280);

	//Mute all input
	mute = (ICE1712_MUTE_VALUE << 0) | (ICE1712_MUTE_VALUE << 8);
	for (i = 0; i < 2 * ICE1712_HARDWARE_VOLUME; i++) {
		write_mt_uint8(ice, MT_VOLUME_CONTROL_CHANNEL_INDEX, i);
		write_mt_uint16(ice, MT_VOLUME_CONTROL_CHANNEL_INDEX, mute);
	}

	//Unmask Interrupt
	write_ccs_uint8(ice, CCS_CONTROL_STATUS, 0x41);

	reg8 = read_ccs_uint8(ice, CCS_INTERRUPT_MASK);
	TRACE("-----CCS----- = %x\n", reg8);
	write_ccs_uint8(ice, CCS_INTERRUPT_MASK, 0xEF);

/*	reg16 = read_ds_uint16(ice, DS_DMA_INT_MASK);
	TRACE("-----DS_DMA----- = %x\n", reg16);
	write_ds_uint16(ice, DS_DMA_INT_MASK, 0x0000);
*/
	reg8 = read_mt_uint8(ice, MT_DMA_INT_MASK_STATUS);
	TRACE("-----MT_DMA----- = %x\n", reg8);
	write_mt_uint8(ice, MT_DMA_INT_MASK_STATUS, 0x00);

	return B_OK;
};
Пример #13
0
OHCI::OHCI(pci_info *info, Stack *stack)
	:	BusManager(stack),
		fPCIInfo(info),
		fStack(stack),
		fOperationalRegisters(NULL),
		fRegisterArea(-1),
		fHccaArea(-1),
		fHcca(NULL),
		fInterruptEndpoints(NULL),
		fDummyControl(NULL),
		fDummyBulk(NULL),
		fDummyIsochronous(NULL),
		fFirstTransfer(NULL),
		fLastTransfer(NULL),
		fFinishTransfersSem(-1),
		fFinishThread(-1),
		fStopFinishThread(false),
		fProcessingPipe(NULL),
		fRootHub(NULL),
		fRootHubAddress(0),
		fPortCount(0)
{
	if (!fInitOK) {
		TRACE_ERROR("bus manager failed to init\n");
		return;
	}

	TRACE("constructing new OHCI host controller driver\n");
	fInitOK = false;

	mutex_init(&fEndpointLock, "ohci endpoint lock");

	// enable busmaster and memory mapped access
	uint16 command = sPCIModule->read_pci_config(fPCIInfo->bus,
		fPCIInfo->device, fPCIInfo->function, PCI_command, 2);
	command &= ~PCI_command_io;
	command |= PCI_command_master | PCI_command_memory;

	sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device,
		fPCIInfo->function, PCI_command, 2, command);

	// map the registers
	uint32 offset = sPCIModule->read_pci_config(fPCIInfo->bus,
		fPCIInfo->device, fPCIInfo->function, PCI_base_registers, 4);
	offset &= PCI_address_memory_32_mask;
	TRACE_ALWAYS("iospace offset: 0x%lx\n", offset);
	fRegisterArea = map_physical_memory("OHCI memory mapped registers",
		(void *)offset,	B_PAGE_SIZE, B_ANY_KERNEL_BLOCK_ADDRESS,
		B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_READ_AREA | B_WRITE_AREA,
		(void **)&fOperationalRegisters);
	if (fRegisterArea < B_OK) {
		TRACE_ERROR("failed to map register memory\n");
		return;
	}

	TRACE("mapped operational registers: %p\n", fOperationalRegisters);

	// Check the revision of the controller, which should be 10h
	uint32 revision = _ReadReg(OHCI_REVISION) & 0xff;
	TRACE("version %ld.%ld%s\n", OHCI_REVISION_HIGH(revision),
		OHCI_REVISION_LOW(revision), OHCI_REVISION_LEGACY(revision)
		? ", legacy support" : "");
	if (OHCI_REVISION_HIGH(revision) != 1 || OHCI_REVISION_LOW(revision) != 0) {
		TRACE_ERROR("unsupported OHCI revision\n");
		return;
	}

	void *hccaPhysicalAddress;
	fHccaArea = fStack->AllocateArea((void **)&fHcca, &hccaPhysicalAddress,
		sizeof(ohci_hcca), "USB OHCI Host Controller Communication Area");

	if (fHccaArea < B_OK) {
		TRACE_ERROR("unable to create the HCCA block area\n");
		return;
	}

	memset(fHcca, 0, sizeof(ohci_hcca));

	// Set Up Host controller
	// Dummy endpoints
	fDummyControl = _AllocateEndpoint();
	if (!fDummyControl)
		return;

	fDummyBulk = _AllocateEndpoint();
	if (!fDummyBulk) {
		_FreeEndpoint(fDummyControl);
		return;
	}

	fDummyIsochronous = _AllocateEndpoint();
	if (!fDummyIsochronous) {
		_FreeEndpoint(fDummyControl);
		_FreeEndpoint(fDummyBulk);
		return;
	}

	// Static endpoints that get linked in the HCCA
	fInterruptEndpoints = new(std::nothrow)
		ohci_endpoint_descriptor *[OHCI_STATIC_ENDPOINT_COUNT];
	if (!fInterruptEndpoints) {
		TRACE_ERROR("failed to allocate memory for interrupt endpoints\n");
		_FreeEndpoint(fDummyControl);
		_FreeEndpoint(fDummyBulk);
		_FreeEndpoint(fDummyIsochronous);
		return;
	}

	for (int32 i = 0; i < OHCI_STATIC_ENDPOINT_COUNT; i++) {
		fInterruptEndpoints[i] = _AllocateEndpoint();
		if (!fInterruptEndpoints[i]) {
			TRACE_ERROR("failed to allocate interrupt endpoint %ld", i);
			while (--i >= 0)
				_FreeEndpoint(fInterruptEndpoints[i]);
			_FreeEndpoint(fDummyBulk);
			_FreeEndpoint(fDummyControl);
			_FreeEndpoint(fDummyIsochronous);
			return;
		}
	}

	// build flat tree so that at each of the static interrupt endpoints
	// fInterruptEndpoints[i] == interrupt endpoint for interval 2^i
	uint32 interval = OHCI_BIGGEST_INTERVAL;
	uint32 intervalIndex = OHCI_STATIC_ENDPOINT_COUNT - 1;
	while (interval > 1) {
		uint32 insertIndex = interval / 2;
		while (insertIndex < OHCI_BIGGEST_INTERVAL) {
			fHcca->interrupt_table[insertIndex]
				= fInterruptEndpoints[intervalIndex]->physical_address;
			insertIndex += interval;
		}

		intervalIndex--;
		interval /= 2;
	}

	// setup the empty slot in the list and linking of all -> first
	fHcca->interrupt_table[0] = fInterruptEndpoints[0]->physical_address;
	for (int32 i = 1; i < OHCI_STATIC_ENDPOINT_COUNT; i++) {
		fInterruptEndpoints[i]->next_physical_endpoint
			= fInterruptEndpoints[0]->physical_address;
		fInterruptEndpoints[i]->next_logical_endpoint
			= fInterruptEndpoints[0];
	}

	// Now link the first endpoint to the isochronous endpoint
	fInterruptEndpoints[0]->next_physical_endpoint
		= fDummyIsochronous->physical_address;

	// Determine in what context we are running (Kindly copied from FreeBSD)
	uint32 control = _ReadReg(OHCI_CONTROL);
	if (control & OHCI_INTERRUPT_ROUTING) {
		TRACE_ALWAYS("smm is in control of the host controller\n");
		uint32 status = _ReadReg(OHCI_COMMAND_STATUS);
		_WriteReg(OHCI_COMMAND_STATUS, status | OHCI_OWNERSHIP_CHANGE_REQUEST);
		for (uint32 i = 0; i < 100 && (control & OHCI_INTERRUPT_ROUTING); i++) {
			snooze(1000);
			control = _ReadReg(OHCI_CONTROL);
		}

		if ((control & OHCI_INTERRUPT_ROUTING) != 0) {
			TRACE_ERROR("smm does not respond. resetting...\n");
			_WriteReg(OHCI_CONTROL, OHCI_HC_FUNCTIONAL_STATE_RESET);
			snooze(USB_DELAY_BUS_RESET);
		} else
			TRACE_ALWAYS("ownership change successful\n");
	} else {
		TRACE("cold started\n");
		snooze(USB_DELAY_BUS_RESET);
	}

	// This reset should not be necessary according to the OHCI spec, but
	// without it some controllers do not start.
	_WriteReg(OHCI_CONTROL, OHCI_HC_FUNCTIONAL_STATE_RESET);
	snooze(USB_DELAY_BUS_RESET);

	// We now own the host controller and the bus has been reset
	uint32 frameInterval = _ReadReg(OHCI_FRAME_INTERVAL);
	uint32 intervalValue = OHCI_GET_INTERVAL_VALUE(frameInterval);

	// Disable interrupts right before we reset
	_WriteReg(OHCI_COMMAND_STATUS, OHCI_HOST_CONTROLLER_RESET);
	// Nominal time for a reset is 10 us
	uint32 reset = 0;
	for (uint32 i = 0; i < 10; i++) {
		spin(10);
		reset = _ReadReg(OHCI_COMMAND_STATUS) & OHCI_HOST_CONTROLLER_RESET;
		if (reset == 0)
			break;
	}

	if (reset) {
		TRACE_ERROR("error resetting the host controller (timeout)\n");
		return;
	}

	// The controller is now in SUSPEND state, we have 2ms to go OPERATIONAL.
	// Interrupts are disabled.

	// Set up host controller register
	_WriteReg(OHCI_HCCA, (uint32)hccaPhysicalAddress);
	_WriteReg(OHCI_CONTROL_HEAD_ED, (uint32)fDummyControl->physical_address);
	_WriteReg(OHCI_BULK_HEAD_ED, (uint32)fDummyBulk->physical_address);
	// Disable all interrupts
	_WriteReg(OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTERRUPTS);
	// Switch on desired functional features
	control = _ReadReg(OHCI_CONTROL);
	control &= ~(OHCI_CONTROL_BULK_SERVICE_RATIO_MASK | OHCI_ENABLE_LIST
		| OHCI_HC_FUNCTIONAL_STATE_MASK | OHCI_INTERRUPT_ROUTING);
	control |= OHCI_ENABLE_LIST | OHCI_CONTROL_BULK_RATIO_1_4
		| OHCI_HC_FUNCTIONAL_STATE_OPERATIONAL;
	// And finally start the controller
	_WriteReg(OHCI_CONTROL, control);

	// The controller is now OPERATIONAL.
	frameInterval = (_ReadReg(OHCI_FRAME_INTERVAL) & OHCI_FRAME_INTERVAL_TOGGLE)
		^ OHCI_FRAME_INTERVAL_TOGGLE;
	frameInterval |= OHCI_FSMPS(intervalValue) | intervalValue;
	_WriteReg(OHCI_FRAME_INTERVAL, frameInterval);
	// 90% periodic
	uint32 periodic = OHCI_PERIODIC(intervalValue);
	_WriteReg(OHCI_PERIODIC_START, periodic);

	// Fiddle the No Over Current Protection bit to avoid chip bug
	uint32 desca = _ReadReg(OHCI_RH_DESCRIPTOR_A);
	_WriteReg(OHCI_RH_DESCRIPTOR_A, desca | OHCI_RH_NO_OVER_CURRENT_PROTECTION);
	_WriteReg(OHCI_RH_STATUS, OHCI_RH_LOCAL_POWER_STATUS_CHANGE);
	snooze(OHCI_ENABLE_POWER_DELAY);
	_WriteReg(OHCI_RH_DESCRIPTOR_A, desca);

	// The AMD756 requires a delay before re-reading the register,
	// otherwise it will occasionally report 0 ports.
	uint32 numberOfPorts = 0;
	for (uint32 i = 0; i < 10 && numberOfPorts == 0; i++) {
		snooze(OHCI_READ_DESC_DELAY);
		uint32 descriptor = _ReadReg(OHCI_RH_DESCRIPTOR_A);
		numberOfPorts = OHCI_RH_GET_PORT_COUNT(descriptor);
	}
	if (numberOfPorts > OHCI_MAX_PORT_COUNT)
		numberOfPorts = OHCI_MAX_PORT_COUNT;
	fPortCount = numberOfPorts;
	TRACE("port count is %d\n", fPortCount);

	// Create semaphore the finisher thread will wait for
	fFinishTransfersSem = create_sem(0, "OHCI Finish Transfers");
	if (fFinishTransfersSem < B_OK) {
		TRACE_ERROR("failed to create semaphore\n");
		return;
	}

	// Create the finisher service thread
	fFinishThread = spawn_kernel_thread(_FinishThread, "ohci finish thread",
		B_URGENT_DISPLAY_PRIORITY, (void *)this);
	resume_thread(fFinishThread);

	// Install the interrupt handler
	TRACE("installing interrupt handler\n");
	install_io_interrupt_handler(fPCIInfo->u.h0.interrupt_line,
		_InterruptHandler, (void *)this, 0);

	// Enable interesting interrupts now that the handler is in place
	_WriteReg(OHCI_INTERRUPT_ENABLE, OHCI_NORMAL_INTERRUPTS
		| OHCI_MASTER_INTERRUPT_ENABLE);

	TRACE("OHCI host controller driver constructed\n");
	fInitOK = true;
}
Пример #14
0
// probe devices with config_manager
static status_t
scan_bus(bus_type bus)
{
	const char *bus_name = "Unknown";
	uint64 cookie = 0;
	//status_t status;
	struct {
		device_info di;
		pci_info pi;
	} big_info;
	struct device_info &dinfo = big_info.di;
	
	switch (bus) {
	case B_ISA_BUS:
		bus_name = "ISA";
		break;
	case B_PCI_BUS:
		bus_name = "PCI";
		break;
	case B_PCMCIA_BUS:
	default:
		return EINVAL;
	}
	TRACE_ALWAYS("scanning %s bus...\n", bus_name);

//XXX: clean up this mess

	while ((gConfigManagerModule->get_next_device_info(bus, 
		&cookie, &big_info.di, sizeof(big_info)) == B_OK)) {
		// skip disabled devices
		if ((dinfo.flags & B_DEVICE_INFO_ENABLED) == 0)
			continue;
		// skip non configured devices
		if ((dinfo.flags & B_DEVICE_INFO_CONFIGURED) == 0)
			continue;
		// and devices in error
		if (dinfo.config_status < B_OK)
			continue;

		
		/*
		TRACE_ALWAYS("device: 0x%08lx 0x%08lx 0x%08lx 0x%08lx\n",
		dinfo.id[0], dinfo.id[1], dinfo.id[2], dinfo.id[3]);
		*/

		/*
		if (bus == B_PCI_BUS) {
			pci_info *pcii = (pci_info *)(((char *)&dinfo) + 
				dinfo.bus_dependent_info_offset);
			TRACE_ALWAYS("pci: %04x:%04x\n",
				pcii->vendor_id, pcii->device_id);
			if ((pcii->header_type & PCI_header_type_mask) == 
				PCI_header_type_generic) {
				TRACE_ALWAYS("subsys: %04x:%04x\n",
					pcii->u.h0.subsystem_vendor_id, pcii->u.h0.subsystem_id);
			}
		}
		*/
		
		const struct serial_support_descriptor *supported = NULL;
		for (int i = 0; sSupportedDevices[i].name; i++) {
			if (sSupportedDevices[i].bus != bus)
				continue;
			if (sSupportedDevices[i].match.class_base != PCI_undefined &&
				sSupportedDevices[i].match.class_base != dinfo.devtype.base)
				continue;
			if (sSupportedDevices[i].match.class_sub != PCI_undefined &&
				sSupportedDevices[i].match.class_sub != dinfo.devtype.subtype)
				continue;
			if (sSupportedDevices[i].match.class_api != PCI_undefined &&
				sSupportedDevices[i].match.class_api != dinfo.devtype.interface)
				continue;

#if 0
			// either this way
			if (bus == B_PCI_BUS) {
				pci_info *pcii = (pci_info *)(((char *)&dinfo) + 
					dinfo.bus_dependent_info_offset);
				if (sSupportedDevices[i].match.vendor_id != PCI_INVAL &&
					sSupportedDevices[i].match.vendor_id != pcii->vendor_id)
					continue;
				if (sSupportedDevices[i].match.device_id != PCI_INVAL &&
					sSupportedDevices[i].match.device_id != pcii->device_id)
					continue;
			}
#endif
			// or this one:
			// .id[0] = vendor_id and .id[1] = device_id
			// .id[3?] = subsys_vendor_id and .id[2?] = subsys_device_id
			if (bus == B_PCI_BUS &&
				sSupportedDevices[i].match.vendor_id != PCI_INVAL &&
				sSupportedDevices[i].match.vendor_id != dinfo.id[0])
				continue;

			if (bus == B_PCI_BUS &&
				sSupportedDevices[i].match.device_id != PCI_INVAL &&
				sSupportedDevices[i].match.device_id != dinfo.id[1])
				continue;


			supported = &sSupportedDevices[i];
			break;
		}
		if (supported == NULL)
			continue;

		struct {
			struct device_configuration c;
			resource_descriptor res[16];
		} config;
		if (gConfigManagerModule->get_size_of_current_configuration_for(
			cookie) > (int)sizeof(config)) {
			TRACE_ALWAYS("config size too big for device\n");
			continue;
		}
			
		if (gConfigManagerModule->get_current_configuration_for(cookie,
			&config.c, sizeof(config)) < B_OK) {
			TRACE_ALWAYS("can't get config for device\n");
			continue;
			
		}

		TRACE_ALWAYS("device %Ld resources: %d irq %d dma %d io %d mem\n",
			cookie,
			gConfigManagerModule->count_resource_descriptors_of_type(
				&config.c, B_IRQ_RESOURCE),
			gConfigManagerModule->count_resource_descriptors_of_type(
				&config.c, B_DMA_RESOURCE),
			gConfigManagerModule->count_resource_descriptors_of_type(
				&config.c, B_IO_PORT_RESOURCE),
			gConfigManagerModule->count_resource_descriptors_of_type(
				&config.c, B_MEMORY_RESOURCE));


		// we first need the IRQ
		resource_descriptor irqdesc;
		if (gConfigManagerModule->get_nth_resource_descriptor_of_type(
			&config.c, 0, B_IRQ_RESOURCE, &irqdesc, sizeof(irqdesc)) < B_OK) {
			TRACE_ALWAYS("can't find IRQ for device\n");
			continue;
		}
		int irq;
		// XXX: what about APIC lines ?
		for (irq = 0; irq < 32; irq++) {
			if (irqdesc.d.m.mask & (1 << irq))
				break;
		}
		//TRACE_ALWAYS("irq %d\n", irq);
		//TRACE_ALWAYS("irq: %lx,%lx,%lx\n", irqdesc.d.m.mask, irqdesc.d.m.flags, irqdesc.d.m.cookie);

		TRACE_ALWAYS("found %s device %Ld [%x|%x|%x] "
			/*"ID: '%16.16s'"*/" irq: %d flags: %08lx status: %s\n",
			bus_name, cookie, dinfo.devtype.base, dinfo.devtype.subtype,
			dinfo.devtype.interface, /*dinfo.id,*/ irq, dinfo.flags,
			strerror(dinfo.config_status));

		// force enable I/O ports on PCI devices
#if 0
		if (bus == B_PCI_BUS) {
			pci_info *pcii = (pci_info *)(((char *)&dinfo) + 
				dinfo.bus_dependent_info_offset);
			
			uint32 cmd = gPCIModule->read_pci_config(pcii->bus, pcii->device,
				pcii->function, PCI_command, 2);
			TRACE_ALWAYS("PCI_command: 0x%04lx\n", cmd);
			cmd |= PCI_command_io;
			gPCIModule->write_pci_config(pcii->bus, pcii->device, 
				pcii->function, PCI_command, 2, cmd);
		}
#endif

		resource_descriptor iodesc;
		SerialDevice *master = NULL;

		//TODO: handle maxports
		//TODO: handle subsystem_id_mask

		// instanciate devices on IO ports
		for (int i = 0;
			gConfigManagerModule->get_nth_resource_descriptor_of_type(
			&config.c, i, B_IO_PORT_RESOURCE, &iodesc, sizeof(iodesc)) == B_OK;
			i++) {
			TRACE_ALWAYS("io at 0x%04lx len 0x%04lx\n", iodesc.d.r.minbase, 
				iodesc.d.r.len);

			if (iodesc.d.r.len < supported->constraints.minsize)
				continue;
			if (iodesc.d.r.len > supported->constraints.maxsize)
				continue;
			SerialDevice *device;
			uint32 ioport = iodesc.d.r.minbase;
next_split:
			// no more to split
			if ((ioport - iodesc.d.r.minbase) >= iodesc.d.r.len)
				continue;
		
			TRACE_ALWAYS("inserting device at io 0x%04lx as %s\n", ioport, 
				supported->name);


			device = new(std::nothrow) SerialDevice(supported, ioport, irq, master);
			if (device == NULL) {
				TRACE_ALWAYS("can't allocate device\n");
				continue;
			}

			if (pc_serial_insert_device(device) < B_OK) {
				TRACE_ALWAYS("can't insert device\n");
				continue;
			}
			if (master == NULL)
				master = device;
			
			ioport += supported->constraints.split;
			goto next_split;
			// try next part of the I/O range now
		}
		// we have at least one device
		if (master) {
			// hook up the irq
#if 0
			status = install_io_interrupt_handler(irq, pc_serial_interrupt, 
				master, 0);
			TRACE_ALWAYS("installing irq %d handler: %s\n", irq, strerror(status));
#endif
		}
	}
	return B_OK;
}
Пример #15
0
static status_t
open_hook(const char *name, uint32 flags, void** cookie)
{

	dp83815_properties_t *data;
	uint8 temp8;
//	uint16 temp16;
	uint32 temp32;
	unsigned char cmd;

	TRACE(( kDevName " open_hook()\n" ));

	// verify device access
	{
		char *thisName;
		int32 mask;

		// search for device name
		for (temp8 = 0; (thisName = dp83815_names[temp8]) != NULL; temp8++) {
			if (!strcmp(name, thisName))
				break;
		}
		if (!thisName)
			return EINVAL;

		// check if device is already open
		mask = 1L << temp8;
		if (atomic_or(&m_openmask, mask) & mask)
			return B_BUSY;
	}

	//Create a structure that contains the internals
	if (!(*cookie = data = (dp83815_properties_t *)malloc(sizeof(dp83815_properties_t))))
	{
		TRACE(( kDevName " open_hook(): Out of memory\n" ));
		return B_NO_MEMORY;
	}

	//Set status to open:
	m_openmask &= ~( 1L << temp8 );

	//Clear memory
	memset( data , 0 , sizeof( dp83815_properties_t ) );

	//Set the ID
	data->device_id = temp8;

	// Create lock
	data->lock = create_sem( 1 , kDevName " data protect" );
	set_sem_owner( data->lock , B_SYSTEM_TEAM );
	data->Rx.Sem = create_sem( 0 , kDevName " read wait" );
	set_sem_owner( data->Rx.Sem , B_SYSTEM_TEAM );
	data->Tx.Sem = create_sem( 1 , kDevName " write wait" );
	set_sem_owner( data->Tx.Sem , B_SYSTEM_TEAM );

	//Set up the cookie
	data->pcii = m_devices[data->device_id];

	//Enable the registers
	dp83815_init_registers( data );

	/* enable pci address access */
	cmd = m_pcimodule->read_pci_config(data->pcii->bus, data->pcii->device, data->pcii->function, PCI_command, 2);
	cmd = cmd | PCI_command_io | PCI_command_master | PCI_command_memory;
	m_pcimodule->write_pci_config(data->pcii->bus, data->pcii->device, data->pcii->function, PCI_command, 2, cmd );

	if (allocate_resources(data) != B_OK)
		goto err1;

	/* We want interrupts! */
	if ( install_io_interrupt_handler( data->pcii->u.h0.interrupt_line , dp83815_interrupt_hook , data , 0 ) != B_OK )
	{
		TRACE(( kDevName " open_hook(): Error installing interrupt handler\n" ));
		return B_ERROR;
	}

	{
		temp32 = read32(REG_SRR);
		TRACE(( "SRR: %x\n", temp32));
	}

	write32(REG_CR, CR_RXR|CR_TXR);			/*	Reset Tx & Rx		*/

	if ( init_ring_buffers(data) != B_OK )		/*	Init ring buffers	*/
		goto err1;

	write32(REG_RFCR, RFCR_RFEN|RFCR_AAB|RFCR_AAM|RFCR_AAU);

	write32(REG_RXCFG, RXCFG_ATP|RXCFG_DRTH(31));					/*	Set the drth		*/

	write32(REG_TXCFG, TXCFG_CSI|
						TXCFG_HBI|
						TXCFG_ATP|
						TXCFG_MXDMA_256|
						TXCFG_FLTH(16)|
						TXCFG_DRTH(16) );

	write32(REG_IMR, ISR_RXIDLE | ISR_TXOK | ISR_RXOK );

	write32(REG_CR, CR_RXE);			/*	Enable Rx				*/
	write32(REG_IER, 1);				/*	Enable interrupts		*/

	return B_OK;

	err1:
		free_resources(data);
		free(data);
		return B_ERROR;
}
Пример #16
0
static status_t
open_hook(const char* name, uint32 flags, void** cookie)
{
	int32 index = 0;
	device_info *di;
	shared_info *si;
	thread_id	thid;
	thread_info	thinfo;
	status_t	result = B_OK;
	char shared_name[B_OS_NAME_LENGTH];
	physical_entry map[1];
	size_t net_buf_size;
	void *unaligned_dma_buffer;

	/* find the device name in the list of devices */
	/* we're never passed a name we didn't publish */
	while (pd->device_names[index]
		&& (strcmp(name, pd->device_names[index]) != 0))
		index++;

	/* for convienience */
	di = &(pd->di[index]);

	/* make sure no one else has write access to the common data */
	AQUIRE_BEN(pd->kernel);

	/* if it's already open for writing */
	if (di->is_open) {
		/* mark it open another time */
		goto mark_as_open;
	}
	/* create the shared_info area */
	sprintf(shared_name, DEVICE_FORMAT " shared",
		di->pcii.vendor_id, di->pcii.device_id,
		di->pcii.bus, di->pcii.device, di->pcii.function);
	/* create this area with NO user-space read or write permissions, to prevent accidental damage */
	di->shared_area = create_area(shared_name, (void **)&(di->si), B_ANY_KERNEL_ADDRESS,
		((sizeof(shared_info) + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1)), B_FULL_LOCK,
		B_USER_CLONEABLE_AREA);
	if (di->shared_area < 0) {
		/* return the error */
		result = di->shared_area;
		goto done;
	}

	/* save a few dereferences */
	si = di->si;

	/* create the DMA command buffer area */
	//fixme? for R4.5 a workaround for cloning would be needed!
	/* we want to setup a 1Mb buffer (size must be multiple of B_PAGE_SIZE) */
	net_buf_size = ((1 * 1024 * 1024) + (B_PAGE_SIZE-1)) & ~(B_PAGE_SIZE-1);
	/* create the area that will hold the DMA command buffer */
	si->unaligned_dma_area =
		create_area("NV DMA cmd buffer",
			(void **)&unaligned_dma_buffer,
			B_ANY_KERNEL_ADDRESS,
			2 * net_buf_size, /* take twice the net size so we can have MTRR-WC even on old systems */
			B_32_BIT_CONTIGUOUS, /* GPU always needs access */
			B_USER_CLONEABLE_AREA | B_READ_AREA | B_WRITE_AREA);
			// TODO: Physical aligning can be done without waste using the
			// private create_area_etc().
	/* on error, abort */
	if (si->unaligned_dma_area < 0)
	{
		/* free the already created shared_info area, and return the error */
		result = si->unaligned_dma_area;
		goto free_shared;
	}
	/* we (also) need the physical adress our DMA buffer is at, as this needs to be
	 * fed into the GPU's engine later on. Get an aligned adress so we can use MTRR-WC
	 * even on older CPU's. */
	get_memory_map(unaligned_dma_buffer, B_PAGE_SIZE, map, 1);
	si->dma_buffer_pci = (void*)
		((map[0].address + net_buf_size - 1) & ~(net_buf_size - 1));

	/* map the net DMA command buffer into vmem, using Write Combining */
	si->dma_area = map_physical_memory(
		"NV aligned DMA cmd buffer", (addr_t)si->dma_buffer_pci, net_buf_size,
		B_ANY_KERNEL_BLOCK_ADDRESS | B_MTR_WC,
		B_READ_AREA | B_WRITE_AREA, &(si->dma_buffer));
	/* if failed with write combining try again without */
	if (si->dma_area < 0) {
		si->dma_area = map_physical_memory(
			"NV aligned DMA cmd buffer", (addr_t)si->dma_buffer_pci,
			net_buf_size, B_ANY_KERNEL_BLOCK_ADDRESS,
			B_READ_AREA | B_WRITE_AREA, &(si->dma_buffer));
	}
	/* if there was an error, delete our other areas and pass on error*/
	if (si->dma_area < 0)
	{
		/* free the already created areas, and return the error */
		result = si->dma_area;
		goto free_shared_and_uadma;
	}

	/* save the vendor and device IDs */
	si->vendor_id = di->pcii.vendor_id;
	si->device_id = di->pcii.device_id;
	si->revision = di->pcii.revision;
	si->bus = di->pcii.bus;
	si->device = di->pcii.device;
	si->function = di->pcii.function;

	/* ensure that the accelerant's INIT_ACCELERANT function can be executed */
	si->accelerant_in_use = false;
	/* preset singlehead card to prevent early INT routine calls (once installed) to
	 * wrongly identify the INT request coming from us! */
	si->ps.secondary_head = false;

	/* note the amount of system RAM the system BIOS assigned to the card if applicable:
	 * unified memory architecture (UMA) */
	switch ((((uint32)(si->device_id)) << 16) | si->vendor_id)
	{
	case 0x01a010de: /* Nvidia GeForce2 Integrated GPU */
		/* device at bus #0, device #0, function #1 holds value at byte-index 0x7C */
		si->ps.memory_size = 1024 * 1024 *
			(((((*pci_bus->read_pci_config)(0, 0, 1, 0x7c, 4)) & 0x000007c0) >> 6) + 1);
		/* last 64kB RAM is used for the BIOS (or something else?) */
		si->ps.memory_size -= (64 * 1024);
		break;
	case 0x01f010de: /* Nvidia GeForce4 MX Integrated GPU */
		/* device at bus #0, device #0, function #1 holds value at byte-index 0x84 */
		si->ps.memory_size = 1024 * 1024 *
			(((((*pci_bus->read_pci_config)(0, 0, 1, 0x84, 4)) & 0x000007f0) >> 4) + 1);
		/* last 64kB RAM is used for the BIOS (or something else?) */
		si->ps.memory_size -= (64 * 1024);
		break;
	default:
		/* all other cards have own RAM: the amount of which is determined in the
		 * accelerant. */
		break;
	}

	/* map the device */
	result = map_device(di);
	if (result < 0) goto free_shared_and_alldma;

	/* we will be returning OK status for sure now */
	result = B_OK;

	/* disable and clear any pending interrupts */
	//fixme:
	//distinquish between crtc1/crtc2 once all heads get seperate driver instances!
	disable_vbi_all(di->regs);

	/* preset we can't use INT related functions */
	si->ps.int_assigned = false;

	/* create a semaphore for vertical blank management */
	si->vblank = create_sem(0, di->name);
	if (si->vblank < 0) goto mark_as_open;

	/* change the owner of the semaphores to the opener's team */
	/* this is required because apps can't aquire kernel semaphores */
	thid = find_thread(NULL);
	get_thread_info(thid, &thinfo);
	set_sem_owner(si->vblank, thinfo.team);

	/* If there is a valid interrupt line assigned then set up interrupts */
	if ((di->pcii.u.h0.interrupt_pin == 0x00) ||
	    (di->pcii.u.h0.interrupt_line == 0xff) || /* no IRQ assigned */
	    (di->pcii.u.h0.interrupt_line <= 0x02))   /* system IRQ assigned */
	{
		/* delete the semaphore as it won't be used */
		delete_sem(si->vblank);
		si->vblank = -1;
	}
	else
	{
		/* otherwise install our interrupt handler */
		result = install_io_interrupt_handler(di->pcii.u.h0.interrupt_line, nv_interrupt, (void *)di, 0);
		/* bail if we couldn't install the handler */
		if (result != B_OK)
		{
			/* delete the semaphore as it won't be used */
			delete_sem(si->vblank);
			si->vblank = -1;
		}
		else
		{
			/* inform accelerant(s) we can use INT related functions */
			si->ps.int_assigned = true;
		}
	}

mark_as_open:
	/* mark the device open */
	di->is_open++;

	/* send the cookie to the opener */
	*cookie = di;

	goto done;


free_shared_and_alldma:
	/* clean up our aligned DMA area */
	delete_area(si->dma_area);
	si->dma_area = -1;
	si->dma_buffer = NULL;

free_shared_and_uadma:
	/* clean up our unaligned DMA area */
	delete_area(si->unaligned_dma_area);
	si->unaligned_dma_area = -1;
	si->dma_buffer_pci = NULL;

free_shared:
	/* clean up our shared area */
	delete_area(di->shared_area);
	di->shared_area = -1;
	di->si = NULL;

done:
	/* end of critical section */
	RELEASE_BEN(pd->kernel);

	/* all done, return the status */
	return result;
}
Пример #17
0
static void
init_interrupt_handler(intel_info &info)
{
    info.shared_info->vblank_sem = create_sem(0, "intel extreme vblank");
    if (info.shared_info->vblank_sem < B_OK)
        return;

    status_t status = B_OK;

    // We need to change the owner of the sem to the calling team (usually the
    // app_server), because userland apps cannot acquire kernel semaphores
    thread_id thread = find_thread(NULL);
    thread_info threadInfo;
    if (get_thread_info(thread, &threadInfo) != B_OK
            || set_sem_owner(info.shared_info->vblank_sem, threadInfo.team)
            != B_OK) {
        status = B_ERROR;
    }

    // Find the right interrupt vector, using MSIs if available.
    info.irq = 0xff;
    info.use_msi = false;
    if (info.pci->u.h0.interrupt_pin != 0x00)
        info.irq = info.pci->u.h0.interrupt_line;
    if (gPCIx86Module != NULL && gPCIx86Module->get_msi_count(info.pci->bus,
            info.pci->device, info.pci->function) >= 1) {
        uint8 msiVector = 0;
        if (gPCIx86Module->configure_msi(info.pci->bus, info.pci->device,
                                         info.pci->function, 1, &msiVector) == B_OK
                && gPCIx86Module->enable_msi(info.pci->bus, info.pci->device,
                                             info.pci->function) == B_OK) {
            ERROR("using message signaled interrupts\n");
            info.irq = msiVector;
            info.use_msi = true;
        }
    }

    if (status == B_OK && info.irq != 0xff) {
        // we've gotten an interrupt line for us to use

        info.fake_interrupts = false;

        status = install_io_interrupt_handler(info.irq,
                                              &intel_interrupt_handler, (void*)&info, 0);
        if (status == B_OK) {
            write32(info, INTEL_DISPLAY_A_PIPE_STATUS,
                    DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED);
            write32(info, INTEL_DISPLAY_B_PIPE_STATUS,
                    DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED);

            write16(info, find_reg(info, INTEL_INTERRUPT_IDENTITY), ~0);

            // enable interrupts - we only want VBLANK interrupts
            bool hasPCH = info.device_type.HasPlatformControlHub();
            uint16 enable = hasPCH
                            ? (PCH_INTERRUPT_VBLANK_PIPEA | PCH_INTERRUPT_VBLANK_PIPEB)
                            : (INTERRUPT_VBLANK_PIPEA | INTERRUPT_VBLANK_PIPEB);

            write16(info, find_reg(info, INTEL_INTERRUPT_ENABLED), enable);
            write16(info, find_reg(info, INTEL_INTERRUPT_MASK), ~enable);
        }
    }
    if (status < B_OK) {
        // There is no interrupt reserved for us, or we couldn't install our
        // interrupt handler, let's fake the vblank interrupt for our clients
        // using a timer interrupt
        info.fake_interrupts = true;

        // TODO: fake interrupts!
        TRACE("Fake interrupt mode (no PCI interrupt line assigned\n");
        status = B_ERROR;
    }

    if (status < B_OK) {
        delete_sem(info.shared_info->vblank_sem);
        info.shared_info->vblank_sem = B_ERROR;
    }
}
Пример #18
0
static status_t
wb840_open(const char *name, uint32 flags, void** cookie)
{
	char *deviceName = NULL;
	int32 i;
	int32 mask;
	struct wb_device *data;
	status_t status;
	
	LOG((DEVICE_NAME ": open()\n"));
	
	for (i = 0; (deviceName = gDevNameList[i]) != NULL; i++) {
		if (!strcmp(name, deviceName))
			break;
	}		
	
	if (deviceName == NULL) {
		LOG(("invalid device name"));
		return EINVAL;
	}
	
	// There can be only one access at time
	mask = 1L << i;
	if (atomic_or(&sOpenMask, mask) & mask)
		return B_BUSY;
	
	// Allocate a wb_device structure
	if (!(data = (wb_device *)malloc(sizeof(wb_device)))) {
		sOpenMask &= ~(1L << i);
		return B_NO_MEMORY;
	}
	
	memset(data, 0, sizeof(wb_device));
	
	*cookie = data;

#ifdef DEBUG
	load_driver_symbols("wb840");
#endif

	data->devId = i;
	data->pciInfo = gDevList[i];
	data->deviceName = gDevNameList[i];
	data->blockFlag = 0;
	data->reg_base = data->pciInfo->u.h0.base_registers[0];	
	data->wb_cachesize = gPci->read_pci_config(data->pciInfo->bus, data->pciInfo->device,
			data->pciInfo->function, PCI_line_size, sizeof (PCI_line_size)) & 0xff;
		
	wb_read_eeprom(data, &data->MAC_Address, 0, 3, false);
	
	status = wb_create_semaphores(data);
	if (status < B_OK) {
		LOG((DEVICE_NAME ": Couldn't create semaphores\n"));
		goto err;
	}
		
	status = wb_stop(data);
	if (status < B_OK) {
		LOG((DEVICE_NAME": Can't stop device\n"));
		goto err1;
	}
			
	status = wb_initPHYs(data);
	if (status < B_OK) {
		LOG((DEVICE_NAME": Can't init PHYs\n"));
		goto err1;
	}
		
	wb_init(data);
		
	/* Setup interrupts */
	data->irq = data->pciInfo->u.h0.interrupt_line;
	status = install_io_interrupt_handler(data->irq, wb_interrupt, data, 0);
	if (status < B_OK) {
		LOG((DEVICE_NAME
			" can't install interrupt handler: %s\n", strerror(status)));
		goto err1;		
	}
	
	LOG(("Interrupts installed at irq line %x\n", data->irq));
		
	status = wb_create_rings(data);
	if (status < B_OK) {
		LOG((DEVICE_NAME": can't create ring buffers\n"));
		goto err2;
	}
	
	wb_enable_interrupts(data);	
	
	WB_SETBIT(data->reg_base + WB_NETCFG, WB_NETCFG_RX_ON);
	write32(data->reg_base + WB_RXSTART, 0xFFFFFFFF);
	WB_SETBIT(data->reg_base + WB_NETCFG, WB_NETCFG_TX_ON);
	
	add_timer(&data->timer, wb_tick, 1000000LL, B_PERIODIC_TIMER);
		
	return B_OK; // Everything after this line is an error
		
err2:
	remove_io_interrupt_handler(data->irq, wb_interrupt, data);
	
err1:
	wb_delete_semaphores(data);
	
err:			
	sOpenMask &= ~(1L << i);
	
	free(data);	
	LOG(("wb840: Open Failed\n"));
	
	return status;
}
Пример #19
0
static status_t open_hook (const char* name, uint32 flags, void** cookie) {
	int32 index = 0;
	device_info *di;
	shared_info *si;
	thread_id	thid;
	thread_info	thinfo;
	status_t	result = B_OK;
	vuint32		*regs;
	char shared_name[B_OS_NAME_LENGTH];

	/* find the device name in the list of devices */
	/* we're never passed a name we didn't publish */
	while (pd->device_names[index] && (strcmp(name, pd->device_names[index]) != 0)) index++;

	/* for convienience */
	di = &(pd->di[index]);

	/* make sure no one else has write access to the common data */
	AQUIRE_BEN(pd->kernel);

	/* if it's already open for writing */
	if (di->is_open) {
		/* mark it open another time */
		goto mark_as_open;
	}
	/* create the shared area */
	sprintf(shared_name, DEVICE_FORMAT " shared",
		di->pcii.vendor_id, di->pcii.device_id,
		di->pcii.bus, di->pcii.device, di->pcii.function);
	/* create this area with NO user-space read or write permissions, to prevent accidental dammage */
	di->shared_area = create_area(shared_name, (void **)&(di->si), B_ANY_KERNEL_ADDRESS, ((sizeof(shared_info) + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1)), B_FULL_LOCK, 0);
	if (di->shared_area < 0) {
		/* return the error */
		result = di->shared_area;
		goto done;
	}

	/* save a few dereferences */
	si = di->si;

	/* save the vendor and device IDs */
	si->vendor_id = di->pcii.vendor_id;
	si->device_id = di->pcii.device_id;
	si->revision = di->pcii.revision;
	si->bus = di->pcii.bus;
	si->device = di->pcii.device;
	si->function = di->pcii.function;

	/* device at bus #0, device #0, function #0 holds byte value at byte-index 0xf6 */
	si->ps.chip_rev = ((*pci_bus->read_pci_config)(0, 0, 0, 0xf6, 1));

	/* map the device */
	result = map_device(di);
	if (result < 0) goto free_shared;
	result = B_OK;

	/* create a semaphore for vertical blank management */
	si->vblank = create_sem(0, di->name);
	if (si->vblank < 0) {
		result = si->vblank;
		goto unmap;
	}

	/* change the owner of the semaphores to the opener's team */
	/* this is required because apps can't aquire kernel semaphores */
	thid = find_thread(NULL);
	get_thread_info(thid, &thinfo);
	set_sem_owner(si->vblank, thinfo.team);

	/* assign local regs pointer for SAMPLExx() macros */
	regs = di->regs;

	/* disable and clear any pending interrupts */
	disable_vbi(regs);

	/* If there is a valid interrupt line assigned then set up interrupts */
	if ((di->pcii.u.h0.interrupt_pin == 0x00) ||
	    (di->pcii.u.h0.interrupt_line == 0xff) || /* no IRQ assigned */
	    (di->pcii.u.h0.interrupt_line <= 0x02))   /* system IRQ assigned */
	{
		/* we are aborting! */
		/* Note: the R4 graphics driver kit lacks this statement!! */
		result = B_ERROR;
		/* interrupt does not exist so exit without installing our handler */
		goto delete_the_sem;
	}
	else
	{
		/* otherwise install our interrupt handler */
		result = install_io_interrupt_handler(di->pcii.u.h0.interrupt_line, eng_interrupt, (void *)di, 0);
		/* bail if we couldn't install the handler */
		if (result != B_OK) goto delete_the_sem;
	}

mark_as_open:
	/* mark the device open */
	di->is_open++;

	/* send the cookie to the opener */
	*cookie = di;

	goto done;


delete_the_sem:
	delete_sem(si->vblank);

unmap:
	unmap_device(di);

free_shared:
	/* clean up our shared area */
	delete_area(di->shared_area);
	di->shared_area = -1;
	di->si = NULL;

done:
	/* end of critical section */
	RELEASE_BEN(pd->kernel);

	/* all done, return the status */
	return result;
}
Пример #20
0
/* init the adapter... if restarting, no bus reset or whathaveyou */
static long init_symbios(Symbios *s, int restarting)
{
    d_printf("symbios%ld: init_symbios()\n",s->num);

	if(restarting){
		s->reset = 1;
	} else {
		s->reset = 0;
	}

	if(!restarting){
		/* reset the SCSI bus */
		dprintf("symbios%ld: scsi bus reset\n",s->num);
		outb(sym_scntl1, sym_scntl1_rst);
		spin(25);
		outb(sym_scntl1, 0);
		spin(250000);

		/* clear ints */
		inb(sym_istat);
		inb(sym_sist0);
		inb(sym_sist1);
		inb(sym_dstat);

		install_io_interrupt_handler(s->irq, scsi_int_dispatch, s, 0);
		d_printf("symbios%ld: registered interrupt handler for irq %ld\n",s->num,s->irq);
	}

	/* enable irqs, prefetch, no 53c700 compat */
	outb(sym_dcntl, sym_dcntl_com);

	/* enable all DMA ints */
	outb(sym_dien, sym_dien_sir | sym_dien_mdpe | sym_dien_bf | sym_dien_abrt
		 | sym_dien_iid);
	/* enable all fatal SCSI ints */
	outb(sym_sien0, sym_sien0_ma | sym_sien0_sge | sym_sien0_udc | sym_sien0_rst |
		 sym_sien0_par);
	outb(sym_sien1, sym_sien1_sto | sym_sien1_sbmc); // XXX

	/* sel / hth timeouts */
	outb(sym_stime0, 0xbb);

	/* clear ints */
	inb(sym_istat);
	inb(sym_sist0);
	inb(sym_sist1);
	inb(sym_dstat);

	/* clear ints */
	inb(sym_sist0);
	inb(sym_sist1);
	inb(sym_dstat);

	if(restarting){
		s->reset = 0;
	} else {
		int i;
		s->status = TEST;

		dprintf("symbios%ld: selftest ",s->num);
		out32(sym_dsp, LE(s->sram_phys + Ent_test));
		for(i=0;(s->status == TEST) && i<10;i++) {
			dprintf(".");
			spin(10000);
		}
		if(s->status == TEST){
			dprintf("FAIL\n");
			return B_ERROR; //XXX teardown
		} else {
			dprintf("PASS\n");
		}
	}

	s->status = IDLE;
	out32(sym_dsp, LE(s->sram_phys + Ent_idle));
    d_printf("symbios%ld: started script\n",s->num);

    return B_NO_ERROR;
}
Пример #21
0
static status_t et6000OpenHook(const char* name, uint32 flags, void** cookie) {
int32 index = 0;
ET6000DeviceInfo *di;
ET6000SharedInfo *si;
status_t        result = B_OK;
char shared_name[B_OS_NAME_LENGTH];

    ddprintf(("SKD et6000OpenHook(%s, %ld, 0x%08lx)\n", name, flags, (uint32)cookie));

    /* find the device name in the list of devices */
    /* we're never passed a name we didn't publish */
    while(pd->deviceNames[index] &&
         (strcmp(name, pd->deviceNames[index]) != 0))
    {
        index++;
    }

    /* for convienience */
    di = &(pd->di[index]);

    /* make sure no one else has write access to the common data */
    AQUIRE_BEN(pd->kernel);

    /* if it's already open for writing */
    if (di->isOpen) {
        /* mark it open another time */
        goto mark_as_open;
    }
    /* create the shared area */
    sprintf(shared_name, "%04X_%04X_%02X%02X%02X shared",
        di->pcii.vendor_id, di->pcii.device_id,
        di->pcii.bus, di->pcii.device, di->pcii.function);
    /* create this area with NO user-space read or write permissions, to prevent accidental dammage */
    di->sharedArea = create_area(shared_name, (void **)&(di->si), B_ANY_KERNEL_ADDRESS, ((sizeof(ET6000SharedInfo) + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1)), B_FULL_LOCK,
		B_FULL_LOCK, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_USER_CLONEABLE_AREA);
    if (di->sharedArea < 0) {
        /* return the error */
        result = di->sharedArea;
        goto done;
    }

    /* save a few dereferences */
    si = di->si;

    /* save the vendor and device IDs */
    si->vendor_id = di->pcii.vendor_id;
    si->device_id = di->pcii.device_id;
    si->revision = di->pcii.revision;

    si->pixelClockMax16 = 135000;
    si->pixelClockMax24 = 135000;
    if (si->vendor_id == 0x100C) { /* Tseng Labs, Inc. */
        switch (si->device_id) {
        case 0x3208:/* ET6000/ET6100 */
            if (si->revision < 0x70) { /* ET6000 */
                si->pixelClockMax16 = 135000;
                si->pixelClockMax24 = 135000;
            }
            else { /* ET6100 */
                si->pixelClockMax16 = 175000;
                si->pixelClockMax24 = 175000;
            }
            break;
        case 0x4702: /* ET6300 */
            si->pixelClockMax16 = 220000;
            si->pixelClockMax24 = 220000;
            break;
        }
    }

    /* map the device */
    result = et6000MapDevice(di);
    if (result < 0)
        goto free_shared;
    result = B_OK;

    /*
     * Clear any pending interrupts and disable interrupts. Driver
     * currently does not use interrupts and unlikely will in future.
     */
    et6000aclReadInterruptClear(si->mmRegs);
    et6000aclWriteInterruptClear(si->mmRegs);
    et6000aclMasterInterruptDisable(si->mmRegs);

    /* Install the interrupt handler */
    result = install_io_interrupt_handler(di->pcii.u.h0.interrupt_line,
                                       et6000Interrupt, (void *)di, 0);
    /* bail if we couldn't install the handler */
    if (result != B_OK)
        goto unmap;

mark_as_open:
    /* mark the device open */
    di->isOpen++;

    /* send the cookie to the opener */
    *cookie = di;

    goto done;

unmap:
    et6000UnmapDevice(di);

free_shared:
    /* clean up our shared area */
    delete_area(di->sharedArea);
    di->sharedArea = -1;
    di->si = NULL;

done:
    /* end of critical section */
    RELEASE_BEN(pd->kernel);

    /* all done, return the status */
    ddprintf(("et6000OpenHook returning 0x%08lx\n", result));

    return result;
}