예제 #1
0
__initfunc(static void
ether3_get_dev(struct device *dev, struct expansion_card *ec))
{
	ecard_claim(ec);

	dev->base_addr = ecard_address(ec, ECARD_MEMC, 0);
	dev->irq = ec->irq;

	if (ec->cid.manufacturer == MANU_ANT &&
	    ec->cid.product == PROD_ANT_ETHERB) {
		dev->base_addr += 0x200;
	}

	ec->irqaddr = (volatile unsigned char *)ioaddr(dev->base_addr);
	ec->irqmask = 0xf0;

	ether3_addr(dev->dev_addr, ec);
}
예제 #2
0
static int
powertecscsi_probe(struct expansion_card *ec)
{
	struct Scsi_Host *host;
    	struct powertec_info *info;
    	unsigned long base;
	int ret;

	base = ecard_address(ec, ECARD_IOC, ECARD_FAST);

	request_region(base + POWERTEC_FAS216_OFFSET,
		       16 << POWERTEC_FAS216_SHIFT, "powertec2-fas");

	host = scsi_register(&powertecscsi_template,
			     sizeof (struct powertec_info));
	if (!host) {
		ret = -ENOMEM;
		goto out_region;
	}

	host->io_port	  = base;
	host->irq	  = ec->irq;
	host->dma_channel = ec->dma;

	ec->irqaddr	= (unsigned char *)ioaddr(base + POWERTEC_INTR_STATUS);
	ec->irqmask	= POWERTEC_INTR_BIT;
	ec->irq_data	= (void *)(base + POWERTEC_INTR_CONTROL);
	ec->ops		= (expansioncard_ops_t *)&powertecscsi_ops;

	info = (struct powertec_info *)host->hostdata;
	info->ec = ec;
	info->term_port = base + POWERTEC_TERM_CONTROL;
	powertecscsi_terminator_ctl(host, term[ec->slot_no]);

	info->info.scsi.io_port		= host->io_port + POWERTEC_FAS216_OFFSET;
	info->info.scsi.io_shift	= POWERTEC_FAS216_SHIFT;
	info->info.scsi.irq		= host->irq;
	info->info.ifcfg.clockrate	= 40; /* MHz */
	info->info.ifcfg.select_timeout	= 255;
	info->info.ifcfg.asyncperiod	= 200; /* ns */
	info->info.ifcfg.sync_max_depth	= 7;
	info->info.ifcfg.cntl3		= CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK;
	info->info.ifcfg.disconnect_ok	= 1;
	info->info.ifcfg.wide_max_size	= 0;
	info->info.ifcfg.capabilities	= 0;
	info->info.dma.setup		= powertecscsi_dma_setup;
	info->info.dma.pseudo		= NULL;
	info->info.dma.stop		= powertecscsi_dma_stop;

	ret = fas216_init(host);
	if (ret)
		goto out_free;

	ret = request_irq(host->irq, powertecscsi_intr,
			  SA_INTERRUPT, "powertec", &info->info);
	if (ret) {
		printk("scsi%d: IRQ%d not free: %d\n",
		       host->host_no, host->irq, ret);
		goto out_release;
	}

	if (host->dma_channel != NO_DMA) {
		if (request_dma(host->dma_channel, "powertec")) {
			printk("scsi%d: DMA%d not free, using PIO\n",
			       host->host_no, host->dma_channel);
			host->dma_channel = NO_DMA;
		} else {
			set_dma_speed(host->dma_channel, 180);
			info->info.ifcfg.capabilities |= FASCAP_DMA;
		}
	}

	ret = fas216_add(host);
	if (ret == 0)
		goto out;

	if (host->dma_channel != NO_DMA)
		free_dma(host->dma_channel);
	free_irq(host->irq, host);

 out_release:
	fas216_release(host);

 out_free:
	scsi_unregister(host);

 out_region:
	release_region(base + POWERTEC_FAS216_OFFSET,
		       16 << POWERTEC_FAS216_SHIFT);

 out:
	return ret;
}
예제 #3
0
static inline int
NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr, int len)
{
  int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
  int oldctrl = *ctrl;
  unsigned long *laddr;
#ifdef NOT_EFFICIENT
  int iobase = instance->io_port;
  int dma_io = iobase & ~(0x3C0000>>2);
#else
  volatile unsigned char *iobase = (unsigned char *)ioaddr(instance->io_port);
  volatile unsigned char *dma_io = (unsigned char *)((int)iobase & ~0x3C0000);
#endif

  if(!len) return 0;

  CTRL(iobase, 0x02);
  laddr = (unsigned long *)addr;
  while(len >= 32)
  {
    int status;
    unsigned long v;
    status = STAT(iobase);
    if(status & 0x80)
      goto end;
    if(!(status & 0x40))
      continue;
    v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
    v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
    v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
    v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
    v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
    v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
    v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
    v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
    len -= 32;
    if(len == 0)
      break;
  }

  addr = (unsigned char *)laddr;
  CTRL(iobase, 0x12);
  while(len > 0)
  {
    int status;
    status = STAT(iobase);
    if(status & 0x80)
      goto end;
    if(status & 0x40)
    {
      OUT(*addr++, dma_io);
      if(--len == 0)
        break;
    }

    status = STAT(iobase);
    if(status & 0x80)
      goto end;
    if(status & 0x40)
    {
      OUT(*addr++, dma_io);
      if(--len == 0)
        break;
    }
  }
end:
  CTRL(iobase, oldctrl|0x40);
  return len;
}
예제 #4
0
/* Prototype: int powertecscsi_detect(Scsi_Host_Template * tpnt)
 * Purpose  : initialises PowerTec SCSI driver
 * Params   : tpnt - template for this SCSI adapter
 * Returns  : >0 if host found, 0 otherwise.
 */
int
powertecscsi_detect(Scsi_Host_Template *tpnt)
{
	static const card_ids powertecscsi_cids[] =
			{ POWERTECSCSI_LIST, { 0xffff, 0xffff} };
	int count = 0;
	struct Scsi_Host *host;
  
	tpnt->proc_dir = &proc_scsi_powertec;
	memset(ecs, 0, sizeof (ecs));

	ecard_startfind();

	while (1) {
	    	PowerTecScsi_Info *info;

		ecs[count] = ecard_find(0, powertecscsi_cids);
		if (!ecs[count])
			break;

		ecard_claim(ecs[count]);

		host = scsi_register(tpnt, sizeof (PowerTecScsi_Info));
		if (!host) {
			ecard_release(ecs[count]);
			break;
		}

		host->io_port = ecard_address(ecs[count], ECARD_IOC, ECARD_FAST);
		host->irq = ecs[count]->irq;
		host->dma_channel = ecs[count]->dma;
		info = (PowerTecScsi_Info *)host->hostdata;

		info->control.term_port = host->io_port + POWERTEC_TERM_CONTROL;
		info->control.terms = term[count] ? POWERTEC_TERM_ENABLE : 0;
		powertecscsi_terminator_ctl(host, info->control.terms);

		info->info.scsi.io_port	=
				host->io_port + POWERTEC_FAS216_OFFSET;
		info->info.scsi.io_shift= POWERTEC_FAS216_SHIFT;
		info->info.scsi.irq		= host->irq;
		info->info.ifcfg.clockrate	= POWERTEC_XTALFREQ;
		info->info.ifcfg.select_timeout	= 255;
		info->info.ifcfg.asyncperiod	= POWERTEC_ASYNC_PERIOD;
		info->info.ifcfg.sync_max_depth	= POWERTEC_SYNC_DEPTH;
		info->info.ifcfg.cntl3		= /*CNTL3_BS8 |*/ CNTL3_FASTSCSI | CNTL3_FASTCLK;
		info->info.ifcfg.disconnect_ok	= 1;
		info->info.ifcfg.wide_max_size	= 0;
		info->info.dma.setup		= powertecscsi_dma_setup;
		info->info.dma.pseudo		= NULL;
		info->info.dma.stop		= powertecscsi_dma_stop;

		ecs[count]->irqaddr	= (unsigned char *)
			    ioaddr(host->io_port + POWERTEC_INTR_STATUS);
		ecs[count]->irqmask	= POWERTEC_INTR_BIT;
		ecs[count]->irq_data	= (void *)
			    (host->io_port + POWERTEC_INTR_CONTROL);
		ecs[count]->ops		= (expansioncard_ops_t *)&powertecscsi_ops;

		request_region(host->io_port + POWERTEC_FAS216_OFFSET,
			       16 << POWERTEC_FAS216_SHIFT, "powertec2-fas");

		if (host->irq != NO_IRQ &&
		    request_irq(host->irq, powertecscsi_intr,
				SA_INTERRUPT, "powertec", host)) {
			printk("scsi%d: IRQ%d not free, interrupts disabled\n",
			       host->host_no, host->irq);
			host->irq = NO_IRQ;
			info->info.scsi.irq = NO_IRQ;
		}

		if (host->dma_channel != NO_DMA &&
		    request_dma(host->dma_channel, "powertec")) {
			printk("scsi%d: DMA%d not free, DMA disabled\n",
			       host->host_no, host->dma_channel);
			host->dma_channel = NO_DMA;
		}

		fas216_init(host);
		++count;
	}
	return count;
}
예제 #5
0
/*
 * Probe for an expansion card.
 *
 * If bit 1 of the first byte of the card is set, then the
 * card does not exist.
 */
static int __init
ecard_probe(int slot, card_type_t type)
{
	ecard_t **ecp;
	ecard_t *ec;
	struct ex_ecid cid;
	int i, rc = -ENOMEM;

	ec = kmalloc(sizeof(ecard_t), GFP_KERNEL);
	if (!ec)
		goto nomem;

	memset(ec, 0, sizeof(ecard_t));

	ec->slot_no	= slot;
	ec->type        = type;
	ec->irq		= NO_IRQ;
	ec->fiq		= NO_IRQ;
	ec->dma		= NO_DMA;
	ec->card_desc	= NULL;
	ec->ops		= &ecard_default_ops;

	rc = -ENODEV;
	if ((ec->podaddr = ecard_address(ec, type, ECARD_SYNC)) == 0)
		goto nodev;

	cid.r_zero = 1;
	ecard_readbytes(&cid, ec, 0, 16, 0);
	if (cid.r_zero)
		goto nodev;

	ec->cid.id	= cid.r_id;
	ec->cid.cd	= cid.r_cd;
	ec->cid.is	= cid.r_is;
	ec->cid.w	= cid.r_w;
	ec->cid.manufacturer = ecard_getu16(cid.r_manu);
	ec->cid.product = ecard_getu16(cid.r_prod);
	ec->cid.country = cid.r_country;
	ec->cid.irqmask = cid.r_irqmask;
	ec->cid.irqoff  = ecard_gets24(cid.r_irqoff);
	ec->cid.fiqmask = cid.r_fiqmask;
	ec->cid.fiqoff  = ecard_gets24(cid.r_fiqoff);
	ec->fiqaddr	=
	ec->irqaddr	= (unsigned char *)ioaddr(ec->podaddr);

	if (ec->cid.is) {
		ec->irqmask = ec->cid.irqmask;
		ec->irqaddr += ec->cid.irqoff;
		ec->fiqmask = ec->cid.fiqmask;
		ec->fiqaddr += ec->cid.fiqoff;
	} else {
		ec->irqmask = 1;
		ec->fiqmask = 4;
	}

	for (i = 0; i < sizeof(blacklist) / sizeof(*blacklist); i++)
		if (blacklist[i].manufacturer == ec->cid.manufacturer &&
		    blacklist[i].product == ec->cid.product) {
			ec->card_desc = blacklist[i].type;
			break;
		}

	snprintf(ec->dev.bus_id, sizeof(ec->dev.bus_id), "ecard%d", slot);
	ec->dev.parent = NULL;
	ec->dev.bus    = &ecard_bus_type;
	ec->dev.dma_mask = &ec->dma_mask;
	ec->dma_mask = (u64)0xffffffff;

	ecard_init_resources(ec);

	/*
	 * hook the interrupt handlers
	 */
	ec->irq = 32 + slot;
	set_irq_chip(ec->irq, &ecard_chip);
	set_irq_handler(ec->irq, do_level_IRQ);
	set_irq_flags(ec->irq, IRQF_VALID);

	for (ecp = &cards; *ecp; ecp = &(*ecp)->next);

	*ecp = ec;
	slot_to_expcard[slot] = ec;

	device_register(&ec->dev);
	device_create_file(&ec->dev, &dev_attr_dma);
	device_create_file(&ec->dev, &dev_attr_irq);
	device_create_file(&ec->dev, &dev_attr_resource);
	device_create_file(&ec->dev, &dev_attr_vendor);
	device_create_file(&ec->dev, &dev_attr_device); 

	return 0;

nodev:
	kfree(ec);
nomem:
	return rc;
}