📄 pt.c
字号:
} if ((k >= tmo) || (s & STAT_ERR)) { if (k >= tmo) printk("%s: %s DSC timeout\n",PT.name,msg); else printk("%s: %s stat=0x%x err=0x%x\n",PT.name,msg,s,e); pt_req_sense(unit,0); return 0; } return 1;}static void pt_media_access_cmd( int unit, int tmo, char *cmd, char *fun){ if (pt_command(unit,cmd,0,fun)) { pt_req_sense(unit,0); return; } pi_disconnect(PI); pt_poll_dsc(unit,HZ,tmo,fun);}static void pt_rewind( int unit ){ char rw_cmd[12] = {ATAPI_REWIND,0,0,0,0,0,0,0,0,0,0,0}; pt_media_access_cmd(unit,PT_REWIND_TMO,rw_cmd,"rewind");}static void pt_write_fm( int unit ){ char wm_cmd[12] = {ATAPI_WFM,0,0,0,1,0,0,0,0,0,0,0}; pt_media_access_cmd(unit,PT_TMO,wm_cmd,"write filemark");}#define DBMSG(msg) ((verbose>1)?(msg):NULL)static int pt_reset( int unit ){ int i, k, flg; int expect[5] = {1,1,1,0x14,0xeb}; pi_connect(PI); WR(0,6,DRIVE); WR(0,7,8); pt_sleep(20*HZ/1000); k = 0; while ((k++ < PT_RESET_TMO) && (RR(1,6)&STAT_BUSY)) pt_sleep(HZ/10); flg = 1; for(i=0;i<5;i++) flg &= (RR(0,i+1) == expect[i]); if (verbose) { printk("%s: Reset (%d) signature = ",PT.name,k); for (i=0;i<5;i++) printk("%3x",RR(0,i+1)); if (!flg) printk(" (incorrect)"); printk("\n"); } pi_disconnect(PI); return flg-1; }static int pt_ready_wait( int unit, int tmo ){ char tr_cmd[12] = {ATAPI_TEST_READY,0,0,0,0,0,0,0,0,0,0,0}; int k, p; k = 0; while (k < tmo) { PT.last_sense = 0; pt_atapi(unit,tr_cmd,0,NULL,DBMSG("test unit ready")); p = PT.last_sense; if (!p) return 0; if (!(((p & 0xffff) == 0x0402)||((p & 0xff) == 6))) return p; k++; pt_sleep(HZ); } return 0x000020; /* timeout */}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 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( int unit ){ 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(unit,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", PT.name,PT.drive,dt); return -1; } xs(buf,mf,8,8); xs(buf,id,16,16); PT.flags = 0; PT.capacity = 0; PT.bs = 0; if (!pt_ready_wait(unit,PT_READY_TMO)) PT.flags |= PT_MEDIA; if (!pt_atapi(unit,ms_cmd,36,buf,"mode sense")) { if (!(buf[2] & 0x80)) PT.flags |= PT_WRITE_OK; PT.bs = xn(buf,10,2); } if (!pt_atapi(unit,ls_cmd,36,buf,"log sense")) PT.capacity = xn(buf,24,4); printk("%s: %s %s, %s", PT.name,mf,id,ms[PT.drive]); if (!(PT.flags & PT_MEDIA)) printk(", no media\n"); else { if (!(PT.flags & PT_WRITE_OK)) printk(", RO"); printk(", blocksize %d, %d MB\n", PT.bs,PT.capacity/1024); } return 0;}static int pt_probe( int unit )/* returns 0, with id set if drive is detected -1, if drive detection failed*/{ if (PT.drive == -1) { for (PT.drive=0;PT.drive<=1;PT.drive++) if (!pt_reset(unit)) return pt_identify(unit); } else { if (!pt_reset(unit)) return pt_identify(unit); } return -1; }static int pt_detect( void ){ int k, unit; printk("%s: %s version %s, major %d\n", name,name,PT_VERSION,major); k = 0; if (pt_drive_count == 0) { unit = 0; if (pi_init(PI,1,-1,-1,-1,-1,-1,pt_scratch, PI_PT,verbose,PT.name)) { if (!pt_probe(unit)) { PT.present = 1; k++; } else pi_release(PI); } } else for (unit=0;unit<PT_UNITS;unit++) if (DU[D_PRT]) if (pi_init(PI,0,DU[D_PRT],DU[D_MOD],DU[D_UNI], DU[D_PRO],DU[D_DLY],pt_scratch,PI_PT,verbose, PT.name)) { if (!pt_probe(unit)) { PT.present = 1; k++; } else pi_release(PI); } if (k) return 0; printk("%s: No ATAPI tape drive detected\n",name); return -1;}#define DEVICE_NR(dev) (MINOR(dev) % 128)static int pt_open (struct inode *inode, struct file *file){ int unit = DEVICE_NR(inode->i_rdev); if ((unit >= PT_UNITS) || (!PT.present)) return -ENODEV; PT.access++; if (PT.access > 1) { PT.access--; return -EBUSY; } pt_identify(unit); if (!PT.flags & PT_MEDIA) { PT.access--; return -ENODEV; } if ((!PT.flags & PT_WRITE_OK) && (file ->f_mode & 2)) { PT.access--; return -EROFS; } if (!(MINOR(inode->i_rdev) & 128)) PT.flags |= PT_REWIND; PT.bufptr = kmalloc(PT_BUFSIZE,GFP_KERNEL); if (PT.bufptr == NULL) { PT.access--; printk("%s: buffer allocation failed\n",PT.name); return -ENOMEM; } return 0;}static int pt_ioctl(struct inode *inode,struct file *file, unsigned int cmd, unsigned long arg){ int unit; struct mtop mtop; if (!inode || !inode->i_rdev) return -EINVAL; unit = DEVICE_NR(inode->i_rdev); if (unit >= PT_UNITS) return -EINVAL; if (!PT.present) return -ENODEV; switch (cmd) { case MTIOCTOP: if (copy_from_user((char *)&mtop, (char *)arg, sizeof(struct mtop))) return -EFAULT; switch (mtop.mt_op) { case MTREW: pt_rewind(unit); return 0; case MTWEOF: pt_write_fm(unit); return 0; default: printk("%s: Unimplemented mt_op %d\n",PT.name, mtop.mt_op); return -EINVAL; } default: printk("%s: Unimplemented ioctl 0x%x\n",PT.name,cmd); return -EINVAL; }}static int pt_release (struct inode *inode, struct file *file){ int unit = DEVICE_NR(inode->i_rdev); if ((unit >= PT_UNITS) || (PT.access <= 0)) return -EINVAL; lock_kernel(); if (PT.flags & PT_WRITING) pt_write_fm(unit); if (PT.flags & PT_REWIND) pt_rewind(unit); PT.access--; kfree(PT.bufptr); PT.bufptr = NULL; unlock_kernel(); return 0;}static ssize_t pt_read(struct file * filp, char * buf, size_t count, loff_t *ppos){ struct inode *ino = filp->f_dentry->d_inode; int unit = DEVICE_NR(ino->i_rdev); 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 (!(PT.flags & (PT_READING|PT_WRITING))) { PT.flags |= PT_READING; if (pt_atapi(unit,rd_cmd,0,NULL,"start read-ahead")) return -EIO; } else if (PT.flags & PT_WRITING) return -EIO; if (PT.flags & PT_EOF) return 0; t = 0; while (count > 0) { if (!pt_poll_dsc(unit,HZ/100,PT_TMO,"read")) return -EIO; n = count; if (n > 32768) n = 32768; /* max per command */ b = (n-1+PT.bs)/PT.bs; n = b*PT.bs; /* rounded up to even block */ rd_cmd[4] = b; r = pt_command(unit,rd_cmd,n,"read"); mdelay(1); if (r) { pt_req_sense(unit,0); return -EIO; } while (1) { r = pt_wait(unit,STAT_BUSY,STAT_DRQ|STAT_ERR|STAT_READY, DBMSG("read DRQ"),""); if (r & STAT_SENSE) { pi_disconnect(PI); pt_req_sense(unit,0); return -EIO; } if (r) PT.flags |= PT_EOF; s = RR(0,7); if (!(s & STAT_DRQ)) break; n = (RR(0,4)+256*RR(0,5)); p = (RR(0,2)&3); if (p != 2) { pi_disconnect(PI); printk("%s: Phase error on read: %d\n",PT.name,p); return -EIO; } while (n > 0) { k = n; if (k > PT_BUFSIZE) k = PT_BUFSIZE; pi_read_block(PI,PT.bufptr,k); n -= k; b = k; if (b > count) b = count; if (copy_to_user(buf + t, PT.bufptr, b)) { pi_disconnect(PI); return -EFAULT; } t += b; count -= b; } } pi_disconnect(PI); if (PT.flags & PT_EOF) break; } return t;}static ssize_t pt_write(struct file * filp, const char * buf, size_t count, loff_t *ppos){ struct inode *ino = filp->f_dentry->d_inode; int unit = DEVICE_NR(ino->i_rdev); 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 (!(PT.flags & PT_WRITE_OK)) return -EROFS; if (!(PT.flags & (PT_READING|PT_WRITING))) { PT.flags |= PT_WRITING; if (pt_atapi(unit,wr_cmd,0,NULL,"start buffer-available mode")) return -EIO; } else if (PT.flags&PT_READING) return -EIO; if (PT.flags & PT_EOF) return -ENOSPC; t = 0; while (count > 0) { if (!pt_poll_dsc(unit,HZ/100,PT_TMO,"write")) return -EIO; n = count; if (n > 32768) n = 32768; /* max per command */ b = (n-1+PT.bs)/PT.bs; n = b*PT.bs; /* rounded up to even block */ wr_cmd[4] = b; r = pt_command(unit,wr_cmd,n,"write"); mdelay(1); if (r) { /* error delivering command only */ pt_req_sense(unit,0); return -EIO; } while (1) { r = pt_wait(unit,STAT_BUSY,STAT_DRQ|STAT_ERR|STAT_READY, DBMSG("write DRQ"),NULL); if (r & STAT_SENSE) { pi_disconnect(PI); pt_req_sense(unit,0); return -EIO; } if (r) PT.flags |= PT_EOF; s = RR(0,7); if (!(s & STAT_DRQ)) break; n = (RR(0,4)+256*RR(0,5)); p = (RR(0,2)&3); if (p != 0) { pi_disconnect(PI); printk("%s: Phase error on write: %d \n",PT.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(PT.bufptr, buf + t, b)) { pi_disconnect(PI); return -EFAULT; } pi_write_block(PI,PT.bufptr,k); t += b; count -= b; n -= k; } } pi_disconnect(PI); if (PT.flags & PT_EOF) break; } return t;}/* end of pt.c */MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -