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

📄 acsi.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		else			printk(" ");		}	printk("\n");	i = data[0] & 0x1f;	printk(KERN_INFO "  Type:   %s ", (i < MAX_SCSI_DEVICE_CODE									   ? scsi_device_types[i]									   : "Unknown          "));	printk("                 ANSI SCSI revision: %02x", data[2] & 0x07);	if ((data[2] & 0x07) == 1 && (data[3] & 0x0f) == 1)	  printk(" CCS\n");	else	  printk("\n");}/*  * Changes by Martin Rogge, 9th Aug 1995:  * acsi_devinit has been taken out of acsi_geninit, because it needs  * to be called from revalidate_acsidisk. The result of request sense  * is now checked for DRIVE NOT READY. * * The structure *aip is only valid when acsi_devinit returns  * DEV_SUPPORTED.  * */	#define DEV_NONE	0#define DEV_UNKNOWN	1#define DEV_SUPPORTED	2#define DEV_SLM		3static int acsi_devinit(struct acsi_info_struct *aip){	int status, got_inquiry;	SENSE_DATA sense;	unsigned char reqsense, extsense;	/*****************************************************************/	/* Do a TEST UNIT READY command to test the presence of a device */	/*****************************************************************/	CMDSET_TARG_LUN(tur_cmd, aip->target, aip->lun);	if (!acsicmd_nodma(tur_cmd, 0)) {		/* timed out -> no device here */#ifdef DEBUG_DETECT		printk("target %d lun %d: timeout\n", aip->target, aip->lun);#endif		return DEV_NONE;	}			/*************************/	/* Read the ACSI status. */	/*************************/	status = acsi_getstatus();	if (status) {		if (status == 0x12) {			/* The SLM printer should be the only device that			 * responds with the error code in the status byte. In			 * correct status bytes, bit 4 is never set.			 */			printk( KERN_INFO "Detected SLM printer at id %d lun %d\n",			       aip->target, aip->lun);			return DEV_SLM;		}		/* ignore CHECK CONDITION, since some devices send a		   UNIT ATTENTION */		if ((status & 0x1e) != 0x2) {#ifdef DEBUG_DETECT			printk("target %d lun %d: status %d\n",			       aip->target, aip->lun, status);#endif			return DEV_UNKNOWN;		}	}	/*******************************/	/* Do a REQUEST SENSE command. */	/*******************************/	if (!acsi_reqsense(acsi_buffer, aip->target, aip->lun)) {		printk( KERN_WARNING "acsi_reqsense failed\n");		acsi_buffer[0] = 0;		acsi_buffer[2] = UNIT_ATTENTION;	}	reqsense = acsi_buffer[0];	extsense = acsi_buffer[2] & 0xf;	if (status) {		if ((reqsense & 0x70) == 0x70) {	/* extended sense */			if (extsense != UNIT_ATTENTION &&			    extsense != NOT_READY) {#ifdef DEBUG_DETECT				printk("target %d lun %d: extended sense %d\n",				       aip->target, aip->lun, extsense);#endif				return DEV_UNKNOWN;			}		}		else {			if (reqsense & 0x7f) {#ifdef DEBUG_DETECT				printk("target %d lun %d: sense %d\n",				       aip->target, aip->lun, reqsense);#endif				return DEV_UNKNOWN;			}		}	}	else 		if (reqsense == 0x4) {	/* SH204 Bug workaround */#ifdef DEBUG_DETECT			printk("target %d lun %d status=0 sense=4\n",			       aip->target, aip->lun);#endif			return DEV_UNKNOWN;		}	/***********************************************************/	/* Do an INQUIRY command to get more infos on this device. */	/***********************************************************/	/* Assume default values */	aip->removable = 1;	aip->read_only = 0;	aip->old_atari_disk = 0;	aip->changed = (extsense == NOT_READY);	/* medium inserted? */	aip->size = DEFAULT_SIZE;	got_inquiry = 0;	/* Fake inquiry result for old atari disks */	memcpy(acsi_buffer, "\000\000\001\000    Adaptec 40xx"	       "                    ", 40);	CMDSET_TARG_LUN(inquiry_cmd, aip->target, aip->lun);	if (acsicmd_dma(inquiry_cmd, acsi_buffer, 1, 0, 0) &&	    acsi_getstatus() == 0) {		acsicmd_nodma(inquiry_cmd, 0);		acsi_getstatus();		dma_cache_maintenance( phys_acsi_buffer, 256, 0 );		got_inquiry = 1;		aip->removable = !!(acsi_buffer[1] & 0x80);	}	if (aip->type == NONE)	/* only at boot time */		print_inquiry(acsi_buffer);	switch(acsi_buffer[0]) {	  case TYPE_DISK:		aip->type = HARDDISK;		break;	  case TYPE_ROM:		aip->type = CDROM;		aip->read_only = 1;		break;	  default:		return DEV_UNKNOWN;	}	/****************************/	/* Do a MODE SENSE command. */	/****************************/	if (!acsi_mode_sense(aip->target, aip->lun, &sense)) {		printk( KERN_WARNING "No mode sense data.\n" );		return DEV_UNKNOWN;	}	if ((SECTOR_SIZE(sense) != 512) &&	    ((aip->type != CDROM) ||	     !acsi_change_blk_size(aip->target, aip->lun) ||	     !acsi_mode_sense(aip->target, aip->lun, &sense) ||	     (SECTOR_SIZE(sense) != 512))) {		printk( KERN_WARNING "Sector size != 512 not supported.\n" );		return DEV_UNKNOWN;	}	/* There are disks out there that claim to have 0 sectors... */	if (CAPACITY(sense))		aip->size = CAPACITY(sense);	/* else keep DEFAULT_SIZE */	if (!got_inquiry && SENSE_TYPE(sense) == SENSE_TYPE_ATARI) {		/* If INQUIRY failed and the sense data suggest an old		 * Atari disk (SH20x, Megafile), the disk is not removable		 */		aip->removable = 0;		aip->old_atari_disk = 1;	}		/******************/	/* We've done it. */	/******************/		return DEV_SUPPORTED;}EXPORT_SYMBOL(acsi_delay_start);EXPORT_SYMBOL(acsi_delay_end);EXPORT_SYMBOL(acsi_wait_for_IRQ);EXPORT_SYMBOL(acsi_wait_for_noIRQ);EXPORT_SYMBOL(acsicmd_nodma);EXPORT_SYMBOL(acsi_getstatus);EXPORT_SYMBOL(acsi_buffer);EXPORT_SYMBOL(phys_acsi_buffer);#ifdef CONFIG_ATARI_SLM_MODULEvoid acsi_attach_SLMs( int (*attach_func)( int, int ) );EXPORT_SYMBOL(acsi_extstatus);EXPORT_SYMBOL(acsi_end_extstatus);EXPORT_SYMBOL(acsi_extcmd);EXPORT_SYMBOL(acsi_attach_SLMs);/* to remember IDs of SLM devices, SLM module is loaded later * (index is target#, contents is lun#, -1 means "no SLM") */int SLM_devices[8];#endifstatic struct block_device_operations acsi_fops = {	open:			acsi_open,	release:		acsi_release,	ioctl:			acsi_ioctl,	check_media_change:	acsi_media_change,	revalidate:		acsi_revalidate,};static void acsi_geninit(void){	int i, target, lun;	struct acsi_info_struct *aip;#ifdef CONFIG_ATARI_SLM	int n_slm = 0;#endif	printk( KERN_INFO "Probing ACSI devices:\n" );	NDevices = 0;#ifdef CONFIG_ATARI_SLM_MODULE	for( i = 0; i < 8; ++i )		SLM_devices[i] = -1;#endif	stdma_lock(NULL, NULL);	for (target = 0; target < 8 && NDevices < MAX_DEV; ++target) {		lun = 0;		do {			aip = &acsi_info[NDevices];			aip->type = NONE;			aip->target = target;			aip->lun = lun;			i = acsi_devinit(aip);			switch (i) {			  case DEV_SUPPORTED:				printk( KERN_INFO "Detected ");				switch (aip->type) {				  case HARDDISK:					printk("disk");					break;				  case CDROM:					printk("cdrom");					break;				  default:				}				printk(" ad%c at id %d lun %d ",				       'a' + NDevices, target, lun);				if (aip->removable) 					printk("(removable) ");				if (aip->read_only) 					printk("(read-only) ");				if (aip->size == DEFAULT_SIZE)					printk(" unkown size, using default ");				printk("%ld MByte\n",				       (aip->size*512+1024*1024/2)/(1024*1024));				NDevices++;				break;			  case DEV_SLM:#ifdef CONFIG_ATARI_SLM				n_slm += attach_slm( target, lun );				break;#endif#ifdef CONFIG_ATARI_SLM_MODULE				SLM_devices[target] = lun;				break;#endif				/* neither of the above: fall through to unknown device */			  case DEV_UNKNOWN:				printk( KERN_INFO "Detected unsupported device at "						"id %d lun %d\n", target, lun);				break;			}		}#ifdef CONFIG_ACSI_MULTI_LUN		while (i != DEV_NONE && ++lun < MAX_LUN);#else		while (0);#endif	}	/* reenable interrupt */	ENABLE_IRQ();	stdma_release();#ifndef CONFIG_ATARI_SLM	printk( KERN_INFO "Found %d ACSI device(s) total.\n", NDevices );#else	printk( KERN_INFO "Found %d ACSI device(s) and %d SLM printer(s) total.\n",			NDevices, n_slm );#endif					 	for( i = 0; i < (MAX_DEV << 4); i++ )		acsi_blocksizes[i] = 1024;	blksize_size[MAJOR_NR] = acsi_blocksizes;	for( i = 0; i < NDevices; ++i )		register_disk(&acsi_gendisk, MKDEV(MAJOR_NR,i<<4),				(acsi_info[i].type==HARDDISK)?1<<4:1,				&acsi_fops,				acsi_info[i].size);	acsi_gendisk.nr_real = NDevices;}#ifdef CONFIG_ATARI_SLM_MODULE/* call attach_slm() for each device that is a printer; needed for init of SLM * driver as a module, since it's not yet present if acsi.c is inited and thus * the bus gets scanned. */void acsi_attach_SLMs( int (*attach_func)( int, int ) ){	int i, n = 0;	for( i = 0; i < 8; ++i )		if (SLM_devices[i] >= 0)			n += (*attach_func)( i, SLM_devices[i] );	printk( KERN_INFO "Found %d SLM printer(s) total.\n", n );}#endif /* CONFIG_ATARI_SLM_MODULE */int acsi_init( void ){	int err = 0;	if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ACSI))		return 0;	if (devfs_register_blkdev( MAJOR_NR, "ad", &acsi_fops )) {		printk( KERN_ERR "Unable to get major %d for ACSI\n", MAJOR_NR );		return -EBUSY;	}	if (!(acsi_buffer =		  (char *)atari_stram_alloc(ACSI_BUFFER_SIZE, "acsi"))) {		printk( KERN_ERR "Unable to get ACSI ST-Ram buffer.\n" );		devfs_unregister_blkdev( MAJOR_NR, "ad" );		return -ENOMEM;	}	phys_acsi_buffer = virt_to_phys( acsi_buffer );	STramMask = ATARIHW_PRESENT(EXTD_DMA) ? 0x00000000 : 0xff000000;		blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);	read_ahead[MAJOR_NR] = 8;		/* 8 sector (4kB) read-ahead */	acsi_gendisk.next = gendisk_head;	gendisk_head = &acsi_gendisk;#ifdef CONFIG_ATARI_SLM	err = slm_init();#endif	if (!err)		acsi_geninit();	return err;}#ifdef MODULEint init_module(void){	int err;	if ((err = acsi_init()))		return( err );	printk( KERN_INFO "ACSI driver loaded as module.\n");	return( 0 );}void cleanup_module(void){	struct gendisk ** gdp;	del_timer( &acsi_timer );	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));	atari_stram_free( acsi_buffer );	if (devfs_unregister_blkdev( MAJOR_NR, "ad" ) != 0)		printk( KERN_ERR "acsi: cleanup_module failed\n");	for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next))		if (*gdp == &acsi_gendisk)			break;	if (!*gdp)		printk( KERN_ERR "acsi: entry in disk chain missing!\n" );	else		*gdp = (*gdp)->next;}#endif#define DEVICE_BUSY busy[device]#define USAGE access_count[device]#define GENDISK_STRUCT acsi_gendisk/* * This routine is called to flush all partitions and partition tables * for a changed scsi disk, and then re-read the new partition table. * If we are revalidating a disk because of a media change, then we * enter with usage == 0.  If we are using an ioctl, we automatically have * usage == 1 (we need an open channel to use an ioctl :-), so this * is our limit. * * Changes by Martin Rogge, 9th Aug 1995:  * got cd-roms to work by calling acsi_devinit. There are only two problems: * First, if there is no medium inserted, the status will remain "changed". * That is no problem at all, but our design of three-valued logic (medium * changed, medium not changed, no medium inserted). * Secondly the check could fail completely and the drive could deliver * nonsensical data, which could mess up the acsi_info[] structure. In * that case we try to make the entry safe. * */static int revalidate_acsidisk( int dev, int maxusage ){	int device;	struct gendisk * gdev;	int max_p, start, i;	struct acsi_info_struct *aip;		device = DEVICE_NR(MINOR(dev));	aip = &acsi_info[device];	gdev = &GENDISK_STRUCT;	cli();	if (DEVICE_BUSY || USAGE > maxusage) {		sti();		return -EBUSY;	};	DEVICE_BUSY = 1;	sti();	max_p = gdev->max_p;	start = device << gdev->minor_shift;	for( i = max_p - 1; i >= 0 ; i-- ) {		if (gdev->part[start + i].nr_sects != 0) {			kdev_t devp = MKDEV(MAJOR_NR, start + i);			struct super_block *sb = get_super(devp);			fsync_dev(devp);			if (sb)				invalidate_inodes(sb);			invalidate_buffers(devp);			gdev->part[start + i].nr_sects = 0;		}		gdev->part[start+i].start_sect = 0;	};	stdma_lock( NULL, NULL );	if (acsi_devinit(aip) != DEV_SUPPORTED) {		printk( KERN_ERR "ACSI: revalidate failed for target %d lun %d\n",		       aip->target, aip->lun);		aip->size = 0;		aip->read_only = 1;		aip->removable = 1;		aip->changed = 1; /* next acsi_open will try again... */	}	ENABLE_IRQ();	stdma_release();		grok_partitions(gdev, device, (aip->type==HARDDISK)?1<<4:1, aip->size);	DEVICE_BUSY = 0;	wake_up(&busy_wait);	return 0;}static int acsi_revalidate (dev_t dev){  return revalidate_acsidisk (dev, 0);}

⌨️ 快捷键说明

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