static int fs_init()

in firestream.c [1657:1888]


static int fs_init(struct fs_dev *dev)
{
	struct pci_dev  *pci_dev;
	int isr, to;
	int i;

	func_enter ();
	pci_dev = dev->pci_dev;

	printk (KERN_INFO "found a FireStream %d card, base %16llx, irq%d.\n",
		IS_FS50(dev)?50:155,
		(unsigned long long)pci_resource_start(pci_dev, 0),
		dev->pci_dev->irq);

	if (fs_debug & FS_DEBUG_INIT)
		my_hd ((unsigned char *) dev, sizeof (*dev));

	undocumented_pci_fix (pci_dev);

	dev->hw_base = pci_resource_start(pci_dev, 0);

	dev->base = ioremap(dev->hw_base, 0x1000);

	reset_chip (dev);
  
	write_fs (dev, SARMODE0, 0 
		  | (0 * SARMODE0_SHADEN) /* We don't use shadow registers. */
		  | (1 * SARMODE0_INTMODE_READCLEAR)
		  | (1 * SARMODE0_CWRE)
		  | (IS_FS50(dev) ? SARMODE0_PRPWT_FS50_5:
			  SARMODE0_PRPWT_FS155_3)
		  | (1 * SARMODE0_CALSUP_1)
		  | (IS_FS50(dev) ? (0
				   | SARMODE0_RXVCS_32
				   | SARMODE0_ABRVCS_32 
				   | SARMODE0_TXVCS_32):
		                  (0
				   | SARMODE0_RXVCS_1k
				   | SARMODE0_ABRVCS_1k 
				   | SARMODE0_TXVCS_1k)));

	/* 10ms * 100 is 1 second. That should be enough, as AN3:9 says it takes
	   1ms. */
	to = 100;
	while (--to) {
		isr = read_fs (dev, ISR);

		/* This bit is documented as "RESERVED" */
		if (isr & ISR_INIT_ERR) {
			printk (KERN_ERR "Error initializing the FS... \n");
			goto unmap;
		}
		if (isr & ISR_INIT) {
			fs_dprintk (FS_DEBUG_INIT, "Ha! Initialized OK!\n");
			break;
		}

		/* Try again after 10ms. */
		msleep(10);
	}

	if (!to) {
		printk (KERN_ERR "timeout initializing the FS... \n");
		goto unmap;
	}

	/* XXX fix for fs155 */
	dev->channel_mask = 0x1f; 
	dev->channo = 0;

	/* AN3: 10 */
	write_fs (dev, SARMODE1, 0 
		  | (fs_keystream * SARMODE1_DEFHEC) /* XXX PHY */
		  | ((loopback == 1) * SARMODE1_TSTLP) /* XXX Loopback mode enable... */
		  | (1 * SARMODE1_DCRM)
		  | (1 * SARMODE1_DCOAM)
		  | (0 * SARMODE1_OAMCRC)
		  | (0 * SARMODE1_DUMPE)
		  | (0 * SARMODE1_GPLEN) 
		  | (0 * SARMODE1_GNAM)
		  | (0 * SARMODE1_GVAS)
		  | (0 * SARMODE1_GPAS)
		  | (1 * SARMODE1_GPRI)
		  | (0 * SARMODE1_PMS)
		  | (0 * SARMODE1_GFCR)
		  | (1 * SARMODE1_HECM2)
		  | (1 * SARMODE1_HECM1)
		  | (1 * SARMODE1_HECM0)
		  | (1 << 12) /* That's what hang's driver does. Program to 0 */
		  | (0 * 0xff) /* XXX FS155 */);


	/* Cal prescale etc */

	/* AN3: 11 */
	write_fs (dev, TMCONF, 0x0000000f);
	write_fs (dev, CALPRESCALE, 0x01010101 * num);
	write_fs (dev, 0x80, 0x000F00E4);

	/* AN3: 12 */
	write_fs (dev, CELLOSCONF, 0
		  | (   0 * CELLOSCONF_CEN)
		  | (       CELLOSCONF_SC1)
		  | (0x80 * CELLOSCONF_COBS)
		  | (num  * CELLOSCONF_COPK)  /* Changed from 0xff to 0x5a */
		  | (num  * CELLOSCONF_COST));/* after a hint from Hang. 
					       * performance jumped 50->70... */

	/* Magic value by Hang */
	write_fs (dev, CELLOSCONF_COST, 0x0B809191);

	if (IS_FS50 (dev)) {
		write_fs (dev, RAS0, RAS0_DCD_XHLT);
		dev->atm_dev->ci_range.vpi_bits = 12;
		dev->atm_dev->ci_range.vci_bits = 16;
		dev->nchannels = FS50_NR_CHANNELS;
	} else {
		write_fs (dev, RAS0, RAS0_DCD_XHLT 
			  | (((1 << FS155_VPI_BITS) - 1) * RAS0_VPSEL)
			  | (((1 << FS155_VCI_BITS) - 1) * RAS0_VCSEL));
		/* We can chose the split arbitrarily. We might be able to 
		   support more. Whatever. This should do for now. */
		dev->atm_dev->ci_range.vpi_bits = FS155_VPI_BITS;
		dev->atm_dev->ci_range.vci_bits = FS155_VCI_BITS;
    
		/* Address bits we can't use should be compared to 0. */
		write_fs (dev, RAC, 0);

		/* Manual (AN9, page 6) says ASF1=0 means compare Utopia address
		 * too.  I can't find ASF1 anywhere. Anyway, we AND with just the
		 * other bits, then compare with 0, which is exactly what we
		 * want. */
		write_fs (dev, RAM, (1 << (28 - FS155_VPI_BITS - FS155_VCI_BITS)) - 1);
		dev->nchannels = FS155_NR_CHANNELS;
	}
	dev->atm_vccs = kcalloc (dev->nchannels, sizeof (struct atm_vcc *),
				 GFP_KERNEL);
	fs_dprintk (FS_DEBUG_ALLOC, "Alloc atmvccs: %p(%zd)\n",
		    dev->atm_vccs, dev->nchannels * sizeof (struct atm_vcc *));

	if (!dev->atm_vccs) {
		printk (KERN_WARNING "Couldn't allocate memory for VCC buffers. Woops!\n");
		/* XXX Clean up..... */
		goto unmap;
	}

	dev->tx_inuse = kzalloc (dev->nchannels / 8 /* bits/byte */ , GFP_KERNEL);
	fs_dprintk (FS_DEBUG_ALLOC, "Alloc tx_inuse: %p(%d)\n", 
		    dev->atm_vccs, dev->nchannels / 8);

	if (!dev->tx_inuse) {
		printk (KERN_WARNING "Couldn't allocate memory for tx_inuse bits!\n");
		/* XXX Clean up..... */
		goto unmap;
	}
	/* -- RAS1 : FS155 and 50 differ. Default (0) should be OK for both */
	/* -- RAS2 : FS50 only: Default is OK. */

	/* DMAMODE, default should be OK. -- REW */
	write_fs (dev, DMAMR, DMAMR_TX_MODE_FULL);

	init_q (dev, &dev->hp_txq, TX_PQ(TXQ_HP), TXQ_NENTRIES, 0);
	init_q (dev, &dev->lp_txq, TX_PQ(TXQ_LP), TXQ_NENTRIES, 0);
	init_q (dev, &dev->tx_relq, TXB_RQ, TXQ_NENTRIES, 1);
	init_q (dev, &dev->st_q, ST_Q, TXQ_NENTRIES, 1);

	for (i=0;i < FS_NR_FREE_POOLS;i++) {
		init_fp (dev, &dev->rx_fp[i], RXB_FP(i), 
			 rx_buf_sizes[i], rx_pool_sizes[i]);
		top_off_fp (dev, &dev->rx_fp[i], GFP_KERNEL);
	}


	for (i=0;i < FS_NR_RX_QUEUES;i++)
		init_q (dev, &dev->rx_rq[i], RXB_RQ(i), RXRQ_NENTRIES, 1);

	dev->irq = pci_dev->irq;
	if (request_irq (dev->irq, fs_irq, IRQF_SHARED, "firestream", dev)) {
		printk (KERN_WARNING "couldn't get irq %d for firestream.\n", pci_dev->irq);
		/* XXX undo all previous stuff... */
		goto unmap;
	}
	fs_dprintk (FS_DEBUG_INIT, "Grabbed irq %d for dev at %p.\n", dev->irq, dev);
  
	/* We want to be notified of most things. Just the statistics count
	   overflows are not interesting */
	write_fs (dev, IMR, 0
		  | ISR_RBRQ0_W 
		  | ISR_RBRQ1_W 
		  | ISR_RBRQ2_W 
		  | ISR_RBRQ3_W 
		  | ISR_TBRQ_W
		  | ISR_CSQ_W);

	write_fs (dev, SARMODE0, 0 
		  | (0 * SARMODE0_SHADEN) /* We don't use shadow registers. */
		  | (1 * SARMODE0_GINT)
		  | (1 * SARMODE0_INTMODE_READCLEAR)
		  | (0 * SARMODE0_CWRE)
		  | (IS_FS50(dev)?SARMODE0_PRPWT_FS50_5: 
		                  SARMODE0_PRPWT_FS155_3)
		  | (1 * SARMODE0_CALSUP_1)
		  | (IS_FS50 (dev)?(0
				    | SARMODE0_RXVCS_32
				    | SARMODE0_ABRVCS_32 
				    | SARMODE0_TXVCS_32):
		                   (0
				    | SARMODE0_RXVCS_1k
				    | SARMODE0_ABRVCS_1k 
				    | SARMODE0_TXVCS_1k))
		  | (1 * SARMODE0_RUN));

	init_phy (dev, PHY_NTC_INIT);

	if (loopback == 2) {
		write_phy (dev, 0x39, 0x000e);
	}

#ifdef FS_POLL_FREQ
	timer_setup(&dev->timer, fs_poll, 0);
	dev->timer.expires = jiffies + FS_POLL_FREQ;
	add_timer (&dev->timer);
#endif

	dev->atm_dev->dev_data = dev;
  
	func_exit ();
	return 0;
unmap:
	iounmap(dev->base);
	return 1;
}