Commit 98ba005d authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] large dev_t - second series (3/15)

	paride/pt.c cleanups - passing pointer to pt_unit instead of index
in array; same as had been done for pd/pcd/pf.
parent 890b6a7a
...@@ -126,7 +126,6 @@ static int drive2[6] = { 0, 0, 0, -1, -1, -1 }; ...@@ -126,7 +126,6 @@ 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;
#define D_PRT 0 #define D_PRT 0
#define D_PRO 1 #define D_PRO 1
...@@ -218,9 +217,7 @@ static ssize_t pt_write(struct file *filp, const char *buf, ...@@ -218,9 +217,7 @@ 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); /* bits in tape->flags */
/* bits in PT.flags */
#define PT_MEDIA 1 #define PT_MEDIA 1
#define PT_WRITE_OK 2 #define PT_WRITE_OK 2
...@@ -246,12 +243,9 @@ struct pt_unit { ...@@ -246,12 +243,9 @@ struct pt_unit {
char name[PT_NAMELEN]; /* pf0, pf1, ... */ char name[PT_NAMELEN]; /* pf0, pf1, ... */
}; };
struct pt_unit pt[PT_UNITS]; static int pt_identify(struct pt_unit *tape);
/* 'unit' must be defined in all functions - either as a local or a param */
#define PT pt[unit] struct pt_unit pt[PT_UNITS];
#define PI PT.pi
static char pt_scratch[512]; /* scratch block buffer */ static char pt_scratch[512]; /* scratch block buffer */
...@@ -266,156 +260,139 @@ static struct file_operations pt_fops = { ...@@ -266,156 +260,139 @@ static struct file_operations pt_fops = {
.release = pt_release, .release = pt_release,
}; };
static void pt_init_units(void) static inline int status_reg(struct pi_adapter *pi)
{ {
int unit, j; return pi_read_regr(pi, 1, 6);
pt_drive_count = 0;
for (unit = 0; unit < PT_UNITS; unit++) {
PT.pi = &PT.pia;
atomic_set(&PT.available, 1);
PT.flags = 0;
PT.last_sense = 0;
PT.present = 0;
PT.bufptr = NULL;
PT.drive = DU[D_SLV];
j = 0;
while ((j < PT_NAMELEN - 2) && (PT.name[j] = name[j]))
j++;
PT.name[j++] = '0' + unit;
PT.name[j] = 0;
if (DU[D_PRT])
pt_drive_count++;
}
} }
static inline int status_reg(int unit) static inline int read_reg(struct pi_adapter *pi, int reg)
{ {
return pi_read_regr(PI, 1, 6); return pi_read_regr(pi, 0, reg);
} }
static inline int read_reg(int unit, int reg) static inline void write_reg(struct pi_adapter *pi, int reg, int val)
{ {
return pi_read_regr(PI, 0, reg); pi_write_regr(pi, 0, reg, val);
} }
static inline void write_reg(int unit, int reg, int val) static inline u8 DRIVE(struct pt_unit *tape)
{ {
pi_write_regr(PI, 0, reg, val); return 0xa0+0x10*tape->drive;
} }
#define DRIVE (0xa0+0x10*PT.drive) static int pt_wait(struct pt_unit *tape, 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;
struct pi_adapter *pi = tape->pi;
j = 0; j = 0;
while ((((r = status_reg(unit)) & go) || (stop && (!(r & stop)))) while ((((r = status_reg(pi)) & go) || (stop && (!(r & stop))))
&& (j++ < PT_SPIN)) && (j++ < PT_SPIN))
udelay(PT_SPIN_DEL); udelay(PT_SPIN_DEL);
if ((r & (STAT_ERR & stop)) || (j >= PT_SPIN)) { if ((r & (STAT_ERR & stop)) || (j >= PT_SPIN)) {
s = read_reg(unit, 7); s = read_reg(pi, 7);
e = read_reg(unit, 1); e = read_reg(pi, 1);
p = read_reg(unit, 2); p = read_reg(pi, 2);
if (j >= PT_SPIN) if (j >= PT_SPIN)
e |= 0x100; e |= 0x100;
if (fun) if (fun)
printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x" printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
" loop=%d phase=%d\n", " loop=%d phase=%d\n",
PT.name, fun, msg, r, s, e, j, p); tape->name, fun, msg, r, s, e, j, p);
return (e << 8) + s; return (e << 8) + s;
} }
return 0; return 0;
} }
static int pt_command(int unit, char *cmd, int dlen, char *fun) static int pt_command(struct pt_unit *tape, char *cmd, int dlen, char *fun)
{ {
pi_connect(PI); struct pi_adapter *pi = tape->pi;
pi_connect(pi);
write_reg(unit, 6, DRIVE); write_reg(pi, 6, DRIVE(tape));
if (pt_wait(unit, STAT_BUSY | STAT_DRQ, 0, fun, "before command")) { if (pt_wait(tape, STAT_BUSY | STAT_DRQ, 0, fun, "before command")) {
pi_disconnect(PI); pi_disconnect(pi);
return -1; return -1;
} }
write_reg(unit, 4, dlen % 256); write_reg(pi, 4, dlen % 256);
write_reg(unit, 5, dlen / 256); write_reg(pi, 5, dlen / 256);
write_reg(unit, 7, 0xa0); /* ATAPI packet command */ write_reg(pi, 7, 0xa0); /* ATAPI packet command */
if (pt_wait(unit, STAT_BUSY, STAT_DRQ, fun, "command DRQ")) { if (pt_wait(tape, STAT_BUSY, STAT_DRQ, fun, "command DRQ")) {
pi_disconnect(PI); pi_disconnect(pi);
return -1; return -1;
} }
if (read_reg(unit, 2) != 1) { if (read_reg(pi, 2) != 1) {
printk("%s: %s: command phase error\n", PT.name, fun); printk("%s: %s: command phase error\n", tape->name, fun);
pi_disconnect(PI); pi_disconnect(pi);
return -1; return -1;
} }
pi_write_block(PI, cmd, 12); pi_write_block(pi, cmd, 12);
return 0; return 0;
} }
static int pt_completion(int unit, char *buf, char *fun) static int pt_completion(struct pt_unit *tape, char *buf, char *fun)
{ {
struct pi_adapter *pi = tape->pi;
int r, s, n, p; int r, s, n, p;
r = pt_wait(unit, STAT_BUSY, STAT_DRQ | STAT_READY | STAT_ERR, r = pt_wait(tape, STAT_BUSY, STAT_DRQ | STAT_READY | STAT_ERR,
fun, "completion"); fun, "completion");
if (read_reg(unit, 7) & STAT_DRQ) { if (read_reg(pi, 7) & STAT_DRQ) {
n = (((read_reg(unit, 4) + 256 * read_reg(unit, 5)) + n = (((read_reg(pi, 4) + 256 * read_reg(pi, 5)) +
3) & 0xfffc); 3) & 0xfffc);
p = read_reg(unit, 2) & 3; p = read_reg(pi, 2) & 3;
if (p == 0) if (p == 0)
pi_write_block(PI, buf, n); pi_write_block(pi, buf, n);
if (p == 2) if (p == 2)
pi_read_block(PI, buf, n); pi_read_block(pi, buf, n);
} }
s = pt_wait(unit, STAT_BUSY, STAT_READY | STAT_ERR, fun, "data done"); s = pt_wait(tape, 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(struct pt_unit *tape, 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(tape, rs_cmd, 16, "Request sense");
mdelay(1); mdelay(1);
if (!r) if (!r)
pt_completion(unit, buf, "Request sense"); pt_completion(tape, buf, "Request sense");
PT.last_sense = -1; tape->last_sense = -1;
if (!r) { if (!r) {
if (!quiet) if (!quiet)
printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n", printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n",
PT.name, buf[2] & 0xf, buf[12], buf[13]); tape->name, buf[2] & 0xf, buf[12], buf[13]);
PT.last_sense = (buf[2] & 0xf) | ((buf[12] & 0xff) << 8) tape->last_sense = (buf[2] & 0xf) | ((buf[12] & 0xff) << 8)
| ((buf[13] & 0xff) << 16); | ((buf[13] & 0xff) << 16);
} }
} }
static int pt_atapi(int unit, char *cmd, int dlen, char *buf, char *fun) static int pt_atapi(struct pt_unit *tape, char *cmd, int dlen, char *buf, char *fun)
{ {
int r; int r;
r = pt_command(unit, cmd, dlen, fun); r = pt_command(tape, cmd, dlen, fun);
mdelay(1); mdelay(1);
if (!r) if (!r)
r = pt_completion(unit, buf, fun); r = pt_completion(tape, buf, fun);
if (r) if (r)
pt_req_sense(unit, !fun); pt_req_sense(tape, !fun);
return r; return r;
} }
...@@ -426,8 +403,9 @@ static void pt_sleep(int cs) ...@@ -426,8 +403,9 @@ static void pt_sleep(int cs)
schedule_timeout(cs); schedule_timeout(cs);
} }
static int pt_poll_dsc(int unit, int pause, int tmo, char *msg) static int pt_poll_dsc(struct pt_unit *tape, int pause, int tmo, char *msg)
{ {
struct pi_adapter *pi = tape->pi;
int k, e, s; int k, e, s;
k = 0; k = 0;
...@@ -436,94 +414,95 @@ static int pt_poll_dsc(int unit, int pause, int tmo, char *msg) ...@@ -436,94 +414,95 @@ static int pt_poll_dsc(int unit, int pause, int tmo, char *msg)
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(pi, 6, DRIVE(tape));
s = read_reg(unit, 7); s = read_reg(pi, 7);
e = read_reg(unit, 1); e = read_reg(pi, 1);
pi_disconnect(PI); pi_disconnect(pi);
if (s & (STAT_ERR | STAT_SEEK)) if (s & (STAT_ERR | STAT_SEEK))
break; break;
} }
if ((k >= tmo) || (s & STAT_ERR)) { if ((k >= tmo) || (s & STAT_ERR)) {
if (k >= tmo) if (k >= tmo)
printk("%s: %s DSC timeout\n", PT.name, msg); printk("%s: %s DSC timeout\n", tape->name, msg);
else else
printk("%s: %s stat=0x%x err=0x%x\n", PT.name, msg, s, printk("%s: %s stat=0x%x err=0x%x\n", tape->name, msg, s,
e); e);
pt_req_sense(unit, 0); pt_req_sense(tape, 0);
return 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(struct pt_unit *tape, int tmo, char *cmd, char *fun)
{ {
if (pt_command(unit, cmd, 0, fun)) { if (pt_command(tape, cmd, 0, fun)) {
pt_req_sense(unit, 0); pt_req_sense(tape, 0);
return; return;
} }
pi_disconnect(PI); pi_disconnect(tape->pi);
pt_poll_dsc(unit, HZ, tmo, fun); pt_poll_dsc(tape, HZ, tmo, fun);
} }
static void pt_rewind(int unit) static void pt_rewind(struct pt_unit *tape)
{ {
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(tape, PT_REWIND_TMO, rw_cmd, "rewind");
} }
static void pt_write_fm(int unit) static void pt_write_fm(struct pt_unit *tape)
{ {
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(tape, 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(struct pt_unit *tape)
{ {
struct pi_adapter *pi = tape->pi;
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(pi, 6, DRIVE(tape));
write_reg(unit, 7, 8); write_reg(pi, 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(pi) & STAT_BUSY))
pt_sleep(HZ / 10); pt_sleep(HZ / 10);
flg = 1; flg = 1;
for (i = 0; i < 5; i++) for (i = 0; i < 5; i++)
flg &= (read_reg(unit, i + 1) == expect[i]); flg &= (read_reg(pi, i + 1) == expect[i]);
if (verbose) { if (verbose) {
printk("%s: Reset (%d) signature = ", PT.name, k); printk("%s: Reset (%d) signature = ", tape->name, k);
for (i = 0; i < 5; i++) for (i = 0; i < 5; i++)
printk("%3x", read_reg(unit, i + 1)); printk("%3x", read_reg(pi, i + 1));
if (!flg) if (!flg)
printk(" (incorrect)"); 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(struct pt_unit *tape, 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; tape->last_sense = 0;
pt_atapi(unit, tr_cmd, 0, NULL, DBMSG("test unit ready")); pt_atapi(tape, tr_cmd, 0, NULL, DBMSG("test unit ready"));
p = PT.last_sense; p = tape->last_sense;
if (!p) if (!p)
return 0; return 0;
if (!(((p & 0xffff) == 0x0402) || ((p & 0xff) == 6))) if (!(((p & 0xffff) == 0x0402) || ((p & 0xff) == 6)))
...@@ -558,7 +537,7 @@ static int xn(char *buf, int offs, int size) ...@@ -558,7 +537,7 @@ static int xn(char *buf, int offs, int size)
return v; return v;
} }
static int pt_identify(int unit) static int pt_identify(struct pt_unit *tape)
{ {
int dt, s; int dt, s;
char *ms[2] = { "master", "slave" }; char *ms[2] = { "master", "slave" };
...@@ -570,7 +549,7 @@ static int pt_identify(int unit) ...@@ -570,7 +549,7 @@ static int pt_identify(int unit)
{ ATAPI_LOG_SENSE, 0, 0x71, 0, 0, 0, 0, 0, 36, 0, 0, 0 }; { ATAPI_LOG_SENSE, 0, 0x71, 0, 0, 0, 0, 0, 36, 0, 0, 0 };
char buf[36]; char buf[36];
s = pt_atapi(unit, id_cmd, 36, buf, "identify"); s = pt_atapi(tape, id_cmd, 36, buf, "identify");
if (s) if (s)
return -1; return -1;
...@@ -578,36 +557,36 @@ static int pt_identify(int unit) ...@@ -578,36 +557,36 @@ static int pt_identify(int unit)
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); tape->name, tape->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; tape->flags = 0;
PT.capacity = 0; tape->capacity = 0;
PT.bs = 0; tape->bs = 0;
if (!pt_ready_wait(unit, PT_READY_TMO)) if (!pt_ready_wait(tape, PT_READY_TMO))
PT.flags |= PT_MEDIA; tape->flags |= PT_MEDIA;
if (!pt_atapi(unit, ms_cmd, 36, buf, "mode sense")) { if (!pt_atapi(tape, ms_cmd, 36, buf, "mode sense")) {
if (!(buf[2] & 0x80)) if (!(buf[2] & 0x80))
PT.flags |= PT_WRITE_OK; tape->flags |= PT_WRITE_OK;
PT.bs = xn(buf, 10, 2); tape->bs = xn(buf, 10, 2);
} }
if (!pt_atapi(unit, ls_cmd, 36, buf, "log sense")) if (!pt_atapi(tape, ls_cmd, 36, buf, "log sense"))
PT.capacity = xn(buf, 24, 4); tape->capacity = xn(buf, 24, 4);
printk("%s: %s %s, %s", PT.name, mf, id, ms[PT.drive]); printk("%s: %s %s, %s", tape->name, mf, id, ms[tape->drive]);
if (!(PT.flags & PT_MEDIA)) if (!(tape->flags & PT_MEDIA))
printk(", no media\n"); printk(", no media\n");
else { else {
if (!(PT.flags & PT_WRITE_OK)) if (!(tape->flags & PT_WRITE_OK))
printk(", RO"); printk(", RO");
printk(", blocksize %d, %d MB\n", PT.bs, PT.capacity / 1024); printk(", blocksize %d, %d MB\n", tape->bs, tape->capacity / 1024);
} }
return 0; return 0;
...@@ -618,109 +597,117 @@ static int pt_identify(int unit) ...@@ -618,109 +597,117 @@ static int pt_identify(int unit)
* returns 0, with id set if drive is detected * returns 0, with id set if drive is detected
* -1, if drive detection failed * -1, if drive detection failed
*/ */
static int pt_probe(int unit) static int pt_probe(struct pt_unit *tape)
{ {
if (PT.drive == -1) { if (tape->drive == -1) {
for (PT.drive = 0; PT.drive <= 1; PT.drive++) for (tape->drive = 0; tape->drive <= 1; tape->drive++)
if (!pt_reset(unit)) if (!pt_reset(tape))
return pt_identify(unit); return pt_identify(tape);
} else { } else {
if (!pt_reset(unit)) if (!pt_reset(tape))
return pt_identify(unit); return pt_identify(tape);
} }
return -1; return -1;
} }
static int pt_detect(void) static int pt_detect(void)
{ {
int k, unit; struct pt_unit *tape;
int specified = 0, found = 0;
int unit;
printk("%s: %s version %s, major %d\n", name, name, PT_VERSION, major); printk("%s: %s version %s, major %d\n", name, name, PT_VERSION, major);
k = 0; specified = 0;
if (pt_drive_count == 0) { for (unit = 0; unit < PT_UNITS; unit++) {
unit = 0; struct pt_unit *tape = &pt[unit];
if (pi_init(PI, 1, -1, -1, -1, -1, -1, pt_scratch, tape->pi = &tape->pia;
PI_PT, verbose, PT.name)) { atomic_set(&tape->available, 1);
if (!pt_probe(unit)) { tape->flags = 0;
PT.present = 1; tape->last_sense = 0;
k++; 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 } else
pi_release(PI); 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);
} }
} else }
for (unit = 0; unit < PT_UNITS; unit++) if (found)
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; return 0;
printk("%s: No ATAPI tape drive detected\n", name); printk("%s: No ATAPI tape drive detected\n", name);
return -1; return -1;
} }
#define DEVICE_NR(inode) (iminor(inode) & 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); int unit = iminor(inode) & 0x7F;
struct pt_unit *tape = pt + unit;
int err;
if ((unit >= PT_UNITS) || (!PT.present)) if (unit >= PT_UNITS || (!tape->present))
return -ENODEV; return -ENODEV;
if (!atomic_dec_and_test(&PT.available)) { err = -EBUSY;
atomic_inc(&PT.available); if (!atomic_dec_and_test(&tape->available))
return -EBUSY; goto out;
}
pt_identify(unit); pt_identify(tape);
if (!PT.flags & PT_MEDIA) { err = -ENODEV;
atomic_inc(&PT.available); if (!tape->flags & PT_MEDIA)
return -ENODEV; goto out;
}
if ((!PT.flags & PT_WRITE_OK) && (file->f_mode & 2)) { err = -EROFS;
atomic_inc(&PT.available); if ((!tape->flags & PT_WRITE_OK) && (file->f_mode & 2))
return -EROFS; goto out;
}
if (!(iminor(inode) & 128)) if (!(iminor(inode) & 128))
PT.flags |= PT_REWIND; tape->flags |= PT_REWIND;
PT.bufptr = kmalloc(PT_BUFSIZE, GFP_KERNEL); err = -ENOMEM;
if (PT.bufptr == NULL) { tape->bufptr = kmalloc(PT_BUFSIZE, GFP_KERNEL);
atomic_inc(&PT.available); if (tape->bufptr == NULL) {
printk("%s: buffer allocation failed\n", PT.name); printk("%s: buffer allocation failed\n", tape->name);
return -ENOMEM; goto out;
} }
file->private_data = tape;
return 0; return 0;
out:
atomic_inc(&tape->available);
return err;
} }
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; struct pt_unit *tape = file->private_data;
struct mtop mtop; struct mtop mtop;
unit = DEVICE_NR(inode);
if (unit >= PT_UNITS)
return -EINVAL;
if (!PT.present)
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,
...@@ -730,21 +717,21 @@ static int pt_ioctl(struct inode *inode, struct file *file, ...@@ -730,21 +717,21 @@ static int pt_ioctl(struct inode *inode, struct file *file,
switch (mtop.mt_op) { switch (mtop.mt_op) {
case MTREW: case MTREW:
pt_rewind(unit); pt_rewind(tape);
return 0; return 0;
case MTWEOF: case MTWEOF:
pt_write_fm(unit); pt_write_fm(tape);
return 0; return 0;
default: default:
printk("%s: Unimplemented mt_op %d\n", PT.name, printk("%s: Unimplemented mt_op %d\n", tape->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", tape->name, cmd);
return -EINVAL; return -EINVAL;
} }
...@@ -753,21 +740,21 @@ static int pt_ioctl(struct inode *inode, struct file *file, ...@@ -753,21 +740,21 @@ static int pt_ioctl(struct inode *inode, struct file *file,
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); struct pt_unit *tape = file->private_data;
if ((unit >= PT_UNITS) || (atomic_read(&PT.available) > 1)) if (atomic_read(&tape->available) > 1)
return -EINVAL; return -EINVAL;
if (PT.flags & PT_WRITING) if (tape->flags & PT_WRITING)
pt_write_fm(unit); pt_write_fm(tape);
if (PT.flags & PT_REWIND) if (tape->flags & PT_REWIND)
pt_rewind(unit); pt_rewind(tape);
kfree(PT.bufptr); kfree(tape->bufptr);
PT.bufptr = NULL; tape->bufptr = NULL;
atomic_inc(&PT.available); atomic_inc(&tape->available);
return 0; return 0;
...@@ -775,70 +762,70 @@ pt_release(struct inode *inode, struct file *file) ...@@ -775,70 +762,70 @@ pt_release(struct inode *inode, struct file *file)
static ssize_t pt_read(struct file *filp, char *buf, size_t count, loff_t * ppos) static ssize_t pt_read(struct file *filp, char *buf, size_t count, loff_t * ppos)
{ {
struct inode *ino = filp->f_dentry->d_inode; struct pt_unit *tape = filp->private_data;
int unit = DEVICE_NR(ino); struct pi_adapter *pi = tape->pi;
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 (!(tape->flags & (PT_READING | PT_WRITING))) {
PT.flags |= PT_READING; tape->flags |= PT_READING;
if (pt_atapi(unit, rd_cmd, 0, NULL, "start read-ahead")) if (pt_atapi(tape, rd_cmd, 0, NULL, "start read-ahead"))
return -EIO; return -EIO;
} else if (PT.flags & PT_WRITING) } else if (tape->flags & PT_WRITING)
return -EIO; return -EIO;
if (PT.flags & PT_EOF) if (tape->flags & PT_EOF)
return 0; return 0;
t = 0; t = 0;
while (count > 0) { while (count > 0) {
if (!pt_poll_dsc(unit, HZ / 100, PT_TMO, "read")) if (!pt_poll_dsc(tape, HZ / 100, PT_TMO, "read"))
return -EIO; return -EIO;
n = count; n = count;
if (n > 32768) if (n > 32768)
n = 32768; /* max per command */ n = 32768; /* max per command */
b = (n - 1 + PT.bs) / PT.bs; b = (n - 1 + tape->bs) / tape->bs;
n = b * PT.bs; /* rounded up to even block */ n = b * tape->bs; /* rounded up to even block */
rd_cmd[4] = b; rd_cmd[4] = b;
r = pt_command(unit, rd_cmd, n, "read"); r = pt_command(tape, rd_cmd, n, "read");
mdelay(1); mdelay(1);
if (r) { if (r) {
pt_req_sense(unit, 0); pt_req_sense(tape, 0);
return -EIO; return -EIO;
} }
while (1) { while (1) {
r = pt_wait(unit, STAT_BUSY, r = pt_wait(tape, STAT_BUSY,
STAT_DRQ | STAT_ERR | STAT_READY, STAT_DRQ | STAT_ERR | STAT_READY,
DBMSG("read DRQ"), ""); DBMSG("read DRQ"), "");
if (r & STAT_SENSE) { if (r & STAT_SENSE) {
pi_disconnect(PI); pi_disconnect(pi);
pt_req_sense(unit, 0); pt_req_sense(tape, 0);
return -EIO; return -EIO;
} }
if (r) if (r)
PT.flags |= PT_EOF; tape->flags |= PT_EOF;
s = read_reg(unit, 7); s = read_reg(pi, 7);
if (!(s & STAT_DRQ)) if (!(s & STAT_DRQ))
break; break;
n = (read_reg(unit, 4) + 256 * read_reg(unit, 5)); n = (read_reg(pi, 4) + 256 * read_reg(pi, 5));
p = (read_reg(unit, 2) & 3); p = (read_reg(pi, 2) & 3);
if (p != 2) { if (p != 2) {
pi_disconnect(PI); pi_disconnect(pi);
printk("%s: Phase error on read: %d\n", PT.name, printk("%s: Phase error on read: %d\n", tape->name,
p); p);
return -EIO; return -EIO;
} }
...@@ -847,13 +834,13 @@ static ssize_t pt_read(struct file *filp, char *buf, size_t count, loff_t * ppos ...@@ -847,13 +834,13 @@ static ssize_t pt_read(struct file *filp, char *buf, size_t count, loff_t * ppos
k = n; k = n;
if (k > PT_BUFSIZE) if (k > PT_BUFSIZE)
k = PT_BUFSIZE; k = PT_BUFSIZE;
pi_read_block(PI, PT.bufptr, k); pi_read_block(pi, tape->bufptr, k);
n -= k; n -= k;
b = k; b = k;
if (b > count) if (b > count)
b = count; b = count;
if (copy_to_user(buf + t, PT.bufptr, b)) { if (copy_to_user(buf + t, tape->bufptr, b)) {
pi_disconnect(PI); pi_disconnect(pi);
return -EFAULT; return -EFAULT;
} }
t += b; t += b;
...@@ -861,8 +848,8 @@ static ssize_t pt_read(struct file *filp, char *buf, size_t count, loff_t * ppos ...@@ -861,8 +848,8 @@ static ssize_t pt_read(struct file *filp, char *buf, size_t count, loff_t * ppos
} }
} }
pi_disconnect(PI); pi_disconnect(pi);
if (PT.flags & PT_EOF) if (tape->flags & PT_EOF)
break; break;
} }
...@@ -872,75 +859,75 @@ static ssize_t pt_read(struct file *filp, char *buf, size_t count, loff_t * ppos ...@@ -872,75 +859,75 @@ static ssize_t pt_read(struct file *filp, char *buf, size_t count, loff_t * ppos
static ssize_t pt_write(struct file *filp, const char *buf, size_t count, loff_t * ppos) 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; struct pt_unit *tape = filp->private_data;
int unit = DEVICE_NR(ino); struct pi_adapter *pi = tape->pi;
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)) if (!(tape->flags & PT_WRITE_OK))
return -EROFS; return -EROFS;
if (!(PT.flags & (PT_READING | PT_WRITING))) { if (!(tape->flags & (PT_READING | PT_WRITING))) {
PT.flags |= PT_WRITING; tape->flags |= PT_WRITING;
if (pt_atapi if (pt_atapi
(unit, wr_cmd, 0, NULL, "start buffer-available mode")) (tape, wr_cmd, 0, NULL, "start buffer-available mode"))
return -EIO; return -EIO;
} else if (PT.flags & PT_READING) } else if (tape->flags & PT_READING)
return -EIO; return -EIO;
if (PT.flags & PT_EOF) if (tape->flags & PT_EOF)
return -ENOSPC; return -ENOSPC;
t = 0; t = 0;
while (count > 0) { while (count > 0) {
if (!pt_poll_dsc(unit, HZ / 100, PT_TMO, "write")) if (!pt_poll_dsc(tape, HZ / 100, PT_TMO, "write"))
return -EIO; return -EIO;
n = count; n = count;
if (n > 32768) if (n > 32768)
n = 32768; /* max per command */ n = 32768; /* max per command */
b = (n - 1 + PT.bs) / PT.bs; b = (n - 1 + tape->bs) / tape->bs;
n = b * PT.bs; /* rounded up to even block */ n = b * tape->bs; /* rounded up to even block */
wr_cmd[4] = b; wr_cmd[4] = b;
r = pt_command(unit, wr_cmd, n, "write"); r = pt_command(tape, wr_cmd, n, "write");
mdelay(1); mdelay(1);
if (r) { /* error delivering command only */ if (r) { /* error delivering command only */
pt_req_sense(unit, 0); pt_req_sense(tape, 0);
return -EIO; return -EIO;
} }
while (1) { while (1) {
r = pt_wait(unit, STAT_BUSY, r = pt_wait(tape, STAT_BUSY,
STAT_DRQ | STAT_ERR | STAT_READY, STAT_DRQ | STAT_ERR | STAT_READY,
DBMSG("write DRQ"), NULL); DBMSG("write DRQ"), NULL);
if (r & STAT_SENSE) { if (r & STAT_SENSE) {
pi_disconnect(PI); pi_disconnect(pi);
pt_req_sense(unit, 0); pt_req_sense(tape, 0);
return -EIO; return -EIO;
} }
if (r) if (r)
PT.flags |= PT_EOF; tape->flags |= PT_EOF;
s = read_reg(unit, 7); s = read_reg(pi, 7);
if (!(s & STAT_DRQ)) if (!(s & STAT_DRQ))
break; break;
n = (read_reg(unit, 4) + 256 * read_reg(unit, 5)); n = (read_reg(pi, 4) + 256 * read_reg(pi, 5));
p = (read_reg(unit, 2) & 3); p = (read_reg(pi, 2) & 3);
if (p != 0) { if (p != 0) {
pi_disconnect(PI); pi_disconnect(pi);
printk("%s: Phase error on write: %d \n", printk("%s: Phase error on write: %d \n",
PT.name, p); tape->name, p);
return -EIO; return -EIO;
} }
...@@ -951,19 +938,19 @@ static ssize_t pt_write(struct file *filp, const char *buf, size_t count, loff_t ...@@ -951,19 +938,19 @@ static ssize_t pt_write(struct file *filp, const char *buf, size_t count, loff_t
b = k; b = k;
if (b > count) if (b > count)
b = count; b = count;
if (copy_from_user(PT.bufptr, buf + t, b)) { if (copy_from_user(tape->bufptr, buf + t, b)) {
pi_disconnect(PI); pi_disconnect(pi);
return -EFAULT; return -EFAULT;
} }
pi_write_block(PI, PT.bufptr, k); pi_write_block(pi, tape->bufptr, k);
t += b; t += b;
count -= b; count -= b;
n -= k; n -= k;
} }
} }
pi_disconnect(PI); pi_disconnect(pi);
if (PT.flags & PT_EOF) if (tape->flags & PT_EOF)
break; break;
} }
...@@ -977,22 +964,20 @@ static int __init pt_init(void) ...@@ -977,22 +964,20 @@ static int __init pt_init(void)
if (disable) if (disable)
return -1; return -1;
pt_init_units();
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", major); printk("pt_init: unable to get major number %d\n", major);
for (unit = 0; unit < PT_UNITS; unit++) for (unit = 0; unit < PT_UNITS; unit++)
if (PT.present) if (pt[unit].present)
pi_release(PI); pi_release(pt[unit].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[unit].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);
...@@ -1007,15 +992,15 @@ static void __exit pt_exit(void) ...@@ -1007,15 +992,15 @@ 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[unit].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[unit].present)
pi_release(PI); pi_release(pt[unit].pi);
} }
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
......
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