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

📄 pt.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	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 xn(char *buf, int offs, int size){	int v, k;	v = 0;	for (k = 0; k < size; k++)		v = v * 256 + (buf[k + offs] & 0xff);	return v;}static int pt_identify(struct pt_unit *tape){	int dt, s;	char *ms[2] = { "master", "slave" };	char mf[10], id[18];	char id_cmd[12] = { ATAPI_IDENTIFY, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 };	char ms_cmd[12] =	    { ATAPI_MODE_SENSE, 0, 0x2a, 0, 36, 0, 0, 0, 0, 0, 0, 0 };	char ls_cmd[12] =	    { ATAPI_LOG_SENSE, 0, 0x71, 0, 0, 0, 0, 0, 36, 0, 0, 0 };	char buf[36];	s = pt_atapi(tape, id_cmd, 36, buf, "identify");	if (s)		return -1;	dt = buf[0] & 0x1f;	if (dt != 1) {		if (verbose)			printk("%s: Drive %d, unsupported type %d\n",			       tape->name, tape->drive, dt);		return -1;	}	xs(buf, mf, 8, 8);	xs(buf, id, 16, 16);	tape->flags = 0;	tape->capacity = 0;	tape->bs = 0;	if (!pt_ready_wait(tape, PT_READY_TMO))		tape->flags |= PT_MEDIA;	if (!pt_atapi(tape, ms_cmd, 36, buf, "mode sense")) {		if (!(buf[2] & 0x80))			tape->flags |= PT_WRITE_OK;		tape->bs = xn(buf, 10, 2);	}	if (!pt_atapi(tape, ls_cmd, 36, buf, "log sense"))		tape->capacity = xn(buf, 24, 4);	printk("%s: %s %s, %s", tape->name, mf, id, ms[tape->drive]);	if (!(tape->flags & PT_MEDIA))		printk(", no media\n");	else {		if (!(tape->flags & PT_WRITE_OK))			printk(", RO");		printk(", blocksize %d, %d MB\n", tape->bs, tape->capacity / 1024);	}	return 0;}/* * returns  0, with id set if drive is detected *	   -1, if drive detection failed */static int pt_probe(struct pt_unit *tape){	if (tape->drive == -1) {		for (tape->drive = 0; tape->drive <= 1; tape->drive++)			if (!pt_reset(tape))				return pt_identify(tape);	} else {		if (!pt_reset(tape))			return pt_identify(tape);	}	return -1;}static int pt_detect(void){	struct pt_unit *tape;	int specified = 0, found = 0;	int unit;	printk("%s: %s version %s, major %d\n", name, name, PT_VERSION, major);	specified = 0;	for (unit = 0; unit < PT_UNITS; unit++) {		struct pt_unit *tape = &pt[unit];		tape->pi = &tape->pia;		atomic_set(&tape->available, 1);		tape->flags = 0;		tape->last_sense = 0;		tape->present = 0;		tape->bufptr = NULL;		tape->drive = DU[D_SLV];		snprintf(tape->name, PT_NAMELEN, "%s%d", name, unit);		if (!DU[D_PRT])			continue;		specified++;		if (pi_init(tape->pi, 0, DU[D_PRT], DU[D_MOD], DU[D_UNI],		     DU[D_PRO], DU[D_DLY], pt_scratch, PI_PT,		     verbose, tape->name)) {			if (!pt_probe(tape)) {				tape->present = 1;				found++;			} else				pi_release(tape->pi);		}	}	if (specified == 0) {		tape = pt;		if (pi_init(tape->pi, 1, -1, -1, -1, -1, -1, pt_scratch,			    PI_PT, verbose, tape->name)) {			if (!pt_probe(tape)) {				tape->present = 1;				found++;			} else				pi_release(tape->pi);		}	}	if (found)		return 0;	printk("%s: No ATAPI tape drive detected\n", name);	return -1;}static int pt_open(struct inode *inode, struct file *file){	int unit = iminor(inode) & 0x7F;	struct pt_unit *tape = pt + unit;	int err;	if (unit >= PT_UNITS || (!tape->present))		return -ENODEV;	err = -EBUSY;	if (!atomic_dec_and_test(&tape->available))		goto out;	pt_identify(tape);	err = -ENODEV;	if (!tape->flags & PT_MEDIA)		goto out;	err = -EROFS;	if ((!tape->flags & PT_WRITE_OK) && (file->f_mode & 2))		goto out;	if (!(iminor(inode) & 128))		tape->flags |= PT_REWIND;	err = -ENOMEM;	tape->bufptr = kmalloc(PT_BUFSIZE, GFP_KERNEL);	if (tape->bufptr == NULL) {		printk("%s: buffer allocation failed\n", tape->name);		goto out;	}	file->private_data = tape;	return 0;out:	atomic_inc(&tape->available);	return err;}static int pt_ioctl(struct inode *inode, struct file *file,	 unsigned int cmd, unsigned long arg){	struct pt_unit *tape = file->private_data;	struct mtop __user *p = (void __user *)arg;	struct mtop mtop;	switch (cmd) {	case MTIOCTOP:		if (copy_from_user(&mtop, p, sizeof(struct mtop)))			return -EFAULT;		switch (mtop.mt_op) {		case MTREW:			pt_rewind(tape);			return 0;		case MTWEOF:			pt_write_fm(tape);			return 0;		default:			printk("%s: Unimplemented mt_op %d\n", tape->name,			       mtop.mt_op);			return -EINVAL;		}	default:		printk("%s: Unimplemented ioctl 0x%x\n", tape->name, cmd);		return -EINVAL;	}}static intpt_release(struct inode *inode, struct file *file){	struct pt_unit *tape = file->private_data;	if (atomic_read(&tape->available) > 1)		return -EINVAL;	if (tape->flags & PT_WRITING)		pt_write_fm(tape);	if (tape->flags & PT_REWIND)		pt_rewind(tape);	kfree(tape->bufptr);	tape->bufptr = NULL;	atomic_inc(&tape->available);	return 0;}static ssize_t pt_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos){	struct pt_unit *tape = filp->private_data;	struct pi_adapter *pi = tape->pi;	char rd_cmd[12] = { ATAPI_READ_6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };	int k, n, r, p, s, t, b;	if (!(tape->flags & (PT_READING | PT_WRITING))) {		tape->flags |= PT_READING;		if (pt_atapi(tape, rd_cmd, 0, NULL, "start read-ahead"))			return -EIO;	} else if (tape->flags & PT_WRITING)		return -EIO;	if (tape->flags & PT_EOF)		return 0;	t = 0;	while (count > 0) {		if (!pt_poll_dsc(tape, HZ / 100, PT_TMO, "read"))			return -EIO;		n = count;		if (n > 32768)			n = 32768;	/* max per command */		b = (n - 1 + tape->bs) / tape->bs;		n = b * tape->bs;	/* rounded up to even block */		rd_cmd[4] = b;		r = pt_command(tape, rd_cmd, n, "read");		mdelay(1);		if (r) {			pt_req_sense(tape, 0);			return -EIO;		}		while (1) {			r = pt_wait(tape, STAT_BUSY,				    STAT_DRQ | STAT_ERR | STAT_READY,				    DBMSG("read DRQ"), "");			if (r & STAT_SENSE) {				pi_disconnect(pi);				pt_req_sense(tape, 0);				return -EIO;			}			if (r)				tape->flags |= PT_EOF;			s = read_reg(pi, 7);			if (!(s & STAT_DRQ))				break;			n = (read_reg(pi, 4) + 256 * read_reg(pi, 5));			p = (read_reg(pi, 2) & 3);			if (p != 2) {				pi_disconnect(pi);				printk("%s: Phase error on read: %d\n", tape->name,				       p);				return -EIO;			}			while (n > 0) {				k = n;				if (k > PT_BUFSIZE)					k = PT_BUFSIZE;				pi_read_block(pi, tape->bufptr, k);				n -= k;				b = k;				if (b > count)					b = count;				if (copy_to_user(buf + t, tape->bufptr, b)) {					pi_disconnect(pi);					return -EFAULT;				}				t += b;				count -= b;			}		}		pi_disconnect(pi);		if (tape->flags & PT_EOF)			break;	}	return t;}static ssize_t pt_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos){	struct pt_unit *tape = filp->private_data;	struct pi_adapter *pi = tape->pi;	char wr_cmd[12] = { ATAPI_WRITE_6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };	int k, n, r, p, s, t, b;	if (!(tape->flags & PT_WRITE_OK))		return -EROFS;	if (!(tape->flags & (PT_READING | PT_WRITING))) {		tape->flags |= PT_WRITING;		if (pt_atapi		    (tape, wr_cmd, 0, NULL, "start buffer-available mode"))			return -EIO;	} else if (tape->flags & PT_READING)		return -EIO;	if (tape->flags & PT_EOF)		return -ENOSPC;	t = 0;	while (count > 0) {		if (!pt_poll_dsc(tape, HZ / 100, PT_TMO, "write"))			return -EIO;		n = count;		if (n > 32768)			n = 32768;	/* max per command */		b = (n - 1 + tape->bs) / tape->bs;		n = b * tape->bs;	/* rounded up to even block */		wr_cmd[4] = b;		r = pt_command(tape, wr_cmd, n, "write");		mdelay(1);		if (r) {	/* error delivering command only */			pt_req_sense(tape, 0);			return -EIO;		}		while (1) {			r = pt_wait(tape, STAT_BUSY,				    STAT_DRQ | STAT_ERR | STAT_READY,				    DBMSG("write DRQ"), NULL);			if (r & STAT_SENSE) {				pi_disconnect(pi);				pt_req_sense(tape, 0);				return -EIO;			}			if (r)				tape->flags |= PT_EOF;			s = read_reg(pi, 7);			if (!(s & STAT_DRQ))				break;			n = (read_reg(pi, 4) + 256 * read_reg(pi, 5));			p = (read_reg(pi, 2) & 3);			if (p != 0) {				pi_disconnect(pi);				printk("%s: Phase error on write: %d \n",				       tape->name, p);				return -EIO;			}			while (n > 0) {				k = n;				if (k > PT_BUFSIZE)					k = PT_BUFSIZE;				b = k;				if (b > count)					b = count;				if (copy_from_user(tape->bufptr, buf + t, b)) {					pi_disconnect(pi);					return -EFAULT;				}				pi_write_block(pi, tape->bufptr, k);				t += b;				count -= b;				n -= k;			}		}		pi_disconnect(pi);		if (tape->flags & PT_EOF)			break;	}	return t;}static int __init pt_init(void){	int unit, err = 0;	if (disable) {		err = -1;		goto out;	}	if (pt_detect()) {		err = -1;		goto out;	}	if (register_chrdev(major, name, &pt_fops)) {		printk("pt_init: unable to get major number %d\n", major);		for (unit = 0; unit < PT_UNITS; unit++)			if (pt[unit].present)				pi_release(pt[unit].pi);		err = -1;		goto out;	}	pt_class = class_simple_create(THIS_MODULE, "pt");	if (IS_ERR(pt_class)) {		err = PTR_ERR(pt_class);		goto out_chrdev;	}	devfs_mk_dir("pt");	for (unit = 0; unit < PT_UNITS; unit++)		if (pt[unit].present) {			class_simple_device_add(pt_class, MKDEV(major, unit), 					NULL, "pt%d", unit);			err = devfs_mk_cdev(MKDEV(major, unit),				      S_IFCHR | S_IRUSR | S_IWUSR,				      "pt/%d", unit);			if (err) {				class_simple_device_remove(MKDEV(major, unit));				goto out_class;			}			class_simple_device_add(pt_class, MKDEV(major, unit + 128),					NULL, "pt%dn", unit);			err = devfs_mk_cdev(MKDEV(major, unit + 128),				      S_IFCHR | S_IRUSR | S_IWUSR,				      "pt/%dn", unit);			if (err) {				class_simple_device_remove(MKDEV(major, unit + 128));				goto out_class;			}		}	goto out;out_class:	class_simple_destroy(pt_class);out_chrdev:	unregister_chrdev(major, "pt");out:	return err;}static void __exit pt_exit(void){	int unit;	for (unit = 0; unit < PT_UNITS; unit++)		if (pt[unit].present) {			class_simple_device_remove(MKDEV(major, unit));			devfs_remove("pt/%d", unit);			class_simple_device_remove(MKDEV(major, unit + 128));			devfs_remove("pt/%dn", unit);		}	class_simple_destroy(pt_class);	devfs_remove("pt");	unregister_chrdev(major, name);	for (unit = 0; unit < PT_UNITS; unit++)		if (pt[unit].present)			pi_release(pt[unit].pi);}MODULE_LICENSE("GPL");module_init(pt_init)module_exit(pt_exit)

⌨️ 快捷键说明

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