Commit 93e0e677 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] pt.c Lindent

pt.c fed through Lindent
parent 46530a99
...@@ -115,17 +115,17 @@ ...@@ -115,17 +115,17 @@
*/ */
static int verbose = 0; static int verbose = 0;
static int major = PT_MAJOR; static int major = PT_MAJOR;
static char *name = PT_NAME; static char *name = PT_NAME;
static int disable = 0; static int disable = 0;
static int drive0[6] = {0,0,0,-1,-1,-1}; static int drive0[6] = { 0, 0, 0, -1, -1, -1 };
static int drive1[6] = {0,0,0,-1,-1,-1}; static int drive1[6] = { 0, 0, 0, -1, -1, -1 };
static int drive2[6] = {0,0,0,-1,-1,-1}; static int drive2[6] = { 0, 0, 0, -1, -1, -1 };
static int drive3[6] = {0,0,0,-1,-1,-1}; static int drive3[6] = { 0, 0, 0, -1, -1, -1 };
static int (*drives[4])[6] = {&drive0,&drive1,&drive2,&drive3}; static int (*drives[4])[6] = {&drive0, &drive1, &drive2, &drive3};
static int pt_drive_count; static int pt_drive_count;
#define D_PRT 0 #define D_PRT 0
...@@ -139,7 +139,6 @@ static int pt_drive_count; ...@@ -139,7 +139,6 @@ static int pt_drive_count;
/* end of parameters */ /* end of parameters */
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/fs.h> #include <linux/fs.h>
...@@ -154,37 +153,40 @@ static int pt_drive_count; ...@@ -154,37 +153,40 @@ static int pt_drive_count;
#include "setup.h" #include "setup.h"
static STT pt_stt[5] = {{"drive0",6,drive0}, static STT pt_stt[5] = {
{"drive1",6,drive1}, {"drive0", 6, drive0},
{"drive2",6,drive2}, {"drive1", 6, drive1},
{"drive3",6,drive3}, {"drive2", 6, drive2},
{"disable",1,&disable}}; {"drive3", 6, drive3},
{"disable", 1, &disable}
void pt_setup( char *str, int *ints) };
{ generic_setup(pt_stt,5,str); void
pt_setup(char *str, int *ints)
{
generic_setup(pt_stt, 5, str);
} }
#endif #endif
MODULE_PARM(verbose,"i"); MODULE_PARM(verbose, "i");
MODULE_PARM(major,"i"); MODULE_PARM(major, "i");
MODULE_PARM(name,"s"); MODULE_PARM(name, "s");
MODULE_PARM(drive0,"1-6i"); MODULE_PARM(drive0, "1-6i");
MODULE_PARM(drive1,"1-6i"); MODULE_PARM(drive1, "1-6i");
MODULE_PARM(drive2,"1-6i"); MODULE_PARM(drive2, "1-6i");
MODULE_PARM(drive3,"1-6i"); MODULE_PARM(drive3, "1-6i");
#include "paride.h" #include "paride.h"
#define PT_MAX_RETRIES 5 #define PT_MAX_RETRIES 5
#define PT_TMO 3000 /* interrupt timeout in jiffies */ #define PT_TMO 3000 /* interrupt timeout in jiffies */
#define PT_SPIN_DEL 50 /* spin delay in micro-seconds */ #define PT_SPIN_DEL 50 /* spin delay in micro-seconds */
#define PT_RESET_TMO 30 /* 30 seconds */ #define PT_RESET_TMO 30 /* 30 seconds */
#define PT_READY_TMO 60 /* 60 seconds */ #define PT_READY_TMO 60 /* 60 seconds */
#define PT_REWIND_TMO 1200 /* 20 minutes */ #define PT_REWIND_TMO 1200 /* 20 minutes */
#define PT_SPIN ((1000000/(HZ*PT_SPIN_DEL))*PT_TMO) #define PT_SPIN ((1000000/(HZ*PT_SPIN_DEL))*PT_TMO)
#define STAT_ERR 0x00001 #define STAT_ERR 0x00001
#define STAT_INDEX 0x00002 #define STAT_INDEX 0x00002
...@@ -207,16 +209,16 @@ MODULE_PARM(drive3,"1-6i"); ...@@ -207,16 +209,16 @@ MODULE_PARM(drive3,"1-6i");
#define ATAPI_LOG_SENSE 0x4d #define ATAPI_LOG_SENSE 0x4d
static int pt_open(struct inode *inode, struct file *file); static int pt_open(struct inode *inode, struct file *file);
static int pt_ioctl(struct inode *inode,struct file *file, static int pt_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
static int pt_release (struct inode *inode, struct file *file); static int pt_release(struct inode *inode, struct file *file);
static ssize_t pt_read(struct file * filp, char * buf, static ssize_t pt_read(struct file *filp, char *buf,
size_t count, loff_t *ppos); size_t count, loff_t * ppos);
static ssize_t pt_write(struct file * filp, const char * buf, static ssize_t pt_write(struct file *filp, const char *buf,
size_t count, loff_t *ppos); size_t count, loff_t * ppos);
static int pt_detect(void); static int pt_detect(void);
static int pt_identify (int unit); static int pt_identify(int unit);
/* bits in PT.flags */ /* bits in PT.flags */
...@@ -231,18 +233,18 @@ static int pt_identify (int unit); ...@@ -231,18 +233,18 @@ static int pt_identify (int unit);
#define PT_BUFSIZE 16384 #define PT_BUFSIZE 16384
struct pt_unit { struct pt_unit {
struct pi_adapter pia; /* interface to paride layer */ struct pi_adapter pia; /* interface to paride layer */
struct pi_adapter *pi; struct pi_adapter *pi;
int flags; /* various state flags */ int flags; /* various state flags */
int last_sense; /* result of last request sense */ int last_sense; /* result of last request sense */
int drive; /* drive */ int drive; /* drive */
atomic_t available; /* 1 if access is available 0 otherwise */ atomic_t available; /* 1 if access is available 0 otherwise */
int bs; /* block size */ int bs; /* block size */
int capacity; /* Size of tape in KB */ int capacity; /* Size of tape in KB */
int present; /* device present ? */ int present; /* device present ? */
char *bufptr; char *bufptr;
char name[PT_NAMELEN]; /* pf0, pf1, ... */ char name[PT_NAMELEN]; /* pf0, pf1, ... */
}; };
struct pt_unit pt[PT_UNITS]; struct pt_unit pt[PT_UNITS];
...@@ -251,38 +253,40 @@ struct pt_unit pt[PT_UNITS]; ...@@ -251,38 +253,40 @@ struct pt_unit pt[PT_UNITS];
#define PT pt[unit] #define PT pt[unit]
#define PI PT.pi #define PI PT.pi
static char pt_scratch[512]; /* scratch block buffer */ static char pt_scratch[512]; /* scratch block buffer */
/* kernel glue structures */ /* kernel glue structures */
static struct file_operations pt_fops = { static struct file_operations pt_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.read = pt_read, .read = pt_read,
.write = pt_write, .write = pt_write,
.ioctl = pt_ioctl, .ioctl = pt_ioctl,
.open = pt_open, .open = pt_open,
.release = pt_release, .release = pt_release,
}; };
void pt_init_units( void ) static void pt_init_units(void)
{
{ int unit, j; int unit, j;
pt_drive_count = 0; pt_drive_count = 0;
for (unit=0;unit<PT_UNITS;unit++) { for (unit = 0; unit < PT_UNITS; unit++) {
PT.pi = & PT.pia; PT.pi = &PT.pia;
atomic_set( &PT.available, 1 ); atomic_set(&PT.available, 1);
PT.flags = 0; PT.flags = 0;
PT.last_sense = 0; PT.last_sense = 0;
PT.present = 0; PT.present = 0;
PT.bufptr = NULL; PT.bufptr = NULL;
PT.drive = DU[D_SLV]; PT.drive = DU[D_SLV];
j = 0; j = 0;
while ((j < PT_NAMELEN-2) && (PT.name[j]=name[j])) j++; while ((j < PT_NAMELEN - 2) && (PT.name[j] = name[j]))
PT.name[j++] = '0' + unit; j++;
PT.name[j] = 0; PT.name[j++] = '0' + unit;
if (DU[D_PRT]) pt_drive_count++; PT.name[j] = 0;
} if (DU[D_PRT])
pt_drive_count++;
}
} }
static inline int status_reg(int unit) static inline int status_reg(int unit)
...@@ -302,602 +306,665 @@ static inline void write_reg(int unit, int reg, int val) ...@@ -302,602 +306,665 @@ static inline void write_reg(int unit, int reg, int val)
#define DRIVE (0xa0+0x10*PT.drive) #define DRIVE (0xa0+0x10*PT.drive)
static int pt_wait( int unit, int go, int stop, char * fun, char * msg ) static int pt_wait(int unit, int go, int stop, char *fun, char *msg)
{
{ int j, r, e, s, p; int j, r, e, s, p;
j = 0;
while ((((r=status_reg(unit))&go)||(stop&&(!(r&stop))))&&(j++<PT_SPIN))
udelay(PT_SPIN_DEL);
if ((r&(STAT_ERR&stop))||(j>=PT_SPIN)) {
s = read_reg(unit, 7);
e = read_reg(unit, 1);
p = read_reg(unit, 2);
if (j >= PT_SPIN) e |= 0x100;
if (fun) printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
" loop=%d phase=%d\n",
PT.name,fun,msg,r,s,e,j,p);
return (e<<8)+s;
}
return 0;
}
static int pt_command( int unit, char * cmd, int dlen, char * fun )
{ pi_connect(PI);
write_reg(unit, 6,DRIVE); j = 0;
while ((((r = status_reg(unit)) & go) || (stop && (!(r & stop))))
&& (j++ < PT_SPIN))
udelay(PT_SPIN_DEL);
if (pt_wait(unit,STAT_BUSY|STAT_DRQ,0,fun,"before command")) { if ((r & (STAT_ERR & stop)) || (j >= PT_SPIN)) {
pi_disconnect(PI); s = read_reg(unit, 7);
return -1; e = read_reg(unit, 1);
} p = read_reg(unit, 2);
if (j >= PT_SPIN)
e |= 0x100;
if (fun)
printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
" loop=%d phase=%d\n",
PT.name, fun, msg, r, s, e, j, p);
return (e << 8) + s;
}
return 0;
}
write_reg(unit, 4,dlen % 256); static int pt_command(int unit, char *cmd, int dlen, char *fun)
write_reg(unit, 5,dlen / 256); {
write_reg(unit, 7,0xa0); /* ATAPI packet command */ pi_connect(PI);
if (pt_wait(unit,STAT_BUSY,STAT_DRQ,fun,"command DRQ")) { write_reg(unit, 6, DRIVE);
pi_disconnect(PI);
return -1;
}
if (read_reg(unit, 2) != 1) { if (pt_wait(unit, STAT_BUSY | STAT_DRQ, 0, fun, "before command")) {
printk("%s: %s: command phase error\n",PT.name,fun); pi_disconnect(PI);
pi_disconnect(PI); return -1;
return -1; }
}
pi_write_block(PI,cmd,12); write_reg(unit, 4, dlen % 256);
write_reg(unit, 5, dlen / 256);
write_reg(unit, 7, 0xa0); /* ATAPI packet command */
return 0; if (pt_wait(unit, STAT_BUSY, STAT_DRQ, fun, "command DRQ")) {
} pi_disconnect(PI);
return -1;
}
static int pt_completion( int unit, char * buf, char * fun ) if (read_reg(unit, 2) != 1) {
printk("%s: %s: command phase error\n", PT.name, fun);
pi_disconnect(PI);
return -1;
}
{ int r, s, n, p; pi_write_block(PI, cmd, 12);
r = pt_wait(unit,STAT_BUSY,STAT_DRQ|STAT_READY|STAT_ERR, return 0;
fun,"completion"); }
if (read_reg(unit, 7)&STAT_DRQ) { static int pt_completion(int unit, char *buf, char *fun)
n = (((read_reg(unit, 4)+256*read_reg(unit, 5))+3)&0xfffc); {
p = read_reg(unit, 2)&3; int r, s, n, p;
if (p == 0) pi_write_block(PI,buf,n);
if (p == 2) pi_read_block(PI,buf,n); r = pt_wait(unit, STAT_BUSY, STAT_DRQ | STAT_READY | STAT_ERR,
} fun, "completion");
if (read_reg(unit, 7) & STAT_DRQ) {
n = (((read_reg(unit, 4) + 256 * read_reg(unit, 5)) +
3) & 0xfffc);
p = read_reg(unit, 2) & 3;
if (p == 0)
pi_write_block(PI, buf, n);
if (p == 2)
pi_read_block(PI, buf, n);
}
s = pt_wait(unit,STAT_BUSY,STAT_READY|STAT_ERR,fun,"data done"); s = pt_wait(unit, STAT_BUSY, STAT_READY | STAT_ERR, fun, "data done");
pi_disconnect(PI); pi_disconnect(PI);
return (r?r:s); return (r ? r : s);
} }
static void pt_req_sense( int unit, int quiet ) static void pt_req_sense(int unit, int quiet)
{
{ char rs_cmd[12] = { ATAPI_REQ_SENSE,0,0,0,16,0,0,0,0,0,0,0 }; char rs_cmd[12] = { ATAPI_REQ_SENSE, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0 };
char buf[16]; char buf[16];
int r; int r;
r = pt_command(unit,rs_cmd,16,"Request sense"); r = pt_command(unit, rs_cmd, 16, "Request sense");
mdelay(1); mdelay(1);
if (!r) pt_completion(unit,buf,"Request sense"); if (!r)
pt_completion(unit, buf, "Request sense");
PT.last_sense = -1; PT.last_sense = -1;
if (!r) { if (!r) {
if (!quiet) printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n", if (!quiet)
PT.name,buf[2]&0xf,buf[12],buf[13]); printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n",
PT.last_sense = (buf[2]&0xf) | ((buf[12]&0xff)<<8) PT.name, buf[2] & 0xf, buf[12], buf[13]);
| ((buf[13]&0xff)<<16) ; PT.last_sense = (buf[2] & 0xf) | ((buf[12] & 0xff) << 8)
} | ((buf[13] & 0xff) << 16);
}
} }
static int pt_atapi( int unit, char * cmd, int dlen, char * buf, char * fun ) static int pt_atapi(int unit, char *cmd, int dlen, char *buf, char *fun)
{
int r;
{ int r; r = pt_command(unit, cmd, dlen, fun);
mdelay(1);
if (!r)
r = pt_completion(unit, buf, fun);
if (r)
pt_req_sense(unit, !fun);
r = pt_command(unit,cmd,dlen,fun); return r;
mdelay(1);
if (!r) r = pt_completion(unit,buf,fun);
if (r) pt_req_sense(unit,!fun);
return r;
} }
static void pt_sleep( int cs ) static void pt_sleep(int cs)
{
{ current->state = TASK_INTERRUPTIBLE; current->state = TASK_INTERRUPTIBLE;
schedule_timeout(cs); schedule_timeout(cs);
} }
static int pt_poll_dsc( int unit, int pause, int tmo, char *msg ) static int pt_poll_dsc(int unit, int pause, int tmo, char *msg)
{
{ int k, e, s; int k, e, s;
k = 0; e = 0; s = 0; k = 0;
e = 0;
s = 0;
while (k < tmo) { while (k < tmo) {
pt_sleep(pause); pt_sleep(pause);
k++; k++;
pi_connect(PI); pi_connect(PI);
write_reg(unit, 6,DRIVE); write_reg(unit, 6, DRIVE);
s = read_reg(unit, 7); s = read_reg(unit, 7);
e = read_reg(unit, 1); e = read_reg(unit, 1);
pi_disconnect(PI); pi_disconnect(PI);
if (s & (STAT_ERR|STAT_SEEK)) break; if (s & (STAT_ERR | STAT_SEEK))
break;
} }
if ((k >= tmo) || (s & STAT_ERR)) { if ((k >= tmo) || (s & STAT_ERR)) {
if (k >= tmo) printk("%s: %s DSC timeout\n",PT.name,msg); if (k >= tmo)
else printk("%s: %s stat=0x%x err=0x%x\n",PT.name,msg,s,e); printk("%s: %s DSC timeout\n", PT.name, msg);
pt_req_sense(unit,0); else
return 0; printk("%s: %s stat=0x%x err=0x%x\n", PT.name, msg, s,
e);
pt_req_sense(unit, 0);
return 0;
} }
return 1; return 1;
} }
static void pt_media_access_cmd( int unit, int tmo, char *cmd, char *fun) static void pt_media_access_cmd(int unit, int tmo, char *cmd, char *fun)
{
{ if (pt_command(unit,cmd,0,fun)) { if (pt_command(unit, cmd, 0, fun)) {
pt_req_sense(unit,0); pt_req_sense(unit, 0);
return; return;
} }
pi_disconnect(PI); pi_disconnect(PI);
pt_poll_dsc(unit,HZ,tmo,fun); pt_poll_dsc(unit, HZ, tmo, fun);
} }
static void pt_rewind( int unit ) static void pt_rewind(int unit)
{
{ char rw_cmd[12] = {ATAPI_REWIND,0,0,0,0,0,0,0,0,0,0,0}; 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"); pt_media_access_cmd(unit, PT_REWIND_TMO, rw_cmd, "rewind");
} }
static void pt_write_fm( int unit ) static void pt_write_fm(int unit)
{
{ char wm_cmd[12] = {ATAPI_WFM,0,0,0,1,0,0,0,0,0,0,0}; 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"); pt_media_access_cmd(unit, PT_TMO, wm_cmd, "write filemark");
} }
#define DBMSG(msg) ((verbose>1)?(msg):NULL) #define DBMSG(msg) ((verbose>1)?(msg):NULL)
static int pt_reset( int unit ) static int pt_reset(int unit)
{
{ int i, k, flg; int i, k, flg;
int expect[5] = {1,1,1,0x14,0xeb}; int expect[5] = { 1, 1, 1, 0x14, 0xeb };
pi_connect(PI); pi_connect(PI);
write_reg(unit, 6,DRIVE); write_reg(unit, 6, DRIVE);
write_reg(unit, 7,8); write_reg(unit, 7, 8);
pt_sleep(20*HZ/1000); pt_sleep(20 * HZ / 1000);
k = 0; k = 0;
while ((k++ < PT_RESET_TMO) && (status_reg(unit)&STAT_BUSY)) while ((k++ < PT_RESET_TMO) && (status_reg(unit) & STAT_BUSY))
pt_sleep(HZ/10); pt_sleep(HZ / 10);
flg = 1; flg = 1;
for(i=0;i<5;i++) flg &= (read_reg(unit, i+1) == expect[i]); for (i = 0; i < 5; i++)
flg &= (read_reg(unit, i + 1) == expect[i]);
if (verbose) { if (verbose) {
printk("%s: Reset (%d) signature = ",PT.name,k); printk("%s: Reset (%d) signature = ", PT.name, k);
for (i=0;i<5;i++) printk("%3x",read_reg(unit, i+1)); for (i = 0; i < 5; i++)
if (!flg) printk(" (incorrect)"); printk("%3x", read_reg(unit, i + 1));
if (!flg)
printk(" (incorrect)");
printk("\n"); printk("\n");
} }
pi_disconnect(PI); pi_disconnect(PI);
return flg-1; return flg - 1;
} }
static int pt_ready_wait( int unit, int tmo ) 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}; char tr_cmd[12] = { ATAPI_TEST_READY, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int k, p; int k, p;
k = 0; k = 0;
while (k < tmo) { while (k < tmo) {
PT.last_sense = 0; PT.last_sense = 0;
pt_atapi(unit,tr_cmd,0,NULL,DBMSG("test unit ready")); pt_atapi(unit, tr_cmd, 0, NULL, DBMSG("test unit ready"));
p = PT.last_sense; p = PT.last_sense;
if (!p) return 0; if (!p)
if (!(((p & 0xffff) == 0x0402)||((p & 0xff) == 6))) return p; return 0;
k++; if (!(((p & 0xffff) == 0x0402) || ((p & 0xff) == 6)))
pt_sleep(HZ); return p;
k++;
pt_sleep(HZ);
} }
return 0x000020; /* timeout */ return 0x000020; /* timeout */
} }
static void xs( char *buf, char *targ, int offs, int len ) static void xs(char *buf, char *targ, int offs, int len)
{
{ int j,k,l; int j, k, l;
j=0; l=0; j = 0;
for (k=0;k<len;k++) l = 0;
if((buf[k+offs]!=0x20)||(buf[k+offs]!=l)) for (k = 0; k < len; k++)
l=targ[j++]=buf[k+offs]; if ((buf[k + offs] != 0x20) || (buf[k + offs] != l))
if (l==0x20) j--; l = targ[j++] = buf[k + offs];
targ[j]=0; if (l == 0x20)
j--;
targ[j] = 0;
} }
static int xn( char *buf, int offs, int size ) static int xn(char *buf, int offs, int size)
{
{ int v,k; int v, k;
v=0; v = 0;
for(k=0;k<size;k++) v=v*256+(buf[k+offs]&0xff); for (k = 0; k < size; k++)
v = v * 256 + (buf[k + offs] & 0xff);
return v; return v;
} }
static int pt_identify( int unit ) static int pt_identify(int unit)
{
{ int dt, s; int dt, s;
char *ms[2] = {"master","slave"}; char *ms[2] = { "master", "slave" };
char mf[10], id[18]; char mf[10], id[18];
char id_cmd[12] = { ATAPI_IDENTIFY,0,0,0,36,0,0,0,0,0,0,0}; 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 ms_cmd[12] =
char ls_cmd[12] = { ATAPI_LOG_SENSE,0,0x71,0,0,0,0,0,36,0,0,0}; { ATAPI_MODE_SENSE, 0, 0x2a, 0, 36, 0, 0, 0, 0, 0, 0, 0 };
char buf[36]; char ls_cmd[12] =
{ ATAPI_LOG_SENSE, 0, 0x71, 0, 0, 0, 0, 0, 36, 0, 0, 0 };
s = pt_atapi(unit,id_cmd,36,buf,"identify"); char buf[36];
if (s) return -1;
s = pt_atapi(unit, id_cmd, 36, buf, "identify");
if (s)
return -1;
dt = buf[0] & 0x1f; dt = buf[0] & 0x1f;
if (dt != 1) { if (dt != 1) {
if (verbose) if (verbose)
printk("%s: Drive %d, unsupported type %d\n", printk("%s: Drive %d, unsupported type %d\n",
PT.name,PT.drive,dt); PT.name, PT.drive, dt);
return -1; return -1;
} }
xs(buf,mf,8,8); xs(buf, mf, 8, 8);
xs(buf,id,16,16); xs(buf, id, 16, 16);
PT.flags = 0; PT.flags = 0;
PT.capacity = 0; PT.capacity = 0;
PT.bs = 0; PT.bs = 0;
if (!pt_ready_wait(unit,PT_READY_TMO)) PT.flags |= PT_MEDIA; if (!pt_ready_wait(unit, PT_READY_TMO))
PT.flags |= PT_MEDIA;
if (!pt_atapi(unit,ms_cmd,36,buf,"mode sense")) { if (!pt_atapi(unit, ms_cmd, 36, buf, "mode sense")) {
if (!(buf[2] & 0x80)) PT.flags |= PT_WRITE_OK; if (!(buf[2] & 0x80))
PT.bs = xn(buf,10,2); PT.flags |= PT_WRITE_OK;
PT.bs = xn(buf, 10, 2);
} }
if (!pt_atapi(unit,ls_cmd,36,buf,"log sense")) if (!pt_atapi(unit, ls_cmd, 36, buf, "log sense"))
PT.capacity = xn(buf,24,4); PT.capacity = xn(buf, 24, 4);
printk("%s: %s %s, %s", printk("%s: %s %s, %s", PT.name, mf, id, ms[PT.drive]);
PT.name,mf,id,ms[PT.drive]); if (!(PT.flags & PT_MEDIA))
if (!(PT.flags & PT_MEDIA)) printk(", no media\n");
printk(", no media\n"); else {
else { if (!(PT.flags & PT_WRITE_OK)) printk(", RO"); if (!(PT.flags & PT_WRITE_OK))
printk(", blocksize %d, %d MB\n", printk(", RO");
PT.bs,PT.capacity/1024); printk(", blocksize %d, %d MB\n", PT.bs, PT.capacity / 1024);
} }
return 0; return 0;
} }
static int pt_probe( int unit )
/* returns 0, with id set if drive is detected /*
-1, if drive detection failed * returns 0, with id set if drive is detected
*/ * -1, if drive detection failed
*/
{ if (PT.drive == -1) { static int pt_probe(int unit)
for (PT.drive=0;PT.drive<=1;PT.drive++) {
if (!pt_reset(unit)) return pt_identify(unit); if (PT.drive == -1) {
for (PT.drive = 0; PT.drive <= 1; PT.drive++)
if (!pt_reset(unit))
return pt_identify(unit);
} else { } else {
if (!pt_reset(unit)) return pt_identify(unit); if (!pt_reset(unit))
return pt_identify(unit);
} }
return -1; return -1;
} }
static int pt_detect( void ) static int pt_detect(void)
{
{ int k, unit; int k, unit;
printk("%s: %s version %s, major %d\n", printk("%s: %s version %s, major %d\n", name, name, PT_VERSION, major);
name,name,PT_VERSION,major);
k = 0; k = 0;
if (pt_drive_count == 0) { if (pt_drive_count == 0) {
unit = 0; unit = 0;
if (pi_init(PI,1,-1,-1,-1,-1,-1,pt_scratch, if (pi_init(PI, 1, -1, -1, -1, -1, -1, pt_scratch,
PI_PT,verbose,PT.name)) { PI_PT, verbose, PT.name)) {
if (!pt_probe(unit)) { if (!pt_probe(unit)) {
PT.present = 1; PT.present = 1;
k++; k++;
} else pi_release(PI); } 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], } else
DU[D_PRO],DU[D_DLY],pt_scratch,PI_PT,verbose, for (unit = 0; unit < PT_UNITS; unit++)
PT.name)) { if (DU[D_PRT])
if (!pt_probe(unit)) { if (pi_init
PT.present = 1; (PI, 0, DU[D_PRT], DU[D_MOD], DU[D_UNI],
k++; DU[D_PRO], DU[D_DLY], pt_scratch, PI_PT,
} else pi_release(PI); verbose, PT.name)) {
} if (!pt_probe(unit)) {
PT.present = 1;
if (k) return 0; k++;
} else
printk("%s: No ATAPI tape drive detected\n",name); pi_release(PI);
}
if (k)
return 0;
printk("%s: No ATAPI tape drive detected\n", name);
return -1; return -1;
} }
#define DEVICE_NR(dev) (minor(dev) & 0x7F) #define DEVICE_NR(dev) (minor(dev) & 0x7F)
static int pt_open (struct inode *inode, struct file *file) static int pt_open(struct inode *inode, struct file *file)
{
{ int unit = DEVICE_NR(inode->i_rdev); int unit = DEVICE_NR(inode->i_rdev);
if ((unit >= PT_UNITS) || (!PT.present)) return -ENODEV; if ((unit >= PT_UNITS) || (!PT.present))
return -ENODEV;
if ( !atomic_dec_and_test(&PT.available) ) { if (!atomic_dec_and_test(&PT.available)) {
atomic_inc( &PT.available ); atomic_inc(&PT.available);
return -EBUSY; return -EBUSY;
} }
pt_identify(unit); pt_identify(unit);
if (!PT.flags & PT_MEDIA) { if (!PT.flags & PT_MEDIA) {
atomic_inc( &PT.available ); atomic_inc(&PT.available);
return -ENODEV; return -ENODEV;
} }
if ((!PT.flags & PT_WRITE_OK) && (file ->f_mode & 2)) { if ((!PT.flags & PT_WRITE_OK) && (file->f_mode & 2)) {
atomic_inc( &PT.available ); atomic_inc(&PT.available);
return -EROFS; return -EROFS;
} }
if (!(minor(inode->i_rdev) & 128)) if (!(minor(inode->i_rdev) & 128))
PT.flags |= PT_REWIND; PT.flags |= PT_REWIND;
PT.bufptr = kmalloc(PT_BUFSIZE,GFP_KERNEL); PT.bufptr = kmalloc(PT_BUFSIZE, GFP_KERNEL);
if (PT.bufptr == NULL) { if (PT.bufptr == NULL) {
atomic_inc( &PT.available ); atomic_inc(&PT.available);
printk("%s: buffer allocation failed\n",PT.name); printk("%s: buffer allocation failed\n", PT.name);
return -ENOMEM; return -ENOMEM;
} }
return 0; return 0;
} }
static int pt_ioctl(struct inode *inode,struct file *file, static int pt_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
int unit; int unit;
struct mtop mtop; struct mtop mtop;
unit = DEVICE_NR(inode->i_rdev); unit = DEVICE_NR(inode->i_rdev);
if (unit >= PT_UNITS) if (unit >= PT_UNITS)
return -EINVAL; return -EINVAL;
if (!PT.present) if (!PT.present)
return -ENODEV; return -ENODEV;
switch (cmd) { switch (cmd) {
case MTIOCTOP: case MTIOCTOP:
if (copy_from_user((char *)&mtop, (char *)arg, if (copy_from_user((char *) &mtop, (char *) arg,
sizeof(struct mtop))) return -EFAULT; sizeof (struct mtop)))
return -EFAULT;
switch (mtop.mt_op) { switch (mtop.mt_op) {
case MTREW: case MTREW:
pt_rewind(unit); pt_rewind(unit);
return 0; return 0;
case MTWEOF: case MTWEOF:
pt_write_fm(unit); pt_write_fm(unit);
return 0; return 0;
default: default:
printk("%s: Unimplemented mt_op %d\n",PT.name, printk("%s: Unimplemented mt_op %d\n", PT.name,
mtop.mt_op); mtop.mt_op);
return -EINVAL; return -EINVAL;
} }
default: default:
printk("%s: Unimplemented ioctl 0x%x\n",PT.name,cmd); printk("%s: Unimplemented ioctl 0x%x\n", PT.name, cmd);
return -EINVAL; return -EINVAL;
} }
} }
static int
static int pt_release (struct inode *inode, struct file *file) pt_release(struct inode *inode, struct file *file)
{ {
int unit = DEVICE_NR(inode->i_rdev); int unit = DEVICE_NR(inode->i_rdev);
if ((unit >= PT_UNITS) || (atomic_read(&PT.available) > 1)) if ((unit >= PT_UNITS) || (atomic_read(&PT.available) > 1))
return -EINVAL; return -EINVAL;
if (PT.flags & PT_WRITING) pt_write_fm(unit); if (PT.flags & PT_WRITING)
pt_write_fm(unit);
if (PT.flags & PT_REWIND) pt_rewind(unit); if (PT.flags & PT_REWIND)
pt_rewind(unit);
kfree(PT.bufptr); kfree(PT.bufptr);
PT.bufptr = NULL; PT.bufptr = NULL;
atomic_inc( &PT.available ); atomic_inc(&PT.available);
return 0; return 0;
} }
static ssize_t pt_read(struct file * filp, char * buf, static ssize_t pt_read(struct file *filp, char *buf, size_t count, loff_t * ppos)
size_t count, loff_t *ppos)
{ {
struct inode *ino = filp->f_dentry->d_inode; struct inode *ino = filp->f_dentry->d_inode;
int unit = DEVICE_NR(ino->i_rdev); 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}; 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; int k, n, r, p, s, t, b;
if (!(PT.flags & (PT_READING|PT_WRITING))) { if (!(PT.flags & (PT_READING | PT_WRITING))) {
PT.flags |= PT_READING; PT.flags |= PT_READING;
if (pt_atapi(unit,rd_cmd,0,NULL,"start read-ahead")) if (pt_atapi(unit, rd_cmd, 0, NULL, "start read-ahead"))
return -EIO; return -EIO;
} else if (PT.flags & PT_WRITING) return -EIO; } else if (PT.flags & PT_WRITING)
return -EIO;
if (PT.flags & PT_EOF) return 0; if (PT.flags & PT_EOF)
return 0;
t = 0; t = 0;
while (count > 0) { while (count > 0) {
if (!pt_poll_dsc(unit,HZ/100,PT_TMO,"read")) return -EIO; 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, n = count;
DBMSG("read DRQ"),""); if (n > 32768)
n = 32768; /* max per command */
b = (n - 1 + PT.bs) / PT.bs;
n = b * PT.bs; /* rounded up to even block */
if (r & STAT_SENSE) { rd_cmd[4] = b;
pi_disconnect(PI);
pt_req_sense(unit,0);
return -EIO;
}
if (r) PT.flags |= PT_EOF; r = pt_command(unit, rd_cmd, n, "read");
s = read_reg(unit, 7); mdelay(1);
if (!(s & STAT_DRQ)) break; if (r) {
pt_req_sense(unit, 0);
return -EIO;
}
n = (read_reg(unit, 4)+256*read_reg(unit, 5)); while (1) {
p = (read_reg(unit, 2)&3);
if (p != 2) { r = pt_wait(unit, STAT_BUSY,
pi_disconnect(PI); STAT_DRQ | STAT_ERR | STAT_READY,
printk("%s: Phase error on read: %d\n",PT.name,p); DBMSG("read DRQ"), "");
return -EIO;
} if (r & STAT_SENSE) {
pi_disconnect(PI);
pt_req_sense(unit, 0);
return -EIO;
}
if (r)
PT.flags |= PT_EOF;
s = read_reg(unit, 7);
if (!(s & STAT_DRQ))
break;
n = (read_reg(unit, 4) + 256 * read_reg(unit, 5));
p = (read_reg(unit, 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;
}
while (n > 0) { }
k = n; pi_disconnect(PI);
if (k > PT_BUFSIZE) k = PT_BUFSIZE; if (PT.flags & PT_EOF)
pi_read_block(PI,PT.bufptr,k); break;
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; return t;
} }
static ssize_t pt_write(struct file * filp, const char * buf, static ssize_t pt_write(struct file *filp, const char *buf, size_t count, loff_t * ppos)
size_t count, loff_t *ppos)
{ {
struct inode *ino = filp->f_dentry->d_inode; struct inode *ino = filp->f_dentry->d_inode;
int unit = DEVICE_NR(ino->i_rdev); 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}; 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; int k, n, r, p, s, t, b;
if (!(PT.flags & PT_WRITE_OK)) return -EROFS; if (!(PT.flags & PT_WRITE_OK))
return -EROFS;
if (!(PT.flags & (PT_READING|PT_WRITING))) { if (!(PT.flags & (PT_READING | PT_WRITING))) {
PT.flags |= PT_WRITING; PT.flags |= PT_WRITING;
if (pt_atapi(unit,wr_cmd,0,NULL,"start buffer-available mode")) if (pt_atapi
return -EIO; (unit, wr_cmd, 0, NULL, "start buffer-available mode"))
} else if (PT.flags&PT_READING) return -EIO; return -EIO;
} else if (PT.flags & PT_READING)
return -EIO;
if (PT.flags & PT_EOF) return -ENOSPC; if (PT.flags & PT_EOF)
return -ENOSPC;
t = 0; t = 0;
while (count > 0) { while (count > 0) {
if (!pt_poll_dsc(unit,HZ/100,PT_TMO,"write")) return -EIO; 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, n = count;
DBMSG("write DRQ"),NULL); if (n > 32768)
n = 32768; /* max per command */
b = (n - 1 + PT.bs) / PT.bs;
n = b * PT.bs; /* rounded up to even block */
if (r & STAT_SENSE) { wr_cmd[4] = b;
pi_disconnect(PI);
pt_req_sense(unit,0);
return -EIO;
}
if (r) PT.flags |= PT_EOF; r = pt_command(unit, wr_cmd, n, "write");
s = read_reg(unit, 7); mdelay(1);
if (!(s & STAT_DRQ)) break; if (r) { /* error delivering command only */
pt_req_sense(unit, 0);
return -EIO;
}
n = (read_reg(unit, 4)+256*read_reg(unit, 5)); while (1) {
p = (read_reg(unit, 2)&3);
if (p != 0) { r = pt_wait(unit, STAT_BUSY,
pi_disconnect(PI); STAT_DRQ | STAT_ERR | STAT_READY,
printk("%s: Phase error on write: %d \n",PT.name,p); DBMSG("write DRQ"), NULL);
return -EIO;
} if (r & STAT_SENSE) {
pi_disconnect(PI);
pt_req_sense(unit, 0);
return -EIO;
}
if (r)
PT.flags |= PT_EOF;
s = read_reg(unit, 7);
if (!(s & STAT_DRQ))
break;
n = (read_reg(unit, 4) + 256 * read_reg(unit, 5));
p = (read_reg(unit, 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;
}
while (n > 0) { }
k = n; pi_disconnect(PI);
if (k > PT_BUFSIZE) k = PT_BUFSIZE; if (PT.flags & PT_EOF)
b = k; break;
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; return t;
...@@ -915,23 +982,23 @@ static int __init pt_init(void) ...@@ -915,23 +982,23 @@ static int __init pt_init(void)
if (pt_detect()) if (pt_detect())
return -1; return -1;
if (register_chrdev(major,name,&pt_fops)) { if (register_chrdev(major, name, &pt_fops)) {
printk("pt_init: unable to get major number %d\n", printk("pt_init: unable to get major number %d\n", major);
major); for (unit = 0; unit < PT_UNITS; unit++)
for (unit=0;unit<PT_UNITS;unit++) if (PT.present)
if (PT.present) pi_release(PI); pi_release(PI);
return -1; return -1;
} }
devfs_mk_dir ("pt"); devfs_mk_dir("pt");
for (unit=0;unit<PT_UNITS;unit++) for (unit = 0; unit < PT_UNITS; unit++)
if (PT.present) { if (PT.present) {
devfs_mk_cdev(MKDEV(major, unit), devfs_mk_cdev(MKDEV(major, unit),
S_IFCHR | S_IRUSR | S_IWUSR, S_IFCHR | S_IRUSR | S_IWUSR,
"pt/%d", unit); "pt/%d", unit);
devfs_mk_cdev(MKDEV(major, unit + 128), devfs_mk_cdev(MKDEV(major, unit + 128),
S_IFCHR | S_IRUSR | S_IWUSR, S_IFCHR | S_IRUSR | S_IWUSR,
"pt/%dn", unit); "pt/%dn", unit);
} }
return 0; return 0;
} }
...@@ -939,14 +1006,14 @@ static int __init pt_init(void) ...@@ -939,14 +1006,14 @@ static int __init pt_init(void)
static void __exit pt_exit(void) static void __exit pt_exit(void)
{ {
int unit; int unit;
for (unit=0;unit<PT_UNITS;unit++) for (unit = 0; unit < PT_UNITS; unit++)
if (PT.present) { if (PT.present) {
devfs_remove("pt/%d", unit); devfs_remove("pt/%d", unit);
devfs_remove("pt/%dn", unit); devfs_remove("pt/%dn", unit);
} }
devfs_remove("pt"); devfs_remove("pt");
unregister_chrdev(major,name); unregister_chrdev(major, name);
for (unit=0;unit<PT_UNITS;unit++) for (unit = 0; unit < PT_UNITS; unit++)
if (PT.present) if (PT.present)
pi_release(PI); pi_release(PI);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment