~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/block/acsi_slm.c

Version: ~ [ 2.2.5 ] ~ [ 2.4.1 ] ~ [ 2.4.9 ] ~ [ 2.6.17.10 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.