static int lanai_dev_open()

in lanai.c [2106:2241]


static int lanai_dev_open(struct atm_dev *atmdev)
{
	struct lanai_dev *lanai = (struct lanai_dev *) atmdev->dev_data;
	unsigned long raw_base;
	int result;

	DPRINTK("In lanai_dev_open()\n");
	/* Basic device fields */
	lanai->number = atmdev->number;
	lanai->num_vci = NUM_VCI;
	bitmap_zero(lanai->backlog_vccs, NUM_VCI);
	bitmap_zero(lanai->transmit_ready, NUM_VCI);
	lanai->naal0 = 0;
#ifdef USE_POWERDOWN
	lanai->nbound = 0;
#endif
	lanai->cbrvcc = NULL;
	memset(&lanai->stats, 0, sizeof lanai->stats);
	spin_lock_init(&lanai->endtxlock);
	spin_lock_init(&lanai->servicelock);
	atmdev->ci_range.vpi_bits = 0;
	atmdev->ci_range.vci_bits = 0;
	while (1 << atmdev->ci_range.vci_bits < lanai->num_vci)
		atmdev->ci_range.vci_bits++;
	atmdev->link_rate = ATM_25_PCR;

	/* 3.2: PCI initialization */
	if ((result = lanai_pci_start(lanai)) != 0)
		goto error;
	raw_base = lanai->pci->resource[0].start;
	lanai->base = (bus_addr_t) ioremap(raw_base, LANAI_MAPPING_SIZE);
	if (lanai->base == NULL) {
		printk(KERN_ERR DEV_LABEL ": couldn't remap I/O space\n");
		result = -ENOMEM;
		goto error_pci;
	}
	/* 3.3: Reset lanai and PHY */
	reset_board(lanai);
	lanai->conf1 = reg_read(lanai, Config1_Reg);
	lanai->conf1 &= ~(CONFIG1_GPOUT1 | CONFIG1_POWERDOWN |
	    CONFIG1_MASK_LEDMODE);
	lanai->conf1 |= CONFIG1_SET_LEDMODE(LEDMODE_NOT_SOOL);
	reg_write(lanai, lanai->conf1 | CONFIG1_GPOUT1, Config1_Reg);
	udelay(1000);
	conf1_write(lanai);

	/*
	 * 3.4: Turn on endian mode for big-endian hardware
	 *   We don't actually want to do this - the actual bit fields
	 *   in the endian register are not documented anywhere.
	 *   Instead we do the bit-flipping ourselves on big-endian
	 *   hardware.
	 *
	 * 3.5: get the board ID/rev by reading the reset register
	 */
	result = check_board_id_and_rev("register",
	    reg_read(lanai, Reset_Reg), &lanai->board_rev);
	if (result != 0)
		goto error_unmap;

	/* 3.6: read EEPROM */
	if ((result = eeprom_read(lanai)) != 0)
		goto error_unmap;
	if ((result = eeprom_validate(lanai)) != 0)
		goto error_unmap;

	/* 3.7: re-reset PHY, do loopback tests, setup PHY */
	reg_write(lanai, lanai->conf1 | CONFIG1_GPOUT1, Config1_Reg);
	udelay(1000);
	conf1_write(lanai);
	/* TODO - loopback tests */
	lanai->conf1 |= (CONFIG1_GPOUT2 | CONFIG1_GPOUT3 | CONFIG1_DMA_ENABLE);
	conf1_write(lanai);

	/* 3.8/3.9: test and initialize card SRAM */
	if ((result = sram_test_and_clear(lanai)) != 0)
		goto error_unmap;

	/* 3.10: initialize lanai registers */
	lanai->conf1 |= CONFIG1_DMA_ENABLE;
	conf1_write(lanai);
	if ((result = service_buffer_allocate(lanai)) != 0)
		goto error_unmap;
	if ((result = vcc_table_allocate(lanai)) != 0)
		goto error_service;
	lanai->conf2 = (lanai->num_vci >= 512 ? CONFIG2_HOWMANY : 0) |
	    CONFIG2_HEC_DROP |	/* ??? */ CONFIG2_PTI7_MODE;
	conf2_write(lanai);
	reg_write(lanai, TX_FIFO_DEPTH, TxDepth_Reg);
	reg_write(lanai, 0, CBR_ICG_Reg);	/* CBR defaults to no limit */
	if ((result = request_irq(lanai->pci->irq, lanai_int, IRQF_SHARED,
	    DEV_LABEL, lanai)) != 0) {
		printk(KERN_ERR DEV_LABEL ": can't allocate interrupt\n");
		goto error_vcctable;
	}
	mb();				/* Make sure that all that made it */
	intr_enable(lanai, INT_ALL & ~(INT_PING | INT_WAKE));
	/* 3.11: initialize loop mode (i.e. turn looping off) */
	lanai->conf1 = (lanai->conf1 & ~CONFIG1_MASK_LOOPMODE) |
	    CONFIG1_SET_LOOPMODE(LOOPMODE_NORMAL) |
	    CONFIG1_GPOUT2 | CONFIG1_GPOUT3;
	conf1_write(lanai);
	lanai->status = reg_read(lanai, Status_Reg);
	/* We're now done initializing this card */
#ifdef USE_POWERDOWN
	lanai->conf1 |= CONFIG1_POWERDOWN;
	conf1_write(lanai);
#endif
	memcpy(atmdev->esi, eeprom_mac(lanai), ESI_LEN);
	lanai_timed_poll_start(lanai);
	printk(KERN_NOTICE DEV_LABEL "(itf %d): rev.%d, base=%p, irq=%u "
		"(%pMF)\n", lanai->number, (int) lanai->pci->revision,
		lanai->base, lanai->pci->irq, atmdev->esi);
	printk(KERN_NOTICE DEV_LABEL "(itf %d): LANAI%s, serialno=%u(0x%X), "
	    "board_rev=%d\n", lanai->number,
	    lanai->type==lanai2 ? "2" : "HB", (unsigned int) lanai->serialno,
	    (unsigned int) lanai->serialno, lanai->board_rev);
	return 0;

    error_vcctable:
	vcc_table_deallocate(lanai);
    error_service:
	service_buffer_deallocate(lanai);
    error_unmap:
	reset_board(lanai);
#ifdef USE_POWERDOWN
	lanai->conf1 = reg_read(lanai, Config1_Reg) | CONFIG1_POWERDOWN;
	conf1_write(lanai);
#endif
	iounmap(lanai->base);
	lanai->base = NULL;
    error_pci:
	pci_disable_device(lanai->pci);
    error:
	return result;
}