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

📄 gscd.c

📁 cdrom device drive for linux.
💻 C
📖 第 1 页 / 共 2 页
字号:
			disk_state = ST_x08 | ST_x04 | ST_INVALID;
			return;
		}

		/* ...and waiting */
		for (i = 1, dummy = 1; i < 0xFFFF; i++) {
			dummy *= i;
		}
	}

	/* LOC_172 */
	/* check the unit */
	/* and wake it up */
	if (cmd_unit_alive() != 0x08) {
		/* LOC_174 */
		/* game over for this unit */
		disk_state = ST_x08 | ST_x04 | ST_INVALID;
		return;
	}

	/* LOC_176 */
#ifdef GSCD_DEBUG
	printk("LOC_176 ");
#endif
	if (drv_mode == 0x09) {
		/* magic... */
		printk("GSCD: magic ...\n");
		outb(result, GSCDPORT(2));
	}

	/* write the command to the drive */
	cmd_write_cmd(cmd);

	/* LOC_178 */
	for (;;) {
		result = wait_drv_ready();
		if (result != drv_mode) {
			/* LOC_179 */
			if (result == 0x04) {	/* Mode 4 */
				/* LOC_205 */
#ifdef GSCD_DEBUG
				printk("LOC_205 ");
#endif
				disk_state = inb(GSCDPORT(2));

				do {
					result = wait_drv_ready();
				} while (result != drv_mode);
				return;

			} else {
				if (result == 0x06) {	/* Mode 6 */
					/* LOC_181 */
#ifdef GSCD_DEBUG
					printk("LOC_181 ");
#endif

					if (cmd_type == TYPE_DATA) {
						/* read data */
						/* LOC_184 */
						if (drv_mode == 9) {
							/* read the data to the buffer (word) */

							/* (*(cmd+1))?(CD_FRAMESIZE/2):(CD_FRAMESIZE_RAW/2) */
							cmd_read_w
							    (respo_buf,
							     respo_count,
							     CD_FRAMESIZE /
							     2);
							return;
						} else {
							/* read the data to the buffer (byte) */

							/* (*(cmd+1))?(CD_FRAMESIZE):(CD_FRAMESIZE_RAW)    */
							cmd_read_b
							    (respo_buf,
							     respo_count,
							     CD_FRAMESIZE);
							return;
						}
					} else {
						/* read the info to the buffer */
						cmd_info_in(respo_buf,
							    respo_count);
						return;
					}

					return;
				}
			}

		} else {
			disk_state = ST_x08 | ST_x04 | ST_INVALID;
			return;
		}
	}			/* for (;;) */


#ifdef GSCD_DEBUG
	printk("\n");
#endif
}


static void cmd_write_cmd(char *pstr)
{
	int i, j;

	/* LOC_177 */
#ifdef GSCD_DEBUG
	printk("LOC_177 ");
#endif

	/* calculate the number of parameter */
	j = *pstr & 0x0F;

	/* shift it out */
	for (i = 0; i < j; i++) {
		outb(*pstr, GSCDPORT(2));
		pstr++;
	}
}


static int cmd_unit_alive(void)
{
	int result;
	unsigned long max_test_loops;


	/* LOC_172 */
#ifdef GSCD_DEBUG
	printk("LOC_172 ");
#endif

	outb(curr_drv_state, GSCDPORT(0));
	max_test_loops = 0xFFFF;

	do {
		result = wait_drv_ready();
		max_test_loops--;
	} while ((result != 0x08) && (max_test_loops > 0));

	return result;
}


static void cmd_info_in(char *pb, int count)
{
	int result;
	char read;


	/* read info */
	/* LOC_182 */
#ifdef GSCD_DEBUG
	printk("LOC_182 ");
#endif

	do {
		read = inb(GSCDPORT(2));
		if (count > 0) {
			*pb = read;
			pb++;
			count--;
		}

		/* LOC_183 */
		do {
			result = wait_drv_ready();
		} while (result == 0x0E);
	} while (result == 6);

	cmd_end();
	return;
}


