Beispiel #1
0
static ssize_t
powertecscsi_store_term(struct device *dev, const char *buf, size_t len)
{
	struct expansion_card *ec = ECARD_DEV(dev);
	struct Scsi_Host *host = ecard_get_drvdata(ec);

	if (len > 1)
		powertecscsi_terminator_ctl(host, buf[0] != '0');

	return len;
}
Beispiel #2
0
/* Prototype: int powertecscsi_set_proc_info(struct Scsi_Host *host, char *buffer, int length)
 * Purpose  : Set a driver specific function
 * Params   : host   - host to setup
 *          : buffer - buffer containing string describing operation
 *          : length - length of string
 * Returns  : -EINVAL, or 0
 */
static int
powertecscsi_set_proc_info(struct Scsi_Host *host, char *buffer, int length)
{
	int ret = length;

	if (length >= 12 && strncmp(buffer, "POWERTECSCSI", 12) == 0) {
		buffer += 12;
		length -= 12;

		if (length >= 5 && strncmp(buffer, "term=", 5) == 0) {
			if (buffer[5] == '1')
				powertecscsi_terminator_ctl(host, 1);
			else if (buffer[5] == '0')
				powertecscsi_terminator_ctl(host, 0);
			else
				ret = -EINVAL;
		} else
			ret = -EINVAL;
	} else
		ret = -EINVAL;

	return ret;
}
Beispiel #3
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;
}
Beispiel #4
0
static int __devinit
powertecscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
{
	struct Scsi_Host *host;
	struct powertec_info *info;
	unsigned long resbase, reslen;
	void __iomem *base;
	int ret;

	ret = ecard_request_resources(ec);
	if (ret)
		goto out;

	resbase = ecard_resource_start(ec, ECARD_RES_IOCFAST);
	reslen = ecard_resource_len(ec, ECARD_RES_IOCFAST);
	base = ioremap(resbase, reslen);
	if (!base) {
		ret = -ENOMEM;
		goto out_region;
	}

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

	ecard_set_drvdata(ec, host);

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

	info->info.scsi.io_base		= base + POWERTEC_FAS216_OFFSET;
	info->info.scsi.io_shift	= POWERTEC_FAS216_SHIFT;
	info->info.scsi.irq		= ec->irq;
	info->info.scsi.dma		= ec->dma;
	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;

	ec->irqaddr	= base + POWERTEC_INTR_STATUS;
	ec->irqmask	= POWERTEC_INTR_BIT;
	ec->irq_data	= info;
	ec->ops		= &powertecscsi_ops;

	device_create_file(&ec->dev, &dev_attr_bus_term);

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

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

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

	ret = fas216_add(host, &ec->dev);
	if (ret == 0)
		goto out;

	if (info->info.scsi.dma != NO_DMA)
		free_dma(info->info.scsi.dma);
	free_irq(ec->irq, host);

 out_release:
	fas216_release(host);

 out_free:
	device_remove_file(&ec->dev, &dev_attr_bus_term);
	scsi_host_put(host);

 out_unmap:
	iounmap(base);

 out_region:
	ecard_release_resources(ec);

 out:
	return ret;
}
Beispiel #5
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;
}