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

📄 ataflop.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *  drivers/block/ataflop.c * *  Copyright (C) 1993  Greg Harp *  Atari Support by Bjoern Brauel, Roman Hodek * *  Big cleanup Sep 11..14 1994 Roman Hodek: *   - Driver now works interrupt driven *   - Support for two drives; should work, but I cannot test that :-( *   - Reading is done in whole tracks and buffered to speed up things *   - Disk change detection and drive deselecting after motor-off *     similar to TOS *   - Autodetection of disk format (DD/HD); untested yet, because I *     don't have an HD drive :-( * *  Fixes Nov 13 1994 Martin Schaller: *   - Autodetection works now *   - Support for 5 1/4'' disks *   - Removed drive type (unknown on atari) *   - Do seeks with 8 Mhz * *  Changes by Andreas Schwab: *   - After errors in multiple read mode try again reading single sectors *  (Feb 1995): *   - Clean up error handling *   - Set blk_size for proper size checking *   - Initialize track register when testing presence of floppy *   - Implement some ioctl's * *  Changes by Torsten Lang: *   - When probing the floppies we should add the FDCCMDADD_H flag since *     the FDC will otherwise wait forever when no disk is inserted... * * ++ Freddi Aschwanden (fa) 20.9.95 fixes for medusa: *  - MFPDELAY() after each FDC access -> atari  *  - more/other disk formats *  - DMA to the block buffer directly if we have a 32bit DMA *  - for medusa, the step rate is always 3ms *  - on medusa, use only cache_push() * Roman: *  - Make disk format numbering independent from minors *  - Let user set max. supported drive type (speeds up format *    detection, saves buffer space) * * Roman 10/15/95: *  - implement some more ioctls *  - disk formatting *   * Andreas 95/12/12: *  - increase gap size at start of track for HD/ED disks * * Michael (MSch) 11/07/96: *  - implemented FDSETPRM and FDDEFPRM ioctl * * Andreas (97/03/19): *  - implemented missing BLK* ioctls * *  Things left to do: *   - Formatting *   - Maybe a better strategy for disk change detection (does anyone *     know one?) */#include <linux/module.h>#include <linux/sched.h>#include <linux/string.h>#include <linux/fs.h>#include <linux/fcntl.h>#include <linux/kernel.h>#include <linux/timer.h>#include <linux/fd.h>#include <linux/errno.h>#include <linux/types.h>#include <linux/delay.h>#include <linux/mm.h>#include <linux/slab.h>#include <linux/init.h>#include <asm/setup.h>#include <asm/system.h>#include <asm/bitops.h>#include <asm/irq.h>#include <asm/pgtable.h>#include <asm/uaccess.h>#include <asm/atafd.h>#include <asm/atafdreg.h>#include <asm/atarihw.h>#include <asm/atariints.h>#include <asm/atari_stdma.h>#include <asm/atari_stram.h>#define MAJOR_NR FLOPPY_MAJOR#include <linux/blk.h>#include <linux/blkpg.h>#define	FD_MAX_UNITS 2#undef DEBUG/* Disk types: DD, HD, ED */static struct atari_disk_type {	const char	*name;	unsigned	spt;		/* sectors per track */	unsigned	blocks;		/* total number of blocks */	unsigned	fdc_speed;	/* fdc_speed setting */	unsigned 	stretch;	/* track doubling ? */} disk_type[] = {	{ "d360",  9, 720, 0, 0},	/*  0: 360kB diskette */	{ "D360",  9, 720, 0, 1},	/*  1: 360kb in 720k or 1.2MB drive */	{ "D720",  9,1440, 0, 0},	/*  2: 720kb in 720k or 1.2MB drive */	{ "D820", 10,1640, 0, 0},	/*  3: DD disk with 82 tracks/10 sectors *//* formats above are probed for type DD */#define	MAX_TYPE_DD 3	{ "h1200",15,2400, 3, 0},	/*  4: 1.2MB diskette */	{ "H1440",18,2880, 3, 0},	/*  5: 1.4 MB diskette (HD) */	{ "H1640",20,3280, 3, 0},	/*  6: 1.64MB diskette (fat HD) 82 tr 20 sec *//* formats above are probed for types DD and HD */#define	MAX_TYPE_HD 6	{ "E2880",36,5760, 3, 0},	/*  7: 2.8 MB diskette (ED) */	{ "E3280",40,6560, 3, 0},	/*  8: 3.2 MB diskette (fat ED) 82 tr 40 sec *//* formats above are probed for types DD, HD and ED */#define	MAX_TYPE_ED 8/* types below are never autoprobed */	{ "H1680",21,3360, 3, 0},	/*  9: 1.68MB diskette (fat HD) 80 tr 21 sec */	{ "h410",10,820, 0, 1},		/* 10: 410k diskette 41 tr 10 sec, stretch */	{ "h1476",18,2952, 3, 0},	/* 11: 1.48MB diskette 82 tr 18 sec */	{ "H1722",21,3444, 3, 0},	/* 12: 1.72MB diskette 82 tr 21 sec */	{ "h420",10,840, 0, 1},		/* 13: 420k diskette 42 tr 10 sec, stretch */	{ "H830",10,1660, 0, 0},	/* 14: 820k diskette 83 tr 10 sec */	{ "h1494",18,2952, 3, 0},	/* 15: 1.49MB diskette 83 tr 18 sec */	{ "H1743",21,3486, 3, 0},	/* 16: 1.74MB diskette 83 tr 21 sec */	{ "h880",11,1760, 0, 0},	/* 17: 880k diskette 80 tr 11 sec */	{ "D1040",13,2080, 0, 0},	/* 18: 1.04MB diskette 80 tr 13 sec */	{ "D1120",14,2240, 0, 0},	/* 19: 1.12MB diskette 80 tr 14 sec */	{ "h1600",20,3200, 3, 0},	/* 20: 1.60MB diskette 80 tr 20 sec */	{ "H1760",22,3520, 3, 0},	/* 21: 1.76MB diskette 80 tr 22 sec */	{ "H1920",24,3840, 3, 0},	/* 22: 1.92MB diskette 80 tr 24 sec */	{ "E3200",40,6400, 3, 0},	/* 23: 3.2MB diskette 80 tr 40 sec */	{ "E3520",44,7040, 3, 0},	/* 24: 3.52MB diskette 80 tr 44 sec */	{ "E3840",48,7680, 3, 0},	/* 25: 3.84MB diskette 80 tr 48 sec */	{ "H1840",23,3680, 3, 0},	/* 26: 1.84MB diskette 80 tr 23 sec */	{ "D800",10,1600, 0, 0},	/* 27: 800k diskette 80 tr 10 sec */};static int StartDiskType[] = {	MAX_TYPE_DD,	MAX_TYPE_HD,	MAX_TYPE_ED};#define	TYPE_DD		0#define	TYPE_HD		1#define	TYPE_ED		2static int DriveType = TYPE_HD;/* Array for translating minors into disk formats */static struct {	int 	 index;	unsigned drive_types;} minor2disktype[] = {	{  0, TYPE_DD },	/*  1: d360 */	{  4, TYPE_HD },	/*  2: h1200 */	{  1, TYPE_DD },	/*  3: D360 */	{  2, TYPE_DD },	/*  4: D720 */	{  1, TYPE_DD },	/*  5: h360 = D360 */	{  2, TYPE_DD },	/*  6: h720 = D720 */	{  5, TYPE_HD },	/*  7: H1440 */	{  7, TYPE_ED },	/*  8: E2880 *//* some PC formats :-) */	{  8, TYPE_ED },	/*  9: E3280    <- was "CompaQ" == E2880 for PC */	{  5, TYPE_HD },	/* 10: h1440 = H1440 */	{  9, TYPE_HD },	/* 11: H1680 */	{ 10, TYPE_DD },	/* 12: h410  */	{  3, TYPE_DD },	/* 13: H820     <- == D820, 82x10 */	{ 11, TYPE_HD },	/* 14: h1476 */	{ 12, TYPE_HD },	/* 15: H1722 */	{ 13, TYPE_DD },	/* 16: h420  */	{ 14, TYPE_DD },	/* 17: H830  */	{ 15, TYPE_HD },	/* 18: h1494 */	{ 16, TYPE_HD },	/* 19: H1743 */	{ 17, TYPE_DD },	/* 20: h880  */	{ 18, TYPE_DD },	/* 21: D1040 */	{ 19, TYPE_DD },	/* 22: D1120 */	{ 20, TYPE_HD },	/* 23: h1600 */	{ 21, TYPE_HD },	/* 24: H1760 */	{ 22, TYPE_HD },	/* 25: H1920 */	{ 23, TYPE_ED },	/* 26: E3200 */	{ 24, TYPE_ED },	/* 27: E3520 */	{ 25, TYPE_ED },	/* 28: E3840 */	{ 26, TYPE_HD },	/* 29: H1840 */	{ 27, TYPE_DD },	/* 30: D800  */	{  6, TYPE_HD },	/* 31: H1640    <- was H1600 == h1600 for PC */};#define NUM_DISK_MINORS (sizeof(minor2disktype)/sizeof(*minor2disktype))/* * Maximum disk size (in kilobytes). This default is used whenever the * current disk size is unknown. */#define MAX_DISK_SIZE 3280/* * MSch: User-provided type information. 'drive' points to * the respective entry of this array. Set by FDSETPRM ioctls. */static struct atari_disk_type user_params[FD_MAX_UNITS];/* * User-provided permanent type information. 'drive' points to * the respective entry of this array.  Set by FDDEFPRM ioctls,  * restored upon disk change by floppy_revalidate() if valid (as seen by * default_params[].blocks > 0 - a bit in unit[].flags might be used for this?) */static struct atari_disk_type default_params[FD_MAX_UNITS];static int floppy_sizes[256];static int floppy_blocksizes[256];/* current info on each unit */static struct atari_floppy_struct {	int connected;				/* !=0 : drive is connected */	int autoprobe;				/* !=0 : do autoprobe	    */	struct atari_disk_type	*disktype;	/* current type of disk */	int track;		/* current head position or -1 if				   unknown */	unsigned int steprate;	/* steprate setting */	unsigned int wpstat;	/* current state of WP signal (for				   disk change detection) */	int flags;		/* flags */} unit[FD_MAX_UNITS];#define	UD	unit[drive]#define	UDT	unit[drive].disktype#define	SUD	unit[SelectedDrive]#define	SUDT	unit[SelectedDrive].disktype#define FDC_READ(reg) ({			\    /* unsigned long __flags; */		\    unsigned short __val;			\    /* save_flags(__flags); cli(); */		\    dma_wd.dma_mode_status = 0x80 | (reg);	\    udelay(25);					\    __val = dma_wd.fdc_acces_seccount;		\    MFPDELAY();					\    /* restore_flags(__flags); */		\    __val & 0xff;				\})#define FDC_WRITE(reg,val)			\    do {					\	/* unsigned long __flags; */		\	/* save_flags(__flags); cli(); */	\	dma_wd.dma_mode_status = 0x80 | (reg);	\	udelay(25);				\	dma_wd.fdc_acces_seccount = (val);	\	MFPDELAY();				\        /* restore_flags(__flags); */		\    } while(0)/* Buffering variables: * First, there is a DMA buffer in ST-RAM that is used for floppy DMA * operations. Second, a track buffer is used to cache a whole track * of the disk to save read operations. These are two separate buffers * because that allows write operations without clearing the track buffer. */static int MaxSectors[] = {	11, 22, 44};static int BufferSize[] = {	15*512, 30*512, 60*512};#define	BUFFER_SIZE	(BufferSize[DriveType])unsigned char *DMABuffer;			  /* buffer for writes */static unsigned long PhysDMABuffer;   /* physical address */static int UseTrackbuffer = -1;		  /* Do track buffering? */MODULE_PARM(UseTrackbuffer, "i");unsigned char *TrackBuffer;			  /* buffer for reads */static unsigned long PhysTrackBuffer; /* physical address */static int BufferDrive, BufferSide, BufferTrack;static int read_track;		/* non-zero if we are reading whole tracks */#define	SECTOR_BUFFER(sec)	(TrackBuffer + ((sec)-1)*512)#define	IS_BUFFERED(drive,side,track) \    (BufferDrive == (drive) && BufferSide == (side) && BufferTrack == (track))/* * These are global variables, as that's the easiest way to give * information to interrupts. They are the data used for the current * request. */static int SelectedDrive = 0;static int ReqCmd, ReqBlock;static int ReqSide, ReqTrack, ReqSector, ReqCnt;static int HeadSettleFlag = 0;static unsigned char *ReqData, *ReqBuffer;static int MotorOn = 0, MotorOffTrys;static int IsFormatting = 0, FormatError;static int UserSteprate[FD_MAX_UNITS] = { -1, -1 };MODULE_PARM(UserSteprate, "1-" __MODULE_STRING(FD_MAX_UNITS) "i");/* Synchronization of FDC access. */static volatile int fdc_busy = 0;static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);static DECLARE_WAIT_QUEUE_HEAD(format_wait);static unsigned long changed_floppies = 0xff, fake_change = 0;#define	CHECK_CHANGE_DELAY	HZ/2#define	FD_MOTOR_OFF_DELAY	(3*HZ)#define	FD_MOTOR_OFF_MAXTRY	(10*20)#define FLOPPY_TIMEOUT		(6*HZ)#define RECALIBRATE_ERRORS	4	/* After this many errors the drive					 * will be recalibrated. */#define MAX_ERRORS		8	/* After this many errors the driver					 * will give up. *//* * The driver is trying to determine the correct media format * while Probing is set. fd_rwsec_done() clears it after a * successful access. */static int Probing = 0;/* This flag is set when a dummy seek is necessary to make the WP * status bit accessible. */static int NeedSeek = 0;#ifdef DEBUG#define DPRINT(a)	printk a#else#define DPRINT(a)#endif/***************************** Prototypes *****************************/static void fd_select_side( int side );static void fd_select_drive( int drive );static void fd_deselect( void );static void fd_motor_off_timer( unsigned long dummy );static void check_change( void );static __inline__ void set_head_settle_flag( void );static __inline__ int get_head_settle_flag( void );static void floppy_irq (int irq, void *dummy, struct pt_regs *fp);static void fd_error( void );static int do_format(kdev_t drive, struct atari_format_descr *desc);static void do_fd_action( int drive );static void fd_calibrate( void );static void fd_calibrate_done( int status );static void fd_seek( void );static void fd_seek_done( int status );static void fd_rwsec( void );static void fd_readtrack_check( unsigned long dummy );static void fd_rwsec_done( int status );static void fd_rwsec_done1(int status);static void fd_writetrack( void );static void fd_writetrack_done( int status );static void fd_times_out( unsigned long dummy );static void finish_fdc( void );static void finish_fdc_done( int dummy );static void floppy_off( unsigned int nr);static __inline__ void copy_buffer( void *from, void *to);static void setup_req_params( int drive );static void redo_fd_request( void);static int invalidate_drive(kdev_t rdev);static int fd_ioctl( struct inode *inode, struct file *filp, unsigned int                     cmd, unsigned long param);static void fd_probe( int drive );static int fd_test_drive_present( int drive );static void config_types( void );static int floppy_open( struct inode *inode, struct file *filp );static int floppy_release( struct inode * inode, struct file * filp );/************************* End of Prototypes **************************/static struct timer_list motor_off_timer =	{ function: fd_motor_off_timer };static struct timer_list readtrack_timer =	{ function: fd_readtrack_check };static struct timer_list timeout_timer =	{ function: fd_times_out };static struct timer_list fd_timer =	{ function: check_change };	static inline voidstart_motor_off_timer(void){	mod_timer(&motor_off_timer, jiffies + FD_MOTOR_OFF_DELAY);	MotorOffTrys = 0;}static inline voidstart_check_change_timer( void ){	mod_timer(&fd_timer, jiffies + CHECK_CHANGE_DELAY);}static inline voidstart_timeout(void){	mod_timer(&timeout_timer, jiffies + FLOPPY_TIMEOUT);}static inline voidstop_timeout(void){	del_timer(&timeout_timer);}/* Select the side to use. */static void fd_select_side( int side ){	unsigned long flags;	save_flags(flags);	cli(); /* protect against various other ints mucking around with the PSG */  	sound_ym.rd_data_reg_sel = 14; /* Select PSG Port A */	sound_ym.wd_data = (side == 0) ? sound_ym.rd_data_reg_sel | 0x01 :	                                 sound_ym.rd_data_reg_sel & 0xfe;	restore_flags(flags);}/* Select a drive, update the FDC's track register and set the correct * clock speed for this disk's type. */static void fd_select_drive( int drive ){	unsigned long flags;	unsigned char tmp;  	if (drive == SelectedDrive)	  return;	save_flags(flags);	cli(); /* protect against various other ints mucking around with the PSG */	sound_ym.rd_data_reg_sel = 14; /* Select PSG Port A */	tmp = sound_ym.rd_data_reg_sel;	sound_ym.wd_data = (tmp | DSKDRVNONE) & ~(drive == 0 ? DSKDRV0 : DSKDRV1);	atari_dont_touch_floppy_select = 1;	restore_flags(flags);	/* restore track register to saved value */	FDC_WRITE( FDCREG_TRACK, UD.track );	udelay(25);	/* select 8/16 MHz */	if (UDT)		if (ATARIHW_PRESENT(FDCSPEED))			dma_wd.fdc_speed = UDT->fdc_speed;		SelectedDrive = drive;}/* Deselect both drives. */static void fd_deselect( void ){	unsigned long flags;	save_flags(flags);	cli(); /* protect against various other ints mucking around with the PSG */	atari_dont_touch_floppy_select = 0;	sound_ym.rd_data_reg_sel=14;	/* Select PSG Port A */	sound_ym.wd_data = (sound_ym.rd_data_reg_sel |			    (MACH_IS_FALCON ? 3 : 7)); /* no drives selected */	/* On Falcon, the drive B select line is used on the printer port, so	 * leave it alone... */	SelectedDrive = -1;	restore_flags(flags);}/* This timer function deselects the drives when the FDC switched the * motor off. The deselection cannot happen earlier because the FDC * counts the index signals, which arrive only if one drive is selected. */static void fd_motor_off_timer( unsigned long dummy ){	unsigned char status;	if (SelectedDrive < 0)		/* no drive selected, needn't deselect anyone */		return;	if (stdma_islocked())		goto retry;	status = FDC_READ( FDCREG_STATUS );	if (!(status & 0x80)) {		/* motor already turned off by FDC -> deselect drives */		MotorOn = 0;		fd_deselect();		return;

⌨️ 快捷键说明

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