static void cmd_read_b(char *pb, int count, int size)
{
	int result;
	int i;


	/* LOC_188 */
	/* LOC_189 */
#ifdef GSCD_DEBUG
	printk("LOC_189 ");
#endif

	do {
		do {
			result = wait_drv_ready();
		} while (result != 6 || result == 0x0E);

		if (result != 6) {
			cmd_end();
			return;
		}
#ifdef GSCD_DEBUG
		printk("LOC_191 ");
#endif

		for (i = 0; i < size; i++) {
			*pb = inb(GSCDPORT(2));
			pb++;
		}
		count--;
	} while (count > 0);

	cmd_end();
	return;
}


static void cmd_end(void)
{
	int result;


	/* LOC_204 */
#ifdef GSCD_DEBUG
	printk("LOC_204 ");
#endif

	do {
		result = wait_drv_ready();
		if (result == drv_mode) {
			return;
		}
	} while (result != 4);

	/* LOC_205 */
#ifdef GSCD_DEBUG
	printk("LOC_205 ");
#endif

	disk_state = inb(GSCDPORT(2));

	do {
		result = wait_drv_ready();
	} while (result != drv_mode);
	return;

}


static void cmd_read_w(char *pb, int count, int size)
{
	int result;
	int i;


#ifdef GSCD_DEBUG
	printk("LOC_185 ");
#endif

	do {
		/* LOC_185 */
		do {
			result = wait_drv_ready();
		} while (result != 6 || result == 0x0E);

		if (result != 6) {
			cmd_end();
			return;
		}

		for (i = 0; i < size; i++) {
			/* na, hier muss ich noch mal drueber nachdenken */
			*pb = inw(GSCDPORT(2));
			pb++;
		}
		count--;
	} while (count > 0);

	cmd_end();
	return;
}

int __init find_drives(void)
{
	int *pdrv;
	int drvnum;
	int subdrv;
	int i;

	speed = 0;
	pdrv = (int *) &drv_states;
	curr_drv_state = 0xFE;
	subdrv = 0;
	drvnum = 0;

	for (i = 0; i < 8; i++) {
		subdrv++;
		cmd_status();
		disk_state &= ST_x08 | ST_x04 | ST_INVALID | ST_x01;
		if (disk_state != (ST_x08 | ST_x04 | ST_INVALID)) {
			/* LOC_240 */
			*pdrv = curr_drv_state;
			init_cd_drive(drvnum);
			pdrv++;
			drvnum++;
		} else {
			if (subdrv < 2) {
				continue;
			} else {
				subdrv = 0;
			}
		}

/*       curr_drv_state<<1;         <-- das geht irgendwie nicht */
/* muss heissen:    curr_drv_state <<= 1; (ist ja Wert-Zuweisung) */
		curr_drv_state *= 2;
		curr_drv_state |= 1;
#ifdef GSCD_DEBUG
		printk("DriveState: %d\n", curr_drv_state);
#endif
	}

	ndrives = drvnum;
	return drvnum;
}

void __init init_cd_drive(int num)
{
	char resp[50];
	int i;

	printk("GSCD: init unit %d\n", num);
	cc_Ident((char *) &resp);

	printk("GSCD: identification: ");
	for (i = 0; i < 0x1E; i++) {
		printk("%c", resp[i]);
	}
	printk("\n");

	cc_SetSpeed();

}

#ifdef FUTURE_WORK
/* return_done */
static void update_state(void)
{
	unsigned int AX;


	if ((disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) == 0) {
		if (disk_state == (ST_x08 | ST_x04 | ST_INVALID)) {
			AX = ST_INVALID;
		}

		if ((disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01))
		    == 0) {
			invalidate();
			f_drv_ok = 0;
		}

		AX |= 0x8000;
	}

	if (disk_state & ST_PLAYING) {
		AX |= 0x200;
	}

	AX |= 0x100;
	/* pkt_esbx = AX; */

	disk_state = 0;

}
#endif

/* Init for the Module-Version */
int init_gscd(void)
{
	long err;


	/* call the GoldStar-init */
	err = my_gscd_init();

	if (err < 0) {
		return err;
	} else {
		printk(KERN_INFO "Happy GoldStar !\n");
		return 0;
	}
}

