forked from mirrors/linux
		
	sun3_scsi: Adopt NCR5380.c core driver
Add support for the custom Sun 3 DMA logic to the NCR5380.c core driver. This code is copied from atari_NCR5380.c. Signed-off-by: Finn Thain <fthain@telegraphics.com.au> Reviewed-by: Hannes Reinecke <hare@suse.com> Tested-by: Michael Schmitz <schmitzmic@gmail.com> Tested-by: Ondrej Zary <linux@rainbow-software.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
		
							parent
							
								
									52d3e561cb
								
							
						
					
					
						commit
						e9db3198e0
					
				
					 2 changed files with 124 additions and 15 deletions
				
			
		|  | @ -31,6 +31,8 @@ | |||
| 
 | ||||
| /* Ported to Atari by Roman Hodek and others. */ | ||||
| 
 | ||||
| /* Adapted for the Sun 3 by Sam Creasey. */ | ||||
| 
 | ||||
| /*
 | ||||
|  * Further development / testing that should be done : | ||||
|  * | ||||
|  | @ -858,6 +860,23 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance) | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| #ifdef CONFIG_SUN3 | ||||
| 	if ((sun3scsi_dma_finish(rq_data_dir(hostdata->connected->request)))) { | ||||
| 		pr_err("scsi%d: overrun in UDC counter -- not prepared to deal with this!\n", | ||||
| 		       instance->host_no); | ||||
| 		BUG(); | ||||
| 	} | ||||
| 
 | ||||
| 	if ((NCR5380_read(BUS_AND_STATUS_REG) & (BASR_PHASE_MATCH | BASR_ACK)) == | ||||
| 	    (BASR_PHASE_MATCH | BASR_ACK)) { | ||||
| 		pr_err("scsi%d: BASR %02x\n", instance->host_no, | ||||
| 		       NCR5380_read(BUS_AND_STATUS_REG)); | ||||
| 		pr_err("scsi%d: bus stuck in data phase -- probably a single byte overrun!\n", | ||||
| 		       instance->host_no); | ||||
| 		BUG(); | ||||
| 	} | ||||
| #endif | ||||
| 
 | ||||
| 	NCR5380_write(MODE_REG, MR_BASE); | ||||
| 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | ||||
| 	NCR5380_read(RESET_PARITY_INTERRUPT_REG); | ||||
|  | @ -981,10 +1000,16 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) | |||
| 			NCR5380_read(RESET_PARITY_INTERRUPT_REG); | ||||
| 
 | ||||
| 			dsprintk(NDEBUG_INTR, instance, "unknown interrupt\n"); | ||||
| #ifdef SUN3_SCSI_VME | ||||
| 			dregs->csr |= CSR_DMA_ENABLE; | ||||
| #endif | ||||
| 		} | ||||
| 		handled = 1; | ||||
| 	} else { | ||||
| 		shost_printk(KERN_NOTICE, instance, "interrupt without IRQ bit\n"); | ||||
| #ifdef SUN3_SCSI_VME | ||||
| 		dregs->csr |= CSR_DMA_ENABLE; | ||||
| #endif | ||||
| 	} | ||||
| 
 | ||||
| 	spin_unlock_irqrestore(&hostdata->lock, flags); | ||||
|  | @ -1274,6 +1299,10 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, | |||
| 	hostdata->connected = cmd; | ||||
| 	hostdata->busy[cmd->device->id] |= 1 << cmd->device->lun; | ||||
| 
 | ||||
| #ifdef SUN3_SCSI_VME | ||||
| 	dregs->csr |= CSR_INTR; | ||||
| #endif | ||||
| 
 | ||||
| 	initialize_SCp(cmd); | ||||
| 
 | ||||
| 	cmd = NULL; | ||||
|  | @ -1557,6 +1586,11 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, | |||
| 	dsprintk(NDEBUG_DMA, instance, "initializing DMA %s: length %d, address %p\n", | ||||
| 	         (p & SR_IO) ? "receive" : "send", c, d); | ||||
| 
 | ||||
| #ifdef CONFIG_SUN3 | ||||
| 	/* send start chain */ | ||||
| 	sun3scsi_dma_start(c, *data); | ||||
| #endif | ||||
| 
 | ||||
| 	NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); | ||||
| 	NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY | | ||||
| 	                        MR_ENABLE_EOP_INTR); | ||||
|  | @ -1577,6 +1611,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, | |||
| 	 */ | ||||
| 
 | ||||
