Example #1
0
static int macscsi_pwrite(struct Scsi_Host *instance,
                          unsigned char *src, int len)
{
	struct NCR5380_hostdata *hostdata = shost_priv(instance);
	unsigned char *s;
	unsigned char *d;

	NCR5380_local_declare();
	NCR5380_setup(instance);

	s = src;
	d = hostdata->pdma_base + (OUTPUT_DATA_REG << 4);

	/* These conditions are derived from MacOS */

	while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ) &&
	       (!(NCR5380_read(STATUS_REG) & SR_REQ) ||
	        (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)))
		;

	if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)) {
		pr_err("Error in macscsi_pwrite\n");
		return -1;
	}

	CP_MEM_TO_IO(s, d, len);

	if (len != 0) {
		pr_notice("Bus error in macscsi_pwrite\n");
		return -1;
	}

	return 0;
}
Example #2
0
static void mac_scsi_reset_boot(struct Scsi_Host *instance)
{
	unsigned long end;

	NCR5380_local_declare();
	NCR5380_setup(instance);
	
	/*
	 * Do a SCSI reset to clean up the bus during initialization. No messing
	 * with the queues, interrupts, or locks necessary here.
	 */

	printk(KERN_INFO "Macintosh SCSI: resetting the SCSI bus..." );

	/* get in phase */
	NCR5380_write( TARGET_COMMAND_REG,
		      PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) ));

	/* assert RST */
	NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST );
	/* The min. reset hold time is 25us, so 40us should be enough */
	udelay( 50 );
	/* reset RST and interrupt */
	NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
	NCR5380_read( RESET_PARITY_INTERRUPT_REG );

	for( end = jiffies + AFTER_RESET_DELAY; time_before(jiffies, end); )
		barrier();

	printk(KERN_INFO " done\n" );
}
Example #3
0
/* clean up after our dma is done */
static int sun3scsi_dma_finish(int write_flag)
{
	unsigned short count;
	unsigned short fifo;
	int ret = 0;
	
	sun3_dma_active = 0;

	// check to empty the fifo on a read
	if(!write_flag) {
		int tmo = 200000; /* 2 sec */
		
		while(1) {
			if(dregs->csr & CSR_FIFO_EMPTY)
				break;

			if(--tmo <= 0) 
				return 1;

			udelay(10);
		}
	}
		

	count = sun3scsi_dma_count(default_instance);
#ifdef OLDDMA

	/* if we've finished a read, copy out the data we read */
 	if(sun3_dma_orig_addr) {
		/* check for residual bytes after dma end */
		if(count && (NCR5380_read(BUS_AND_STATUS_REG) &
			     (BASR_PHASE_MATCH | BASR_ACK))) {
			printk("scsi%d: sun3_scsi_finish: read overrun baby... ", default_instance->host_no);
			printk("basr now %02x\n", NCR5380_read(BUS_AND_STATUS_REG));
			ret = count;
		}
		
		/* copy in what we dma'd no matter what */
		memcpy(sun3_dma_orig_addr, dmabuf, sun3_dma_orig_count);
		sun3_dma_orig_addr = NULL;

	}
#else

	fifo = dregs->fifo_count;
	last_residual = fifo;

	/* empty bytes from the fifo which didn't make it */
	if((!write_flag) && (count - fifo) == 2) {
		unsigned short data;
		unsigned char *vaddr;

		data = dregs->fifo_data;
		vaddr = (unsigned char *)dvma_btov(sun3_dma_orig_addr);
		
		vaddr += (sun3_dma_orig_count - fifo);

		vaddr[-2] = (data & 0xff00) >> 8;
		vaddr[-1] = (data & 0xff);
	}
Example #4
0
static void __init atari_scsi_reset_boot(void)
{
	unsigned long end;
	
	/*
	 * Do a SCSI reset to clean up the bus during initialization. No messing
	 * with the queues, interrupts, or locks necessary here.
	 */

	printk( "Atari SCSI: resetting the SCSI bus..." );

	/* get in phase */
	NCR5380_write( TARGET_COMMAND_REG,
		      PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) ));

	/* assert RST */
	NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST );
	/* The min. reset hold time is 25us, so 40us should be enough */
	udelay( 50 );
	/* reset RST and interrupt */
	NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
	NCR5380_read( RESET_PARITY_INTERRUPT_REG );

	end = jiffies + AFTER_RESET_DELAY;
	while (time_before(jiffies, end))
		barrier();

	printk( " done\n" );
}
Example #5
0
static int macscsi_pwrite (struct Scsi_Host *instance,
				  unsigned char *src, int len)
{
   unsigned char *s;
   volatile unsigned char *d;

   NCR5380_local_declare();
   NCR5380_setup(instance);

   s = src;
   d = mac_scsi_drq;
   
/* These conditions are derived from MacOS */

   while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ) 
         && (!(NCR5380_read(STATUS_REG) & SR_REQ) 
            || (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH))) 
      ;
   if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)) {
      printk(KERN_ERR "Error in macscsi_pwrite\n");
      return -1;
   }

   CP_MEM_TO_IO(s, d, len);   

   if (len != 0) {
      printk(KERN_NOTICE "Bus error in macscsi_pwrite\n");
      return -1;
   }
   
   return 0;
}
Example #6
0
static void mac_scsi_reset_boot(struct Scsi_Host *instance)
{
    unsigned long end;

    NCR5380_local_declare();
    NCR5380_setup(instance);



    printk(KERN_INFO "Macintosh SCSI: resetting the SCSI bus..." );


    disable_irq(IRQ_MAC_SCSI);


    NCR5380_write( TARGET_COMMAND_REG,
                   PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) ));


    NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST );

    udelay( 50 );

    NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
    NCR5380_read( RESET_PARITY_INTERRUPT_REG );

    for( end = jiffies + AFTER_RESET_DELAY; time_before(jiffies, end); )
        barrier();


    enable_irq(IRQ_MAC_SCSI);

    printk(KERN_INFO " done\n" );
}
Example #7
0
static int macscsi_pread (struct Scsi_Host *instance,
                          unsigned char *dst, int len)
{
    unsigned char *d;
    volatile unsigned char *s;

    NCR5380_local_declare();
    NCR5380_setup(instance);

    s = mac_scsi_drq+0x60;
    d = dst;



    while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)
            && !(NCR5380_read(STATUS_REG) & SR_REQ))
        ;
    if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)
            && (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) {
        printk(KERN_ERR "Error in macscsi_pread\n");
        return -1;
    }

    CP_IO_TO_MEM(s, d, len);

    if (len != 0) {
        printk(KERN_NOTICE "Bus error in macscsi_pread\n");
        return -1;
    }

    return 0;
}
Example #8
0
static int g_NCR5380_probe_irq(struct Scsi_Host *instance)
{
	struct NCR5380_hostdata *hostdata = shost_priv(instance);
	int irq_mask, irq;

	NCR5380_read(RESET_PARITY_INTERRUPT_REG);
	irq_mask = probe_irq_on();
	g_NCR5380_trigger_irq(instance);
	irq = probe_irq_off(irq_mask);
	NCR5380_read(RESET_PARITY_INTERRUPT_REG);

	if (irq <= 0)
		return NO_IRQ;
	return irq;
}
Example #9
0
static void g_NCR5380_trigger_irq(struct Scsi_Host *instance)
{
	struct NCR5380_hostdata *hostdata = shost_priv(instance);

	/*
	 * An interrupt is triggered whenever BSY = false, SEL = true
	 * and a bit set in the SELECT_ENABLE_REG is asserted on the
	 * SCSI bus.
	 *
	 * Note that the bus is only driven when the phase control signals
	 * (I/O, C/D, and MSG) match those in the TCR.
	 */
	NCR5380_write(TARGET_COMMAND_REG,
	              PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG) & PHASE_MASK));
	NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
	NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
	NCR5380_write(INITIATOR_COMMAND_REG,
	              ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_SEL);

	msleep(1);

	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
	NCR5380_write(SELECT_ENABLE_REG, 0);
	NCR5380_write(TARGET_COMMAND_REG, 0);
}
Example #10
0
static void sun3_scsi_reset_boot(struct Scsi_Host *instance)
{
	unsigned long end;

	NCR5380_local_declare();
	NCR5380_setup(instance);

	/*
	 * Do a SCSI reset to clean up the bus during initialization. No
	 * messing with the queues, interrupts, or locks necessary here.
	 */

	printk( "Sun3 SCSI: resetting the SCSI bus..." );

	/* switch off SCSI IRQ - catch an interrupt without IRQ bit set else */
//       	sun3_disable_irq( IRQ_SUN3_SCSI );

	/* get in phase */
	NCR5380_write( TARGET_COMMAND_REG,
		      PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) ));

	/* assert RST */
	NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST );

	/* The min. reset hold time is 25us, so 40us should be enough */
	udelay( 50 );

	/* reset RST and interrupt */
	NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
	NCR5380_read( RESET_PARITY_INTERRUPT_REG );

	for( end = jiffies + AFTER_RESET_DELAY; time_before(jiffies, end); )
		barrier();

	/* switch on SCSI IRQ again */
//       	sun3_enable_irq( IRQ_SUN3_SCSI );

	printk( " done\n" );
}
Example #11
0
/* clean up after our dma is done */
static int sun3scsi_dma_finish(void)
{
	unsigned short count;
	int ret = 0;
	
	count = sun3scsi_dma_residual(default_instance);

	sun3_dma_active = 0;

	/* if we've finished a read, copy out the data we read */
 	if(sun3_dma_orig_addr) {
		/* check for residual bytes after dma end */
		if(count && (NCR5380_read(BUS_AND_STATUS_REG) &
			     (BASR_PHASE_MATCH | BASR_ACK))) {
			printk("scsi%d: sun3_scsi_finish: read overrun baby... ", default_instance->host_no);
			printk("basr now %02x\n", NCR5380_read(BUS_AND_STATUS_REG));
			ret = count;
		}
		
		/* copy in what we dma'd no matter what */
		memcpy(sun3_dma_orig_addr, dmabuf, sun3_dma_orig_count);
		sun3_dma_orig_addr = NULL;

	}
	
	sun3_udc_write(UDC_RESET, UDC_CSR);
	
	dregs->csr &= ~CSR_SEND;

	/* reset fifo */
	dregs->csr &= ~CSR_FIFO;
	dregs->csr |= CSR_FIFO;
	
	sun3_dma_setup_done = NULL;

	return ret;

}
Example #12
0
static inline int macscsi_pwrite(struct NCR5380_hostdata *hostdata,
                                 unsigned char *src, int len)
{
	unsigned char *s = src;
	unsigned char *d = hostdata->pdma_io + (OUTPUT_DATA_REG << 4);
	int n = len;
	int transferred;

	while (!NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG,
	                              BASR_DRQ | BASR_PHASE_MATCH,
	                              BASR_DRQ | BASR_PHASE_MATCH, HZ / 64)) {
		CP_MEM_TO_IO(s, d, n);

		transferred = s - src - n;
		hostdata->pdma_residual = len - transferred;

		/* Target changed phase early? */
		if (NCR5380_poll_politely2(hostdata, STATUS_REG, SR_REQ, SR_REQ,
		                           BUS_AND_STATUS_REG, BASR_ACK, BASR_ACK, HZ / 64) < 0)
			scmd_printk(KERN_ERR, hostdata->connected,
			            "%s: !REQ and !ACK\n", __func__);
		if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH))
			return 0;

		/* No bus error. */
		if (n == 0) {
			if (NCR5380_poll_politely(hostdata, TARGET_COMMAND_REG,
			                          TCR_LAST_BYTE_SENT,
			                          TCR_LAST_BYTE_SENT, HZ / 64) < 0)
				scmd_printk(KERN_ERR, hostdata->connected,
				            "%s: Last Byte Sent timeout\n", __func__);
			return 0;
		}

		dsprintk(NDEBUG_PSEUDO_DMA, hostdata->host,
		         "%s: bus error (%d/%d)\n", __func__, transferred, len);
		NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host);
		s = src + transferred;
		n = len - transferred;
	}

	scmd_printk(KERN_ERR, hostdata->connected,
	            "%s: phase mismatch or !DRQ\n", __func__);
	NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host);

	return -1;
}
Example #13
0
static inline int macscsi_pread(struct NCR5380_hostdata *hostdata,
                                unsigned char *dst, int len)
{
	unsigned char *s = hostdata->pdma_io + (INPUT_DATA_REG << 4);
	unsigned char *d = dst;
	int n = len;
	int transferred;

	while (!NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG,
	                              BASR_DRQ | BASR_PHASE_MATCH,
	                              BASR_DRQ | BASR_PHASE_MATCH, HZ / 64)) {
		CP_IO_TO_MEM(s, d, n);

		transferred = d - dst - n;
		hostdata->pdma_residual = len - transferred;

		/* No bus error. */
		if (n == 0)
			return 0;

		/* Target changed phase early? */
		if (NCR5380_poll_politely2(hostdata, STATUS_REG, SR_REQ, SR_REQ,
		                           BUS_AND_STATUS_REG, BASR_ACK, BASR_ACK, HZ / 64) < 0)
			scmd_printk(KERN_ERR, hostdata->connected,
			            "%s: !REQ and !ACK\n", __func__);
		if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH))
			return 0;

		dsprintk(NDEBUG_PSEUDO_DMA, hostdata->host,
		         "%s: bus error (%d/%d)\n", __func__, transferred, len);
		NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host);
		d = dst + transferred;
		n = len - transferred;
	}

	scmd_printk(KERN_ERR, hostdata->connected,
	            "%s: phase mismatch or !DRQ\n", __func__);
	NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host);
	return -1;
}
Example #14
0
static inline int generic_NCR5380_pread(struct NCR5380_hostdata *hostdata,
                                        unsigned char *dst, int len)
{
	int blocks = len / 128;
	int start = 0;

	NCR5380_write(hostdata->c400_ctl_status, CSR_BASE | CSR_TRANS_DIR);
	NCR5380_write(hostdata->c400_blk_cnt, blocks);
	while (1) {
		if (NCR5380_read(hostdata->c400_blk_cnt) == 0)
			break;
		if (NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ) {
			printk(KERN_ERR "53C400r: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks);
			return -1;
		}
		while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
			; /* FIXME - no timeout */

		if (hostdata->io_port && hostdata->io_width == 2)
			insw(hostdata->io_port + hostdata->c400_host_buf,
							dst + start, 64);
		else if (hostdata->io_port)
			insb(hostdata->io_port + hostdata->c400_host_buf,
							dst + start, 128);
		else
			memcpy_fromio(dst + start,
				hostdata->io + NCR53C400_host_buffer, 128);

		start += 128;
		blocks--;
	}

	if (blocks) {
		while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
			; /* FIXME - no timeout */

		if (hostdata->io_port && hostdata->io_width == 2)
			insw(hostdata->io_port + hostdata->c400_host_buf,
							dst + start, 64);
		else if (hostdata->io_port)
			insb(hostdata->io_port + hostdata->c400_host_buf,
							dst + start, 128);
		else
			memcpy_fromio(dst + start,
				hostdata->io + NCR53C400_host_buffer, 128);

		start += 128;
		blocks--;
	}

	if (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ))
		printk("53C400r: no 53C80 gated irq after transfer");

	/* wait for 53C80 registers to be available */
	while (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG))
		;

	if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER))
		printk(KERN_ERR "53C400r: no end dma signal\n");
		
	return 0;
}
Example #15
0
static inline int generic_NCR5380_pwrite(struct NCR5380_hostdata *hostdata,
                                         unsigned char *src, int len)
{
	int blocks = len / 128;
	int start = 0;

	NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
	NCR5380_write(hostdata->c400_blk_cnt, blocks);
	while (1) {
		if (NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ) {
			printk(KERN_ERR "53C400w: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks);
			return -1;
		}

		if (NCR5380_read(hostdata->c400_blk_cnt) == 0)
			break;
		while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
			; // FIXME - timeout

		if (hostdata->io_port && hostdata->io_width == 2)
			outsw(hostdata->io_port + hostdata->c400_host_buf,
							src + start, 64);
		else if (hostdata->io_port)
			outsb(hostdata->io_port + hostdata->c400_host_buf,
							src + start, 128);
		else
			memcpy_toio(hostdata->io + NCR53C400_host_buffer,
			            src + start, 128);

		start += 128;
		blocks--;
	}
	if (blocks) {
		while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
			; // FIXME - no timeout

		if (hostdata->io_port && hostdata->io_width == 2)
			outsw(hostdata->io_port + hostdata->c400_host_buf,
							src + start, 64);
		else if (hostdata->io_port)
			outsb(hostdata->io_port + hostdata->c400_host_buf,
							src + start, 128);
		else
			memcpy_toio(hostdata->io + NCR53C400_host_buffer,
			            src + start, 128);

		start += 128;
		blocks--;
	}

	/* wait for 53C80 registers to be available */
	while (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG)) {
		udelay(4); /* DTC436 chip hangs without this */
		/* FIXME - no timeout */
	}

	if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER)) {
		printk(KERN_ERR "53C400w: no end dma signal\n");
	}

	while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT))
		; 	// TIMEOUT
	return 0;
}
Example #16
0
static __inline__ int macscsi_pread(struct Scsi_Host *instance, unsigned char *addr,
              int len)
{
  volatile unsigned char *dma_io = mac_scsi_drq + 0x60;

   NCR5380_local_declare();
   NCR5380_setup(instance);

	len = pdma_read_count;

	dprintk(NDEBUG_PSEUDO_DMA, ("scsi%d : about to pread %d bytes...", instance->host_no, len));

  if(!len) return 0;

	counter = 0;
	while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ) 
		&& !(NCR5380_read(STATUS_REG) & SR_REQ)) {
		counter++;
	}
	if (counter)
		printk("_%d_", (unsigned int)counter);
	counter = 0;
	if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ) 
		&& (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) {
		printk(KERN_ERR "Error in macscsi_pread\n");
		pdma_read_count = 0;
		return -1;
	}

