⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 atari_scsi.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
#ifdef MODULEint atari_scsi_release (struct Scsi_Host *sh){	if (IS_A_TT())		free_irq(IRQ_TT_MFP_SCSI, scsi_tt_intr);	if (atari_dma_buffer)		atari_stram_free (atari_dma_buffer);	return 1;}#endifvoid __init atari_scsi_setup(char *str, int *ints){	/* Format of atascsi parameter is:	 *   atascsi=<can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags>	 * Defaults depend on TT or Falcon, hostid determined at run time.	 * Negative values mean don't change.	 */		if (ints[0] < 1) {		printk( "atari_scsi_setup: no arguments!\n" );		return;	}	if (ints[0] >= 1) {		if (ints[1] > 0)			/* no limits on this, just > 0 */			setup_can_queue = ints[1];	}	if (ints[0] >= 2) {		if (ints[2] > 0)			setup_cmd_per_lun = ints[2];	}	if (ints[0] >= 3) {		if (ints[3] >= 0) {			setup_sg_tablesize = ints[3];			/* Must be <= SG_ALL (255) */			if (setup_sg_tablesize > SG_ALL)				setup_sg_tablesize = SG_ALL;		}	}	if (ints[0] >= 4) {		/* Must be between 0 and 7 */		if (ints[4] >= 0 && ints[4] <= 7)			setup_hostid = ints[4];		else if (ints[4] > 7)			printk( "atari_scsi_setup: invalid host ID %d !\n", ints[4] );	}#ifdef SUPPORT_TAGS	if (ints[0] >= 5) {		if (ints[5] >= 0)			setup_use_tagged_queuing = !!ints[5];	}#endif}int atari_scsi_reset( Scsi_Cmnd *cmd, unsigned int reset_flags){	int		rv;	struct NCR5380_hostdata *hostdata =		(struct NCR5380_hostdata *)cmd->host->hostdata;	/* For doing the reset, SCSI interrupts must be disabled first,	 * since the 5380 raises its IRQ line while _RST is active and we	 * can't disable interrupts completely, since we need the timer.	 */	/* And abort a maybe active DMA transfer */	if (IS_A_TT()) {		atari_turnoff_irq( IRQ_TT_MFP_SCSI );#ifdef REAL_DMA		tt_scsi_dma.dma_ctrl = 0;#endif /* REAL_DMA */	}	else {		atari_turnoff_irq( IRQ_MFP_FSCSI );#ifdef REAL_DMA		st_dma.dma_mode_status = 0x90;		atari_dma_active = 0;		atari_dma_orig_addr = NULL;#endif /* REAL_DMA */	}	rv = NCR5380_reset(cmd, reset_flags);	/* Re-enable ints */	if (IS_A_TT()) {		atari_turnon_irq( IRQ_TT_MFP_SCSI );	}	else {		atari_turnon_irq( IRQ_MFP_FSCSI );	}	if ((rv & SCSI_RESET_ACTION) == SCSI_RESET_SUCCESS)		falcon_release_lock_if_possible(hostdata);	return( rv );}	#ifdef CONFIG_ATARI_SCSI_RESET_BOOTstatic 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" );}#endifconst char * atari_scsi_info (struct Scsi_Host *host){	/* atari_scsi_detect() is verbose enough... */	static const char string[] = "Atari native SCSI";	return string;}#if defined(REAL_DMA)unsigned long atari_scsi_dma_setup( struct Scsi_Host *instance, void *data,				   unsigned long count, int dir ){	unsigned long addr = virt_to_phys( data );	DMA_PRINTK("scsi%d: setting up dma, data = %p, phys = %lx, count = %ld, "		   "dir = %d\n", instance->host_no, data, addr, count, dir);	if (!IS_A_TT() && !STRAM_ADDR(addr)) {		/* If we have a non-DMAable address on a Falcon, use the dribble		 * buffer; 'orig_addr' != 0 in the read case tells the interrupt		 * handler to copy data from the dribble buffer to the originally		 * wanted address.		 */		if (dir)			memcpy( atari_dma_buffer, data, count );		else			atari_dma_orig_addr = data;		addr = atari_dma_phys_buffer;	}		atari_dma_startaddr = addr;	/* Needed for calculating residual later. */  	/* Cache cleanup stuff: On writes, push any dirty cache out before sending	 * it to the peripheral. (Must be done before DMA setup, since at least	 * the ST-DMA begins to fill internal buffers right after setup. For	 * reads, invalidate any cache, may be altered after DMA without CPU	 * knowledge.	 * 	 * ++roman: For the Medusa, there's no need at all for that cache stuff,	 * because the hardware does bus snooping (fine!).	 */	dma_cache_maintenance( addr, count, dir );	if (count == 0)		printk(KERN_NOTICE "SCSI warning: DMA programmed for 0 bytes !\n");	if (IS_A_TT()) {		tt_scsi_dma.dma_ctrl = dir;		SCSI_DMA_WRITE_P( dma_addr, addr );		SCSI_DMA_WRITE_P( dma_cnt, count );		tt_scsi_dma.dma_ctrl = dir | 2;	}	else { /* ! IS_A_TT */  		/* set address */		SCSI_DMA_SETADR( addr );		/* toggle direction bit to clear FIFO and set DMA direction */		dir <<= 8;		st_dma.dma_mode_status = 0x90 | dir;		st_dma.dma_mode_status = 0x90 | (dir ^ 0x100);		st_dma.dma_mode_status = 0x90 | dir;		udelay(40);		/* On writes, round up the transfer length to the next multiple of 512		 * (see also comment at atari_dma_xfer_len()). */		st_dma.fdc_acces_seccount = (count + (dir ? 511 : 0)) >> 9;		udelay(40);		st_dma.dma_mode_status = 0x10 | dir;		udelay(40);		/* need not restore value of dir, only boolean value is tested */		atari_dma_active = 1;	}	return( count );}static long atari_scsi_dma_residual( struct Scsi_Host *instance ){	return( atari_dma_residual );}#define	CMD_SURELY_BLOCK_MODE	0#define	CMD_SURELY_BYTE_MODE	1#define	CMD_MODE_UNKNOWN		2static int falcon_classify_cmd( Scsi_Cmnd *cmd ){	unsigned char opcode = cmd->cmnd[0];		if (opcode == READ_DEFECT_DATA || opcode == READ_LONG ||		opcode == READ_BUFFER)		return( CMD_SURELY_BYTE_MODE );	else if (opcode == READ_6 || opcode == READ_10 ||		 opcode == 0xa8 /* READ_12 */ || opcode == READ_REVERSE ||		 opcode == RECOVER_BUFFERED_DATA) {		/* In case of a sequential-access target (tape), special care is		 * needed here: The transfer is block-mode only if the 'fixed' bit is		 * set! */		if (cmd->device->type == TYPE_TAPE && !(cmd->cmnd[1] & 1))			return( CMD_SURELY_BYTE_MODE );		else			return( CMD_SURELY_BLOCK_MODE );	}	else		return( CMD_MODE_UNKNOWN );}/* This function calculates the number of bytes that can be transferred via * DMA. On the TT, this is arbitrary, but on the Falcon we have to use the * ST-DMA chip. There are only multiples of 512 bytes possible and max. * 255*512 bytes :-( This means also, that defining READ_OVERRUNS is not * possible on the Falcon, since that would require to program the DMA for * n*512 - atari_read_overrun bytes. But it seems that the Falcon doesn't have * the overrun problem, so this question is academic :-) */static unsigned long atari_dma_xfer_len( unsigned long wanted_len,					Scsi_Cmnd *cmd,					int write_flag ){	unsigned long	possible_len, limit;#ifndef CONFIG_TT_DMA_EMUL	if (MACH_IS_HADES)		/* Hades has no SCSI DMA at all :-( Always force use of PIO */		return( 0 );#endif		if (IS_A_TT())		/* TT SCSI DMA can transfer arbitrary #bytes */		return( wanted_len );	/* ST DMA chip is stupid -- only multiples of 512 bytes! (and max.	 * 255*512 bytes, but this should be enough)	 *	 * ++roman: Aaargl! Another Falcon-SCSI problem... There are some commands	 * that return a number of bytes which cannot be known beforehand. In this	 * case, the given transfer length is an "allocation length". Now it	 * can happen that this allocation length is a multiple of 512 bytes and	 * the DMA is used. But if not n*512 bytes really arrive, some input data	 * will be lost in the ST-DMA's FIFO :-( Thus, we have to distinguish	 * between commands that do block transfers and those that do byte	 * transfers. But this isn't easy... there are lots of vendor specific	 * commands, and the user can issue any command via the	 * SCSI_IOCTL_SEND_COMMAND.	 *	 * The solution: We classify SCSI commands in 1) surely block-mode cmd.s,	 * 2) surely byte-mode cmd.s and 3) cmd.s with unknown mode. In case 1)	 * and 3), the thing to do is obvious: allow any number of blocks via DMA	 * or none. In case 2), we apply some heuristic: Byte mode is assumed if	 * the transfer (allocation) length is < 1024, hoping that no cmd. not	 * explicitly known as byte mode have such big allocation lengths...	 * BTW, all the discussion above applies only to reads. DMA writes are	 * unproblematic anyways, since the targets aborts the transfer after	 * receiving a sufficient number of bytes.	 *	 * Another point: If the transfer is from/to an non-ST-RAM address, we	 * use the dribble buffer and thus can do only STRAM_BUFFER_SIZE bytes.	 */	if (write_flag) {		/* Write operation can always use the DMA, but the transfer size must		 * be rounded up to the next multiple of 512 (atari_dma_setup() does		 * this).		 */		possible_len = wanted_len;	}	else {		/* Read operations: if the wanted transfer length is not a multiple of		 * 512, we cannot use DMA, since the ST-DMA cannot split transfers		 * (no interrupt on DMA finished!)		 */		if (wanted_len & 0x1ff)			possible_len = 0;		else {			/* Now classify the command (see above) and decide whether it is			 * allowed to do DMA at all */			switch( falcon_classify_cmd( cmd )) {			  case CMD_SURELY_BLOCK_MODE:				possible_len = wanted_len;				break;			  case CMD_SURELY_BYTE_MODE:				possible_len = 0; /* DMA prohibited */				break;			  case CMD_MODE_UNKNOWN:			  default:				/* For unknown commands assume block transfers if the transfer				 * size/allocation length is >= 1024 */				possible_len = (wanted_len < 1024) ? 0 : wanted_len;				break;			}		}	}		/* Last step: apply the hard limit on DMA transfers */	limit = (atari_dma_buffer && !STRAM_ADDR( virt_to_phys(cmd->SCp.ptr) )) ?		    STRAM_BUFFER_SIZE : 255*512;	if (possible_len > limit)		possible_len = limit;	if (possible_len != wanted_len)		DMA_PRINTK("Sorry, must cut DMA transfer size to %ld bytes "			   "instead of %ld\n", possible_len, wanted_len);	return( possible_len );}#endif	/* REAL_DMA *//* NCR5380 register access functions * * There are separate functions for TT and Falcon, because the access * methods are quite different. The calling macros NCR5380_read and * NCR5380_write call these functions via function pointers. */static unsigned char atari_scsi_tt_reg_read( unsigned char reg ){	return( tt_scsi_regp[reg * 2] );}static void atari_scsi_tt_reg_write( unsigned char reg, unsigned char value ){	tt_scsi_regp[reg * 2] = value;}static unsigned char atari_scsi_falcon_reg_read( unsigned char reg ){	dma_wd.dma_mode_status= (u_short)(0x88 + reg);	return( (u_char)dma_wd.fdc_acces_seccount );}static void atari_scsi_falcon_reg_write( unsigned char reg, unsigned char value ){	dma_wd.dma_mode_status = (u_short)(0x88 + reg);	dma_wd.fdc_acces_seccount = (u_short)value;}#include "atari_NCR5380.c"static Scsi_Host_Template driver_template = ATARI_SCSI;#include "scsi_module.c"

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -