OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [block/] [acsi_slm.c] - Blame information for rev 1780

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
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 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
                count = length;
382
                goto out;
383
        }
384
        if (file->f_pos >= length) {
385
                count = 0;
386
                goto out;
387
        }
388
        if (count + file->f_pos > length)
389
                count = length - file->f_pos;
390
        end = count + file->f_pos;
391
        if (copy_to_user(buf, (char *)page + file->f_pos, count)) {
392
                count = -EFAULT;
393
                goto out;
394
        }
395
        file->f_pos = end;
396
out:    free_page( page );
397
        return( count );
398
}
399
 
400
 
401
/* ---------------------------------------------------------------------- */
402
/*                                                                 Printing                                                               */
403
 
404
 
405
static void start_print( int device )
406
 
407
{       struct slm *sip = &slm_info[device];
408
        unsigned char   *cmd;
409
        unsigned long   paddr;
410
        int                             i;
411
 
412
        stdma_lock( slm_interrupt, NULL );
413
 
414
        CMDSET_TARG_LUN( slmprint_cmd, sip->target, sip->lun );
415
        cmd = slmprint_cmd;
416
        paddr = virt_to_phys( SLMBuffer );
417
        dma_cache_maintenance( paddr, virt_to_phys(BufferP)-paddr, 1 );
418
        DISABLE_IRQ();
419
 
420
        /* Low on A1 */
421
        dma_wd.dma_mode_status = 0x88;
422
        MFPDELAY();
423
 
424
        /* send the command bytes except the last */
425
        for( i = 0; i < 5; ++i ) {
426
                DMA_LONG_WRITE( *cmd++, 0x8a );
427
                udelay(20);
428
                if (!acsi_wait_for_IRQ( HZ/2 )) {
429
                        SLMError = 1;
430
                        return; /* timeout */
431
                }
432
        }
433
        /* last command byte */
434
        DMA_LONG_WRITE( *cmd++, 0x82 );
435
        MFPDELAY();
436
        /* set DMA address */
437
        set_dma_addr( paddr );
438
        /* program DMA for write and select sector counter reg */
439
        dma_wd.dma_mode_status = 0x192;
440
        MFPDELAY();
441
        /* program for 255*512 bytes and start DMA */
442
        DMA_LONG_WRITE( SLM_DMA_AMOUNT, 0x112 );
443
 
444
#ifndef SLM_CONT_CNT_REPROG
445
        SLMCurAddr = paddr;
446
        SLMEndAddr = paddr + SLMSliceSize + SLM_DMA_INT_OFFSET;
447
#endif
448
        START_TIMER( DMA_STARTUP_TIME + DMA_TIME_FOR( SLMSliceSize ));
449
#if !defined(SLM_CONT_CNT_REPROG) && defined(DEBUG)
450
        printk( "SLM: CurAddr=%#lx EndAddr=%#lx timer=%ld\n",
451
                        SLMCurAddr, SLMEndAddr, DMA_TIME_FOR( SLMSliceSize ) );
452
#endif
453
 
454
        ENABLE_IRQ();
455
}
456
 
457
 
458
/* Only called when an error happened or at the end of a page */
459
 
460
static void slm_interrupt(int irc, void *data, struct pt_regs *fp)
461
 
462
{       unsigned long   addr;
463
        int                             stat;
464
 
465
        STOP_TIMER();
466
        addr = get_dma_addr();
467
        stat = acsi_getstatus();
468
        SLMError = (stat < 0)             ? SLMSTAT_ACSITO :
469
                       (addr < virt_to_phys(BufferP)) ? SLMSTAT_NOTALL :
470
                                                                            stat;
471
 
472
        dma_wd.dma_mode_status = 0x80;
473
        MFPDELAY();
474
#ifdef DEBUG
475
        printk( "SLM: interrupt, addr=%#lx, error=%d\n", addr, SLMError );
476
#endif
477
 
478
        wake_up( &print_wait );
479
        stdma_release();
480
        ENABLE_IRQ();
481
}
482
 
483
 
484
static void slm_test_ready( unsigned long dummy )
485
 