//	m2_poll_start();
//	pmu_suspend();

	pdma_read_residue = len;

	dprintk(NDEBUG_PSEUDO_DMA, ("preading: "));

	cycle_counter = 0;
  while(pdma_read_residue >= 1)
  {
    int status;
#ifdef DRQ_INTERRUPT
	spin_lock_irq(&io_request_lock);
#endif
	if(pdma_read_residue == 0) {
#ifdef DRQ_INTERRUPT
		spin_unlock_irq(&io_request_lock);
#endif
		break;
	}
	cycle_counter++;
	counter = 0;
	while (!((status = NCR5380_read(BUS_AND_STATUS_REG)) & BASR_DRQ)) {
//		pmu_poll();
		counter++;
		if (!(status & BASR_PHASE_MATCH)) {
			(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
			len = pdma_read_residue;
			pdma_read_residue = 0;
#ifdef DRQ_INTERRUPT
			spin_unlock_irq(&io_request_lock);
#endif
//			m2_poll_stop();
//			pmu_resume();
			return len;
		}
		if (!(NCR5380_read(MODE_REG) & MR_DMA_MODE)) {
			len = pdma_read_residue;
			pdma_read_residue = 0;
#ifdef DRQ_INTERRUPT
			spin_unlock_irq(&io_request_lock);
#endif
//			m2_poll_stop();
//			pmu_resume();
			return len;
		}
//		udelay(1);
	}

	*pdma_dst++ = in_8((void *)dma_io);
	pdma_read_residue -= 1;

	average += counter;
#ifdef DRQ_INTERRUPT
	spin_unlock_irq(&io_request_lock);
#endif
//	while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ);
	}

	average /= cycle_counter;
//	printk(".%d.\n", average);
	average = 0;

	len = pdma_read_residue;
	pdma_read_residue = 0;
//	m2_poll_stop();
//	pmu_resume();
	return len;
}
Example #17
0
static int generic_NCR5380_init_one(struct scsi_host_template *tpnt,
			struct device *pdev, int base, int irq, int board)
{
	bool is_pmio = base <= 0xffff;
	int ret;
	int flags = 0;
	unsigned int *ports = NULL;
	u8 *magic = NULL;
	int i;
	int port_idx = -1;
	unsigned long region_size;
	struct Scsi_Host *instance;
	struct NCR5380_hostdata *hostdata;
	u8 __iomem *iomem;

