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

📄 pcd.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		r = pcd_completion(cd, buf, fun);	if (r)		pcd_req_sense(cd, fun);	return r;}static int pcd_packet(struct cdrom_device_info *cdi, struct packet_command *cgc){	return pcd_atapi(cdi->handle, cgc->cmd, cgc->buflen, cgc->buffer,			 "generic packet");}#define DBMSG(msg)	((verbose>1)?(msg):NULL)static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr){	struct pcd_unit *cd = cdi->handle;	int res = cd->changed;	if (res)		cd->changed = 0;	return res;}static int pcd_lock_door(struct cdrom_device_info *cdi, int lock){	char un_cmd[12] = { 0x1e, 0, 0, 0, lock, 0, 0, 0, 0, 0, 0, 0 };	return pcd_atapi(cdi->handle, un_cmd, 0, pcd_scratch,			 lock ? "lock door" : "unlock door");}static int pcd_tray_move(struct cdrom_device_info *cdi, int position){	char ej_cmd[12] = { 0x1b, 0, 0, 0, 3 - position, 0, 0, 0, 0, 0, 0, 0 };	return pcd_atapi(cdi->handle, ej_cmd, 0, pcd_scratch,			 position ? "eject" : "close tray");}static void pcd_sleep(int cs){	current->state = TASK_INTERRUPTIBLE;	schedule_timeout(cs);}static int pcd_reset(struct pcd_unit *cd){	int i, k, flg;	int expect[5] = { 1, 1, 1, 0x14, 0xeb };	pi_connect(cd->pi);	write_reg(cd, 6, 0xa0 + 0x10 * cd->drive);	write_reg(cd, 7, 8);	pcd_sleep(20 * HZ / 1000);	/* delay a bit */	k = 0;	while ((k++ < PCD_RESET_TMO) && (status_reg(cd) & IDE_BUSY))		pcd_sleep(HZ / 10);	flg = 1;	for (i = 0; i < 5; i++)		flg &= (read_reg(cd, i + 1) == expect[i]);	if (verbose) {		printk("%s: Reset (%d) signature = ", cd->name, k);		for (i = 0; i < 5; i++)			printk("%3x", read_reg(cd, i + 1));		if (!flg)			printk(" (incorrect)");		printk("\n");	}	pi_disconnect(cd->pi);	return flg - 1;}static int pcd_drive_reset(struct cdrom_device_info *cdi){	return pcd_reset(cdi->handle);}static int pcd_ready_wait(struct pcd_unit *cd, int tmo){	char tr_cmd[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };	int k, p;	k = 0;	while (k < tmo) {		cd->last_sense = 0;		pcd_atapi(cd, tr_cmd, 0, NULL, DBMSG("test unit ready"));		p = cd->last_sense;		if (!p)			return 0;		if (!(((p & 0xffff) == 0x0402) || ((p & 0xff) == 6)))			return p;		k++;		pcd_sleep(HZ);	}	return 0x000020;	/* timeout */}static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr){	char rc_cmd[12] = { 0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };	struct pcd_unit *cd = cdi->handle;	if (pcd_ready_wait(cd, PCD_READY_TMO))		return CDS_DRIVE_NOT_READY;	if (pcd_atapi(cd, rc_cmd, 8, pcd_scratch, DBMSG("check media")))		return CDS_NO_DISC;	return CDS_DISC_OK;}static int pcd_identify(struct pcd_unit *cd, char *id){	int k, s;	char id_cmd[12] = { 0x12, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 };	pcd_bufblk = -1;	s = pcd_atapi(cd, id_cmd, 36, pcd_buffer, "identify");	if (s)		return -1;	if ((pcd_buffer[0] & 0x1f) != 5) {		if (verbose)			printk("%s: %s is not a CD-ROM\n",			       cd->name, cd->drive ? "Slave" : "Master");		return -1;	}	memcpy(id, pcd_buffer + 16, 16);	id[16] = 0;	k = 16;	while ((k >= 0) && (id[k] <= 0x20)) {		id[k] = 0;		k--;	}	printk("%s: %s: %s\n", cd->name, cd->drive ? "Slave" : "Master", id);	return 0;}/* * returns  0, with id set if drive is detected *	    -1, if drive detection failed */static int pcd_probe(struct pcd_unit *cd, int ms, char *id){	if (ms == -1) {		for (cd->drive = 0; cd->drive <= 1; cd->drive++)			if (!pcd_reset(cd) && !pcd_identify(cd, id))				return 0;	} else {		cd->drive = ms;		if (!pcd_reset(cd) && !pcd_identify(cd, id))			return 0;	}	return -1;}static void pcd_probe_capabilities(void){	int unit, r;	char buffer[32];	char cmd[12] = { 0x5a, 1 << 3, 0x2a, 0, 0, 0, 0, 18, 0, 0, 0, 0 };	struct pcd_unit *cd;	for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {		if (!cd->present)			continue;		r = pcd_atapi(cd, cmd, 18, buffer, "mode sense capabilities");		if (r)			continue;		/* we should now have the cap page */		if ((buffer[11] & 1) == 0)			cd->info.mask |= CDC_CD_R;		if ((buffer[11] & 2) == 0)			cd->info.mask |= CDC_CD_RW;		if ((buffer[12] & 1) == 0)			cd->info.mask |= CDC_PLAY_AUDIO;		if ((buffer[14] & 1) == 0)			cd->info.mask |= CDC_LOCK;		if ((buffer[14] & 8) == 0)			cd->info.mask |= CDC_OPEN_TRAY;		if ((buffer[14] >> 6) == 0)			cd->info.mask |= CDC_CLOSE_TRAY;	}}static int pcd_detect(void){	char id[18];	int k, unit;	struct pcd_unit *cd;	printk("%s: %s version %s, major %d, nice %d\n",	       name, name, PCD_VERSION, major, nice);	k = 0;	if (pcd_drive_count == 0) { /* nothing spec'd - so autoprobe for 1 */		cd = pcd;		if (pi_init(cd->pi, 1, -1, -1, -1, -1, -1, pcd_buffer,			    PI_PCD, verbose, cd->name)) {			if (!pcd_probe(cd, -1, id) && cd->disk) {				cd->present = 1;				k++;			} else				pi_release(cd->pi);		}	} else {		for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {			int *conf = *drives[unit];			if (!conf[D_PRT])				continue;			if (!pi_init(cd->pi, 0, conf[D_PRT], conf[D_MOD],				     conf[D_UNI], conf[D_PRO], conf[D_DLY],				     pcd_buffer, PI_PCD, verbose, cd->name)) 				continue;			if (!pcd_probe(cd, conf[D_SLV], id) && cd->disk) {				cd->present = 1;				k++;			} else				pi_release(cd->pi);		}	}	if (k)		return 0;	printk("%s: No CD-ROM drive found\n", name);	for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++)		put_disk(cd->disk);	return -1;}/* I/O request processing */static struct request_queue *pcd_queue;static void do_pcd_request(request_queue_t * q){	if (pcd_busy)		return;	while (1) {		pcd_req = elv_next_request(q);		if (!pcd_req)			return;		if (rq_data_dir(pcd_req) == READ) {			struct pcd_unit *cd = pcd_req->rq_disk->private_data;			if (cd != pcd_current)				pcd_bufblk = -1;			pcd_current = cd;			pcd_sector = pcd_req->sector;			pcd_count = pcd_req->current_nr_sectors;			pcd_buf = pcd_req->buffer;			pcd_busy = 1;			ps_set_intr(do_pcd_read, NULL, 0, nice);			return;		} else			end_request(pcd_req, 0);	}}static inline void next_request(int success){	unsigned long saved_flags;	spin_lock_irqsave(&pcd_lock, saved_flags);	end_request(pcd_req, success);	pcd_busy = 0;	do_pcd_request(pcd_queue);	spin_unlock_irqrestore(&pcd_lock, saved_flags);}static int pcd_ready(void){	return (((status_reg(pcd_current) & (IDE_BUSY | IDE_DRQ)) == IDE_DRQ));}static void pcd_transfer(void){	while (pcd_count && (pcd_sector / 4 == pcd_bufblk)) {		int o = (pcd_sector % 4) * 512;		memcpy(pcd_buf, pcd_buffer + o, 512);		pcd_count--;		pcd_buf += 512;		pcd_sector++;	}}static void pcd_start(void){	int b, i;	char rd_cmd[12] = { 0xa8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 };	pcd_bufblk = pcd_sector / 4;	b = pcd_bufblk;	for (i = 0; i < 4; i++) {		rd_cmd[5 - i] = b & 0xff;		b = b >> 8;	}	if (pcd_command(pcd_current, rd_cmd, 2048, "read block")) {		pcd_bufblk = -1;		next_request(0);		return;	}	mdelay(1);	ps_set_intr(do_pcd_read_drq, pcd_ready, PCD_TMO, nice);}static void do_pcd_read(void){	pcd_busy = 1;	pcd_retries = 0;	pcd_transfer();	if (!pcd_count) {		next_request(1);		return;	}	pi_do_claimed(pcd_current->pi, pcd_start);}static void do_pcd_read_drq(void){	unsigned long saved_flags;	if (pcd_completion(pcd_current, pcd_buffer, "read block")) {		if (pcd_retries < PCD_RETRIES) {			mdelay(1);			pcd_retries++;			pi_do_claimed(pcd_current->pi, pcd_start);			return;		}		pcd_bufblk = -1;		next_request(0);		return;	}	do_pcd_read();	spin_lock_irqsave(&pcd_lock, saved_flags);	do_pcd_request(pcd_queue);	spin_unlock_irqrestore(&pcd_lock, saved_flags);}/* the audio_ioctl stuff is adapted from sr_ioctl.c */static int pcd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg){	struct pcd_unit *cd = cdi->handle;	switch (cmd) {	case CDROMREADTOCHDR:		{			char cmd[12] =			    { GPCMD_READ_TOC_PMA_ATIP, 0, 0, 0, 0, 0, 0, 0, 12,			 0, 0, 0 };			struct cdrom_tochdr *tochdr =			    (struct cdrom_tochdr *) arg;			char buffer[32];			int r;			r = pcd_atapi(cd, cmd, 12, buffer, "read toc header");			tochdr->cdth_trk0 = buffer[2];			tochdr->cdth_trk1 = buffer[3];			return r ? -EIO : 0;		}	case CDROMREADTOCENTRY:		{			char cmd[12] =			    { GPCMD_READ_TOC_PMA_ATIP, 0, 0, 0, 0, 0, 0, 0, 12,			 0, 0, 0 };			struct cdrom_tocentry *tocentry =			    (struct cdrom_tocentry *) arg;			unsigned char buffer[32];			int r;			cmd[1] =			    (tocentry->cdte_format == CDROM_MSF ? 0x02 : 0);			cmd[6] = tocentry->cdte_track;			r = pcd_atapi(cd, cmd, 12, buffer, "read toc entry");			tocentry->cdte_ctrl = buffer[5] & 0xf;			tocentry->cdte_adr = buffer[5] >> 4;			tocentry->cdte_datamode =			    (tocentry->cdte_ctrl & 0x04) ? 1 : 0;			if (tocentry->cdte_format == CDROM_MSF) {				tocentry->cdte_addr.msf.minute = buffer[9];				tocentry->cdte_addr.msf.second = buffer[10];				tocentry->cdte_addr.msf.frame = buffer[11];			} else				tocentry->cdte_addr.lba =				    (((((buffer[8] << 8) + buffer[9]) << 8)				      + buffer[10]) << 8) + buffer[11];			return r ? -EIO : 0;		}	default:		return -ENOSYS;	}}static int pcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn){	char cmd[12] =	    { GPCMD_READ_SUBCHANNEL, 0, 0x40, 2, 0, 0, 0, 0, 24, 0, 0, 0 };	char buffer[32];	if (pcd_atapi(cdi->handle, cmd, 24, buffer, "get mcn"))		return -EIO;	memcpy(mcn->medium_catalog_number, buffer + 9, 13);	mcn->medium_catalog_number[13] = 0;	return 0;}static int __init pcd_init(void){	struct pcd_unit *cd;	int unit;	if (disable)		return -1;	pcd_init_units();	if (pcd_detect())		return -1;	/* get the atapi capabilities page */	pcd_probe_capabilities();	if (register_blkdev(major, name)) {		for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++)			put_disk(cd->disk);		return -1;	}	pcd_queue = blk_init_queue(do_pcd_request, &pcd_lock);	if (!pcd_queue) {		unregister_blkdev(major, name);		for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++)			put_disk(cd->disk);		return -1;	}	for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {		if (cd->present) {			register_cdrom(&cd->info);			cd->disk->private_data = cd;			cd->disk->queue = pcd_queue;			add_disk(cd->disk);		}	}	return 0;}static void __exit pcd_exit(void){	struct pcd_unit *cd;	int unit;	for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {		if (cd->present) {			del_gendisk(cd->disk);			pi_release(cd->pi);			unregister_cdrom(&cd->info);		}		put_disk(cd->disk);	}	blk_cleanup_queue(pcd_queue);	unregister_blkdev(major, name);}MODULE_LICENSE("GPL");module_init(pcd_init)module_exit(pcd_exit)

⌨️ 快捷键说明

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