Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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