	switch (board) {
	case BOARD_NCR5380:
		flags = FLAG_NO_PSEUDO_DMA | FLAG_DMA_FIXUP;
		break;
	case BOARD_NCR53C400A:
		ports = ncr_53c400a_ports;
		magic = ncr_53c400a_magic;
		break;
	case BOARD_HP_C2502:
		ports = ncr_53c400a_ports;
		magic = hp_c2502_magic;
		break;
	case BOARD_DTC3181E:
		ports = dtc_3181e_ports;
		magic = ncr_53c400a_magic;
		break;
	}

	if (is_pmio && ports && magic) {
		/* wakeup sequence for the NCR53C400A and DTC3181E */

		/* Disable the adapter and look for a free io port */
		magic_configure(-1, 0, magic);

		region_size = 16;
		if (base)
			for (i = 0; ports[i]; i++) {
				if (base == ports[i]) {	/* index found */
					if (!request_region(ports[i],
							    region_size,
							    "ncr53c80"))
						return -EBUSY;
					break;
				}
			}
		else
			for (i = 0; ports[i]; i++) {
				if (!request_region(ports[i], region_size,
						    "ncr53c80"))
					continue;
				if (inb(ports[i]) == 0xff)
					break;
				release_region(ports[i], region_size);
			}
		if (ports[i]) {
			/* At this point we have our region reserved */
			magic_configure(i, 0, magic); /* no IRQ yet */
			base = ports[i];
			outb(0xc0, base + 9);
			if (inb(base + 9) != 0x80) {
				ret = -ENODEV;
				goto out_release;
			}
			port_idx = i;
		} else
			return -EINVAL;
	} else if (is_pmio) {
		/* NCR5380 - no configuration, just grab */
		region_size = 8;
		if (!base || !request_region(base, region_size, "ncr5380"))
			return -EBUSY;
	} else {	/* MMIO */
		region_size = NCR53C400_region_size;
		if (!request_mem_region(base, region_size, "ncr5380"))
			return -EBUSY;
	}

