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

📄 pf.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		r = pf_completion(pf, buf, fun);	if (r)		pf_req_sense(pf, !fun);	return r;}#define DBMSG(msg)      ((verbose>1)?(msg):NULL)static void pf_lock(struct pf_unit *pf, int func){	char lo_cmd[12] = { ATAPI_LOCK, pf->lun << 5, 0, 0, func, 0, 0, 0, 0, 0, 0, 0 };	pf_atapi(pf, lo_cmd, 0, pf_scratch, func ? "unlock" : "lock");}static void pf_eject(struct pf_unit *pf){	char ej_cmd[12] = { ATAPI_DOOR, pf->lun << 5, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0 };	pf_lock(pf, 0);	pf_atapi(pf, ej_cmd, 0, pf_scratch, "eject");}#define PF_RESET_TMO   30	/* in tenths of a second */static void pf_sleep(int cs){	current->state = TASK_INTERRUPTIBLE;	schedule_timeout(cs);}/* the ATAPI standard actually specifies the contents of all 7 registers   after a reset, but the specification is ambiguous concerning the last   two bytes, and different drives interpret the standard differently. */static int pf_reset(struct pf_unit *pf){	int i, k, flg;	int expect[5] = { 1, 1, 1, 0x14, 0xeb };	pi_connect(pf->pi);	write_reg(pf, 6, 0xa0+0x10*pf->drive);	write_reg(pf, 7, 8);	pf_sleep(20 * HZ / 1000);	k = 0;	while ((k++ < PF_RESET_TMO) && (status_reg(pf) & STAT_BUSY))		pf_sleep(HZ / 10);	flg = 1;	for (i = 0; i < 5; i++)		flg &= (read_reg(pf, i + 1) == expect[i]);	if (verbose) {		printk("%s: Reset (%d) signature = ", pf->name, k);		for (i = 0; i < 5; i++)			printk("%3x", read_reg(pf, i + 1));		if (!flg)			printk(" (incorrect)");		printk("\n");	}	pi_disconnect(pf->pi);	return flg - 1;}static void pf_mode_sense(struct pf_unit *pf){	char ms_cmd[12] =	    { ATAPI_MODE_SENSE, pf->lun << 5, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0 };	char buf[8];	pf_atapi(pf, ms_cmd, 8, buf, DBMSG("mode sense"));	pf->media_status = PF_RW;	if (buf[3] & 0x80)		pf->media_status = PF_RO;}static void xs(char *buf, char *targ, int offs, int len){	int j, k, l;	j = 0;	l = 0;	for (k = 0; k < len; k++)		if ((buf[k + offs] != 0x20) || (buf[k + offs] != l))			l = targ[j++] = buf[k + offs];	if (l == 0x20)		j--;	targ[j] = 0;}static int xl(char *buf, int offs){	int v, k;	v = 0;	for (k = 0; k < 4; k++)		v = v * 256 + (buf[k + offs] & 0xff);	return v;}static void pf_get_capacity(struct pf_unit *pf){	char rc_cmd[12] = { ATAPI_CAPACITY, pf->lun << 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };	char buf[8];	int bs;	if (pf_atapi(pf, rc_cmd, 8, buf, DBMSG("get capacity"))) {		pf->media_status = PF_NM;		return;	}	set_capacity(pf->disk, xl(buf, 0) + 1);	bs = xl(buf, 4);	if (bs != 512) {		set_capacity(pf->disk, 0);		if (verbose)			printk("%s: Drive %d, LUN %d,"			       " unsupported block size %d\n",			       pf->name, pf->drive, pf->lun, bs);	}}static int pf_identify(struct pf_unit *pf){	int dt, s;	char *ms[2] = { "master", "slave" };	char mf[10], id[18];	char id_cmd[12] =	    { ATAPI_IDENTIFY, pf->lun << 5, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 };	char buf[36];	s = pf_atapi(pf, id_cmd, 36, buf, "identify");	if (s)		return -1;	dt = buf[0] & 0x1f;	if ((dt != 0) && (dt != 7)) {		if (verbose)			printk("%s: Drive %d, LUN %d, unsupported type %d\n",			       pf->name, pf->drive, pf->lun, dt);		return -1;	}	xs(buf, mf, 8, 8);	xs(buf, id, 16, 16);	pf->removable = (buf[1] & 0x80);	pf_mode_sense(pf);	pf_mode_sense(pf);	pf_mode_sense(pf);	pf_get_capacity(pf);	printk("%s: %s %s, %s LUN %d, type %d",	       pf->name, mf, id, ms[pf->drive], pf->lun, dt);	if (pf->removable)		printk(", removable");	if (pf->media_status == PF_NM)		printk(", no media\n");	else {		if (pf->media_status == PF_RO)			printk(", RO");		printk(", %llu blocks\n",			(unsigned long long)get_capacity(pf->disk));	}	return 0;}/*	returns  0, with id set if drive is detected	        -1, if drive detection failed*/static int pf_probe(struct pf_unit *pf){	if (pf->drive == -1) {		for (pf->drive = 0; pf->drive <= 1; pf->drive++)			if (!pf_reset(pf)) {				if (pf->lun != -1)					return pf_identify(pf);				else					for (pf->lun = 0; pf->lun < 8; pf->lun++)						if (!pf_identify(pf))							return 0;			}	} else {		if (pf_reset(pf))			return -1;		if (pf->lun != -1)			return pf_identify(pf);		for (pf->lun = 0; pf->lun < 8; pf->lun++)			if (!pf_identify(pf))				return 0;	}	return -1;}static int pf_detect(void){	struct pf_unit *pf = units;	int k, unit;	printk("%s: %s version %s, major %d, cluster %d, nice %d\n",	       name, name, PF_VERSION, major, cluster, nice);	k = 0;	if (pf_drive_count == 0) {		if (pi_init(pf->pi, 1, -1, -1, -1, -1, -1, pf_scratch, PI_PF,			    verbose, pf->name)) {			if (!pf_probe(pf) && pf->disk) {				pf->present = 1;				k++;			} else				pi_release(pf->pi);		}	} else		for (unit = 0; unit < PF_UNITS; unit++, pf++) {			int *conf = *drives[unit];			if (!conf[D_PRT])				continue;			if (pi_init(pf->pi, 0, conf[D_PRT], conf[D_MOD],				    conf[D_UNI], conf[D_PRO], conf[D_DLY],				    pf_scratch, PI_PF, verbose, pf->name)) {				if (!pf_probe(pf) && pf->disk) {					pf->present = 1;					k++;				} else					pi_release(pf->pi);			}		}	if (k)		return 0;	printk("%s: No ATAPI disk detected\n", name);	for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++)		put_disk(pf->disk);	return -1;}/* The i/o request engine */static int pf_start(struct pf_unit *pf, int cmd, int b, int c){	int i;	char io_cmd[12] = { cmd, pf->lun << 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };	for (i = 0; i < 4; i++) {		io_cmd[5 - i] = b & 0xff;		b = b >> 8;	}	io_cmd[8] = c & 0xff;	io_cmd[7] = (c >> 8) & 0xff;	i = pf_command(pf, io_cmd, c * 512, "start i/o");	mdelay(1);	return i;}static int pf_ready(void){	return (((status_reg(pf_current) & (STAT_BUSY | pf_mask)) == pf_mask));}static struct request_queue *pf_queue;static void do_pf_request(request_queue_t * q){	if (pf_busy)		return;repeat:	pf_req = elv_next_request(q);	if (!pf_req)		return;	pf_current = pf_req->rq_disk->private_data;	pf_block = pf_req->sector;	pf_run = pf_req->nr_sectors;	pf_count = pf_req->current_nr_sectors;	if (pf_block + pf_count > get_capacity(pf_req->rq_disk)) {		end_request(pf_req, 0);		goto repeat;	}	pf_cmd = rq_data_dir(pf_req);	pf_buf = pf_req->buffer;	pf_retries = 0;	pf_busy = 1;	if (pf_cmd == READ)		pi_do_claimed(pf_current->pi, do_pf_read);	else if (pf_cmd == WRITE)		pi_do_claimed(pf_current->pi, do_pf_write);	else {		pf_busy = 0;		end_request(pf_req, 0);		goto repeat;	}}static int pf_next_buf(void){	unsigned long saved_flags;	pf_count--;	pf_run--;	pf_buf += 512;	pf_block++;	if (!pf_run)		return 0;	if (!pf_count)		return 1;	spin_lock_irqsave(&pf_spin_lock, saved_flags);	end_request(pf_req, 1);	pf_count = pf_req->current_nr_sectors;	pf_buf = pf_req->buffer;	spin_unlock_irqrestore(&pf_spin_lock, saved_flags);	return 1;}static inline void next_request(int success){	unsigned long saved_flags;	spin_lock_irqsave(&pf_spin_lock, saved_flags);	end_request(pf_req, success);	pf_busy = 0;	do_pf_request(pf_queue);	spin_unlock_irqrestore(&pf_spin_lock, saved_flags);}/* detach from the calling context - in case the spinlock is held */static void do_pf_read(void){	ps_set_intr(do_pf_read_start, NULL, 0, nice);}static void do_pf_read_start(void){	pf_busy = 1;	if (pf_start(pf_current, ATAPI_READ_10, pf_block, pf_run)) {		pi_disconnect(pf_current->pi);		if (pf_retries < PF_MAX_RETRIES) {			pf_retries++;			pi_do_claimed(pf_current->pi, do_pf_read_start);			return;		}		next_request(0);		return;	}	pf_mask = STAT_DRQ;	ps_set_intr(do_pf_read_drq, pf_ready, PF_TMO, nice);}static void do_pf_read_drq(void){	while (1) {		if (pf_wait(pf_current, STAT_BUSY, STAT_DRQ | STAT_ERR,			    "read block", "completion") & STAT_ERR) {			pi_disconnect(pf_current->pi);			if (pf_retries < PF_MAX_RETRIES) {				pf_req_sense(pf_current, 0);				pf_retries++;				pi_do_claimed(pf_current->pi, do_pf_read_start);				return;			}			next_request(0);			return;		}		pi_read_block(pf_current->pi, pf_buf, 512);		if (pf_next_buf())			break;	}	pi_disconnect(pf_current->pi);	next_request(1);}static void do_pf_write(void){	ps_set_intr(do_pf_write_start, NULL, 0, nice);}static void do_pf_write_start(void){	pf_busy = 1;	if (pf_start(pf_current, ATAPI_WRITE_10, pf_block, pf_run)) {		pi_disconnect(pf_current->pi);		if (pf_retries < PF_MAX_RETRIES) {			pf_retries++;			pi_do_claimed(pf_current->pi, do_pf_write_start);			return;		}		next_request(0);		return;	}	while (1) {		if (pf_wait(pf_current, STAT_BUSY, STAT_DRQ | STAT_ERR,			    "write block", "data wait") & STAT_ERR) {			pi_disconnect(pf_current->pi);			if (pf_retries < PF_MAX_RETRIES) {				pf_retries++;				pi_do_claimed(pf_current->pi, do_pf_write_start);				return;			}			next_request(0);			return;		}		pi_write_block(pf_current->pi, pf_buf, 512);		if (pf_next_buf())			break;	}	pf_mask = 0;	ps_set_intr(do_pf_write_done, pf_ready, PF_TMO, nice);}static void do_pf_write_done(void){	if (pf_wait(pf_current, STAT_BUSY, 0, "write block", "done") & STAT_ERR) {		pi_disconnect(pf_current->pi);		if (pf_retries < PF_MAX_RETRIES) {			pf_retries++;			pi_do_claimed(pf_current->pi, do_pf_write_start);			return;		}		next_request(0);		return;	}	pi_disconnect(pf_current->pi);	next_request(1);}static int __init pf_init(void){				/* preliminary initialisation */	struct pf_unit *pf;	int unit;	if (disable)		return -1;	pf_init_units();	if (pf_detect())		return -1;	pf_busy = 0;	if (register_blkdev(major, name)) {		for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++)			put_disk(pf->disk);		return -1;	}	pf_queue = blk_init_queue(do_pf_request, &pf_spin_lock);	if (!pf_queue) {		unregister_blkdev(major, name);		for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++)			put_disk(pf->disk);		return -1;	}	blk_queue_max_phys_segments(pf_queue, cluster);	blk_queue_max_hw_segments(pf_queue, cluster);	for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++) {		struct gendisk *disk = pf->disk;		if (!pf->present)			continue;		disk->private_data = pf;		disk->queue = pf_queue;		add_disk(disk);	}	return 0;}static void __exit pf_exit(void){	struct pf_unit *pf;	int unit;	unregister_blkdev(major, name);	for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++) {		if (!pf->present)			continue;		del_gendisk(pf->disk);		put_disk(pf->disk);		pi_release(pf->pi);	}	blk_cleanup_queue(pf_queue);}MODULE_LICENSE("GPL");module_init(pf_init)module_exit(pf_exit)

⌨️ 快捷键说明

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