| 	if (p & SR_IO) { | ||||
| 		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | ||||
| 		NCR5380_io_delay(1); | ||||
| 		NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0); | ||||
| 	} else { | ||||
|  | @ -1587,6 +1622,13 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, | |||
| 		NCR5380_io_delay(1); | ||||
| 	} | ||||
| 
 | ||||
| #ifdef CONFIG_SUN3 | ||||
| #ifdef SUN3_SCSI_VME | ||||
| 	dregs->csr |= CSR_DMA_ENABLE; | ||||
| #endif | ||||
| 	sun3_dma_active = 1; | ||||
| #endif | ||||
| 
 | ||||
| 	if (hostdata->flags & FLAG_LATE_DMA_SETUP) { | ||||
| 		/* On the Falcon, the DMA setup must be done after the last
 | ||||
| 		 * NCR access, else the DMA setup gets trashed! | ||||
|  | @ -1718,6 +1760,10 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) | |||
| 	unsigned char phase, tmp, extended_msg[10], old_phase = 0xff; | ||||
| 	struct scsi_cmnd *cmd; | ||||
| 
 | ||||
| #ifdef SUN3_SCSI_VME | ||||
| 	dregs->csr |= CSR_INTR; | ||||
| #endif | ||||
| 
 | ||||
| 	while ((cmd = hostdata->connected)) { | ||||
| 		struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd); | ||||
| 
 | ||||
|  | @ -1729,6 +1775,31 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) | |||
| 				old_phase = phase; | ||||
| 				NCR5380_dprint_phase(NDEBUG_INFORMATION, instance); | ||||
| 			} | ||||
| #ifdef CONFIG_SUN3 | ||||
| 			if (phase == PHASE_CMDOUT) { | ||||
| 				void *d; | ||||
| 				unsigned long count; | ||||
| 
 | ||||
| 				if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) { | ||||
| 					count = cmd->SCp.buffer->length; | ||||
| 					d = sg_virt(cmd->SCp.buffer); | ||||
| 				} else { | ||||
| 					count = cmd->SCp.this_residual; | ||||
| 					d = cmd->SCp.ptr; | ||||
| 				} | ||||
| 
 | ||||
| 				if (sun3_dma_setup_done != cmd && | ||||
| 				    sun3scsi_dma_xfer_len(count, cmd) > 0) { | ||||
| 					sun3scsi_dma_setup(instance, d, count, | ||||
| 					                   rq_data_dir(cmd->request)); | ||||
| 					sun3_dma_setup_done = cmd; | ||||
| 				} | ||||
| #ifdef SUN3_SCSI_VME | ||||
| 				dregs->csr |= CSR_INTR; | ||||
| #endif | ||||
| 			} | ||||
| #endif /* CONFIG_SUN3 */ | ||||
| 
 | ||||
| 			if (sink && (phase != PHASE_MSGOUT)) { | ||||
| 				NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp)); | ||||
| 
 | ||||
|  | @ -1811,6 +1882,10 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) | |||
| 					                     (unsigned char **)&cmd->SCp.ptr); | ||||
| 					cmd->SCp.this_residual -= transfersize - len; | ||||
| 				} | ||||
| #ifdef CONFIG_SUN3 | ||||
| 				if (sun3_dma_setup_done == cmd) | ||||
| 					sun3_dma_setup_done = NULL; | ||||
| #endif | ||||
| 				return; | ||||
| 			case PHASE_MSGIN: | ||||
| 				len = 1; | ||||
|  | @ -1889,6 +1964,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) | |||
| 
 | ||||
| 					/* Enable reselect interrupts */ | ||||
| 					NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); | ||||
| #ifdef SUN3_SCSI_VME | ||||
| 					dregs->csr |= CSR_DMA_ENABLE; | ||||
| #endif | ||||
| 					return; | ||||
| 					/*
 | ||||
| 					 * The SCSI data pointer is *IMPLICITLY* saved on a disconnect | ||||
|  | @ -2040,10 +2118,8 @@ static void NCR5380_reselect(struct Scsi_Host *instance) | |||
| { | ||||
| 	struct NCR5380_hostdata *hostdata = shost_priv(instance); | ||||
| 	unsigned char target_mask; | ||||
| 	unsigned char lun, phase; | ||||
| 	int len; | ||||
| 	unsigned char lun; | ||||
| 	unsigned char msg[3]; | ||||
| 	unsigned char *data; | ||||
| 	struct NCR5380_cmd *ncmd; | ||||
| 	struct scsi_cmnd *tmp; | ||||
| 
 | ||||
|  | @ -2085,15 +2161,26 @@ static void NCR5380_reselect(struct Scsi_Host *instance) | |||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	len = 1; | ||||
| 	data = msg; | ||||
| 	phase = PHASE_MSGIN; | ||||
| 	NCR5380_transfer_pio(instance, &phase, &len, &data); | ||||
| #ifdef CONFIG_SUN3 | ||||
| 	/* acknowledge toggle to MSGIN */ | ||||
| 	NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(PHASE_MSGIN)); | ||||
| 
 | ||||