	if (is_pmio)
		iomem = ioport_map(base, region_size);
	else
		iomem = ioremap(base, region_size);

	if (!iomem) {
		ret = -ENOMEM;
		goto out_release;
	}

	instance = scsi_host_alloc(tpnt, sizeof(struct NCR5380_hostdata));
	if (instance == NULL) {
		ret = -ENOMEM;
		goto out_unmap;
	}
	hostdata = shost_priv(instance);

	hostdata->io = iomem;
	hostdata->region_size = region_size;

	if (is_pmio) {
		hostdata->io_port = base;
		hostdata->io_width = 1; /* 8-bit PDMA by default */
		hostdata->offset = 0;

		/*
		 * On NCR53C400 boards, NCR5380 registers are mapped 8 past
		 * the base address.
		 */
		switch (board) {
		case BOARD_NCR53C400:
			hostdata->io_port += 8;
			hostdata->c400_ctl_status = 0;
			hostdata->c400_blk_cnt = 1;
			hostdata->c400_host_buf = 4;
			break;
		case BOARD_DTC3181E:
			hostdata->io_width = 2;	/* 16-bit PDMA */
			/* fall through */
		case BOARD_NCR53C400A:
		case BOARD_HP_C2502:
			hostdata->c400_ctl_status = 9;
			hostdata->c400_blk_cnt = 10;
			hostdata->c400_host_buf = 8;
			break;
		}
	} else {
		hostdata->base = base;
		hostdata->offset = NCR53C400_mem_base;
		switch (board) {
		case BOARD_NCR53C400:
			hostdata->c400_ctl_status = 0x100;
			hostdata->c400_blk_cnt = 0x101;
			hostdata->c400_host_buf = 0x104;
			break;
		case BOARD_DTC3181E:
		case BOARD_NCR53C400A:
		case BOARD_HP_C2502:
			pr_err(DRV_MODULE_NAME ": unknown register offsets\n");
			ret = -EINVAL;
			goto out_unregister;
		}
	}

