2 * acsi_slm.c -- Device driver for the Atari SLM laser printer
4 * Copyright 1995 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
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
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.
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:
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.
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
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)...
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
55 #include <linux/module.h>
57 #include <linux/errno.h>
58 #include <linux/sched.h>
59 #include <linux/timer.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>
67 #include <linux/slab.h>
69 #include <asm/pgtable.h>
70 #include <asm/system.h>
71 #include <asm/uaccess.h>
72 #include <asm/atarihw.h>
73 #include <asm/atariints.h>
74 #include <asm/atari_acsi.h>
75 #include <asm/atari_stdma.h>
76 #include <asm/atari_stram.h>
77 #include <asm/atari_SLM.h>
82 /* Define this if the page data are continuous in physical memory. That
83 * requires less reprogramming of the ST-DMA */
84 #define SLM_CONTINUOUS_DMA
86 /* Use continuous reprogramming of the ST-DMA counter register. This is
87 * --strictly speaking-- not allowed, Atari recommends not to look at the
88 * counter register while a DMA is going on. But I don't know if that applies
89 * only for reading the register, or also writing to it. Writing only works
90 * fine for me... The advantage is that the timing becomes absolutely
91 * uncritical: Just update each, say 200ms, the counter reg to its maximum,
92 * and the DMA will work until the status byte interrupt occurs.
94 #define SLM_CONT_CNT_REPROG
96 #define CMDSET_TARG_LUN(cmd,targ,lun) \
98 cmd[0] = (cmd[0] & ~0xe0) | (targ)<<5; \
99 cmd[1] = (cmd[1] & ~0xe0) | (lun)<<5; \
102 #define START_TIMER(to) mod_timer(&slm_timer, jiffies + (to))
103 #define STOP_TIMER() del_timer(&slm_timer)
106 static char slmreqsense_cmd[6] = { 0x03, 0, 0, 0, 0, 0 };
107 static char slmprint_cmd[6] = { 0x0a, 0, 0, 0, 0, 0 };
108 static char slminquiry_cmd[6] = { 0x12, 0, 0, 0, 0, 0x80 };
109 static char slmmsense_cmd[6] = { 0x1a, 0, 0, 0, 255, 0 };
111 static char slmmselect_cmd[6] = { 0x15, 0, 0, 0, 0, 0 };
118 unsigned target; /* target number */
119 unsigned lun; /* LUN in target controller */
120 atomic_t wr_ok; /* set to 0 if output part busy */
121 atomic_t rd_ok; /* set to 0 if status part busy */
124 int N_SLM_Printers = 0;
127 static unsigned char *SLMBuffer; /* start of buffer */
128 static unsigned char *BufferP; /* current position in buffer */
129 static int BufferSize; /* length of buffer for page size */
131 typedef enum { IDLE, FILLING, PRINTING } SLMSTATE;
132 static SLMSTATE SLMState;
133 static int SLMBufOwner; /* SLM# currently using the buffer */
136 #ifndef SLM_CONT_CNT_REPROG
137 static unsigned long SLMCurAddr; /* current base addr of DMA chunk */
138 static unsigned long SLMEndAddr; /* expected end addr */
139 static unsigned long SLMSliceSize; /* size of one DMA chunk */
144 static DECLARE_WAIT_QUEUE_HEAD(slm_wait); /* waiting for buffer */
145 static DECLARE_WAIT_QUEUE_HEAD(print_wait); /* waiting for printing finished */
148 #define SLMSTAT_OK 0x00
149 #define SLMSTAT_ORNERY 0x02
150 #define SLMSTAT_TONER 0x03
151 #define SLMSTAT_WARMUP 0x04
152 #define SLMSTAT_PAPER 0x05
153 #define SLMSTAT_DRUM 0x06
154 #define SLMSTAT_INJAM 0x07
155 #define SLMSTAT_THRJAM 0x08
156 #define SLMSTAT_OUTJAM 0x09
157 #define SLMSTAT_COVER 0x0a
158 #define SLMSTAT_FUSER 0x0b
159 #define SLMSTAT_IMAGER 0x0c
160 #define SLMSTAT_MOTOR 0x0d
161 #define SLMSTAT_VIDEO 0x0e
162 #define SLMSTAT_SYSTO 0x10
163 #define SLMSTAT_OPCODE 0x12
164 #define SLMSTAT_DEVNUM 0x15
165 #define SLMSTAT_PARAM 0x1a
166 #define SLMSTAT_ACSITO 0x1b /* driver defined */
167 #define SLMSTAT_NOTALL 0x1c /* driver defined */
169 static char *SLMErrors[] = {
170 /* 0x00 */ "OK and ready",
172 /* 0x02 */ "ornery printer",
173 /* 0x03 */ "toner empty",
174 /* 0x04 */ "warming up",
175 /* 0x05 */ "paper empty",
176 /* 0x06 */ "drum empty",
177 /* 0x07 */ "input jam",
178 /* 0x08 */ "through jam",
179 /* 0x09 */ "output jam",
180 /* 0x0a */ "cover open",
181 /* 0x0b */ "fuser malfunction",
182 /* 0x0c */ "imager malfunction",
183 /* 0x0d */ "motor malfunction",
184 /* 0x0e */ "video malfunction",
186 /* 0x10 */ "printer system timeout",
188 /* 0x12 */ "invalid operation code",
191 /* 0x15 */ "invalid device number",
196 /* 0x1a */ "invalid parameter list",
197 /* 0x1b */ "ACSI timeout",
198 /* 0x1c */ "not all printed"
201 #define N_ERRORS (sizeof(SLMErrors)/sizeof(*SLMErrors))
203 /* real (driver caused) error? */
204 #define IS_REAL_ERROR(x) (x > 0x10)
211 { "Letter", 2400, 3180 },
212 { "Legal", 2400, 4080 },
213 { "A4", 2336, 3386 },
217 #define N_STD_SIZES (sizeof(StdPageSize)/sizeof(*StdPageSize))
219 #define SLM_BUFFER_SIZE (2336*3386/8) /* A4 for now */
220 #define SLM_DMA_AMOUNT 255 /* #sectors to program the DMA for */
222 #ifdef SLM_CONTINUOUS_DMA
223 # define SLM_DMA_INT_OFFSET 0 /* DMA goes until seccnt 0, no offs */
224 # define SLM_DMA_END_OFFSET 32 /* 32 Byte ST-DMA FIFO */
225 # define SLM_SLICE_SIZE(w) (255*512)
227 # define SLM_DMA_INT_OFFSET 32 /* 32 Byte ST-DMA FIFO */
228 # define SLM_DMA_END_OFFSET 32 /* 32 Byte ST-DMA FIFO */
229 # define SLM_SLICE_SIZE(w) ((254*512)/(w/8)*(w/8))
232 /* calculate the number of jiffies to wait for 'n' bytes */
233 #ifdef SLM_CONT_CNT_REPROG
234 #define DMA_TIME_FOR(n) 50
235 #define DMA_STARTUP_TIME 0
237 #define DMA_TIME_FOR(n) (n/1400-1)
238 #define DMA_STARTUP_TIME 650
241 /***************************** Prototypes *****************************/
243 static char *slm_errstr( int stat );
244 static int slm_getstats( char *buffer, int device );
245 static ssize_t slm_read( struct file* file, char *buf, size_t count, loff_t
247 static void start_print( int device );
248 static irqreturn_t slm_interrupt(int irc, void *data);
249 static void slm_test_ready( unsigned long dummy );
250 static void set_dma_addr( unsigned long paddr );
251 static unsigned long get_dma_addr( void );
252 static ssize_t slm_write( struct file *file, const char *buf, size_t count,
254 static int slm_ioctl( struct inode *inode, struct file *file, unsigned int
255 cmd, unsigned long arg );
256 static int slm_open( struct inode *inode, struct file *file );
257 static int slm_release( struct inode *inode, struct file *file );
258 static int slm_req_sense( int device );
259 static int slm_mode_sense( int device, char *buffer, int abs_flag );
261 static int slm_mode_select( int device, char *buffer, int len, int
264 static int slm_get_pagesize( int device, int *w, int *h );
266 /************************* End of Prototypes **************************/
269 static DEFINE_TIMER(slm_timer, slm_test_ready, 0, 0);
271 static const struct file_operations slm_fops = {
272 .owner = THIS_MODULE,
277 .release = slm_release,
281 /* ---------------------------------------------------------------------- */
282 /* Status Functions */
285 static char *slm_errstr( int stat )
291 if (stat >= 0 && stat < N_ERRORS && (p = SLMErrors[stat]))
293 sprintf( str, "unknown status 0x%02x", stat );
298 static int slm_getstats( char *buffer, int device )
300 { int len = 0, stat, i, w, h;
301 unsigned char buf[256];
303 stat = slm_mode_sense( device, buf, 0 );
304 if (IS_REAL_ERROR(stat))
307 #define SHORTDATA(i) ((buf[i] << 8) | buf[i+1])
308 #define BOOLDATA(i,mask) ((buf[i] & mask) ? "on" : "off")
313 len += sprintf( buffer+len, "Status\t\t%s\n",
314 slm_errstr( stat ) );
315 len += sprintf( buffer+len, "Page Size\t%dx%d",
318 for( i = 0; i < N_STD_SIZES; ++i ) {
319 if (w == StdPageSize[i].w && h == StdPageSize[i].h)
323 len += sprintf( buffer+len, " (%s)", StdPageSize[i].name );
324 buffer[len++] = '\n';
326 len += sprintf( buffer+len, "Top/Left Margin\t%d/%d\n",
327 SHORTDATA( 5 ), SHORTDATA( 7 ) );
328 len += sprintf( buffer+len, "Manual Feed\t%s\n",
329 BOOLDATA( 9, 0x01 ) );
330 len += sprintf( buffer+len, "Input Select\t%d\n",
332 len += sprintf( buffer+len, "Auto Select\t%s\n",
333 BOOLDATA( 9, 0x10 ) );
334 len += sprintf( buffer+len, "Prefeed Paper\t%s\n",
335 BOOLDATA( 9, 0x20 ) );
336 len += sprintf( buffer+len, "Thick Pixels\t%s\n",
337 BOOLDATA( 9, 0x40 ) );
338 len += sprintf( buffer+len, "H/V Resol.\t%d/%d dpi\n",
339 SHORTDATA( 12 ), SHORTDATA( 10 ) );
340 len += sprintf( buffer+len, "System Timeout\t%d\n",
342 len += sprintf( buffer+len, "Scan Time\t%d\n",
344 len += sprintf( buffer+len, "Page Count\t%d\n",
346 len += sprintf( buffer+len, "In/Out Cap.\t%d/%d\n",
347 SHORTDATA( 19 ), SHORTDATA( 21 ) );
348 len += sprintf( buffer+len, "Stagger Output\t%s\n",
349 BOOLDATA( 23, 0x01 ) );
350 len += sprintf( buffer+len, "Output Select\t%d\n",
351 (buf[23] >> 1) & 7 );
352 len += sprintf( buffer+len, "Duplex Print\t%s\n",
353 BOOLDATA( 23, 0x10 ) );
354 len += sprintf( buffer+len, "Color Sep.\t%s\n",
355 BOOLDATA( 23, 0x20 ) );
361 static ssize_t slm_read( struct file *file, char *buf, size_t count,
365 struct inode *node = file->f_path.dentry->d_inode;
370 if (!(page = __get_free_page( GFP_KERNEL )))
373 length = slm_getstats( (char *)page, iminor(node) );
378 if (file->f_pos >= length) {
382 if (count + file->f_pos > length)
383 count = length - file->f_pos;
384 end = count + file->f_pos;
385 if (copy_to_user(buf, (char *)page + file->f_pos, count)) {
390 out: free_page( page );
395 /* ---------------------------------------------------------------------- */
399 static void start_print( int device )
401 { struct slm *sip = &slm_info[device];
406 stdma_lock( slm_interrupt, NULL );
408 CMDSET_TARG_LUN( slmprint_cmd, sip->target, sip->lun );
410 paddr = virt_to_phys( SLMBuffer );
411 dma_cache_maintenance( paddr, virt_to_phys(BufferP)-paddr, 1 );
415 dma_wd.dma_mode_status = 0x88;
418 /* send the command bytes except the last */
419 for( i = 0; i < 5; ++i ) {
420 DMA_LONG_WRITE( *cmd++, 0x8a );
422 if (!acsi_wait_for_IRQ( HZ/2 )) {
424 return; /* timeout */
427 /* last command byte */
428 DMA_LONG_WRITE( *cmd++, 0x82 );
430 /* set DMA address */
431 set_dma_addr( paddr );
432 /* program DMA for write and select sector counter reg */
433 dma_wd.dma_mode_status = 0x192;
435 /* program for 255*512 bytes and start DMA */
436 DMA_LONG_WRITE( SLM_DMA_AMOUNT, 0x112 );
438 #ifndef SLM_CONT_CNT_REPROG
440 SLMEndAddr = paddr + SLMSliceSize + SLM_DMA_INT_OFFSET;
442 START_TIMER( DMA_STARTUP_TIME + DMA_TIME_FOR( SLMSliceSize ));
443 #if !defined(SLM_CONT_CNT_REPROG) && defined(DEBUG)
444 printk( "SLM: CurAddr=%#lx EndAddr=%#lx timer=%ld\n",
445 SLMCurAddr, SLMEndAddr, DMA_TIME_FOR( SLMSliceSize ) );
452 /* Only called when an error happened or at the end of a page */
454 static irqreturn_t slm_interrupt(int irc, void *data)
456 { unsigned long addr;
460 addr = get_dma_addr();
461 stat = acsi_getstatus();
462 SLMError = (stat < 0) ? SLMSTAT_ACSITO :
463 (addr < virt_to_phys(BufferP)) ? SLMSTAT_NOTALL :
466 dma_wd.dma_mode_status = 0x80;
469 printk( "SLM: interrupt, addr=%#lx, error=%d\n", addr, SLMError );
472 wake_up( &print_wait );
479 static void slm_test_ready( unsigned long dummy )
482 #ifdef SLM_CONT_CNT_REPROG
483 /* program for 255*512 bytes again */
484 dma_wd.fdc_acces_seccount = SLM_DMA_AMOUNT;
485 START_TIMER( DMA_TIME_FOR(0) );
487 printk( "SLM: reprogramming timer for %d jiffies, addr=%#lx\n",
488 DMA_TIME_FOR(0), get_dma_addr() );
491 #else /* !SLM_CONT_CNT_REPROG */
493 unsigned long flags, addr;
496 struct timeval start_tm, end_tm;
500 local_irq_save(flags);
502 addr = get_dma_addr();
503 if ((d = SLMEndAddr - addr) > 0) {
504 local_irq_restore(flags);
506 /* slice not yet finished, decide whether to start another timer or to
508 ti = DMA_TIME_FOR( d );
511 printk( "SLM: reprogramming timer for %d jiffies, rest %d bytes\n",
517 /* wait for desired end address to be reached */
519 do_gettimeofday( &start_tm );
523 while( get_dma_addr() < SLMEndAddr )
527 /* slice finished, start next one */
528 SLMCurAddr += SLMSliceSize;
530 #ifdef SLM_CONTINUOUS_DMA
531 /* program for 255*512 bytes again */
532 dma_wd.fdc_acces_seccount = SLM_DMA_AMOUNT;
535 * add 2 bytes for the ones in the SLM controller FIFO! */
536 set_dma_addr( SLMCurAddr + 2 );
537 /* toggle DMA to write and select sector counter reg */
538 dma_wd.dma_mode_status = 0x92;
540 dma_wd.dma_mode_status = 0x192;
542 /* program for 255*512 bytes and start DMA */
543 DMA_LONG_WRITE( SLM_DMA_AMOUNT, 0x112 );
546 local_irq_restore(flags);
551 do_gettimeofday( &end_tm );
552 ms = (end_tm.tv_sec*1000000+end_tm.tv_usec) -
553 (start_tm.tv_sec*1000000+start_tm.tv_usec);
554 printk( "SLM: did %ld.%ld ms busy waiting for %d bytes\n",
555 ms/1000, ms%1000, d );
558 printk( "SLM: didn't wait (!)\n" );
561 if ((unsigned char *)PTOV( SLMCurAddr + SLMSliceSize ) >= BufferP) {
562 /* will be last slice, no timer necessary */
564 printk( "SLM: CurAddr=%#lx EndAddr=%#lx last slice -> no timer\n",
565 SLMCurAddr, SLMEndAddr );
570 SLMEndAddr = SLMCurAddr + SLMSliceSize + SLM_DMA_INT_OFFSET;
571 START_TIMER( DMA_TIME_FOR( SLMSliceSize ));
573 printk( "SLM: CurAddr=%#lx EndAddr=%#lx timer=%ld\n",
574 SLMCurAddr, SLMEndAddr, DMA_TIME_FOR( SLMSliceSize ) );
577 #endif /* SLM_CONT_CNT_REPROG */
581 static void set_dma_addr( unsigned long paddr )
583 { unsigned long flags;
585 local_irq_save(flags);
586 dma_wd.dma_lo = (unsigned char)paddr;
589 dma_wd.dma_md = (unsigned char)paddr;
592 if (ATARIHW_PRESENT( EXTD_DMA ))
593 st_dma_ext_dmahi = (unsigned short)paddr;
595 dma_wd.dma_hi = (unsigned char)paddr;
597 local_irq_restore(flags);
601 static unsigned long get_dma_addr( void )
603 { unsigned long addr;
605 addr = dma_wd.dma_lo & 0xff;
607 addr |= (dma_wd.dma_md & 0xff) << 8;
609 addr |= (dma_wd.dma_hi & 0xff) << 16;
616 static ssize_t slm_write( struct file *file, const char *buf, size_t count,
620 struct inode *node = file->f_path.dentry->d_inode;
621 int device = iminor(node);
624 while( SLMState == PRINTING ||
625 (SLMState == FILLING && SLMBufOwner != device) ) {
626 interruptible_sleep_on( &slm_wait );
627 if (signal_pending(current))
628 return( -ERESTARTSYS );
630 if (SLMState == IDLE) {
631 /* first data of page: get current page size */
632 if (slm_get_pagesize( device, &w, &h ))
635 if (BufferSize > SLM_BUFFER_SIZE)
639 SLMBufOwner = device;
643 filled = BufferP - SLMBuffer;
644 if (filled + n > BufferSize)
645 n = BufferSize - filled;
647 if (copy_from_user(BufferP, buf, n))
652 if (filled == BufferSize) {
653 /* Check the paper size again! The user may have switched it in the
654 * time between starting the data and finishing them. Would end up in
655 * a trashy page... */
656 if (slm_get_pagesize( device, &w, &h ))
658 if (BufferSize != w*h/8) {
659 printk( KERN_NOTICE "slm%d: page size changed while printing\n",
665 /* choose a slice size that is a multiple of the line size */
666 #ifndef SLM_CONT_CNT_REPROG
667 SLMSliceSize = SLM_SLICE_SIZE(w);
670 start_print( device );
671 sleep_on( &print_wait );
672 if (SLMError && IS_REAL_ERROR(SLMError)) {
673 printk( KERN_ERR "slm%d: %s\n", device, slm_errstr(SLMError) );
679 wake_up_interruptible( &slm_wait );
686 /* ---------------------------------------------------------------------- */
687 /* ioctl Functions */
690 static int slm_ioctl( struct inode *inode, struct file *file,
691 unsigned int cmd, unsigned long arg )
693 { int device = iminor(inode), err;
695 /* I can think of setting:
700 * but haven't implemented that yet :-)
701 * BTW, has anybody better docs about the MODE SENSE/MODE SELECT data?
705 case SLMIORESET: /* reset buffer, i.e. empty the buffer */
706 if (!(file->f_mode & 2))
708 if (SLMState == PRINTING)
712 wake_up_interruptible( &slm_wait );
715 case SLMIOGSTAT: { /* get status */
719 stat = slm_req_sense( device );
721 str = slm_errstr( stat );
723 (long *)&((struct SLM_status *)arg)->stat))
725 if (copy_to_user( ((struct SLM_status *)arg)->str, str,
732 case SLMIOGPSIZE: { /* get paper size */
735 if ((err = slm_get_pagesize( device, &w, &h ))) return( err );
737 if (put_user(w, (long *)&((struct SLM_paper_size *)arg)->width))
739 if (put_user(h, (long *)&((struct SLM_paper_size *)arg)->height))
744 case SLMIOGMFEED: /* get manual feed */
747 case SLMIOSPSIZE: /* set paper size */
750 case SLMIOSMFEED: /* set manual feed */
758 /* ---------------------------------------------------------------------- */
759 /* Opening and Closing */
762 static int slm_open( struct inode *inode, struct file *file )
767 device = iminor(inode);
768 if (device >= N_SLM_Printers)
770 sip = &slm_info[device];
772 if (file->f_mode & 2) {
773 /* open for writing is exclusive */
774 if ( !atomic_dec_and_test(&sip->wr_ok) ) {
775 atomic_inc(&sip->wr_ok);
779 if (file->f_mode & 1) {
780 /* open for reading is exclusive */
781 if ( !atomic_dec_and_test(&sip->rd_ok) ) {
782 atomic_inc(&sip->rd_ok);
791 static int slm_release( struct inode *inode, struct file *file )
796 device = iminor(inode);
797 sip = &slm_info[device];
799 if (file->f_mode & 2)
800 atomic_inc( &sip->wr_ok );
801 if (file->f_mode & 1)
802 atomic_inc( &sip->rd_ok );
808 /* ---------------------------------------------------------------------- */
809 /* ACSI Primitives for the SLM */
812 static int slm_req_sense( int device )
815 struct slm *sip = &slm_info[device];
817 stdma_lock( NULL, NULL );
819 CMDSET_TARG_LUN( slmreqsense_cmd, sip->target, sip->lun );
820 if (!acsicmd_nodma( slmreqsense_cmd, 0 ) ||
821 (stat = acsi_getstatus()) < 0)
832 static int slm_mode_sense( int device, char *buffer, int abs_flag )
834 { unsigned char stat, len;
836 struct slm *sip = &slm_info[device];
838 stdma_lock( NULL, NULL );
840 CMDSET_TARG_LUN( slmmsense_cmd, sip->target, sip->lun );
841 slmmsense_cmd[5] = abs_flag ? 0x80 : 0;
842 if (!acsicmd_nodma( slmmsense_cmd, 0 )) {
847 if (!acsi_extstatus( &stat, 1 )) {
848 acsi_end_extstatus();
853 if (!acsi_extstatus( &len, 1 )) {
854 acsi_end_extstatus();
859 if (!acsi_extstatus( buffer+1, len )) {
860 acsi_end_extstatus();
865 acsi_end_extstatus();
876 /* currently unused */
877 static int slm_mode_select( int device, char *buffer, int len,
881 struct slm *sip = &slm_info[device];
883 stdma_lock( NULL, NULL );
885 CMDSET_TARG_LUN( slmmselect_cmd, sip->target, sip->lun );
886 slmmselect_cmd[5] = default_flag ? 0x80 : 0;
887 if (!acsicmd_nodma( slmmselect_cmd, 0 )) {
893 unsigned char c = len;
894 if (!acsi_extcmd( &c, 1 )) {
898 if (!acsi_extcmd( buffer, len )) {
904 stat = acsi_getstatus();
905 rv = (stat < 0 ? SLMSTAT_ACSITO : stat);
915 static int slm_get_pagesize( int device, int *w, int *h )
920 stat = slm_mode_sense( device, buf, 0 );
924 if (stat != SLMSTAT_OK)
927 *w = (buf[3] << 8) | buf[4];
928 *h = (buf[1] << 8) | buf[2];
933 /* ---------------------------------------------------------------------- */
937 int attach_slm( int target, int lun )
939 { static int did_register;
942 if (N_SLM_Printers >= MAX_SLM) {
943 printk( KERN_WARNING "Too much SLMs\n" );
949 CMDSET_TARG_LUN( slminquiry_cmd, target, lun );
950 if (!acsicmd_nodma( slminquiry_cmd, 0 )) {
952 printk( KERN_ERR "SLM inquiry command timed out.\n" );
954 acsi_end_extstatus();
957 /* read status and header of return data */
958 if (!acsi_extstatus( SLMBuffer, 6 ))
961 if (SLMBuffer[1] != 2) { /* device type == printer? */
962 printk( KERN_ERR "SLM inquiry returned device type != printer\n" );
968 if (!acsi_extstatus( SLMBuffer, len ))
970 acsi_end_extstatus();
977 slm_info[N_SLM_Printers].target = target;
978 slm_info[N_SLM_Printers].lun = lun;
979 atomic_set(&slm_info[N_SLM_Printers].wr_ok, 1 );
980 atomic_set(&slm_info[N_SLM_Printers].rd_ok, 1 );
982 printk( KERN_INFO " Printer: %s\n", SLMBuffer );
983 printk( KERN_INFO "Detected slm%d at id %d lun %d\n",
984 N_SLM_Printers, target, lun );
993 if (register_chrdev( ACSI_MAJOR, "slm", &slm_fops )) {
994 printk( KERN_ERR "Unable to get major %d for ACSI SLM\n", ACSI_MAJOR );
998 if (!(SLMBuffer = atari_stram_alloc( SLM_BUFFER_SIZE, "SLM" ))) {
999 printk( KERN_ERR "Unable to get SLM ST-Ram buffer.\n" );
1000 unregister_chrdev( ACSI_MAJOR, "slm" );
1003 BufferP = SLMBuffer;
1012 void acsi_attach_SLMs( int (*attach_func)( int, int ) );
1014 int init_module(void)
1018 if ((err = slm_init()))
1020 /* This calls attach_slm() for every target/lun where acsi.c detected a
1022 acsi_attach_SLMs( attach_slm );
1026 void cleanup_module(void)
1028 if (unregister_chrdev( ACSI_MAJOR, "slm" ) != 0)
1029 printk( KERN_ERR "acsi_slm: cleanup_module failed\n");
1030 atari_stram_free( SLMBuffer );