1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107#define PT_VERSION "1.04"
108#define PT_MAJOR 96
109#define PT_NAME "pt"
110#define PT_UNITS 4
111
112
113
114
115
116
117
118static int verbose = 0;
119static int major = PT_MAJOR;
120static char *name = PT_NAME;
121static int disable = 0;
122
123static int drive0[6] = {0,0,0,-1,-1,-1};
124static int drive1[6] = {0,0,0,-1,-1,-1};
125static int drive2[6] = {0,0,0,-1,-1,-1};
126static int drive3[6] = {0,0,0,-1,-1,-1};
127
128static int (*drives[4])[6] = {&drive0,&drive1,&drive2,&drive3};
129static int pt_drive_count;
130
131#define D_PRT 0
132#define D_PRO 1
133#define D_UNI 2
134#define D_MOD 3
135#define D_SLV 4
136#define D_DLY 5
137
138#define DU (*drives[unit])
139
140
141
142
143#include <linux/module.h>
144#include <linux/errno.h>
145#include <linux/fs.h>
146#include <linux/devfs_fs_kernel.h>
147#include <linux/kernel.h>
148#include <linux/delay.h>
149#include <linux/slab.h>
150#include <linux/mtio.h>
151#include <linux/wait.h>
152#include <linux/smp_lock.h>
153
154#include <asm/uaccess.h>
155
156#ifndef MODULE
157
158#include "setup.h"
159
160static STT pt_stt[5] = {{"drive0",6,drive0},
161 {"drive1",6,drive1},
162 {"drive2",6,drive2},
163 {"drive3",6,drive3},
164 {"disable",1,&disable}};
165
166void pt_setup( char *str, int *ints)
167
168{ generic_setup(pt_stt,5,str);
169}
170
171#endif
172
173MODULE_PARM(verbose,"i");
174MODULE_PARM(major,"i");
175MODULE_PARM(name,"s");
176MODULE_PARM(drive0,"1-6i");
177MODULE_PARM(drive1,"1-6i");
178MODULE_PARM(drive2,"1-6i");
179MODULE_PARM(drive3,"1-6i");
180
181#include "paride.h"
182
183#define PT_MAX_RETRIES 5
184#define PT_TMO 3000
185#define PT_SPIN_DEL 50
186#define PT_RESET_TMO 30
187#define PT_READY_TMO 60
188#define PT_REWIND_TMO 1200
189
190#define PT_SPIN ((1000000/(HZ*PT_SPIN_DEL))*PT_TMO)
191
192#define STAT_ERR 0x00001
193#define STAT_INDEX 0x00002
194#define STAT_ECC 0x00004
195#define STAT_DRQ 0x00008
196#define STAT_SEEK 0x00010
197#define STAT_WRERR 0x00020
198#define STAT_READY 0x00040
199#define STAT_BUSY 0x00080
200#define STAT_SENSE 0x1f000
201
202#define ATAPI_TEST_READY 0x00
203#define ATAPI_REWIND 0x01
204#define ATAPI_REQ_SENSE 0x03
205#define ATAPI_READ_6 0x08
206#define ATAPI_WRITE_6 0x0a
207#define ATAPI_WFM 0x10
208#define ATAPI_IDENTIFY 0x12
209#define ATAPI_MODE_SENSE 0x1a
210#define ATAPI_LOG_SENSE 0x4d
211
212int pt_init(void);
213#ifdef MODULE
214void cleanup_module( void );
215#endif
216
217static int pt_open(struct inode *inode, struct file *file);
218static int pt_ioctl(struct inode *inode,struct file *file,
219 unsigned int cmd, unsigned long arg);
220static int pt_release (struct inode *inode, struct file *file);
221static ssize_t pt_read(struct file * filp, char * buf,
222 size_t count, loff_t *ppos);
223static ssize_t pt_write(struct file * filp, const char * buf,
224 size_t count, loff_t *ppos);
225static int pt_detect(void);
226
227static int pt_identify (int unit);
228
229
230
231#define PT_MEDIA 1
232#define PT_WRITE_OK 2
233#define PT_REWIND 4
234#define PT_WRITING 8
235#define PT_READING 16
236#define PT_EOF 32
237
238#define PT_NAMELEN 8
239#define PT_BUFSIZE 16384
240
241struct pt_unit {
242 struct pi_adapter pia;
243 struct pi_adapter *pi;
244 int flags;
245 int last_sense;
246 int drive;
247 int access;
248 int bs;
249 int capacity;
250 int present;
251 char *bufptr;
252 char name[PT_NAMELEN];
253 };
254
255struct pt_unit pt[PT_UNITS];
256
257
258
259#define PT pt[unit]
260#define PI PT.pi
261
262static char pt_scratch[512];
263
264
265
266static struct file_operations pt_fops = {
267 owner: THIS_MODULE,
268 read: pt_read,
269 write: pt_write,
270 ioctl: pt_ioctl,
271 open: pt_open,
272 release: pt_release,
273};
274
275void pt_init_units( void )
276
277{ int unit, j;
278
279 pt_drive_count = 0;
280 for (unit=0;unit<PT_UNITS;unit++) {
281 PT.pi = & PT.pia;
282 PT.access = 0;
283 PT.flags = 0;
284 PT.last_sense = 0;
285 PT.present = 0;
286 PT.bufptr = NULL;
287 PT.drive = DU[D_SLV];
288 j = 0;
289 while ((j < PT_NAMELEN-2) && (PT.name[j]=name[j])) j++;
290 PT.name[j++] = '0' + unit;
291 PT.name[j] = 0;
292 if (DU[D_PRT]) pt_drive_count++;
293 }
294}
295
296static devfs_handle_t devfs_handle;
297
298int pt_init (void)
299
300{ int unit;
301
302 if (disable) return -1;
303
304 pt_init_units();
305
306 if (pt_detect()) return -1;
307
308 if (devfs_register_chrdev(major,name,&pt_fops)) {
309 printk("pt_init: unable to get major number %d\n",
310 major);
311 for (unit=0;unit<PT_UNITS;unit++)
312 if (PT.present) pi_release(PI);
313 return -1;
314 }
315
316 devfs_handle = devfs_mk_dir (NULL, "pt", NULL);
317 devfs_register_series (devfs_handle, "%u", 4, DEVFS_FL_DEFAULT,
318 major, 0, S_IFCHR | S_IRUSR | S_IWUSR,
319 &pt_fops, NULL);
320 devfs_register_series (devfs_handle, "%un", 4, DEVFS_FL_DEFAULT,
321 major, 128, S_IFCHR | S_IRUSR | S_IWUSR,
322 &pt_fops, NULL);
323 return 0;
324}
325
326#ifdef MODULE
327
328
329
330void cleanup_module(void);
331
332int init_module(void)
333
334{ int err;
335
336#ifdef PARIDE_JUMBO
337 { extern paride_init();
338 paride_init();
339 }
340#endif
341
342 err = pt_init();
343
344 return err;
345}
346
347void cleanup_module(void)
348
349{ int unit;
350
351 devfs_unregister (devfs_handle);
352 devfs_unregister_chrdev(major,name);
353
354 for (unit=0;unit<PT_UNITS;unit++)
355 if (PT.present) pi_release(PI);
356}
357
358#endif
359
360#define WR(c,r,v) pi_write_regr(PI,c,r,v)
361#define RR(c,r) (pi_read_regr(PI,c,r))
362
363#define DRIVE (0xa0+0x10*PT.drive)
364
365static int pt_wait( int unit, int go, int stop, char * fun, char * msg )
366
367{ int j, r, e, s, p;
368
369 j = 0;
370 while ((((r=RR(1,6))&go)||(stop&&(!(r&stop))))&&(j++<PT_SPIN))
371 udelay(PT_SPIN_DEL);
372
373 if ((r&(STAT_ERR&stop))||(j>=PT_SPIN)) {
374 s = RR(0,7);
375 e = RR(0,1);
376 p = RR(0,2);
377 if (j >= PT_SPIN) e |= 0x100;
378 if (fun) printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
379 " loop=%d phase=%d\n",
380 PT.name,fun,msg,r,s,e,j,p);
381 return (e<<8)+s;
382 }
383 return 0;
384}
385
386static int pt_command( int unit, char * cmd, int dlen, char * fun )
387
388{ pi_connect(PI);
389
390 WR(0,6,DRIVE);
391
392 if (pt_wait(unit,STAT_BUSY|STAT_DRQ,0,fun,"before command")) {
393 pi_disconnect(PI);
394 return -1;
395 }
396
397 WR(0,4,dlen % 256);
398 WR(0,5,dlen / 256);
399 WR(0,7,0xa0);
400
401 if (pt_wait(unit,STAT_BUSY,STAT_DRQ,fun,"command DRQ")) {
402 pi_disconnect(PI);
403 return -1;
404 }
405
406 if (RR(0,2) != 1) {
407 printk("%s: %s: command phase error\n",PT.name,fun);
408 pi_disconnect(PI);
409 return -1;
410 }
411
412 pi_write_block(PI,cmd,12);
413
414 return 0;
415}
416
417static int pt_completion( int unit, char * buf, char * fun )
418
419{ int r, s, n, p;
420
421 r = pt_wait(unit,STAT_BUSY,STAT_DRQ|STAT_READY|STAT_ERR,
422 fun,"completion");
423
424 if (RR(0,7)&STAT_DRQ) {
425 n = (((RR(0,4)+256*RR(0,5))+3)&0xfffc);
426 p = RR(0,2)&3;
427 if (p == 0) pi_write_block(PI,buf,n);
428 if (p == 2) pi_read_block(PI,buf,n);
429 }
430
431 s = pt_wait(unit,STAT_BUSY,STAT_READY|STAT_ERR,fun,"data done");
432
433 pi_disconnect(PI);
434
435 return (r?r:s);
436}
437
438static void pt_req_sense( int unit, int quiet )
439
440{ char rs_cmd[12] = { ATAPI_REQ_SENSE,0,0,0,16,0,0,0,0,0,0,0 };
441 char buf[16];
442 int r;
443
444 r = pt_command(unit,rs_cmd,16,"Request sense");
445 mdelay(1);
446 if (!r) pt_completion(unit,buf,"Request sense");
447
448 PT.last_sense = -1;
449 if (!r) {
450 if (!quiet) printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n",
451 PT.name,buf[2]&0xf,buf[12],buf[13]);
452 PT.last_sense = (buf[2]&0xf) | ((buf[12]&0xff)<<8)
453 | ((buf[13]&0xff)<<16) ;
454 }
455}
456
457static int pt_atapi( int unit, char * cmd, int dlen, char * buf, char * fun )
458
459{ int r;
460
461 r = pt_command(unit,cmd,dlen,fun);
462 mdelay(1);
463 if (!r) r = pt_completion(unit,buf,fun);
464 if (r) pt_req_sense(unit,!fun);
465
466 return r;
467}
468
469static void pt_sleep( int cs )
470
471{ current->state = TASK_INTERRUPTIBLE;
472 schedule_timeout(cs);
473}
474
475static int pt_poll_dsc( int unit, int pause, int tmo, char *msg )
476
477{ int k, e, s;
478
479 k = 0; e = 0; s = 0;
480 while (k < tmo) {
481 pt_sleep(pause);
482 k++;
483 pi_connect(PI);
484 WR(0,6,DRIVE);
485 s = RR(0,7);
486 e = RR(0,1);
487 pi_disconnect(PI);
488 if (s & (STAT_ERR|STAT_SEEK)) break;
489 }
490 if ((k >= tmo) || (s & STAT_ERR)) {
491 if (k >= tmo) printk("%s: %s DSC timeout\n",PT.name,msg);
492 else printk("%s: %s stat=0x%x err=0x%x\n",PT.name,msg,s,e);
493 pt_req_sense(unit,0);
494 return 0;
495 }
496 return 1;
497}
498
499static void pt_media_access_cmd( int unit, int tmo, char *cmd, char *fun)
500
501{ if (pt_command(unit,cmd,0,fun)) {
502 pt_req_sense(unit,0);
503 return;
504 }
505 pi_disconnect(PI);
506 pt_poll_dsc(unit,HZ,tmo,fun);
507}
508
509static void pt_rewind( int unit )
510
511{ char rw_cmd[12] = {ATAPI_REWIND,0,0,0,0,0,0,0,0,0,0,0};
512
513 pt_media_access_cmd(unit,PT_REWIND_TMO,rw_cmd,"rewind");
514}
515
516static void pt_write_fm( int unit )
517
518{ char wm_cmd[12] = {ATAPI_WFM,0,0,0,1,0,0,0,0,0,0,0};
519
520 pt_media_access_cmd(unit,PT_TMO,wm_cmd,"write filemark");
521}
522
523#define DBMSG(msg) ((verbose>1)?(msg):NULL)
524
525static int pt_reset( int unit )
526
527{ int i, k, flg;
528 int expect[5] = {1,1,1,0x14,0xeb};
529
530 pi_connect(PI);
531 WR(0,6,DRIVE);
532 WR(0,7,8);
533
534 pt_sleep(20*HZ/1000);
535
536 k = 0;
537 while ((k++ < PT_RESET_TMO) && (RR(1,6)&STAT_BUSY))
538 pt_sleep(HZ/10);
539
540 flg = 1;
541 for(i=0;i<5;i++) flg &= (RR(0,i+1) == expect[i]);
542
543 if (verbose) {
544 printk("%s: Reset (%d) signature = ",PT.name,k);
545 for (i=0;i<5;i++) printk("%3x",RR(0,i+1));
546 if (!flg) printk(" (incorrect)");
547 printk("\n");
548 }
549
550 pi_disconnect(PI);
551 return flg-1;
552}
553
554static int pt_ready_wait( int unit, int tmo )
555
556{ char tr_cmd[12] = {ATAPI_TEST_READY,0,0,0,0,0,0,0,0,0,0,0};
557 int k, p;
558
559 k = 0;
560 while (k < tmo) {
561 PT.last_sense = 0;
562 pt_atapi(unit,tr_cmd,0,NULL,DBMSG("test unit ready"));
563 p = PT.last_sense;
564 if (!p) return 0;
565 if (!(((p & 0xffff) == 0x0402)||((p & 0xff) == 6))) return p;
566 k++;
567 pt_sleep(HZ);
568 }
569 return 0x000020;
570}
571
572static void xs( char *buf, char *targ, int offs, int len )
573
574{ int j,k,l;
575
576 j=0; l=0;
577 for (k=0;k<len;k++)
578 if((buf[k+offs]!=0x20)||(buf[k+offs]!=l))
579 l=targ[j++]=buf[k+offs];
580 if (l==0x20) j--;
581 targ[j]=0;
582}
583
584static int xn( char *buf, int offs, int size )
585
586{ int v,k;
587
588 v=0;
589 for(k=0;k<size;k++) v=v*256+(buf[k+offs]&0xff);
590 return v;
591}
592
593static int pt_identify( int unit )
594
595{ int dt, s;
596 char *ms[2] = {"master","slave"};
597 char mf[10], id[18];
598 char id_cmd[12] = { ATAPI_IDENTIFY,0,0,0,36,0,0,0,0,0,0,0};
599 char ms_cmd[12] = { ATAPI_MODE_SENSE,0,0x2a,0,36,0,0,0,0,0,0,0};
600 char ls_cmd[12] = { ATAPI_LOG_SENSE,0,0x71,0,0,0,0,0,36,0,0,0};
601 char buf[36];
602
603 s = pt_atapi(unit,id_cmd,36,buf,"identify");
604 if (s) return -1;
605
606 dt = buf[0] & 0x1f;
607 if (dt != 1) {
608 if (verbose)
609 printk("%s: Drive %d, unsupported type %d\n",
610 PT.name,PT.drive,dt);
611 return -1;
612 }
613
614 xs(buf,mf,8,8);
615 xs(buf,id,16,16);
616
617 PT.flags = 0;
618 PT.capacity = 0;
619 PT.bs = 0;
620
621 if (!pt_ready_wait(unit,PT_READY_TMO)) PT.flags |= PT_MEDIA;
622
623 if (!pt_atapi(unit,ms_cmd,36,buf,"mode sense")) {
624 if (!(buf[2] & 0x80)) PT.flags |= PT_WRITE_OK;
625 PT.bs = xn(buf,10,2);
626 }
627
628 if (!pt_atapi(unit,ls_cmd,36,buf,"log sense"))
629 PT.capacity = xn(buf,24,4);
630
631 printk("%s: %s %s, %s",
632 PT.name,mf,id,ms[PT.drive]);
633 if (!(PT.flags & PT_MEDIA))
634 printk(", no media\n");
635 else { if (!(PT.flags & PT_WRITE_OK)) printk(", RO");
636 printk(", blocksize %d, %d MB\n",
637 PT.bs,PT.capacity/1024);
638 }
639
640 return 0;
641}
642
643static int pt_probe( int unit )
644
645
646
647
648
649{ if (PT.drive == -1) {
650 for (PT.drive=0;PT.drive<=1;PT.drive++)
651 if (!pt_reset(unit)) return pt_identify(unit);
652 } else {
653 if (!pt_reset(unit)) return pt_identify(unit);
654 }
655 return -1;
656}
657
658static int pt_detect( void )
659
660{ int k, unit;
661
662 printk("%s: %s version %s, major %d\n",
663 name,name,PT_VERSION,major);
664
665 k = 0;
666 if (pt_drive_count == 0) {
667 unit = 0;
668 if (pi_init(PI,1,-1,-1,-1,-1,-1,pt_scratch,
669 PI_PT,verbose,PT.name)) {
670 if (!pt_probe(unit)) {
671 PT.present = 1;
672 k++;
673 } else pi_release(PI);
674 }
675
676 } else for (unit=0;unit<PT_UNITS;unit++) if (DU[D_PRT])
677 if (pi_init(PI,0,DU[D_PRT],DU[D_MOD],DU[D_UNI],
678 DU[D_PRO],DU[D_DLY],pt_scratch,PI_PT,verbose,
679 PT.name)) {
680 if (!pt_probe(unit)) {
681 PT.present = 1;
682 k++;
683 } else pi_release(PI);
684 }
685
686 if (k) return 0;
687
688 printk("%s: No ATAPI tape drive detected\n",name);
689 return -1;
690}
691
692#define DEVICE_NR(dev) (MINOR(dev) % 128)
693
694static int pt_open (struct inode *inode, struct file *file)
695
696{ int unit = DEVICE_NR(inode->i_rdev);
697
698 if ((unit >= PT_UNITS) || (!PT.present)) return -ENODEV;
699
700 PT.access++;
701
702 if (PT.access > 1) {
703 PT.access--;
704 return -EBUSY;
705 }
706
707 pt_identify(unit);
708
709 if (!PT.flags & PT_MEDIA) {
710 PT.access--;
711 return -ENODEV;
712 }
713
714 if ((!PT.flags & PT_WRITE_OK) && (file ->f_mode & 2)) {
715 PT.access--;
716 return -EROFS;
717 }
718
719 if (!(MINOR(inode->i_rdev) & 128))
720 PT.flags |= PT_REWIND;
721
722 PT.bufptr = kmalloc(PT_BUFSIZE,GFP_KERNEL);
723 if (PT.bufptr == NULL) {
724 PT.access--;
725 printk("%s: buffer allocation failed\n",PT.name);
726 return -ENOMEM;
727 }
728
729 return 0;
730}
731
732static int pt_ioctl(struct inode *inode,struct file *file,
733 unsigned int cmd, unsigned long arg)
734{
735 int unit;
736 struct mtop mtop;
737
738 if (!inode || !inode->i_rdev)
739 return -EINVAL;
740 unit = DEVICE_NR(inode->i_rdev);
741 if (unit >= PT_UNITS)
742 return -EINVAL;
743 if (!PT.present)
744 return -ENODEV;
745
746 switch (cmd) {
747 case MTIOCTOP:
748 if (copy_from_user((char *)&mtop, (char *)arg,
749 sizeof(struct mtop))) return -EFAULT;
750
751 switch (mtop.mt_op) {
752
753 case MTREW:
754 pt_rewind(unit);
755 return 0;
756
757 case MTWEOF:
758 pt_write_fm(unit);
759 return 0;
760
761 default:
762 printk("%s: Unimplemented mt_op %d\n",PT.name,
763 mtop.mt_op);
764 return -EINVAL;
765 }
766
767 default:
768 printk("%s: Unimplemented ioctl 0x%x\n",PT.name,cmd);
769 return -EINVAL;
770
771 }
772}
773
774
775static int pt_release (struct inode *inode, struct file *file)
776{
777 int unit = DEVICE_NR(inode->i_rdev);
778
779 if ((unit >= PT_UNITS) || (PT.access <= 0))
780 return -EINVAL;
781
782 lock_kernel();
783 if (PT.flags & PT_WRITING) pt_write_fm(unit);
784
785 if (PT.flags & PT_REWIND) pt_rewind(unit);
786
787 PT.access--;
788
789 kfree(PT.bufptr);
790 PT.bufptr = NULL;
791 unlock_kernel();
792
793 return 0;
794
795}
796
797static ssize_t pt_read(struct file * filp, char * buf,
798 size_t count, loff_t *ppos)
799{
800 struct inode *ino = filp->f_dentry->d_inode;
801 int unit = DEVICE_NR(ino->i_rdev);
802 char rd_cmd[12] = {ATAPI_READ_6,1,0,0,0,0,0,0,0,0,0,0};
803 int k, n, r, p, s, t, b;
804
805 if (!(PT.flags & (PT_READING|PT_WRITING))) {
806 PT.flags |= PT_READING;
807 if (pt_atapi(unit,rd_cmd,0,NULL,"start read-ahead"))
808 return -EIO;
809 } else if (PT.flags & PT_WRITING) return -EIO;
810
811 if (PT.flags & PT_EOF) return 0;
812
813 t = 0;
814
815 while (count > 0) {
816
817 if (!pt_poll_dsc(unit,HZ/100,PT_TMO,"read")) return -EIO;
818
819 n = count;
820 if (n > 32768) n = 32768;
821 b = (n-1+PT.bs)/PT.bs;
822 n = b*PT.bs;
823
824 rd_cmd[4] = b;
825
826 r = pt_command(unit,rd_cmd,n,"read");
827
828 mdelay(1);
829
830 if (r) {
831 pt_req_sense(unit,0);
832 return -EIO;
833 }
834
835 while (1) {
836
837 r = pt_wait(unit,STAT_BUSY,STAT_DRQ|STAT_ERR|STAT_READY,
838 DBMSG("read DRQ"),"");
839
840 if (r & STAT_SENSE) {
841 pi_disconnect(PI);
842 pt_req_sense(unit,0);
843 return -EIO;
844 }
845
846 if (r) PT.flags |= PT_EOF;
847
848 s = RR(0,7);
849
850 if (!(s & STAT_DRQ)) break;
851
852 n = (RR(0,4)+256*RR(0,5));
853 p = (RR(0,2)&3);
854 if (p != 2) {
855 pi_disconnect(PI);
856 printk("%s: Phase error on read: %d\n",PT.name,p);
857 return -EIO;
858 }
859
860 while (n > 0) {
861 k = n;
862 if (k > PT_BUFSIZE) k = PT_BUFSIZE;
863 pi_read_block(PI,PT.bufptr,k);
864 n -= k;
865 b = k;
866 if (b > count) b = count;
867 if (copy_to_user(buf + t, PT.bufptr, b)) {
868 pi_disconnect(PI);
869 return -EFAULT;
870 }
871 t += b;
872 count -= b;
873 }
874
875 }
876 pi_disconnect(PI);
877 if (PT.flags & PT_EOF) break;
878 }
879
880 return t;
881
882}
883
884static ssize_t pt_write(struct file * filp, const char * buf,
885 size_t count, loff_t *ppos)
886{
887 struct inode *ino = filp->f_dentry->d_inode;
888 int unit = DEVICE_NR(ino->i_rdev);
889 char wr_cmd[12] = {ATAPI_WRITE_6,1,0,0,0,0,0,0,0,0,0,0};
890 int k, n, r, p, s, t, b;
891
892 if (!(PT.flags & PT_WRITE_OK)) return -EROFS;
893
894 if (!(PT.flags & (PT_READING|PT_WRITING))) {
895 PT.flags |= PT_WRITING;
896 if (pt_atapi(unit,wr_cmd,0,NULL,"start buffer-available mode"))
897 return -EIO;
898 } else if (PT.flags&PT_READING) return -EIO;
899
900 if (PT.flags & PT_EOF) return -ENOSPC;
901
902 t = 0;
903
904 while (count > 0) {
905
906 if (!pt_poll_dsc(unit,HZ/100,PT_TMO,"write")) return -EIO;
907
908 n = count;
909 if (n > 32768) n = 32768;
910 b = (n-1+PT.bs)/PT.bs;
911 n = b*PT.bs;
912
913 wr_cmd[4] = b;
914
915 r = pt_command(unit,wr_cmd,n,"write");
916
917 mdelay(1);
918
919 if (r) {
920 pt_req_sense(unit,0);
921 return -EIO;
922 }
923
924 while (1) {
925
926 r = pt_wait(unit,STAT_BUSY,STAT_DRQ|STAT_ERR|STAT_READY,
927 DBMSG("write DRQ"),NULL);
928
929 if (r & STAT_SENSE) {
930 pi_disconnect(PI);
931 pt_req_sense(unit,0);
932 return -EIO;
933 }
934
935 if (r) PT.flags |= PT_EOF;
936
937 s = RR(0,7);
938
939 if (!(s & STAT_DRQ)) break;
940
941 n = (RR(0,4)+256*RR(0,5));
942 p = (RR(0,2)&3);
943 if (p != 0) {
944 pi_disconnect(PI);
945 printk("%s: Phase error on write: %d \n",PT.name,p);
946 return -EIO;
947 }
948
949 while (n > 0) {
950 k = n;
951 if (k > PT_BUFSIZE) k = PT_BUFSIZE;
952 b = k;
953 if (b > count) b = count;
954 if (copy_from_user(PT.bufptr, buf + t, b)) {
955 pi_disconnect(PI);
956 return -EFAULT;
957 }
958 pi_write_block(PI,PT.bufptr,k);
959 t += b;
960 count -= b;
961 n -= k;
962 }
963
964 }
965 pi_disconnect(PI);
966 if (PT.flags & PT_EOF) break;
967 }
968
969 return t;
970}
971
972
973
974MODULE_LICENSE("GPL");
975