	/* Check for vacant slot */
	NCR5380_write(MODE_REG, 0);
	if (NCR5380_read(MODE_REG) != 0) {
		ret = -ENODEV;
		goto out_unregister;
	}

	ret = NCR5380_init(instance, flags | FLAG_LATE_DMA_SETUP);
	if (ret)
		goto out_unregister;

	switch (board) {
	case BOARD_NCR53C400:
	case BOARD_DTC3181E:
	case BOARD_NCR53C400A:
	case BOARD_HP_C2502:
		NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
	}

	NCR5380_maybe_reset_bus(instance);

	/* Compatibility with documented NCR5380 kernel parameters */
	if (irq == 255 || irq == 0)
		irq = NO_IRQ;
	else if (irq == -1)
		irq = IRQ_AUTO;

	if (board == BOARD_HP_C2502) {
		int *irq_table = hp_c2502_irqs;
		int board_irq = -1;

		switch (irq) {
		case NO_IRQ:
			board_irq = 0;
			break;
		case IRQ_AUTO:
			board_irq = legacy_find_free_irq(irq_table);
			break;
		default:
			while (*irq_table != -1)
				if (*irq_table++ == irq)
					board_irq = irq;
		}

		if (board_irq <= 0) {
			board_irq = 0;
			irq = NO_IRQ;
		}

		magic_configure(port_idx, board_irq, magic);
	}