| 	if (len) { | ||||
| 		do_abort(instance); | ||||
| 		return; | ||||
| 	/* peek at the byte without really hitting the bus */ | ||||
| 	msg[0] = NCR5380_read(CURRENT_SCSI_DATA_REG); | ||||
| #else | ||||
| 	{ | ||||
| 		int len = 1; | ||||
| 		unsigned char *data = msg; | ||||
| 		unsigned char phase = PHASE_MSGIN; | ||||
| 
 | ||||
| 		NCR5380_transfer_pio(instance, &phase, &len, &data); | ||||
| 
 | ||||
| 		if (len) { | ||||
| 			do_abort(instance); | ||||
| 			return; | ||||
| 		} | ||||
| 	} | ||||
| #endif /* CONFIG_SUN3 */ | ||||
| 
 | ||||
| 	if (!(msg[0] & 0x80)) { | ||||
| 		shost_printk(KERN_ERR, instance, "expecting IDENTIFY message, got "); | ||||
|  | @ -2141,6 +2228,30 @@ static void NCR5380_reselect(struct Scsi_Host *instance) | |||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| #ifdef CONFIG_SUN3 | ||||
| 	{ | ||||
| 		void *d; | ||||
| 		unsigned long count; | ||||
| 
 | ||||
| 		if (!tmp->SCp.this_residual && tmp->SCp.buffers_residual) { | ||||
| 			count = tmp->SCp.buffer->length; | ||||
| 			d = sg_virt(tmp->SCp.buffer); | ||||
| 		} else { | ||||
| 			count = tmp->SCp.this_residual; | ||||
| 			d = tmp->SCp.ptr; | ||||
| 		} | ||||
| 
 | ||||
| 		if (sun3_dma_setup_done != tmp && | ||||
| 		    sun3scsi_dma_xfer_len(count, tmp) > 0) { | ||||
| 			sun3scsi_dma_setup(instance, d, count, | ||||
| 			                   rq_data_dir(tmp->request)); | ||||
| 			sun3_dma_setup_done = tmp; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK); | ||||
| #endif /* CONFIG_SUN3 */ | ||||
| 
 | ||||
| 	/* Accept message by clearing ACK */ | ||||
| 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | ||||
| 
 | ||||
|  |  | |||
|  | @ -54,10 +54,8 @@ | |||
| #define NCR5380_abort                   sun3scsi_abort | ||||
| #define NCR5380_info                    sun3scsi_info | ||||
| 
 | ||||
| #define NCR5380_dma_read_setup(instance, data, count) \ | ||||
|         sun3scsi_dma_setup(instance, data, count, 0) | ||||
| #define NCR5380_dma_write_setup(instance, data, count) \ | ||||
|         sun3scsi_dma_setup(instance, data, count, 1) | ||||
| #define NCR5380_dma_recv_setup(instance, data, count) (count) | ||||
| #define NCR5380_dma_send_setup(instance, data, count) (count) | ||||
| #define NCR5380_dma_residual(instance) \ | ||||
|         sun3scsi_dma_residual(instance) | ||||
| #define NCR5380_dma_xfer_len(instance, cmd, phase) \ | ||||
|  | @ -406,7 +404,7 @@ static int sun3scsi_dma_finish(int write_flag) | |||
| 
 | ||||
| } | ||||
| 	 | ||||
| #include "atari_NCR5380.c" | ||||
| #include "NCR5380.c" | ||||
| 
 | ||||
| #ifdef SUN3_SCSI_VME | ||||
| #define SUN3_SCSI_NAME          "Sun3 NCR5380 VME SCSI" | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Finn Thain
						Finn Thain