[PATCH] isdn4linux: Siemens Gigaset base driver: fix disconnect handling
[linux-2.6] / drivers / block / acsi_slm.c
1 /*
2  * acsi_slm.c -- Device driver for the Atari SLM laser printer
3  *
4  * Copyright 1995 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
5  *
6  * This file is subject to the terms and conditions of the GNU General Public
7  * License.  See the file COPYING in the main directory of this archive for
8  * more details.
9  * 
10  */
11
12 /*
13
14 Notes:
15
16 The major number for SLM printers is 28 (like ACSI), but as a character
17 device, not block device. The minor number is the number of the printer (if
18 you have more than one SLM; currently max. 2 (#define-constant) SLMs are
19 supported). The device can be opened for reading and writing. If reading it,
20 you get some status infos (MODE SENSE data). Writing mode is used for the data
21 to be printed. Some ioctls allow to get the printer status and to tune printer
22 modes and some internal variables.
23
24 A special problem of the SLM driver is the timing and thus the buffering of
25 the print data. The problem is that all the data for one page must be present
26 in memory when printing starts, else --when swapping occurs-- the timing could
27 not be guaranteed. There are several ways to assure this:
28
29  1) Reserve a buffer of 1196k (maximum page size) statically by
30     atari_stram_alloc(). The data are collected there until they're complete,
31         and then printing starts. Since the buffer is reserved, no further
32         considerations about memory and swapping are needed. So this is the
33         simplest method, but it needs a lot of memory for just the SLM.
34
35     An striking advantage of this method is (supposed the SLM_CONT_CNT_REPROG
36         method works, see there), that there are no timing problems with the DMA
37         anymore.
38         
39  2) The other method would be to reserve the buffer dynamically each time
40     printing is required. I could think of looking at mem_map where the
41         largest unallocted ST-RAM area is, taking the area, and then extending it
42         by swapping out the neighbored pages, until the needed size is reached.
43         This requires some mm hacking, but seems possible. The only obstacle could
44         be pages that cannot be swapped out (reserved pages)...
45
46  3) Another possibility would be to leave the real data in user space and to
47     work with two dribble buffers of about 32k in the driver: While the one
48         buffer is DMAed to the SLM, the other can be filled with new data. But
49         to keep the timing, that requires that the user data remain in memory and
50         are not swapped out. Requires mm hacking, too, but maybe not so bad as
51         method 2).
52
53 */
54
55 #include <linux/module.h>
56
57 #include <linux/errno.h>
58 #include <linux/sched.h>
59 #include <linux/timer.h>
60 #include <linux/fs.h>
61 #include <linux/major.h>
62 #include <linux/kernel.h>
63 #include <linux/delay.h>
64 #include <linux/interrupt.h>
65 #include <linux/time.h>
66 #include <linux/mm.h>
67 #include <linux/slab.h>
68 #include <linux/devfs_fs_kernel.h>
69 #include <linux/smp_lock.h>
70
71 #include <asm/pgtable.h>
72 #include <asm/system.h>
73 #include <asm/uaccess.h>
74 #include <asm/atarihw.h>
75 #include <asm/atariints.h>
76 #include <asm/atari_acsi.h>
77 #include <asm/atari_stdma.h>
78 #include <asm/atari_stram.h>
79 #include <asm/atari_SLM.h>
80
81
82 #undef  DEBUG
83
84 /* Define this if the page data are continuous in physical memory. That
85  * requires less reprogramming of the ST-DMA */
86 #define SLM_CONTINUOUS_DMA
87
88 /* Use continuous reprogramming of the ST-DMA counter register. This is
89  * --strictly speaking-- not allowed, Atari recommends not to look at the
90  * counter register while a DMA is going on. But I don't know if that applies
91  * only for reading the register, or also writing to it. Writing only works
92  * fine for me... The advantage is that the timing becomes absolutely
93  * uncritical: Just update each, say 200ms, the counter reg to its maximum,
94  * and the DMA will work until the status byte interrupt occurs.
95  */
96 #define SLM_CONT_CNT_REPROG
97
98 #define CMDSET_TARG_LUN(cmd,targ,lun)                   \
99     do {                                                                                \
100                 cmd[0] = (cmd[0] & ~0xe0) | (targ)<<5;  \
101                 cmd[1] = (cmd[1] & ~0xe0) | (lun)<<5;   \
102         } while(0)
103
104 #define START_TIMER(to) mod_timer(&slm_timer, jiffies + (to))
105 #define STOP_TIMER()    del_timer(&slm_timer)
106
107
108 static char slmreqsense_cmd[6] = { 0x03, 0, 0, 0, 0, 0 };
109 static char slmprint_cmd[6]    = { 0x0a, 0, 0, 0, 0, 0 };
110 static char slminquiry_cmd[6]  = { 0x12, 0, 0, 0, 0, 0x80 };
111 static char slmmsense_cmd[6]   = { 0x1a, 0, 0, 0, 255, 0 };
112 #if 0
113 static char slmmselect_cmd[6]  = { 0x15, 0, 0, 0, 0, 0 };
114 #endif
115
116
117 #define MAX_SLM         2
118
119 static struct slm {
120         unsigned        target;                 /* target number */
121         unsigned        lun;                    /* LUN in target controller */
122         atomic_t        wr_ok;                  /* set to 0 if output part busy */
123         atomic_t        rd_ok;                  /* set to 0 if status part busy */
124 } slm_info[MAX_SLM];
125
126 int N_SLM_Printers = 0;
127
128 /* printer buffer */
129 static unsigned char    *SLMBuffer;     /* start of buffer */
130 static unsigned char    *BufferP;       /* current position in buffer */
131 static int                              BufferSize;     /* length of buffer for page size */
132
133 typedef enum { IDLE, FILLING, PRINTING } SLMSTATE;
134 static SLMSTATE                 SLMState;
135 static int                              SLMBufOwner;    /* SLM# currently using the buffer */
136
137 /* DMA variables */
138 #ifndef SLM_CONT_CNT_REPROG
139 static unsigned long    SLMCurAddr;             /* current base addr of DMA chunk */
140 static unsigned long    SLMEndAddr;             /* expected end addr */
141 static unsigned long    SLMSliceSize;   /* size of one DMA chunk */
142 #endif
143 static int                              SLMError;
144
145 /* wait queues */
146 static DECLARE_WAIT_QUEUE_HEAD(slm_wait);       /* waiting for buffer */
147 static DECLARE_WAIT_QUEUE_HEAD(print_wait);     /* waiting for printing finished */
148
149 /* status codes */
150 #define SLMSTAT_OK              0x00
151 #define SLMSTAT_ORNERY  0x02
152 #define SLMSTAT_TONER   0x03
153 #define SLMSTAT_WARMUP  0x04
154 #define SLMSTAT_PAPER   0x05
155 #define SLMSTAT_DRUM    0x06
156 #define SLMSTAT_INJAM   0x07
157 #define SLMSTAT_THRJAM  0x08
158 #define SLMSTAT_OUTJAM  0x09
159 #define SLMSTAT_COVER   0x0a
160 #define SLMSTAT_FUSER   0x0b
161 #define SLMSTAT_IMAGER  0x0c
162 #define SLMSTAT_MOTOR   0x0d
163 #define SLMSTAT_VIDEO   0x0e
164 #define SLMSTAT_SYSTO   0x10
165 #define SLMSTAT_OPCODE  0x12
166 #define SLMSTAT_DEVNUM  0x15
167 #define SLMSTAT_PARAM   0x1a
168 #define SLMSTAT_ACSITO  0x1b    /* driver defined */
169 #define SLMSTAT_NOTALL  0x1c    /* driver defined */
170
171 static char *SLMErrors[] = {
172         /* 0x00 */      "OK and ready",
173         /* 0x01 */      NULL,
174         /* 0x02 */      "ornery printer",
175         /* 0x03 */      "toner empty",
176         /* 0x04 */      "warming up",
177         /* 0x05 */      "paper empty",
178         /* 0x06 */      "drum empty",
179         /* 0x07 */      "input jam",
180         /* 0x08 */      "through jam",
181         /* 0x09 */      "output jam",
182         /* 0x0a */      "cover open",
183         /* 0x0b */      "fuser malfunction",
184         /* 0x0c */      "imager malfunction",
185         /* 0x0d */      "motor malfunction",
186         /* 0x0e */      "video malfunction",
187         /* 0x0f */      NULL,
188         /* 0x10 */      "printer system timeout",
189         /* 0x11 */      NULL,
190         /* 0x12 */      "invalid operation code",
191         /* 0x13 */      NULL,
192         /* 0x14 */      NULL,
193         /* 0x15 */      "invalid device number",
194         /* 0x16 */      NULL,
195         /* 0x17 */      NULL,
196         /* 0x18 */      NULL,
197         /* 0x19 */      NULL,
198         /* 0x1a */      "invalid parameter list",
199         /* 0x1b */      "ACSI timeout",
200         /* 0x1c */      "not all printed"
201 };
202
203 #define N_ERRORS        (sizeof(SLMErrors)/sizeof(*SLMErrors))
204
205 /* real (driver caused) error? */
206 #define IS_REAL_ERROR(x)        (x > 0x10)
207
208
209 static struct {
210         char    *name;
211         int     w, h;
212 } StdPageSize[] = {
213         { "Letter", 2400, 3180 },
214         { "Legal",  2400, 4080 },
215         { "A4",     2336, 3386 },
216         { "B5",     2016, 2914 }
217 };
218
219 #define N_STD_SIZES             (sizeof(StdPageSize)/sizeof(*StdPageSize))
220
221 #define SLM_BUFFER_SIZE (2336*3386/8)   /* A4 for now */
222 #define SLM_DMA_AMOUNT  255                             /* #sectors to program the DMA for */
223
224 #ifdef  SLM_CONTINUOUS_DMA
225 # define        SLM_DMA_INT_OFFSET      0               /* DMA goes until seccnt 0, no offs */
226 # define        SLM_DMA_END_OFFSET      32              /* 32 Byte ST-DMA FIFO */
227 # define        SLM_SLICE_SIZE(w)       (255*512)
228 #else
229 # define        SLM_DMA_INT_OFFSET      32              /* 32 Byte ST-DMA FIFO */
230 # define        SLM_DMA_END_OFFSET      32              /* 32 Byte ST-DMA FIFO */
231 # define        SLM_SLICE_SIZE(w)       ((254*512)/(w/8)*(w/8))
232 #endif
233
234 /* calculate the number of jiffies to wait for 'n' bytes */
235 #ifdef SLM_CONT_CNT_REPROG
236 #define DMA_TIME_FOR(n)         50
237 #define DMA_STARTUP_TIME        0
238 #else
239 #define DMA_TIME_FOR(n)         (n/1400-1)
240 #define DMA_STARTUP_TIME        650
241 #endif
242
243 /***************************** Prototypes *****************************/
244
245 static char *slm_errstr( int stat );
246 static int slm_getstats( char *buffer, int device );
247 static ssize_t slm_read( struct file* file, char *buf, size_t count, loff_t
248                          *ppos );
249 static void start_print( int device );
250 static irqreturn_t slm_interrupt(int irc, void *data, struct pt_regs *fp);
251 static void slm_test_ready( unsigned long dummy );
252 static void set_dma_addr( unsigned long paddr );
253 static unsigned long get_dma_addr( void );
254 static ssize_t slm_write( struct file *file, const char *buf, size_t count,
255                           loff_t *ppos );
256 static int slm_ioctl( struct inode *inode, struct file *file, unsigned int
257                       cmd, unsigned long arg );
258 static int slm_open( struct inode *inode, struct file *file );
259 static int slm_release( struct inode *inode, struct file *file );
260 static int slm_req_sense( int device );
261 static int slm_mode_sense( int device, char *buffer, int abs_flag );
262 #if 0
263 static int slm_mode_select( int device, char *buffer, int len, int
264                             default_flag );
265 #endif
266 static int slm_get_pagesize( int device, int *w, int *h );
267
268 /************************* End of Prototypes **************************/
269
270
271 static DEFINE_TIMER(slm_timer, slm_test_ready, 0, 0);
272
273 static struct file_operations slm_fops = {
274         .owner =        THIS_MODULE,
275         .read =         slm_read,
276         .write =        slm_write,
277         .ioctl =        slm_ioctl,
278         .open =         slm_open,
279         .release =      slm_release,
280 };
281
282
283 /* ---------------------------------------------------------------------- */
284 /*                                                         Status Functions                                                       */
285
286
287 static char *slm_errstr( int stat )
288
289 {       char *p;
290         static char     str[22];
291
292         stat &= 0x1f;
293         if (stat >= 0 && stat < N_ERRORS && (p = SLMErrors[stat]))
294                 return( p );
295         sprintf( str, "unknown status 0x%02x", stat );
296         return( str );
297 }
298
299
300 static int slm_getstats( char *buffer, int device )
301
302 {       int                     len = 0, stat, i, w, h;
303         unsigned char   buf[256];
304         
305         stat = slm_mode_sense( device, buf, 0 );
306         if (IS_REAL_ERROR(stat))
307                 return( -EIO );
308         
309 #define SHORTDATA(i)            ((buf[i] << 8) | buf[i+1])
310 #define BOOLDATA(i,mask)        ((buf[i] & mask) ? "on" : "off")
311
312         w = SHORTDATA( 3 );
313         h = SHORTDATA( 1 );
314                 
315         len += sprintf( buffer+len, "Status\t\t%s\n",
316                                         slm_errstr( stat ) );
317         len += sprintf( buffer+len, "Page Size\t%dx%d",
318                                         w, h );
319
320         for( i = 0; i < N_STD_SIZES; ++i ) {
321                 if (w == StdPageSize[i].w && h == StdPageSize[i].h)
322                         break;
323         }
324         if (i < N_STD_SIZES)
325                 len += sprintf( buffer+len, " (%s)", StdPageSize[i].name );
326         buffer[len++] = '\n';
327
328         len += sprintf( buffer+len, "Top/Left Margin\t%d/%d\n",
329                                         SHORTDATA( 5 ), SHORTDATA( 7 ) );
330         len += sprintf( buffer+len, "Manual Feed\t%s\n",
331                                         BOOLDATA( 9, 0x01 ) );
332         len += sprintf( buffer+len, "Input Select\t%d\n",
333                                         (buf[9] >> 1) & 7 );
334         len += sprintf( buffer+len, "Auto Select\t%s\n",
335                                         BOOLDATA( 9, 0x10 ) );
336         len += sprintf( buffer+len, "Prefeed Paper\t%s\n",
337                                         BOOLDATA( 9, 0x20 ) );
338         len += sprintf( buffer+len, "Thick Pixels\t%s\n",
339                                         BOOLDATA( 9, 0x40 ) );
340         len += sprintf( buffer+len, "H/V Resol.\t%d/%d dpi\n",
341                                         SHORTDATA( 12 ), SHORTDATA( 10 ) );
342         len += sprintf( buffer+len, "System Timeout\t%d\n",
343                                         buf[14] );
344         len += sprintf( buffer+len, "Scan Time\t%d\n",
345                                         SHORTDATA( 15 ) );
346         len += sprintf( buffer+len, "Page Count\t%d\n",
347                                         SHORTDATA( 17 ) );
348         len += sprintf( buffer+len, "In/Out Cap.\t%d/%d\n",
349                                         SHORTDATA( 19 ), SHORTDATA( 21 ) );
350         len += sprintf( buffer+len, "Stagger Output\t%s\n",
351                                         BOOLDATA( 23, 0x01 ) );
352         len += sprintf( buffer+len, "Output Select\t%d\n",
353                                         (buf[23] >> 1) & 7 );
354         len += sprintf( buffer+len, "Duplex Print\t%s\n",
355                                         BOOLDATA( 23, 0x10 ) );
356         len += sprintf( buffer+len, "Color Sep.\t%s\n",
357                                         BOOLDATA( 23, 0x20 ) );
358
359         return( len );
360 }
361
362
363 static ssize_t slm_read( struct file *file, char *buf, size_t count,
364                                                  loff_t *ppos )
365
366 {
367         struct inode *node = file->f_dentry->d_inode;
368         unsigned long page;
369         int length;
370         int end;
371
372         if (!(page = __get_free_page( GFP_KERNEL )))
373                 return( -ENOMEM );
374         
375         length = slm_getstats( (char *)page, iminor(node) );
376         if (length < 0) {
377                 count = length;
378                 goto out;
379         }
380         if (file->f_pos >= length) {
381                 count = 0;
382                 goto out;
383         }
384         if (count + file->f_pos > length)
385                 count = length - file->f_pos;
386         end = count + file->f_pos;
387         if (copy_to_user(buf, (char *)page + file->f_pos, count)) {
388                 count = -EFAULT;
389                 goto out;
390         }
391         file->f_pos = end;
392 out:    free_page( page );
393         return( count );
394 }
395
396
397 /* ---------------------------------------------------------------------- */
398 /*                                                                 Printing                                                               */
399
400
401 static void start_print( int device )
402
403 {       struct slm *sip = &slm_info[device];
404         unsigned char   *cmd;
405         unsigned long   paddr;
406         int                             i;
407         
408         stdma_lock( slm_interrupt, NULL );
409
410         CMDSET_TARG_LUN( slmprint_cmd, sip->target, sip->lun );
411         cmd = slmprint_cmd;
412         paddr = virt_to_phys( SLMBuffer );
413         dma_cache_maintenance( paddr, virt_to_phys(BufferP)-paddr, 1 );
414         DISABLE_IRQ();
415
416         /* Low on A1 */
417         dma_wd.dma_mode_status = 0x88;
418         MFPDELAY();
419
420         /* send the command bytes except the last */
421         for( i = 0; i < 5; ++i ) {
422                 DMA_LONG_WRITE( *cmd++, 0x8a );
423                 udelay(20);
424                 if (!acsi_wait_for_IRQ( HZ/2 )) {
425                         SLMError = 1;
426                         return; /* timeout */
427                 }
428         }
429         /* last command byte */
430         DMA_LONG_WRITE( *cmd++, 0x82 );
431         MFPDELAY();
432         /* set DMA address */
433         set_dma_addr( paddr );
434         /* program DMA for write and select sector counter reg */
435         dma_wd.dma_mode_status = 0x192;
436         MFPDELAY();
437         /* program for 255*512 bytes and start DMA */
438         DMA_LONG_WRITE( SLM_DMA_AMOUNT, 0x112 );
439
440 #ifndef SLM_CONT_CNT_REPROG
441         SLMCurAddr = paddr;
442         SLMEndAddr = paddr + SLMSliceSize + SLM_DMA_INT_OFFSET;
443 #endif
444         START_TIMER( DMA_STARTUP_TIME + DMA_TIME_FOR( SLMSliceSize ));
445 #if !defined(SLM_CONT_CNT_REPROG) && defined(DEBUG)
446         printk( "SLM: CurAddr=%#lx EndAddr=%#lx timer=%ld\n",
447                         SLMCurAddr, SLMEndAddr, DMA_TIME_FOR( SLMSliceSize ) );
448 #endif
449         
450         ENABLE_IRQ();
451 }
452
453
454 /* Only called when an error happened or at the end of a page */
455
456 static irqreturn_t slm_interrupt(int irc, void *data, struct pt_regs *fp)
457
458 {       unsigned long   addr;
459         int                             stat;
460         
461         STOP_TIMER();
462         addr = get_dma_addr();
463         stat = acsi_getstatus();
464         SLMError = (stat < 0)             ? SLMSTAT_ACSITO :
465                        (addr < virt_to_phys(BufferP)) ? SLMSTAT_NOTALL :
466                                                                             stat;
467
468         dma_wd.dma_mode_status = 0x80;
469         MFPDELAY();
470 #ifdef DEBUG
471         printk( "SLM: interrupt, addr=%#lx, error=%d\n", addr, SLMError );
472 #endif
473
474         wake_up( &print_wait );
475         stdma_release();
476         ENABLE_IRQ();
477         return IRQ_HANDLED;
478 }
479
480
481 static void slm_test_ready( unsigned long dummy )
482
483 {
484 #ifdef SLM_CONT_CNT_REPROG
485         /* program for 255*512 bytes again */
486         dma_wd.fdc_acces_seccount = SLM_DMA_AMOUNT;
487         START_TIMER( DMA_TIME_FOR(0) );
488 #ifdef DEBUG
489         printk( "SLM: reprogramming timer for %d jiffies, addr=%#lx\n",
490                         DMA_TIME_FOR(0), get_dma_addr() );
491 #endif
492         
493 #else /* !SLM_CONT_CNT_REPROG */
494
495         unsigned long   flags, addr;
496         int                             d, ti;
497 #ifdef DEBUG
498         struct timeval start_tm, end_tm;
499         int                        did_wait = 0;
500 #endif
501
502         local_irq_save(flags);
503
504         addr = get_dma_addr();
505         if ((d = SLMEndAddr - addr) > 0) {
506                 local_irq_restore(flags);
507                 
508                 /* slice not yet finished, decide whether to start another timer or to
509                  * busy-wait */
510                 ti = DMA_TIME_FOR( d );
511                 if (ti > 0) {
512 #ifdef DEBUG
513                         printk( "SLM: reprogramming timer for %d jiffies, rest %d bytes\n",
514                                         ti, d );
515 #endif
516                         START_TIMER( ti );
517                         return;
518                 }
519                 /* wait for desired end address to be reached */
520 #ifdef DEBUG
521                 do_gettimeofday( &start_tm );
522                 did_wait = 1;
523 #endif
524                 local_irq_disable();
525                 while( get_dma_addr() < SLMEndAddr )
526                         barrier();
527         }
528
529         /* slice finished, start next one */
530         SLMCurAddr += SLMSliceSize;
531
532 #ifdef SLM_CONTINUOUS_DMA
533         /* program for 255*512 bytes again */
534         dma_wd.fdc_acces_seccount = SLM_DMA_AMOUNT;
535 #else
536         /* set DMA address;
537          * add 2 bytes for the ones in the SLM controller FIFO! */
538         set_dma_addr( SLMCurAddr + 2 );
539         /* toggle DMA to write and select sector counter reg */
540         dma_wd.dma_mode_status = 0x92;
541         MFPDELAY();
542         dma_wd.dma_mode_status = 0x192;
543         MFPDELAY();
544         /* program for 255*512 bytes and start DMA */
545         DMA_LONG_WRITE( SLM_DMA_AMOUNT, 0x112 );
546 #endif
547         
548         local_irq_restore(flags);
549
550 #ifdef DEBUG
551         if (did_wait) {
552                 int ms;
553                 do_gettimeofday( &end_tm );
554                 ms = (end_tm.tv_sec*1000000+end_tm.tv_usec) -
555                          (start_tm.tv_sec*1000000+start_tm.tv_usec); 
556                 printk( "SLM: did %ld.%ld ms busy waiting for %d bytes\n",
557                                 ms/1000, ms%1000, d );
558         }
559         else
560                 printk( "SLM: didn't wait (!)\n" );
561 #endif
562
563         if ((unsigned char *)PTOV( SLMCurAddr + SLMSliceSize ) >= BufferP) {
564                 /* will be last slice, no timer necessary */
565 #ifdef DEBUG
566                 printk( "SLM: CurAddr=%#lx EndAddr=%#lx last slice -> no timer\n",
567                                 SLMCurAddr, SLMEndAddr );
568 #endif
569         }
570         else {
571                 /* not last slice */
572                 SLMEndAddr = SLMCurAddr + SLMSliceSize + SLM_DMA_INT_OFFSET;
573                 START_TIMER( DMA_TIME_FOR( SLMSliceSize ));
574 #ifdef DEBUG
575                 printk( "SLM: CurAddr=%#lx EndAddr=%#lx timer=%ld\n",
576                                 SLMCurAddr, SLMEndAddr, DMA_TIME_FOR( SLMSliceSize ) );
577 #endif
578         }
579 #endif /* SLM_CONT_CNT_REPROG */
580 }
581
582
583 static void set_dma_addr( unsigned long paddr )
584
585 {       unsigned long flags;
586
587         local_irq_save(flags);
588         dma_wd.dma_lo = (unsigned char)paddr;
589         paddr >>= 8;
590         MFPDELAY();
591         dma_wd.dma_md = (unsigned char)paddr;
592         paddr >>= 8;
593         MFPDELAY();
594         if (ATARIHW_PRESENT( EXTD_DMA ))
595                 st_dma_ext_dmahi = (unsigned short)paddr;
596         else
597                 dma_wd.dma_hi = (unsigned char)paddr;
598         MFPDELAY();
599         local_irq_restore(flags);
600 }
601
602
603 static unsigned long get_dma_addr( void )
604
605 {       unsigned long   addr;
606         
607         addr = dma_wd.dma_lo & 0xff;
608         MFPDELAY();
609         addr |= (dma_wd.dma_md & 0xff) << 8;
610         MFPDELAY();
611         addr |= (dma_wd.dma_hi & 0xff) << 16;
612         MFPDELAY();
613
614         return( addr );
615 }
616
617
618 static ssize_t slm_write( struct file *file, const char *buf, size_t count,
619                                                   loff_t *ppos )
620
621 {
622         struct inode *node = file->f_dentry->d_inode;
623         int             device = iminor(node);
624         int             n, filled, w, h;
625
626         while( SLMState == PRINTING ||
627                    (SLMState == FILLING && SLMBufOwner != device) ) {
628                 interruptible_sleep_on( &slm_wait );
629                 if (signal_pending(current))
630                         return( -ERESTARTSYS );
631         }
632         if (SLMState == IDLE) {
633                 /* first data of page: get current page size  */
634                 if (slm_get_pagesize( device, &w, &h ))
635                         return( -EIO );
636                 BufferSize = w*h/8;
637                 if (BufferSize > SLM_BUFFER_SIZE)
638                         return( -ENOMEM );
639
640                 SLMState = FILLING;
641                 SLMBufOwner = device;
642         }
643
644         n = count;
645         filled = BufferP - SLMBuffer;
646         if (filled + n > BufferSize)
647                 n = BufferSize - filled;
648
649         if (copy_from_user(BufferP, buf, n))
650                 return -EFAULT;
651         BufferP += n;
652         filled += n;
653
654         if (filled == BufferSize) {
655                 /* Check the paper size again! The user may have switched it in the
656                  * time between starting the data and finishing them. Would end up in
657                  * a trashy page... */
658                 if (slm_get_pagesize( device, &w, &h ))
659                         return( -EIO );
660                 if (BufferSize != w*h/8) {
661                         printk( KERN_NOTICE "slm%d: page size changed while printing\n",
662                                         device );
663                         return( -EAGAIN );
664                 }
665
666                 SLMState = PRINTING;
667                 /* choose a slice size that is a multiple of the line size */
668 #ifndef SLM_CONT_CNT_REPROG
669                 SLMSliceSize = SLM_SLICE_SIZE(w);
670 #endif
671                 
672                 start_print( device );
673                 sleep_on( &print_wait );
674                 if (SLMError && IS_REAL_ERROR(SLMError)) {
675                         printk( KERN_ERR "slm%d: %s\n", device, slm_errstr(SLMError) );
676                         n = -EIO;
677                 }
678
679                 SLMState = IDLE;
680                 BufferP = SLMBuffer;
681                 wake_up_interruptible( &slm_wait );
682         }
683         
684         return( n );
685 }
686
687
688 /* ---------------------------------------------------------------------- */
689 /*                                                         ioctl Functions                                                        */
690
691
692 static int slm_ioctl( struct inode *inode, struct file *file,
693                                           unsigned int cmd, unsigned long arg )
694
695 {       int             device = iminor(inode), err;
696         
697         /* I can think of setting:
698          *  - manual feed
699          *  - paper format
700          *  - copy count
701          *  - ...
702          * but haven't implemented that yet :-)
703          * BTW, has anybody better docs about the MODE SENSE/MODE SELECT data?
704          */
705         switch( cmd ) {
706
707           case SLMIORESET:              /* reset buffer, i.e. empty the buffer */
708                 if (!(file->f_mode & 2))
709                         return( -EINVAL );
710                 if (SLMState == PRINTING)
711                         return( -EBUSY );
712                 SLMState = IDLE;
713                 BufferP = SLMBuffer;
714                 wake_up_interruptible( &slm_wait );
715                 return( 0 );
716                 
717           case SLMIOGSTAT: {    /* get status */
718                 int stat;
719                 char *str;
720
721                 stat = slm_req_sense( device );
722                 if (arg) {
723                         str = slm_errstr( stat );
724                         if (put_user(stat,
725                                      (long *)&((struct SLM_status *)arg)->stat))
726                                 return -EFAULT;
727                         if (copy_to_user( ((struct SLM_status *)arg)->str, str,
728                                                  strlen(str) + 1))
729                                 return -EFAULT;
730                 }
731                 return( stat );
732           }
733                 
734           case SLMIOGPSIZE: {   /* get paper size */
735                 int w, h;
736                 
737                 if ((err = slm_get_pagesize( device, &w, &h ))) return( err );
738                 
739                 if (put_user(w, (long *)&((struct SLM_paper_size *)arg)->width))
740                         return -EFAULT;
741                 if (put_user(h, (long *)&((struct SLM_paper_size *)arg)->height))
742                         return -EFAULT;
743                 return( 0 );
744           }
745                 
746           case SLMIOGMFEED:     /* get manual feed */
747                 return( -EINVAL );
748
749           case SLMIOSPSIZE:     /* set paper size */
750                 return( -EINVAL );
751
752           case SLMIOSMFEED:     /* set manual feed */
753                 return( -EINVAL );
754
755         }
756         return( -EINVAL );
757 }
758
759
760 /* ---------------------------------------------------------------------- */
761 /*                                                       Opening and Closing                                              */
762
763
764 static int slm_open( struct inode *inode, struct file *file )
765
766 {       int device;
767         struct slm *sip;
768         
769         device = iminor(inode);
770         if (device >= N_SLM_Printers)
771                 return( -ENXIO );
772         sip = &slm_info[device];
773
774         if (file->f_mode & 2) {
775                 /* open for writing is exclusive */
776                 if ( !atomic_dec_and_test(&sip->wr_ok) ) {
777                         atomic_inc(&sip->wr_ok);        
778                         return( -EBUSY );
779                 }
780         }
781         if (file->f_mode & 1) {
782                 /* open for reading is exclusive */
783                 if ( !atomic_dec_and_test(&sip->rd_ok) ) {
784                         atomic_inc(&sip->rd_ok);
785                         return( -EBUSY );
786                 }
787         }
788
789         return( 0 );
790 }
791
792
793 static int slm_release( struct inode *inode, struct file *file )
794
795 {       int device;
796         struct slm *sip;
797         
798         device = iminor(inode);
799         sip = &slm_info[device];
800
801         if (file->f_mode & 2)
802                 atomic_inc( &sip->wr_ok );
803         if (file->f_mode & 1)
804                 atomic_inc( &sip->rd_ok );
805         
806         return( 0 );
807 }
808
809
810 /* ---------------------------------------------------------------------- */
811 /*                                               ACSI Primitives for the SLM                                      */
812
813
814 static int slm_req_sense( int device )
815
816 {       int                     stat, rv;
817         struct slm *sip = &slm_info[device];
818         
819         stdma_lock( NULL, NULL );
820
821         CMDSET_TARG_LUN( slmreqsense_cmd, sip->target, sip->lun );
822         if (!acsicmd_nodma( slmreqsense_cmd, 0 ) ||
823                 (stat = acsi_getstatus()) < 0)
824                 rv = SLMSTAT_ACSITO;
825         else
826                 rv = stat & 0x1f;
827
828         ENABLE_IRQ();
829         stdma_release();
830         return( rv );
831 }
832
833
834 static int slm_mode_sense( int device, char *buffer, int abs_flag )
835
836 {       unsigned char   stat, len;
837         int                             rv = 0;
838         struct slm              *sip = &slm_info[device];
839         
840         stdma_lock( NULL, NULL );
841
842         CMDSET_TARG_LUN( slmmsense_cmd, sip->target, sip->lun );
843         slmmsense_cmd[5] = abs_flag ? 0x80 : 0;
844         if (!acsicmd_nodma( slmmsense_cmd, 0 )) {
845                 rv = SLMSTAT_ACSITO;
846                 goto the_end;
847         }
848
849         if (!acsi_extstatus( &stat, 1 )) {
850                 acsi_end_extstatus();
851                 rv = SLMSTAT_ACSITO;
852                 goto the_end;
853         }
854         
855         if (!acsi_extstatus( &len, 1 )) {
856                 acsi_end_extstatus();
857                 rv = SLMSTAT_ACSITO;
858                 goto the_end;
859         }
860         buffer[0] = len;
861         if (!acsi_extstatus( buffer+1, len )) {
862                 acsi_end_extstatus();
863                 rv = SLMSTAT_ACSITO;
864                 goto the_end;
865         }
866         
867         acsi_end_extstatus();
868         rv = stat & 0x1f;
869
870   the_end:
871         ENABLE_IRQ();
872         stdma_release();
873         return( rv );
874 }
875
876
877 #if 0
878 /* currently unused */
879 static int slm_mode_select( int device, char *buffer, int len,
880                                                         int default_flag )
881
882 {       int                     stat, rv;
883         struct slm      *sip = &slm_info[device];
884         
885         stdma_lock( NULL, NULL );
886
887         CMDSET_TARG_LUN( slmmselect_cmd, sip->target, sip->lun );
888         slmmselect_cmd[5] = default_flag ? 0x80 : 0;
889         if (!acsicmd_nodma( slmmselect_cmd, 0 )) {
890                 rv = SLMSTAT_ACSITO;
891                 goto the_end;
892         }
893
894         if (!default_flag) {
895                 unsigned char c = len;
896                 if (!acsi_extcmd( &c, 1 )) {
897                         rv = SLMSTAT_ACSITO;
898                         goto the_end;
899                 }
900                 if (!acsi_extcmd( buffer, len )) {
901                         rv = SLMSTAT_ACSITO;
902                         goto the_end;
903                 }
904         }
905         
906         stat = acsi_getstatus();
907         rv = (stat < 0 ? SLMSTAT_ACSITO : stat);
908
909   the_end:
910         ENABLE_IRQ();
911         stdma_release();
912         return( rv );
913 }
914 #endif
915
916
917 static int slm_get_pagesize( int device, int *w, int *h )
918
919 {       char    buf[256];
920         int             stat;
921         
922         stat = slm_mode_sense( device, buf, 0 );
923         ENABLE_IRQ();
924         stdma_release();
925
926         if (stat != SLMSTAT_OK)
927                 return( -EIO );
928
929         *w = (buf[3] << 8) | buf[4];
930         *h = (buf[1] << 8) | buf[2];
931         return( 0 );
932 }
933
934
935 /* ---------------------------------------------------------------------- */
936 /*                                                              Initialization                                                    */
937
938
939 int attach_slm( int target, int lun )
940
941 {       static int      did_register;
942         int                     len;
943
944         if (N_SLM_Printers >= MAX_SLM) {
945                 printk( KERN_WARNING "Too much SLMs\n" );
946                 return( 0 );
947         }
948         
949         /* do an INQUIRY */
950         udelay(100);
951         CMDSET_TARG_LUN( slminquiry_cmd, target, lun );
952         if (!acsicmd_nodma( slminquiry_cmd, 0 )) {
953           inq_timeout:
954                 printk( KERN_ERR "SLM inquiry command timed out.\n" );
955           inq_fail:
956                 acsi_end_extstatus();
957                 return( 0 );
958         }
959         /* read status and header of return data */
960         if (!acsi_extstatus( SLMBuffer, 6 ))
961                 goto inq_timeout;
962
963         if (SLMBuffer[1] != 2) { /* device type == printer? */
964                 printk( KERN_ERR "SLM inquiry returned device type != printer\n" );
965                 goto inq_fail;
966         }
967         len = SLMBuffer[5];
968         
969         /* read id string */
970         if (!acsi_extstatus( SLMBuffer, len ))
971                 goto inq_timeout;
972         acsi_end_extstatus();
973         SLMBuffer[len] = 0;
974
975         if (!did_register) {
976                 did_register = 1;
977         }
978
979         slm_info[N_SLM_Printers].target = target;
980         slm_info[N_SLM_Printers].lun    = lun;
981         atomic_set(&slm_info[N_SLM_Printers].wr_ok, 1 ); 
982         atomic_set(&slm_info[N_SLM_Printers].rd_ok, 1 );
983         
984         printk( KERN_INFO "  Printer: %s\n", SLMBuffer );
985         printk( KERN_INFO "Detected slm%d at id %d lun %d\n",
986                         N_SLM_Printers, target, lun );
987         N_SLM_Printers++;
988         return( 1 );
989 }
990
991 int slm_init( void )
992
993 {
994         int i;
995         if (register_chrdev( ACSI_MAJOR, "slm", &slm_fops )) {
996                 printk( KERN_ERR "Unable to get major %d for ACSI SLM\n", ACSI_MAJOR );
997                 return -EBUSY;
998         }
999         
1000         if (!(SLMBuffer = atari_stram_alloc( SLM_BUFFER_SIZE, "SLM" ))) {
1001                 printk( KERN_ERR "Unable to get SLM ST-Ram buffer.\n" );
1002                 unregister_chrdev( ACSI_MAJOR, "slm" );
1003                 return -ENOMEM;
1004         }
1005         BufferP = SLMBuffer;
1006         SLMState = IDLE;
1007         
1008         devfs_mk_dir("slm");
1009         for (i = 0; i < MAX_SLM; i++) {
1010                 devfs_mk_cdev(MKDEV(ACSI_MAJOR, i),
1011                                 S_IFCHR|S_IRUSR|S_IWUSR, "slm/%d", i);
1012         }
1013         return 0;
1014 }
1015
1016 #ifdef MODULE
1017
1018 /* from acsi.c */
1019 void acsi_attach_SLMs( int (*attach_func)( int, int ) );
1020
1021 int init_module(void)
1022 {
1023         int err;
1024
1025         if ((err = slm_init()))
1026                 return( err );
1027         /* This calls attach_slm() for every target/lun where acsi.c detected a
1028          * printer */
1029         acsi_attach_SLMs( attach_slm );
1030         return( 0 );
1031 }
1032
1033 void cleanup_module(void)
1034 {
1035         int i;
1036         for (i = 0; i < MAX_SLM; i++)
1037                 devfs_remove("slm/%d", i);
1038         devfs_remove("slm");
1039         if (unregister_chrdev( ACSI_MAJOR, "slm" ) != 0)
1040                 printk( KERN_ERR "acsi_slm: cleanup_module failed\n");
1041         atari_stram_free( SLMBuffer );
1042 }
1043 #endif