486
{
487
#ifdef SLM_CONT_CNT_REPROG
488
        /* program for 255*512 bytes again */
489
        dma_wd.fdc_acces_seccount = SLM_DMA_AMOUNT;
490
        START_TIMER( DMA_TIME_FOR(0) );
491
#ifdef DEBUG
492
        printk( "SLM: reprogramming timer for %d jiffies, addr=%#lx\n",
493
                        DMA_TIME_FOR(0), get_dma_addr() );
494
#endif
495
 
496
#else /* !SLM_CONT_CNT_REPROG */
497
 
498
        unsigned long   flags, addr;
499
        int                             d, ti;
500
#ifdef DEBUG
501
        struct timeval start_tm, end_tm;
502
        int                        did_wait = 0;
503
#endif
504
 
505
        save_flags(flags);
506
        cli();
507
 
508
        addr = get_dma_addr();
509
        if ((d = SLMEndAddr - addr) > 0) {
510
                restore_flags(flags);
511
 
512
                /* slice not yet finished, decide whether to start another timer or to
513
                 * busy-wait */
514
                ti = DMA_TIME_FOR( d );
515
                if (ti > 0) {
516
#ifdef DEBUG
517
                        printk( "SLM: reprogramming timer for %d jiffies, rest %d bytes\n",
518
                                        ti, d );
519
#endif
520
                        START_TIMER( ti );
521
                        return;
522
                }
523
                /* wait for desired end address to be reached */
524
#ifdef DEBUG
525
                do_gettimeofday( &start_tm );
526
                did_wait = 1;
527
#endif
528
                cli();
529
                while( get_dma_addr() < SLMEndAddr )
530
                        barrier();
531
        }
532
 
533
        /* slice finished, start next one */
534
        SLMCurAddr += SLMSliceSize;
535
 
536
#ifdef SLM_CONTINUOUS_DMA
537
        /* program for 255*512 bytes again */
538
        dma_wd.fdc_acces_seccount = SLM_DMA_AMOUNT;
539
#else
540
        /* set DMA address;
541
         * add 2 bytes for the ones in the SLM controller FIFO! */
542
        set_dma_addr( SLMCurAddr + 2 );
543
        /* toggle DMA to write and select sector counter reg */
544
        dma_wd.dma_mode_status = 0x92;
545
        MFPDELAY();
546
        dma_wd.dma_mode_status = 0x192;
547
        MFPDELAY();
548
        /* program for 255*512 bytes and start DMA */
549
        DMA_LONG_WRITE( SLM_DMA_AMOUNT, 0x112 );
550
#endif
551
 
552
        restore_flags(flags);
553
 
554
#ifdef DEBUG
555
        if (did_wait) {
556
                int ms;
557
                do_gettimeofday( &end_tm );
558
                ms = (end_tm.tv_sec*1000000+end_tm.tv_usec) -
559
                         (start_tm.tv_sec*1000000+start_tm.tv_usec);
560
                printk( "SLM: did %ld.%ld ms busy waiting for %d bytes\n",
561
                                ms/1000, ms%1000, d );
562
        }
563
        else
564
                printk( "SLM: didn't wait (!)\n" );
565
#endif
566
 
567
        if ((unsigned char *)PTOV( SLMCurAddr + SLMSliceSize ) >= BufferP) {
568
                /* will be last slice, no timer necessary */
569
#ifdef DEBUG
570
                printk( "SLM: CurAddr=%#lx EndAddr=%#lx last slice -> no timer\n",
571
                                SLMCurAddr, SLMEndAddr );
572
#endif
573
        }
574
        else {
575
                /* not last slice */
576
                SLMEndAddr = SLMCurAddr + SLMSliceSize + SLM_DMA_INT_OFFSET;
577
                START_TIMER( DMA_TIME_FOR( SLMSliceSize ));
578
#ifdef DEBUG
579
                printk( "SLM: CurAddr=%#lx EndAddr=%#lx timer=%ld\n",
580
                                SLMCurAddr, SLMEndAddr, DMA_TIME_FOR( SLMSliceSize ) );
581
#endif
582
        }
583
#endif /* SLM_CONT_CNT_REPROG */
584
}
585
 
586
 
587
static void set_dma_addr( unsigned long paddr )
588
 
589
{       unsigned long   flags;
590
 
591
        save_flags(flags);
592
        cli();
593
        dma_wd.dma_lo = (unsigned char)paddr;
594
        paddr >>= 8;
595
        MFPDELAY();
596
        dma_wd.dma_md = (unsigned char)paddr;
597
        paddr >>= 8;
598
        MFPDELAY();
599
        if (ATARIHW_PRESENT( EXTD_DMA ))
600
                st_dma_ext_dmahi = (unsigned short)paddr;
601
        else
602
                dma_wd.dma_hi = (unsigned char)paddr;
603
        MFPDELAY();
604
        restore_flags(flags);
605
}
606
 
607
 
608
static unsigned long get_dma_addr( void )
609
 
610
{       unsigned long   addr;
611
 
612
        addr = dma_wd.dma_lo & 0xff;
613
        MFPDELAY();
614
        addr |= (dma_wd.dma_md & 0xff) << 8;
615
        MFPDELAY();
616
        addr |= (dma_wd.dma_hi & 0xff) << 16;
617
        MFPDELAY();
618
 
619
        return( addr );
620
}
621
 
622
 
623
static ssize_t slm_write( struct file *file, const char *buf, size_t count,
624
                                                  loff_t *ppos )
625
 
626
{
627
        struct inode *node = file->f_dentry->d_inode;
628
        int             device = MINOR( node->i_rdev );
629
        int             n, filled, w, h;
630
 
631
        while( SLMState == PRINTING ||
632
                   (SLMState == FILLING && SLMBufOwner != device) ) {
633
                interruptible_sleep_on( &slm_wait );
634
                if (signal_pending(current))
635
                        return( -ERESTARTSYS );
636
        }
637
        if (SLMState == IDLE) {
638
                /* first data of page: get current page size  */
639
                if (slm_get_pagesize( device, &w, &h ))
640
                        return( -EIO );
641
                BufferSize = w*h/8;
642
                if (BufferSize > SLM_BUFFER_SIZE)
643
                        return( -ENOMEM );
644
 
645
                SLMState = FILLING;
646
                SLMBufOwner = device;
647
        }
648
 
649
        n = count;
650
        filled = BufferP - SLMBuffer;
651
        if (filled + n > BufferSize)
652
                n = BufferSize - filled;
653
 
654
        if (copy_from_user(BufferP, buf, n))
655
                return -EFAULT;
656
        BufferP += n;
657
        filled += n;
658
 
659
        if (filled == BufferSize) {
660
                /* Check the paper size again! The user may have switched it in the
661
                 * time between starting the data and finishing them. Would end up in
662
                 * a trashy page... */
663
                if (slm_get_pagesize( device, &w, &h ))
664
                        return( -EIO );
665
                if (BufferSize != w*h/8) {
666
                        printk( KERN_NOTICE "slm%d: page size changed while printing\n",
667
                                        device );
668
                        return( -EAGAIN );
669
                }
670
 
671
                SLMState = PRINTING;
672
                /* choose a slice size that is a multiple of the line size */
673
#ifndef SLM_CONT_CNT_REPROG
674
                SLMSliceSize = SLM_SLICE_SIZE(w);
675
#endif
676
 
677
                start_print( device );
678
                sleep_on( &print_wait );
679
                if (SLMError && IS_REAL_ERROR(SLMError)) {
680
                        printk( KERN_ERR "slm%d: %s\n", device, slm_errstr(SLMError) );
681
                        n = -EIO;
682
                }
683
 
684
                SLMState = IDLE;
685
                BufferP = SLMBuffer;
686
                wake_up_interruptible( &slm_wait );
687
        }
688
 
689
        return( n );
690
}
691
 
692
 
693
/* ---------------------------------------------------------------------- */
694
/*                                                         ioctl Functions                                                        */
695
 
696
 
