blob: 4cb9c13362874cedbed44c24a2982046d1e74e4c [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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
14Notes:
15
16The major number for SLM printers is 28 (like ACSI), but as a character
17device, not block device. The minor number is the number of the printer (if
18you have more than one SLM; currently max. 2 (#define-constant) SLMs are
19supported). The device can be opened for reading and writing. If reading it,
20you get some status infos (MODE SENSE data). Writing mode is used for the data
21to be printed. Some ioctls allow to get the printer status and to tune printer
22modes and some internal variables.
23
24A special problem of the SLM driver is the timing and thus the buffering of
25the print data. The problem is that all the data for one page must be present
26in memory when printing starts, else --when swapping occurs-- the timing could
27not 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
108static char slmreqsense_cmd[6] = { 0x03, 0, 0, 0, 0, 0 };
109static char slmprint_cmd[6] = { 0x0a, 0, 0, 0, 0, 0 };
110static char slminquiry_cmd[6] = { 0x12, 0, 0, 0, 0, 0x80 };
111static char slmmsense_cmd[6] = { 0x1a, 0, 0, 0, 255, 0 };
112#if 0
113static char slmmselect_cmd[6] = { 0x15, 0, 0, 0, 0, 0 };
114#endif
115
116
117#define MAX_SLM 2
118
119static 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
126int N_SLM_Printers = 0;
127
128/* printer buffer */
129static unsigned char *SLMBuffer; /* start of buffer */
130static unsigned char *BufferP; /* current position in buffer */
131static int BufferSize; /* length of buffer for page size */
132
133typedef enum { IDLE, FILLING, PRINTING } SLMSTATE;
134static SLMSTATE SLMState;
135static int SLMBufOwner; /* SLM# currently using the buffer */
136
137/* DMA variables */
138#ifndef SLM_CONT_CNT_REPROG
139static unsigned long SLMCurAddr; /* current base addr of DMA chunk */
140static unsigned long SLMEndAddr; /* expected end addr */
141static unsigned long SLMSliceSize; /* size of one DMA chunk */
142#endif
143static int SLMError;
144
145/* wait queues */
146static DECLARE_WAIT_QUEUE_HEAD(slm_wait); /* waiting for buffer */
147static 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
171static 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
209static 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
245static char *slm_errstr( int stat );
246static int slm_getstats( char *buffer, int device );
247static ssize_t slm_read( struct file* file, char *buf, size_t count, loff_t
248 *ppos );
249static void start_print( int device );
250static irqreturn_t slm_interrupt(int irc, void *data, struct pt_regs *fp);
251static void slm_test_ready( unsigned long dummy );
252static void set_dma_addr( unsigned long paddr );
253static unsigned long get_dma_addr( void );
254static ssize_t slm_write( struct file *file, const char *buf, size_t count,
255 loff_t *ppos );
256static int slm_ioctl( struct inode *inode, struct file *file, unsigned int
257 cmd, unsigned long arg );
258static int slm_open( struct inode *inode, struct file *file );
259static int slm_release( struct inode *inode, struct file *file );
260static int slm_req_sense( int device );
261static int slm_mode_sense( int device, char *buffer, int abs_flag );
262#if 0
263static int slm_mode_select( int device, char *buffer, int len, int
264 default_flag );
265#endif
266static int slm_get_pagesize( int device, int *w, int *h );
267
268/************************* End of Prototypes **************************/
269
270
Ingo Molnar8d06afa2005-09-09 13:10:40 -0700271static DEFINE_TIMER(slm_timer, slm_test_ready, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272
273static 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
287static 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
300static 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
363static 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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 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;
392out: free_page( page );
393 return( count );
394}
395
396
397/* ---------------------------------------------------------------------- */
398/* Printing */
399
400
401static 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
456static 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
481static 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
583static 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
603static 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
618static 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
692static 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
764static 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
793static 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
814static 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
834static 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 */
879static 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
917static 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
939int 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
991int 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 */
1019void acsi_attach_SLMs( int (*attach_func)( int, int ) );
1020
1021int 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
1033void 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