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

📄 amiflop.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 4 页
字号:
			return 0;		}	}	unit[drive].track = 0;	ms_delay(unit[drive].type->settle_time);	rel_fdc();	fd_deselect(drive);	return 1;}static int fd_seek(int drive, int track){	unsigned char prb;	int cnt;#ifdef DEBUG	printk("seeking drive %d to track %d\n",drive,track);#endif	drive &= 3;	get_fdc(drive);	if (unit[drive].track == track) {		rel_fdc();		return 1;	}	if (!fd_motor_on(drive)) {		rel_fdc();		return 0;	}	if (unit[drive].track < 0 && !fd_calibrate(drive)) {		rel_fdc();		return 0;	}	fd_select (drive);	cnt = unit[drive].track/2 - track/2;	prb = ciab.prb;	prb |= DSKSIDE | DSKDIREC;	if (track % 2 != 0)		prb &= ~DSKSIDE;	if (cnt < 0) {		cnt = - cnt;		prb &= ~DSKDIREC;	}	ciab.prb = prb;	if (track % 2 != unit[drive].track % 2)		ms_delay (unit[drive].type->side_time);	unit[drive].track = track;	if (cnt == 0) {		rel_fdc();		fd_deselect(drive);		return 1;	}	do {		prb &= ~DSKSTEP;		ciab.prb = prb;		prb |= DSKSTEP;		udelay (1);		ciab.prb = prb;		ms_delay (unit[drive].type->step_delay);	} while (--cnt != 0);	ms_delay (unit[drive].type->settle_time);	rel_fdc();	fd_deselect(drive);	return 1;}static unsigned long fd_get_drive_id(int drive){	int i;	ulong id = 0;  	drive&=3;  	get_fdc(drive);	/* set up for ID */	MOTOR_ON;	udelay(2);	SELECT(SELMASK(drive));	udelay(2);	DESELECT(SELMASK(drive));	udelay(2);	MOTOR_OFF;	udelay(2);	SELECT(SELMASK(drive));	udelay(2);	DESELECT(SELMASK(drive));	udelay(2);	/* loop and read disk ID */	for (i=0; i<32; i++) {		SELECT(SELMASK(drive));		udelay(2);		/* read and store value of DSKRDY */		id <<= 1;		id |= (ciaa.pra & DSKRDY) ? 0 : 1;	/* cia regs are low-active! */		DESELECT(SELMASK(drive));	}	rel_fdc();        /*         * RB: At least A500/A2000's df0: don't identify themselves.         * As every (real) Amiga has at least a 3.5" DD drive as df0:         * we default to that if df0: doesn't identify as a certain         * type.         */        if(drive == 0 && id == FD_NODRIVE)	{                id = fd_def_df0;                printk(KERN_NOTICE "fd: drive 0 didn't identify, setting default %08lx\n", (ulong)fd_def_df0);	}	/* return the ID value */	return (id);}static void fd_block_done(int irq, void *dummy, struct pt_regs *fp){	if (block_flag)		custom.dsklen = 0x4000;	if (block_flag == 2) { /* writing */		writepending = 2;		post_write_timer.expires = jiffies + 1; /* at least 2 ms */		post_write_timer.data = selected;		add_timer(&post_write_timer);	}	else {                /* reading */		block_flag = 0;		wake_up (&wait_fd_block);	}}static void raw_read(int drive){	drive&=3;	get_fdc(drive);	while (block_flag)		sleep_on(&wait_fd_block);	fd_select(drive);	/* setup adkcon bits correctly */	custom.adkcon = ADK_MSBSYNC;	custom.adkcon = ADK_SETCLR|ADK_WORDSYNC|ADK_FAST;	custom.dsksync = MFM_SYNC;	custom.dsklen = 0;	custom.dskptr = (u_char *)ZTWO_PADDR((u_char *)raw_buf);	custom.dsklen = unit[drive].type->read_size/sizeof(short) | DSKLEN_DMAEN;	custom.dsklen = unit[drive].type->read_size/sizeof(short) | DSKLEN_DMAEN;	block_flag = 1;	while (block_flag)		sleep_on (&wait_fd_block);	custom.dsklen = 0;	fd_deselect(drive);	rel_fdc();}static int raw_write(int drive){	ushort adk;	drive&=3;	get_fdc(drive); /* corresponds to rel_fdc() in post_write() */	if ((ciaa.pra & DSKPROT) == 0) {		rel_fdc();		return 0;	}	while (block_flag)		sleep_on(&wait_fd_block);	fd_select(drive);	/* clear adkcon bits */	custom.adkcon = ADK_PRECOMP1|ADK_PRECOMP0|ADK_WORDSYNC|ADK_MSBSYNC;	/* set appropriate adkcon bits */	adk = ADK_SETCLR|ADK_FAST;	if ((ulong)unit[drive].track >= unit[drive].type->precomp2)		adk |= ADK_PRECOMP1;	else if ((ulong)unit[drive].track >= unit[drive].type->precomp1)		adk |= ADK_PRECOMP0;	custom.adkcon = adk;	custom.dsklen = DSKLEN_WRITE;	custom.dskptr = (u_char *)ZTWO_PADDR((u_char *)raw_buf);	custom.dsklen = unit[drive].type->write_size/sizeof(short) | DSKLEN_DMAEN|DSKLEN_WRITE;	custom.dsklen = unit[drive].type->write_size/sizeof(short) | DSKLEN_DMAEN|DSKLEN_WRITE;	block_flag = 2;	return 1;}/* * to be called at least 2ms after the write has finished but before any * other access to the hardware. */static void post_write (unsigned long drive){#ifdef DEBUG	printk("post_write for drive %ld\n",drive);#endif	drive &= 3;	custom.dsklen = 0;	block_flag = 0;	writepending = 0;	writefromint = 0;	unit[drive].dirty = 0;	wake_up(&wait_fd_block);	fd_deselect(drive);	rel_fdc(); /* corresponds to get_fdc() in raw_write */}/* * The following functions are to convert the block contents into raw data * written to disk and vice versa. * (Add other formats here ;-)) */static unsigned long scan_sync(unsigned long raw, unsigned long end){	ushort *ptr = (ushort *)raw, *endp = (ushort *)end;	while (ptr < endp && *ptr++ != 0x4489)		;	if (ptr < endp) {		while (*ptr == 0x4489 && ptr < endp)			ptr++;		return (ulong)ptr;	}	return 0;}static inline unsigned long checksum(unsigned long *addr, int len){	unsigned long csum = 0;	len /= sizeof(*addr);	while (len-- > 0)		csum ^= *addr++;	csum = ((csum>>1) & 0x55555555)  ^  (csum & 0x55555555);	return csum;}static unsigned long decode (unsigned long *data, unsigned long *raw,			     int len){	ulong *odd, *even;	/* convert length from bytes to longwords */	len >>= 2;	odd = raw;	even = odd + len;	/* prepare return pointer */	raw += len * 2;	do {		*data++ = ((*odd++ & 0x55555555) << 1) | (*even++ & 0x55555555);	} while (--len != 0);	return (ulong)raw;}struct header {	unsigned char magic;	unsigned char track;	unsigned char sect;	unsigned char ord;	unsigned char labels[16];	unsigned long hdrchk;	unsigned long datachk;};static int amiga_read(int drive){	unsigned long raw;	unsigned long end;	int scnt;	unsigned long csum;	struct header hdr;	drive&=3;	raw = (long) raw_buf;	end = raw + unit[drive].type->read_size;	for (scnt = 0;scnt < unit[drive].dtype->sects * unit[drive].type->sect_mult; scnt++) {		if (!(raw = scan_sync(raw, end))) {			printk (KERN_INFO "can't find sync for sector %d\n", scnt);			return MFM_NOSYNC;		}		raw = decode ((ulong *)&hdr.magic, (ulong *)raw, 4);		raw = decode ((ulong *)&hdr.labels, (ulong *)raw, 16);		raw = decode ((ulong *)&hdr.hdrchk, (ulong *)raw, 4);		raw = decode ((ulong *)&hdr.datachk, (ulong *)raw, 4);		csum = checksum((ulong *)&hdr,				(char *)&hdr.hdrchk-(char *)&hdr);#ifdef DEBUG		printk ("(%x,%d,%d,%d) (%lx,%lx,%lx,%lx) %lx %lx\n",			hdr.magic, hdr.track, hdr.sect, hdr.ord,			*(ulong *)&hdr.labels[0], *(ulong *)&hdr.labels[4],			*(ulong *)&hdr.labels[8], *(ulong *)&hdr.labels[12],			hdr.hdrchk, hdr.datachk);#endif		if (hdr.hdrchk != csum) {			printk(KERN_INFO "MFM_HEADER: %08lx,%08lx\n", hdr.hdrchk, csum);			return MFM_HEADER;		}		/* verify track */		if (hdr.track != unit[drive].track) {			printk(KERN_INFO "MFM_TRACK: %d, %d\n", hdr.track, unit[drive].track);			return MFM_TRACK;		}		raw = decode ((ulong *)(unit[drive].trackbuf + hdr.sect*512),			      (ulong *)raw, 512);		csum = checksum((ulong *)(unit[drive].trackbuf + hdr.sect*512), 512);		if (hdr.datachk != csum) {			printk(KERN_INFO "MFM_DATA: (%x:%d:%d:%d) sc=%d %lx, %lx\n",			       hdr.magic, hdr.track, hdr.sect, hdr.ord, scnt,			       hdr.datachk, csum);			printk (KERN_INFO "data=(%lx,%lx,%lx,%lx)\n",				((ulong *)(unit[drive].trackbuf+hdr.sect*512))[0],				((ulong *)(unit[drive].trackbuf+hdr.sect*512))[1],				((ulong *)(unit[drive].trackbuf+hdr.sect*512))[2],				((ulong *)(unit[drive].trackbuf+hdr.sect*512))[3]);			return MFM_DATA;		}	}	return 0;}static void encode(unsigned long data, unsigned long *dest){	unsigned long data2;	data &= 0x55555555;	data2 = data ^ 0x55555555;	data |= ((data2 >> 1) | 0x80000000) & (data2 << 1);	if (*(dest - 1) & 0x00000001)		data &= 0x7FFFFFFF;	*dest = data;}static void encode_block(unsigned long *dest, unsigned long *src, int len){	int cnt, to_cnt = 0;	unsigned long data;	/* odd bits */	for (cnt = 0; cnt < len / 4; cnt++) {		data = src[cnt] >> 1;		encode(data, dest + to_cnt++);	}	/* even bits */	for (cnt = 0; cnt < len / 4; cnt++) {		data = src[cnt];		encode(data, dest + to_cnt++);	}}static unsigned long *putsec(int disk, unsigned long *raw, int cnt){	struct header hdr;	int i;	disk&=3;	*raw = (raw[-1]&1) ? 0x2AAAAAAA : 0xAAAAAAAA;	raw++;	*raw++ = 0x44894489;	hdr.magic = 0xFF;	hdr.track = unit[disk].track;	hdr.sect = cnt;	hdr.ord = unit[disk].dtype->sects * unit[disk].type->sect_mult - cnt;	for (i = 0; i < 16; i++)		hdr.labels[i] = 0;	hdr.hdrchk = checksum((ulong *)&hdr,			      (char *)&hdr.hdrchk-(char *)&hdr);	hdr.datachk = checksum((ulong *)(unit[disk].trackbuf+cnt*512), 512);	encode_block(raw, (ulong *)&hdr.magic, 4);	raw += 2;	encode_block(raw, (ulong *)&hdr.labels, 16);	raw += 8;	encode_block(raw, (ulong *)&hdr.hdrchk, 4);	raw += 2;	encode_block(raw, (ulong *)&hdr.datachk, 4);	raw += 2;	encode_block(raw, (ulong *)(unit[disk].trackbuf+cnt*512), 512);	raw += 256;	return raw;}static void amiga_write(int disk){	unsigned int cnt;	unsigned long *ptr = (unsigned long *)raw_buf;	disk&=3;	/* gap space */	for (cnt = 0; cnt < 415 * unit[disk].type->sect_mult; cnt++)		*ptr++ = 0xaaaaaaaa;	/* sectors */	for (cnt = 0; cnt < unit[disk].dtype->sects * unit[disk].type->sect_mult; cnt++)		ptr = putsec (disk, ptr, cnt);	*(ushort *)ptr = (ptr[-1]&1) ? 0x2AA8 : 0xAAA8;}struct dos_header {	unsigned char track,   /* 0-80 */		side,    /* 0-1 */		sec,     /* 0-...*/		len_desc;/* 2 */	unsigned short crc;     /* on 68000 we got an alignment problem, 				   but this compiler solves it  by adding silently 				   adding a pad byte so data won't fit				   and this took about 3h to discover.... */	unsigned char gap1[22];     /* for longword-alignedness (0x4e) */};/* crc routines are borrowed from the messydos-handler  *//* excerpt from the messydos-device           ; The CRC is computed not only over the actual data, but including; the SYNC mark (3 * $a1) and the 'ID/DATA - Address Mark' ($fe/$fb).; As we don't read or encode these fields into our buffers, we have to; preload the registers containing the CRC with the values they would have; after stepping over these fields.;; How CRCs "really" work:;; First, you should regard a bitstring as a series of coefficients of; polynomials. We calculate with these polynomials in modulo-2; arithmetic, in which both add and subtract are done the same as; exclusive-or. Now, we modify our data (a very long polynomial) in; such a way that it becomes divisible by the CCITT-standard 16-bit;		 16   12   5; polynomial:	x  + x	+ x + 1, represented by $11021. The easiest; way to do this would be to multiply (using proper arithmetic) our; datablock with $11021. So we have:;   data * $11021		 =;   data * ($10000 + $1021)      =;   data * $10000 + data * $1021; The left part of this is simple: Just add two 0 bytes. But then; the right part (data $1021) remains difficult and even could have; a carry into the left part. The solution is to use a modified; multiplication, which has a result that is not correct, but with; a difference of any multiple of $11021. We then only need to keep; the 16 least significant bits of the result.;; The following algorithm does this for us:;;   unsigned char *data, c, crclo, crchi;;   while (not done) {;	c = *data++ + crchi;;	crchi = (@ c) >> 8 + crclo;;	crclo = @ c;;   };; Remember, + is done with EOR, the @ operator is in two tables (high

⌨️ 快捷键说明

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