697
static int slm_ioctl( struct inode *inode, struct file *file,
698
                                          unsigned int cmd, unsigned long arg )
699
 
700
{       int             device = MINOR( inode->i_rdev ), err;
701
 
702
        /* I can think of setting:
703
         *  - manual feed
704
         *  - paper format
705
         *  - copy count
706
         *  - ...
707
         * but haven't implemented that yet :-)
708
         * BTW, has anybody better docs about the MODE SENSE/MODE SELECT data?
709
         */
710
        switch( cmd ) {
711
 
712
          case SLMIORESET:              /* reset buffer, i.e. empty the buffer */
713
                if (!(file->f_mode & 2))
714
                        return( -EINVAL );
715
                if (SLMState == PRINTING)
716
                        return( -EBUSY );
717
                SLMState = IDLE;
718
                BufferP = SLMBuffer;
719
                wake_up_interruptible( &slm_wait );
720
                return( 0 );
721
 
722
          case SLMIOGSTAT: {    /* get status */
723
                int stat;
724
                char *str;
725
 
726
                stat = slm_req_sense( device );
727
                if (arg) {
728
                        str = slm_errstr( stat );
729
                        if (put_user(stat,
730
                                     (long *)&((struct SLM_status *)arg)->stat))
731
                                return -EFAULT;
732
                        if (copy_to_user( ((struct SLM_status *)arg)->str, str,
733
                                                 strlen(str) + 1))
734
                                return -EFAULT;
735
                }
736
                return( stat );
737
          }
738
 
739
          case SLMIOGPSIZE: {   /* get paper size */
740
                int w, h;
741
 
742
                if ((err = slm_get_pagesize( device, &w, &h ))) return( err );
743
 
744
                if (put_user(w, (long *)&((struct SLM_paper_size *)arg)->width))
745
                        return -EFAULT;
746
                if (put_user(h, (long *)&((struct SLM_paper_size *)arg)->height))
747
                        return -EFAULT;
748
                return( 0 );
749
          }
750
 
751
          case SLMIOGMFEED:     /* get manual feed */
752
                return( -EINVAL );
753
 
754
          case SLMIOSPSIZE:     /* set paper size */
755
                return( -EINVAL );
756
 
757
          case SLMIOSMFEED:     /* set manual feed */
758
                return( -EINVAL );
759
 
760
        }
761
        return( -EINVAL );
762
}
763
 
764
 
765
/* ---------------------------------------------------------------------- */
766
/*                                                       Opening and Closing                                              */
767
 
768
 
769
static int slm_open( struct inode *inode, struct file *file )
770
 
771
{       int device;
772
        struct slm *sip;
773
 
774
        device = MINOR(inode->i_rdev);
775
        if (device >= N_SLM_Printers)
776
                return( -ENXIO );
777
        sip = &slm_info[device];
778
 
779
        if (file->f_mode & 2) {
780
                /* open for writing is exclusive */
781
                if (sip->wbusy)
782
                        return( -EBUSY );
783
                sip->wbusy = 1;
784
        }
785
        if (file->f_mode & 1) {
786
                /* open for writing is exclusive */
787
                if (sip->rbusy)
788
                        return( -EBUSY );
789
                sip->rbusy = 1;
790
        }
791
 
792
        return( 0 );
793
}
794
 
795
 
796
static int slm_release( struct inode *inode, struct file *file )
797
 
798
{       int device;
799
        struct slm *sip;
800
 
801
        device = MINOR(inode->i_rdev);
802
        sip = &slm_info[device];
803
 
804
        lock_kernel();
805
        if (file->f_mode & 2)
806
                sip->wbusy = 0;
807
        if (file->f_mode & 1)
808
                sip->rbusy = 0;
809
        unlock_kernel();
810
 
811
        return( 0 );
812
}
813
 
814
 
815
/* ---------------------------------------------------------------------- */
816
/*                                               ACSI Primitives for the SLM                                      */
817
 
818
 
819
static int slm_req_sense( int device )
820
 
821
{       int                     stat, rv;
822
        struct slm *sip = &slm_info[device];
823
 
824
        stdma_lock( NULL, NULL );
825
 
826
        CMDSET_TARG_LUN( slmreqsense_cmd, sip->target, sip->lun );
827
        if (!acsicmd_nodma( slmreqsense_cmd, 0 ) ||
828
                (stat = acsi_getstatus()) < 0)
829
                rv = SLMSTAT_ACSITO;
830
        else
831
                rv = stat & 0x1f;
832
 
833
        ENABLE_IRQ();
834
        stdma_release();
835
        return( rv );
836
}
837
 
838
 
839
static int slm_mode_sense( int device, char *buffer, int abs_flag )
840
 
841
{       unsigned char   stat, len;
842
        int                             rv = 0;
843
        struct slm              *sip = &slm_info[device];
844
 
845
        stdma_lock( NULL, NULL );
846
 
847
        CMDSET_TARG_LUN( slmmsense_cmd, sip->target, sip->lun );
848
        slmmsense_cmd[5] = abs_flag ? 0x80 : 0;
849
        if (!acsicmd_nodma( slmmsense_cmd, 0 )) {
850
                rv = SLMSTAT_ACSITO;
851
                goto the_end;
852
        }
853
 
854
        if (!acsi_extstatus( &stat, 1 )) {
855
                acsi_end_extstatus();
856
                rv = SLMSTAT_ACSITO;
857
                goto the_end;
858
        }
859
 
860
        if (!acsi_extstatus( &len, 1 )) {
861
                acsi_end_extstatus();
862
                rv = SLMSTAT_ACSITO;
863
                goto the_end;
864
        }
865
        buffer[0] = len;
866
        if (!acsi_extstatus( buffer+1, len )) {
867
                acsi_end_extstatus();
868
                rv = SLMSTAT_ACSITO;
869
                goto the_end;
870
        }
871
 
872
        acsi_end_extstatus();
873
        rv = stat & 0x1f;
874
 
875
  the_end:
876
        ENABLE_IRQ();
877
        stdma_release();
878
        return( rv );
879
}
880
 
881
 
882
#if 0
883
/* currently unused */
884
static int slm_mode_select( int device, char *buffer, int len,
885
                                                        int default_flag )
886
 
887
{       int                     stat, rv;
888
        struct slm      *sip = &slm_info[device];
889
 
890
        stdma_lock( NULL, NULL );
891
 
892
        CMDSET_TARG_LUN( slmmselect_cmd, sip->target, sip->lun );
893
        slmmselect_cmd[5] = default_flag ? 0x80 : 0;
894
        if (!acsicmd_nodma( slmmselect_cmd, 0 )) {
895
                rv = SLMSTAT_ACSITO;
896
                goto the_end;
897
        }
898
 
899
        if (!default_flag) {
900
                unsigned char c = len;
901
                if (!acsi_extcmd( &c, 1 )) {
902
                        rv = SLMSTAT_ACSITO;
903
                        goto the_end;
904
                }
905
                if (!acsi_extcmd( buffer, len )) {
906
                        rv = SLMSTAT_ACSITO;
907
                        goto the_end;
908
                }
909
        }
910
 
911
        stat = acsi_getstatus();
912
        rv = (stat < 0 ? SLMSTAT_ACSITO : stat);
913
 
914
  the_end:
915
        ENABLE_IRQ();
916
        stdma_release();
917
        return( rv );
918
}
919
#endif
920
 
921
 
922
static int slm_get_pagesize( int device, int *w, int *h )
923
 
924
{       char    buf[256];
925
        int             stat;
926
 
927
        stat = slm_mode_sense( device, buf, 0 );
928
        ENABLE_IRQ();
929
        stdma_release();
930
 
931
        if (stat != SLMSTAT_OK)
932
                return( -EIO );
933
 
934
        *w = (buf[3] << 8) | buf[4];
935
        *h = (buf[1] << 8) | buf[2];
936
        return( 0 );
937
}
938
 
939
 
940
/* ---------------------------------------------------------------------- */
941
/*                                                              Initialization                                                    */
942
 
943
 
944
int attach_slm( int target, int lun )
945
 
946
{       static int      did_register;
947
        int                     len;
948
 
949
        if (N_SLM_Printers >= MAX_SLM) {
950
                printk( KERN_WARNING "Too much SLMs\n" );
951
                return( 0 );
952
        }
953
 
954
        /* do an INQUIRY */
955
        udelay(100);
956
        CMDSET_TARG_LUN( slminquiry_cmd, target, lun );
957
        if (!acsicmd_nodma( slminquiry_cmd, 0 )) {
958
          inq_timeout:
959
                printk( KERN_ERR "SLM inquiry command timed out.\n" );
960
          inq_fail:
961
                acsi_end_extstatus();
962
                return( 0 );
963
        }
964
        /* read status and header of return data */
965
        if (!acsi_extstatus( SLMBuffer, 6 ))
966
                goto inq_timeout;
967
 
968
        if (SLMBuffer[1] != 2) { /* device type == printer? */
969
                printk( KERN_ERR "SLM inquiry returned device type != printer\n" );
970
                goto inq_fail;
971
        }
972
        len = SLMBuffer[5];
973
 
974
        /* read id string */
975
        if (!acsi_extstatus( SLMBuffer, len ))
976
                goto inq_timeout;
977
        acsi_end_extstatus();
978
        SLMBuffer[len] = 0;
979
 
980
        if (!did_register) {
981
                did_register = 1;
982
        }
983
 
984
        slm_info[N_SLM_Printers].target = target;
985
        slm_info[N_SLM_Printers].lun    = lun;
986
        slm_info[N_SLM_Printers].wbusy  = 0;
987
        slm_info[N_SLM_Printers].rbusy  = 0;
988
 
989
        printk( KERN_INFO "  Printer: %s\n", SLMBuffer );
990
        printk( KERN_INFO "Detected slm%d at id %d lun %d\n",
991
                        N_SLM_Printers, target, lun );
992
        N_SLM_Printers++;
993
        return( 1 );
994
}
995
 
996
static devfs_handle_t devfs_handle;
997
 
998
int slm_init( void )
999
 
1000
{
1001
        if (devfs_register_chrdev( MAJOR_NR, "slm", &slm_fops )) {
1002
                printk( KERN_ERR "Unable to get major %d for ACSI SLM\n", MAJOR_NR );
1003
                return -EBUSY;
1004
        }
1005
 
1006
        if (!(SLMBuffer = atari_stram_alloc( SLM_BUFFER_SIZE, "SLM" ))) {
1007
                printk( KERN_ERR "Unable to get SLM ST-Ram buffer.\n" );
1008
                devfs_unregister_chrdev( MAJOR_NR, "slm" );
1009
                return -ENOMEM;
1010
        }
1011
        BufferP = SLMBuffer;
1012
        SLMState = IDLE;
1013
 
1014
        devfs_handle = devfs_mk_dir (NULL, "slm", NULL);
1015
        devfs_register_series (devfs_handle, "%u", MAX_SLM, DEVFS_FL_DEFAULT,
1016
                               MAJOR_NR, 0, S_IFCHR | S_IRUSR | S_IWUSR,
1017
                               &slm_fops, NULL);
1018
        return 0;
1019
}
1020
 
1021
#ifdef MODULE
1022
 
1023
/* from acsi.c */
1024
void acsi_attach_SLMs( int (*attach_func)( int, int ) );
1025
 
1026
int init_module(void)
1027
{
1028
        int err;
1029
 
1030
        if ((err = slm_init()))
1031
                return( err );
1032
        /* This calls attach_slm() for every target/lun where acsi.c detected a
1033
         * printer */
1034
        acsi_attach_SLMs( attach_slm );
1035
        return( 0 );
1036
}
1037
 
1038
void cleanup_module(void)
1039
{
1040
        devfs_unregister (devfs_handle);
1041
        if (devfs_unregister_chrdev( MAJOR_NR, "slm" ) != 0)
1042
                printk( KERN_ERR "acsi_slm: cleanup_module failed\n");
1043
        atari_stram_free( SLMBuffer );
1044
}
1045
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.