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