void __exit exit_gscd(void)
{
	CLEAR_TIMER;

	devfs_unregister(devfs_find_handle
			 (NULL, "gscd", 0, 0, DEVFS_SPECIAL_BLK, 0));
	if ((devfs_unregister_blkdev(MAJOR_NR, "gscd") == -EINVAL)) {
		printk("What's that: can't unregister GoldStar-module\n");
		return;
	}
	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
	release_region(gscd_port, 4);
	printk(KERN_INFO "GoldStar-module released.\n");
}

#ifdef MODULE
module_init(init_gscd);
#endif
module_exit(exit_gscd);


/* Test for presence of drive and initialize it.  Called only at boot time. */
int __init gscd_init(void)
{
	return my_gscd_init();
}


/* This is the common initialisation for the GoldStar drive. */
/* It is called at boot time AND for module init.           */
int __init my_gscd_init(void)
{
	int i;
	int result;

	printk(KERN_INFO "GSCD: version %s\n", GSCD_VERSION);
	printk(KERN_INFO
	       "GSCD: Trying to detect a Goldstar R420 CD-ROM drive at 0x%X.\n",
	       gscd_port);

	if (check_region(gscd_port, 4)) {
		printk
		    ("GSCD: Init failed, I/O port (%X) already in use.\n",
		     gscd_port);
		return -EIO;
	}


	/* check for card */
	result = wait_drv_ready();
	if (result == 0x09) {
		printk("GSCD: DMA kann ich noch nicht!\n");
		return -EIO;
	}

	if (result == 0x0b) {
		drv_mode = result;
		i = find_drives();
		if (i == 0) {
			printk
			    ("GSCD: GoldStar CD-ROM Drive is not found.\n");
			return -EIO;
		}
	}

	if ((result != 0x0b) && (result != 0x09)) {
		printk
		    ("GSCD: GoldStar Interface Adapter does not exist or H/W error\n");
		return -EIO;
	}

	/* reset all drives */
	i = 0;
	while (drv_states[i] != 0) {
		curr_drv_state = drv_states[i];
		printk(KERN_INFO "GSCD: Reset unit %d ... ", i);
		cc_Reset();
		printk("done\n");
		i++;
	}

	if (devfs_register_blkdev(MAJOR_NR, "gscd", &gscd_fops) != 0) {
		printk
		    ("GSCD: Unable to get major %d for GoldStar CD-ROM\n",
		     MAJOR_NR);
		return -EIO;
	}
	devfs_register(NULL, "gscd", DEVFS_FL_DEFAULT, MAJOR_NR, 0,
		       S_IFBLK | S_IRUGO | S_IWUGO, &gscd_fops, NULL);

	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
	blksize_size[MAJOR_NR] = gscd_blocksizes;
	read_ahead[MAJOR_NR] = 4;

	disk_state = 0;
	gscdPresent = 1;

	request_region(gscd_port, 4, "gscd");
	register_disk(NULL, MKDEV(MAJOR_NR, 0), 1, &gscd_fops, 0);

	printk(KERN_INFO "GSCD: GoldStar CD-ROM Drive found.\n");
	return 0;
}

static void gscd_hsg2msf(long hsg, struct msf *msf)
{
	hsg += CD_MSF_OFFSET;
	msf->min = hsg / (CD_FRAMES * CD_SECS);
	hsg %= CD_FRAMES * CD_SECS;
	msf->sec = hsg / CD_FRAMES;
	msf->frame = hsg % CD_FRAMES;

	gscd_bin2bcd(&msf->min);	/* convert to BCD */
	gscd_bin2bcd(&msf->sec);
	gscd_bin2bcd(&msf->frame);
}


static void gscd_bin2bcd(unsigned char *p)
{
	int u, t;

	u = *p % 10;
	t = *p / 10;
	*p = u | (t << 4);
}


#ifdef FUTURE_WORK
static long gscd_msf2hsg(struct msf *mp)
{
	return gscd_bcd2bin(mp->frame)
	    + gscd_bcd2bin(mp->sec) * CD_FRAMES
	    + gscd_bcd2bin(mp->min) * CD_FRAMES * CD_SECS - CD_MSF_OFFSET;
}

static int gscd_bcd2bin(unsigned char bcd)
{
	return (bcd >> 4) * 10 + (bcd & 0xF);
}
#endif

MODULE_AUTHOR("Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>");
MODULE_LICENSE("GPL");
EXPORT_NO_SYMBOLS;

⌨️ 快捷键说明

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