	if (irq == IRQ_AUTO) {
		instance->irq = g_NCR5380_probe_irq(instance);
		if (instance->irq == NO_IRQ)
			shost_printk(KERN_INFO, instance, "no irq detected\n");
	} else {
		instance->irq = irq;
		if (instance->irq == NO_IRQ)
			shost_printk(KERN_INFO, instance, "no irq provided\n");
	}

	if (instance->irq != NO_IRQ) {
		if (request_irq(instance->irq, generic_NCR5380_intr,
				0, "NCR5380", instance)) {
			instance->irq = NO_IRQ;
			shost_printk(KERN_INFO, instance,
			             "irq %d denied\n", instance->irq);
		} else {
			shost_printk(KERN_INFO, instance,
			             "irq %d acquired\n", instance->irq);
		}
	}

	ret = scsi_add_host(instance, pdev);
	if (ret)
		goto out_free_irq;
	scsi_scan_host(instance);
	dev_set_drvdata(pdev, instance);
	return 0;

out_free_irq:
	if (instance->irq != NO_IRQ)
		free_irq(instance->irq, instance);
	NCR5380_exit(instance);
out_unregister:
	scsi_host_put(instance);
out_unmap:
	iounmap(iomem);
out_release:
	if (is_pmio)
		release_region(base, region_size);
	else
		release_mem_region(base, region_size);
	return ret;
}