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

📄 mfmhd.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 3 页
字号:
			DBG("mfm: end_request for CURRENT=0x%p CURRENT(sector=%d current_nr_sectors=%d nr_sectors=%d)\n",				       CURRENT, CURRENT->sector, CURRENT->current_nr_sectors, CURRENT->nr_sectors);			CURRENT->nr_sectors -= CURRENT->current_nr_sectors;			CURRENT->sector += CURRENT->current_nr_sectors;			SectorsLeftInRequest -= CURRENT->current_nr_sectors;			end_request(1);			if (SectorsLeftInRequest) {				hdc63463_dataptr = (unsigned int) CURRENT->buffer;				Copy_buffer = CURRENT->buffer;				Sectors256LeftInCurrent = CURRENT->current_nr_sectors * 2;				errors = &(CURRENT->errors);				/* These should match the present calculations of the next logical sector				   on the device				   Copy_Sector=CURRENT->sector*2; */				if (Copy_Sector != CURRENT->sector * 2)#ifdef DEBUG					/*console_printf*/printk("mfm: Copy_Sector mismatch. Copy_Sector=%d CURRENT->sector*2=%d\n",					Copy_Sector, CURRENT->sector * 2);#else					printk("mfm: Copy_Sector mismatch! Eek!\n");#endif			};	/* CURRENT */		};	/* Sectors256LeftInCurrent */	};	old_status = mfm_status;	mfm_status = inw(MFM_STATUS);	if (mfm_status & (STAT_DER | STAT_ABN)) {		/* Something has gone wrong - let's try that again */		if (cont) {			DBG("mfm_rw_intr: DER/ABN error\n");			cont->error();			cont->redo();		};		return;	};	/* If this code wasn't entered due to command_end but there is	   now a command end we must read the command results out. If it was	   entered like this then mfm_interrupt_handler would have done the	   job. */	if ((!((old_status & (STAT_CPR | STAT_BSY)) == STAT_CPR)) &&	    ((mfm_status & (STAT_CPR | STAT_BSY)) == STAT_CPR)) {		int len = 0;		while (len < 16) {			int in;			in = inw(MFM_DATAIN);			result[len++] = in >> 8;			result[len++] = in;		};	};			/* Result read */	/*console_printf ("mfm_rw_intr nearexit [%02X]\n", __raw_readb(mfm_IRQPollLoc)); */	/* If end of command move on */	if (mfm_status & (STAT_CED)) {		outw(CMD_RCAL, MFM_COMMAND);	/* Clear interrupt condition */		/* End of command - trigger the next command */		if (cont) {			cont->done(1);		}		DBG("mfm_rw_intr: returned from cont->done\n");	} else {		/* Its going to generate another interrupt */		SET_INTR(mfm_rw_intr);	};}static void mfm_setup_rw(void){	DBG("setting up for rw...\n");	SET_INTR(mfm_rw_intr);	issue_command(raw_cmd.cmdcode, raw_cmd.cmddata, raw_cmd.cmdlen);}static void mfm_recal_intr(void){#ifdef DEBUG	console_printf("recal intr - status = ");	print_status();#endif	outw(CMD_RCAL, MFM_COMMAND);	/* Clear interrupt condition */	if (mfm_status & (STAT_DER | STAT_ABN)) {		printk("recal failed\n");		MFM_DRV_INFO.cylinder = NEED_2_RECAL;		if (cont) {			cont->error();			cont->redo();		}		return;	}	/* Thats seek end - we are finished */	if (mfm_status & STAT_SED) {		issue_command(CMD_POD, NULL, 0);		MFM_DRV_INFO.cylinder = 0;		mfm_seek();		return;	}	/* Command end without seek end (see data sheet p.20) for parallel seek	   - we have to send a POL command to wait for the seek */	if (mfm_status & STAT_CED) {		SET_INTR(mfm_recal_intr);		issue_command(CMD_POL, NULL, 0);		return;	}	printk("recal: unknown status\n");}static void mfm_seek_intr(void){#ifdef DEBUG	console_printf("seek intr - status = ");	print_status();#endif	outw(CMD_RCAL, MFM_COMMAND);	/* Clear interrupt condition */	if (mfm_status & (STAT_DER | STAT_ABN)) {		printk("seek failed\n");		MFM_DRV_INFO.cylinder = NEED_2_RECAL;		if (cont) {			cont->error();			cont->redo();		}		return;	}	if (mfm_status & STAT_SED) {		issue_command(CMD_POD, NULL, 0);		MFM_DRV_INFO.cylinder = raw_cmd.cylinder;		mfm_seek();		return;	}	if (mfm_status & STAT_CED) {		SET_INTR(mfm_seek_intr);		issue_command(CMD_POL, NULL, 0);		return;	}	printk("seek: unknown status\n");}/* IDEA2 seems to work better - its what RiscOS sets my * disc to - on its SECOND call to specify! */#define IDEA2#ifndef IDEA2#define SPEC_SL 0x16#define SPEC_SH 0xa9		/* Step pulse high=21, Record Length=001 (256 bytes) */#else#define SPEC_SL 0x00		/* OM2 - SL - step pulse low */#define SPEC_SH 0x21		/* Step pulse high=4, Record Length=001 (256 bytes) */#endifstatic void mfm_setupspecify (int drive, unsigned char *cmdb){	cmdb[0]  = 0x1f;		/* OM0 - !SECT,!MOD,!DIF,PADP,ECD,CRCP,CRCI,ACOR */	cmdb[1]  = 0xc3;		/* OM1 - DTM,BRST,!CEDM,!SEDM,!DERM,0,AMEX,PSK */	cmdb[2]  = SPEC_SL;		/* OM2 - SL - step pulse low */	cmdb[3]  = (number_mfm_drives == 1) ? 0x02 : 0x06;	/* 1 or 2 drives */	cmdb[4]  = 0xfc | ((mfm_info[drive].cylinders - 1) >> 8);/* RW time over/high part of number of cylinders */	cmdb[5]  = mfm_info[drive].cylinders - 1;		/* low part of number of cylinders */	cmdb[6]  = mfm_info[drive].heads - 1;			/* Number of heads */	cmdb[7]  = mfm_info[drive].sectors - 1;			/* Number of sectors */	cmdb[8]  = SPEC_SH;	cmdb[9]  = 0x0a;		/* gap length 1 */	cmdb[10] = 0x0d;		/* gap length 2 */	cmdb[11] = 0x0c;		/* gap length 3 */	cmdb[12] = (mfm_info[drive].precomp - 1) >> 8;	/* pre comp cylinder */	cmdb[13] = mfm_info[drive].precomp - 1;	cmdb[14] = (mfm_info[drive].lowcurrent - 1) >> 8;	/* Low current cylinder */	cmdb[15] = mfm_info[drive].lowcurrent - 1;}static void mfm_specify (void){	unsigned char cmdb[16];	DBG("specify...dev=%d lastspecified=%d\n", raw_cmd.dev, lastspecifieddrive);	mfm_setupspecify (raw_cmd.dev, cmdb);	issue_command (CMD_SPC, cmdb, 16);	/* Ensure that we will do another specify if we move to the other drive */	lastspecifieddrive = raw_cmd.dev;	wait_for_completion();}static void mfm_seek(void){	unsigned char cmdb[4];	DBG("seeking...\n");	if (MFM_DRV_INFO.cylinder < 0) {		SET_INTR(mfm_recal_intr);		DBG("mfm_seek: about to call specify\n");		mfm_specify ();	/* DAG added this */		cmdb[0] = raw_cmd.dev + 1;		cmdb[1] = 0;		issue_command(CMD_RCLB, cmdb, 2);		return;	}	if (MFM_DRV_INFO.cylinder != raw_cmd.cylinder) {		cmdb[0] = raw_cmd.dev + 1;		cmdb[1] = 0;	/* raw_cmd.head; DAG: My data sheet says this should be 0 */		cmdb[2] = raw_cmd.cylinder >> 8;		cmdb[3] = raw_cmd.cylinder;		SET_INTR(mfm_seek_intr);		issue_command(CMD_SEK, cmdb, 4);	} else		mfm_setup_rw();}static void mfm_initialise(void){	DBG("init...\n");	mfm_seek();}static void request_done(int uptodate){	DBG("mfm:request_done\n");	if (uptodate) {		unsigned char block[2] = {0, 0};		/* Apparently worked - let's check bytes left to DMA */		if (hdc63463_dataleft != (PartFragRead_SectorsLeft * 256)) {			printk("mfm: request_done - dataleft=%d - should be %d - Eek!\n", hdc63463_dataleft, PartFragRead_SectorsLeft * 256);			end_request(0);			Busy = 0;		};		/* Potentially this means that we've done; but we might be doing		   a partial access, (over two cylinders) or we may have a number		   of fragments in an image file.  First let's deal with partial accesss		 */		if (PartFragRead) {			/* Yep - a partial access */			/* and issue the remainder */			issue_request(MINOR(CURRENT->rq_dev), PartFragRead_RestartBlock, PartFragRead_SectorsLeft, CURRENT);			return;		}		/* ah well - perhaps there is another fragment to go */		/* Increment pointers/counts to start of next fragment */		if (SectorsLeftInRequest > 0) printk("mfm: SectorsLeftInRequest>0 - Eek! Shouldn't happen!\n");		/* No - its the end of the line */		/* end_request's should have happened at the end of sector DMAs */		/* Turns Drive LEDs off - may slow it down? */		if (QUEUE_EMPTY)			issue_command(CMD_CKV, block, 2);		Busy = 0;		DBG("request_done: About to mfm_request\n");		/* Next one please */		mfm_request();	/* Moved from mfm_rw_intr */		DBG("request_done: returned from mfm_request\n");	} else {		printk("mfm:request_done: update=0\n");		end_request(0);		Busy = 0;	}}static void error_handler(void){	printk("error detected... status = ");	print_status();	(*errors)++;	if (*errors > MFM_DRV_INFO.errors.abort)		cont->done(0);	if (*errors > MFM_DRV_INFO.errors.recal)		MFM_DRV_INFO.cylinder = NEED_2_RECAL;}static void rw_interrupt(void){	printk("rw_interrupt\n");}static struct cont rw_cont ={	rw_interrupt,	error_handler,	mfm_rerequest,	request_done};/* * Actually gets round to issuing the request - note everything at this * point is in 256 byte sectors not Linux 512 byte blocks */static void issue_request(int dev, unsigned int block, unsigned int nsect,			  struct request *req){	int track, start_head, start_sector;	int sectors_to_next_cyl;	dev >>= 6;	track = block / mfm_info[dev].sectors;	start_sector = block % mfm_info[dev].sectors;	start_head = track % mfm_info[dev].heads;	/* First get the number of whole tracks which are free before the next	   track */	sectors_to_next_cyl = (mfm_info[dev].heads - (start_head + 1)) * mfm_info[dev].sectors;	/* Then add in the number of sectors left on this track */	sectors_to_next_cyl += (mfm_info[dev].sectors - start_sector);	DBG("issue_request: mfm_info[dev].sectors=%d track=%d\n", mfm_info[dev].sectors, track);	raw_cmd.dev = dev;	raw_cmd.sector = start_sector;	raw_cmd.head = start_head;	raw_cmd.cylinder = track / mfm_info[dev].heads;	raw_cmd.cmdtype = CURRENT->cmd;	raw_cmd.cmdcode = CURRENT->cmd == WRITE ? CMD_WD : CMD_RD;	raw_cmd.cmddata[0] = dev + 1;	/* DAG: +1 to get US */	raw_cmd.cmddata[1] = raw_cmd.head;	raw_cmd.cmddata[2] = raw_cmd.cylinder >> 8;	raw_cmd.cmddata[3] = raw_cmd.cylinder;	raw_cmd.cmddata[4] = raw_cmd.head;	raw_cmd.cmddata[5] = raw_cmd.sector;	/* Was == and worked - how the heck??? */	if (lastspecifieddrive != raw_cmd.dev)		mfm_specify ();	if (nsect <= sectors_to_next_cyl) {		raw_cmd.cmddata[6] = nsect >> 8;		raw_cmd.cmddata[7] = nsect;		PartFragRead = 0;	/* All in one */		PartFragRead_SectorsLeft = 0;	/* Must set this - used in DMA calcs */	} else {		raw_cmd.cmddata[6] = sectors_to_next_cyl >> 8;		raw_cmd.cmddata[7] = sectors_to_next_cyl;		PartFragRead = sectors_to_next_cyl;	/* only do this many this time */		PartFragRead_RestartBlock = block + sectors_to_next_cyl;	/* Where to restart from */		PartFragRead_SectorsLeft = nsect - sectors_to_next_cyl;	}	raw_cmd.cmdlen = 8;	/* Setup DMA pointers */	hdc63463_dataptr = (unsigned int) Copy_buffer;	hdc63463_dataleft = nsect * 256;	/* Better way? */	DBG("mfm%c: %sing: CHS=%d/%d/%d, sectors=%d, buffer=0x%08lx (%p)\n",	     raw_cmd.dev + 'a', (CURRENT->cmd == READ) ? "read" : "writ",		       raw_cmd.cylinder,		       raw_cmd.head,	    raw_cmd.sector, nsect, (unsigned long) Copy_buffer, CURRENT);	cont = &rw_cont;	errors = &(CURRENT->errors);#if 0	mfm_tq.routine = (void (*)(void *)) mfm_initialise;	queue_task(&mfm_tq, &tq_immediate);	mark_bh(IMMEDIATE_BH);#else	mfm_initialise();#endif}				/* issue_request *//* * Called when an error has just happened - need to trick mfm_request * into thinking we weren't busy * * Turn off ints - mfm_request expects them this way */static void mfm_rerequest(void){	DBG("mfm_rerequest\n");	cli();	Busy = 0;	mfm_request();}static void mfm_request(void){	DBG("mfm_request CURRENT=%p Busy=%d\n", CURRENT, Busy);	if (QUEUE_EMPTY) {		DBG("mfm_request: Exited due to NULL Current 1\n");		return;	}	if (CURRENT->rq_status == RQ_INACTIVE) {		/* Hmm - seems to be happening a lot on 1.3.45 */		/*console_printf("mfm_request: Exited due to INACTIVE Current\n"); */		return;	}	/* If we are still processing then return; we will get called again */	if (Busy) {		/* Again seems to be common in 1.3.45 */		/*DBG*/printk("mfm_request: Exiting due to busy\n");		return;	}	Busy = 1;	while (1) {		unsigned int dev, block, nsect;		DBG("mfm_request: loop start\n");		sti();		DBG("mfm_request: before INIT_REQUEST\n");		if (QUEUE_EMPTY) {			printk("mfm_request: Exiting due to !CURRENT (pre)\n");			CLEAR_INTR;			Busy = 0;			return;		};		INIT_REQUEST;		DBG("mfm_request:                 before arg extraction\n");		dev = MINOR(CURRENT->rq_dev);		block = CURRENT->sector;		nsect = CURRENT->nr_sectors;#ifdef DEBUG		/*if ((dev>>6)==1) */ console_printf("mfm_request:                                raw vals: dev=%d (block=512 bytes) block=%d nblocks=%d\n", dev, block, nsect);#endif		if (dev >= (mfm_drives << 6) ||		    block >= mfm[dev].nr_sects || ((block+nsect) > mfm[dev].nr_sects)) {			if (dev >= (mfm_drives << 6))				printk("mfm: bad minor number: device=%s\n", kdevname(CURRENT->rq_dev));			else				printk("mfm%c: bad access: block=%d, count=%d, nr_sects=%ld\n", (dev >> 6)+'a',				       block, nsect, mfm[dev].nr_sects);			printk("mfm: continue 1\n");			end_request(0);			Busy = 0;			continue;		}		block += mfm[dev].start_sect;		/* DAG: Linux doesn't cope with this - even though it has an array telling		   it the hardware block size - silly */		block <<= 1;	/* Now in 256 byte sectors */		nsect <<= 1;	/* Ditto */		SectorsLeftInRequest = nsect >> 1;		Sectors256LeftInCurrent = CURRENT->current_nr_sectors * 2;		Copy_buffer = CURRENT->buffer;		Copy_Sector = CURRENT->sector << 1;		DBG("mfm_request: block after offset=%d\n", block);		if (CURRENT->cmd != READ && CURRENT->cmd != WRITE) {			printk("unknown mfm-command %d\n", CURRENT->cmd);			end_request(0);			Busy = 0;			printk("mfm: continue 4\n");			continue;		}		issue_request(dev, block, nsect, CURRENT);		break;	}	DBG("mfm_request: Dropping out bottom\n");}static void do_mfm_request(request_queue_t *q){	DBG("do_mfm_request: about to mfm_request\n");	mfm_request();}static void mfm_interrupt_handler(int unused, void *dev_id, struct pt_regs *regs){	void (*handler) (void) = DEVICE_INTR;	CLEAR_INTR;	DBG("mfm_interrupt_handler (handler=0x%p)\n", handler);	mfm_status = inw(MFM_STATUS);	/* If CPR (Command Parameter Reject) and not busy it means that the command	   has some return message to give us */	if ((mfm_status & (STAT_CPR | STAT_BSY)) == STAT_CPR) {		int len = 0;		while (len < 16) {			int in;			in = inw(MFM_DATAIN);			result[len++] = in >> 8;			result[len++] = in;		}	}	if (handler) {		handler();		return;	}	outw (CMD_RCAL, MFM_COMMAND);	/* Clear interrupt condition */	printk ("mfm: unexpected interrupt - status = ");	print_status ();	while (1);}

⌨️ 快捷键说明

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