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 v2.6.20-rc7 1033 lines 26 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/smp_lock.h> 69 70#include <asm/pgtable.h> 71#include <asm/system.h> 72#include <asm/uaccess.h> 73#include <asm/atarihw.h> 74#include <asm/atariints.h> 75#include <asm/atari_acsi.h> 76#include <asm/atari_stdma.h> 77#include <asm/atari_stram.h> 78#include <asm/atari_SLM.h> 79 80 81#undef DEBUG 82 83/* Define this if the page data are continuous in physical memory. That 84 * requires less reprogramming of the ST-DMA */ 85#define SLM_CONTINUOUS_DMA 86 87/* Use continuous reprogramming of the ST-DMA counter register. This is 88 * --strictly speaking-- not allowed, Atari recommends not to look at the 89 * counter register while a DMA is going on. But I don't know if that applies 90 * only for reading the register, or also writing to it. Writing only works 91 * fine for me... The advantage is that the timing becomes absolutely 92 * uncritical: Just update each, say 200ms, the counter reg to its maximum, 93 * and the DMA will work until the status byte interrupt occurs. 94 */ 95#define SLM_CONT_CNT_REPROG 96 97#define CMDSET_TARG_LUN(cmd,targ,lun) \ 98 do { \ 99 cmd[0] = (cmd[0] & ~0xe0) | (targ)<<5; \ 100 cmd[1] = (cmd[1] & ~0xe0) | (lun)<<5; \ 101 } while(0) 102 103#define START_TIMER(to) mod_timer(&slm_timer, jiffies + (to)) 104#define STOP_TIMER() del_timer(&slm_timer) 105 106 107static char slmreqsense_cmd[6] = { 0x03, 0, 0, 0, 0, 0 }; 108static char slmprint_cmd[6] = { 0x0a, 0, 0, 0, 0, 0 }; 109static char slminquiry_cmd[6] = { 0x12, 0, 0, 0, 0, 0x80 }; 110static char slmmsense_cmd[6] = { 0x1a, 0, 0, 0, 255, 0 }; 111#if 0 112static char slmmselect_cmd[6] = { 0x15, 0, 0, 0, 0, 0 }; 113#endif 114 115 116#define MAX_SLM 2 117 118static struct slm { 119 unsigned target; /* target number */ 120 unsigned lun; /* LUN in target controller */ 121 atomic_t wr_ok; /* set to 0 if output part busy */ 122 atomic_t rd_ok; /* set to 0 if status part busy */ 123} slm_info[MAX_SLM]; 124 125int N_SLM_Printers = 0; 126 127/* printer buffer */ 128static unsigned char *SLMBuffer; /* start of buffer */ 129static unsigned char *BufferP; /* current position in buffer */ 130static int BufferSize; /* length of buffer for page size */ 131 132typedef enum { IDLE, FILLING, PRINTING } SLMSTATE; 133static SLMSTATE SLMState; 134static int SLMBufOwner; /* SLM# currently using the buffer */ 135 136/* DMA variables */ 137#ifndef SLM_CONT_CNT_REPROG 138static unsigned long SLMCurAddr; /* current base addr of DMA chunk */ 139static unsigned long SLMEndAddr; /* expected end addr */ 140static unsigned long SLMSliceSize; /* size of one DMA chunk */ 141#endif 142static int SLMError; 143 144/* wait queues */ 145static DECLARE_WAIT_QUEUE_HEAD(slm_wait); /* waiting for buffer */ 146static DECLARE_WAIT_QUEUE_HEAD(print_wait); /* waiting for printing finished */ 147 148/* status codes */ 149#define SLMSTAT_OK 0x00 150#define SLMSTAT_ORNERY 0x02 151#define SLMSTAT_TONER 0x03 152#define SLMSTAT_WARMUP 0x04 153#define SLMSTAT_PAPER 0x05 154#define SLMSTAT_DRUM 0x06 155#define SLMSTAT_INJAM 0x07 156#define SLMSTAT_THRJAM 0x08 157#define SLMSTAT_OUTJAM 0x09 158#define SLMSTAT_COVER 0x0a 159#define SLMSTAT_FUSER 0x0b 160#define SLMSTAT_IMAGER 0x0c 161#define SLMSTAT_MOTOR 0x0d 162#define SLMSTAT_VIDEO 0x0e 163#define SLMSTAT_SYSTO 0x10 164#define SLMSTAT_OPCODE 0x12 165#define SLMSTAT_DEVNUM 0x15 166#define SLMSTAT_PARAM 0x1a 167#define SLMSTAT_ACSITO 0x1b /* driver defined */ 168#define SLMSTAT_NOTALL 0x1c /* driver defined */ 169 170static char *SLMErrors[] = { 171 /* 0x00 */ "OK and ready", 172 /* 0x01 */ NULL, 173 /* 0x02 */ "ornery printer", 174 /* 0x03 */ "toner empty", 175 /* 0x04 */ "warming up", 176 /* 0x05 */ "paper empty", 177 /* 0x06 */ "drum empty", 178 /* 0x07 */ "input jam", 179 /* 0x08 */ "through jam", 180 /* 0x09 */ "output jam", 181 /* 0x0a */ "cover open", 182 /* 0x0b */ "fuser malfunction", 183 /* 0x0c */ "imager malfunction", 184 /* 0x0d */ "motor malfunction", 185 /* 0x0e */ "video malfunction", 186 /* 0x0f */ NULL, 187 /* 0x10 */ "printer system timeout", 188 /* 0x11 */ NULL, 189 /* 0x12 */ "invalid operation code", 190 /* 0x13 */ NULL, 191 /* 0x14 */ NULL, 192 /* 0x15 */ "invalid device number", 193 /* 0x16 */ NULL, 194 /* 0x17 */ NULL, 195 /* 0x18 */ NULL, 196 /* 0x19 */ NULL, 197 /* 0x1a */ "invalid parameter list", 198 /* 0x1b */ "ACSI timeout", 199 /* 0x1c */ "not all printed" 200}; 201 202#define N_ERRORS (sizeof(SLMErrors)/sizeof(*SLMErrors)) 203 204/* real (driver caused) error? */ 205#define IS_REAL_ERROR(x) (x > 0x10) 206 207 208static struct { 209 char *name; 210 int w, h; 211} StdPageSize[] = { 212 { "Letter", 2400, 3180 }, 213 { "Legal", 2400, 4080 }, 214 { "A4", 2336, 3386 }, 215 { "B5", 2016, 2914 } 216}; 217 218#define N_STD_SIZES (sizeof(StdPageSize)/sizeof(*StdPageSize)) 219 220#define SLM_BUFFER_SIZE (2336*3386/8) /* A4 for now */ 221#define SLM_DMA_AMOUNT 255 /* #sectors to program the DMA for */ 222 223#ifdef SLM_CONTINUOUS_DMA 224# define SLM_DMA_INT_OFFSET 0 /* DMA goes until seccnt 0, no offs */ 225# define SLM_DMA_END_OFFSET 32 /* 32 Byte ST-DMA FIFO */ 226# define SLM_SLICE_SIZE(w) (255*512) 227#else 228# define SLM_DMA_INT_OFFSET 32 /* 32 Byte ST-DMA FIFO */ 229# define SLM_DMA_END_OFFSET 32 /* 32 Byte ST-DMA FIFO */ 230# define SLM_SLICE_SIZE(w) ((254*512)/(w/8)*(w/8)) 231#endif 232 233/* calculate the number of jiffies to wait for 'n' bytes */ 234#ifdef SLM_CONT_CNT_REPROG 235#define DMA_TIME_FOR(n) 50 236#define DMA_STARTUP_TIME 0 237#else 238#define DMA_TIME_FOR(n) (n/1400-1) 239#define DMA_STARTUP_TIME 650 240#endif 241 242/***************************** Prototypes *****************************/ 243 244static char *slm_errstr( int stat ); 245static int slm_getstats( char *buffer, int device ); 246static ssize_t slm_read( struct file* file, char *buf, size_t count, loff_t 247 *ppos ); 248static void start_print( int device ); 249static irqreturn_t slm_interrupt(int irc, void *data); 250static void slm_test_ready( unsigned long dummy ); 251static void set_dma_addr( unsigned long paddr ); 252static unsigned long get_dma_addr( void ); 253static ssize_t slm_write( struct file *file, const char *buf, size_t count, 254 loff_t *ppos ); 255static int slm_ioctl( struct inode *inode, struct file *file, unsigned int 256 cmd, unsigned long arg ); 257static int slm_open( struct inode *inode, struct file *file ); 258static int slm_release( struct inode *inode, struct file *file ); 259static int slm_req_sense( int device ); 260static int slm_mode_sense( int device, char *buffer, int abs_flag ); 261#if 0 262static int slm_mode_select( int device, char *buffer, int len, int 263 default_flag ); 264#endif 265static int slm_get_pagesize( int device, int *w, int *h ); 266 267/************************* End of Prototypes **************************/ 268 269 270static DEFINE_TIMER(slm_timer, slm_test_ready, 0, 0); 271 272static struct file_operations slm_fops = { 273 .owner = THIS_MODULE, 274 .read = slm_read, 275 .write = slm_write, 276 .ioctl = slm_ioctl, 277 .open = slm_open, 278 .release = slm_release, 279}; 280 281 282/* ---------------------------------------------------------------------- */ 283/* Status Functions */ 284 285 286static char *slm_errstr( int stat ) 287 288{ char *p; 289 static char str[22]; 290 291 stat &= 0x1f; 292 if (stat >= 0 && stat < N_ERRORS && (p = SLMErrors[stat])) 293 return( p ); 294 sprintf( str, "unknown status 0x%02x", stat ); 295 return( str ); 296} 297 298 299static int slm_getstats( char *buffer, int device ) 300 301{ int len = 0, stat, i, w, h; 302 unsigned char buf[256]; 303 304 stat = slm_mode_sense( device, buf, 0 ); 305 if (IS_REAL_ERROR(stat)) 306 return( -EIO ); 307 308#define SHORTDATA(i) ((buf[i] << 8) | buf[i+1]) 309#define BOOLDATA(i,mask) ((buf[i] & mask) ? "on" : "off") 310 311 w = SHORTDATA( 3 ); 312 h = SHORTDATA( 1 ); 313 314 len += sprintf( buffer+len, "Status\t\t%s\n", 315 slm_errstr( stat ) ); 316 len += sprintf( buffer+len, "Page Size\t%dx%d", 317 w, h ); 318 319 for( i = 0; i < N_STD_SIZES; ++i ) { 320 if (w == StdPageSize[i].w && h == StdPageSize[i].h) 321 break; 322 } 323 if (i < N_STD_SIZES) 324 len += sprintf( buffer+len, " (%s)", StdPageSize[i].name ); 325 buffer[len++] = '\n'; 326 327 len += sprintf( buffer+len, "Top/Left Margin\t%d/%d\n", 328 SHORTDATA( 5 ), SHORTDATA( 7 ) ); 329 len += sprintf( buffer+len, "Manual Feed\t%s\n", 330 BOOLDATA( 9, 0x01 ) ); 331 len += sprintf( buffer+len, "Input Select\t%d\n", 332 (buf[9] >> 1) & 7 ); 333 len += sprintf( buffer+len, "Auto Select\t%s\n", 334 BOOLDATA( 9, 0x10 ) ); 335 len += sprintf( buffer+len, "Prefeed Paper\t%s\n", 336 BOOLDATA( 9, 0x20 ) ); 337 len += sprintf( buffer+len, "Thick Pixels\t%s\n", 338 BOOLDATA( 9, 0x40 ) ); 339 len += sprintf( buffer+len, "H/V Resol.\t%d/%d dpi\n", 340 SHORTDATA( 12 ), SHORTDATA( 10 ) ); 341 len += sprintf( buffer+len, "System Timeout\t%d\n", 342 buf[14] ); 343 len += sprintf( buffer+len, "Scan Time\t%d\n", 344 SHORTDATA( 15 ) ); 345 len += sprintf( buffer+len, "Page Count\t%d\n", 346 SHORTDATA( 17 ) ); 347 len += sprintf( buffer+len, "In/Out Cap.\t%d/%d\n", 348 SHORTDATA( 19 ), SHORTDATA( 21 ) ); 349 len += sprintf( buffer+len, "Stagger Output\t%s\n", 350 BOOLDATA( 23, 0x01 ) ); 351 len += sprintf( buffer+len, "Output Select\t%d\n", 352 (buf[23] >> 1) & 7 ); 353 len += sprintf( buffer+len, "Duplex Print\t%s\n", 354 BOOLDATA( 23, 0x10 ) ); 355 len += sprintf( buffer+len, "Color Sep.\t%s\n", 356 BOOLDATA( 23, 0x20 ) ); 357 358 return( len ); 359} 360 361 362static ssize_t slm_read( struct file *file, char *buf, size_t count, 363 loff_t *ppos ) 364 365{ 366 struct inode *node = file->f_path.dentry->d_inode; 367 unsigned long page; 368 int length; 369 int end; 370 371 if (!(page = __get_free_page( GFP_KERNEL ))) 372 return( -ENOMEM ); 373 374 length = slm_getstats( (char *)page, iminor(node) ); 375 if (length < 0) { 376 count = length; 377 goto out; 378 } 379 if (file->f_pos >= length) { 380 count = 0; 381 goto out; 382 } 383 if (count + file->f_pos > length) 384 count = length - file->f_pos; 385 end = count + file->f_pos; 386 if (copy_to_user(buf, (char *)page + file->f_pos, count)) { 387 count = -EFAULT; 388 goto out; 389 } 390 file->f_pos = end; 391out: free_page( page ); 392 return( count ); 393} 394 395 396/* ---------------------------------------------------------------------- */ 397/* Printing */ 398 399 400static void start_print( int device ) 401 402{ struct slm *sip = &slm_info[device]; 403 unsigned char *cmd; 404 unsigned long paddr; 405 int i; 406 407 stdma_lock( slm_interrupt, NULL ); 408 409 CMDSET_TARG_LUN( slmprint_cmd, sip->target, sip->lun ); 410 cmd = slmprint_cmd; 411 paddr = virt_to_phys( SLMBuffer ); 412 dma_cache_maintenance( paddr, virt_to_phys(BufferP)-paddr, 1 ); 413 DISABLE_IRQ(); 414 415 /* Low on A1 */ 416 dma_wd.dma_mode_status = 0x88; 417 MFPDELAY(); 418 419 /* send the command bytes except the last */ 420 for( i = 0; i < 5; ++i ) { 421 DMA_LONG_WRITE( *cmd++, 0x8a ); 422 udelay(20); 423 if (!acsi_wait_for_IRQ( HZ/2 )) { 424 SLMError = 1; 425 return; /* timeout */ 426 } 427 } 428 /* last command byte */ 429 DMA_LONG_WRITE( *cmd++, 0x82 ); 430 MFPDELAY(); 431 /* set DMA address */ 432 set_dma_addr( paddr ); 433 /* program DMA for write and select sector counter reg */ 434 dma_wd.dma_mode_status = 0x192; 435 MFPDELAY(); 436 /* program for 255*512 bytes and start DMA */ 437 DMA_LONG_WRITE( SLM_DMA_AMOUNT, 0x112 ); 438 439#ifndef SLM_CONT_CNT_REPROG 440 SLMCurAddr = paddr; 441 SLMEndAddr = paddr + SLMSliceSize + SLM_DMA_INT_OFFSET; 442#endif 443 START_TIMER( DMA_STARTUP_TIME + DMA_TIME_FOR( SLMSliceSize )); 444#if !defined(SLM_CONT_CNT_REPROG) && defined(DEBUG) 445 printk( "SLM: CurAddr=%#lx EndAddr=%#lx timer=%ld\n", 446 SLMCurAddr, SLMEndAddr, DMA_TIME_FOR( SLMSliceSize ) ); 447#endif 448 449 ENABLE_IRQ(); 450} 451 452 453/* Only called when an error happened or at the end of a page */ 454 455static irqreturn_t slm_interrupt(int irc, void *data) 456 457{ unsigned long addr; 458 int stat; 459 460 STOP_TIMER(); 461 addr = get_dma_addr(); 462 stat = acsi_getstatus(); 463 SLMError = (stat < 0) ? SLMSTAT_ACSITO : 464 (addr < virt_to_phys(BufferP)) ? SLMSTAT_NOTALL : 465 stat; 466 467 dma_wd.dma_mode_status = 0x80; 468 MFPDELAY(); 469#ifdef DEBUG 470 printk( "SLM: interrupt, addr=%#lx, error=%d\n", addr, SLMError ); 471#endif 472 473 wake_up( &print_wait ); 474 stdma_release(); 475 ENABLE_IRQ(); 476 return IRQ_HANDLED; 477} 478 479 480static void slm_test_ready( unsigned long dummy ) 481 482{ 483#ifdef SLM_CONT_CNT_REPROG 484 /* program for 255*512 bytes again */ 485 dma_wd.fdc_acces_seccount = SLM_DMA_AMOUNT; 486 START_TIMER( DMA_TIME_FOR(0) ); 487#ifdef DEBUG 488 printk( "SLM: reprogramming timer for %d jiffies, addr=%#lx\n", 489 DMA_TIME_FOR(0), get_dma_addr() ); 490#endif 491 492#else /* !SLM_CONT_CNT_REPROG */ 493 494 unsigned long flags, addr; 495 int d, ti; 496#ifdef DEBUG 497 struct timeval start_tm, end_tm; 498 int did_wait = 0; 499#endif 500 501 local_irq_save(flags); 502 503 addr = get_dma_addr(); 504 if ((d = SLMEndAddr - addr) > 0) { 505 local_irq_restore(flags); 506 507 /* slice not yet finished, decide whether to start another timer or to 508 * busy-wait */ 509 ti = DMA_TIME_FOR( d ); 510 if (ti > 0) { 511#ifdef DEBUG 512 printk( "SLM: reprogramming timer for %d jiffies, rest %d bytes\n", 513 ti, d ); 514#endif 515 START_TIMER( ti ); 516 return; 517 } 518 /* wait for desired end address to be reached */ 519#ifdef DEBUG 520 do_gettimeofday( &start_tm ); 521 did_wait = 1; 522#endif 523 local_irq_disable(); 524 while( get_dma_addr() < SLMEndAddr ) 525 barrier(); 526 } 527 528 /* slice finished, start next one */ 529 SLMCurAddr += SLMSliceSize; 530 531#ifdef SLM_CONTINUOUS_DMA 532 /* program for 255*512 bytes again */ 533 dma_wd.fdc_acces_seccount = SLM_DMA_AMOUNT; 534#else 535 /* set DMA address; 536 * add 2 bytes for the ones in the SLM controller FIFO! */ 537 set_dma_addr( SLMCurAddr + 2 ); 538 /* toggle DMA to write and select sector counter reg */ 539 dma_wd.dma_mode_status = 0x92; 540 MFPDELAY(); 541 dma_wd.dma_mode_status = 0x192; 542 MFPDELAY(); 543 /* program for 255*512 bytes and start DMA */ 544 DMA_LONG_WRITE( SLM_DMA_AMOUNT, 0x112 ); 545#endif 546 547 local_irq_restore(flags); 548 549#ifdef DEBUG 550 if (did_wait) { 551 int ms; 552 do_gettimeofday( &end_tm ); 553 ms = (end_tm.tv_sec*1000000+end_tm.tv_usec) - 554 (start_tm.tv_sec*1000000+start_tm.tv_usec); 555 printk( "SLM: did %ld.%ld ms busy waiting for %d bytes\n", 556 ms/1000, ms%1000, d ); 557 } 558 else 559 printk( "SLM: didn't wait (!)\n" ); 560#endif 561 562 if ((unsigned char *)PTOV( SLMCurAddr + SLMSliceSize ) >= BufferP) { 563 /* will be last slice, no timer necessary */ 564#ifdef DEBUG 565 printk( "SLM: CurAddr=%#lx EndAddr=%#lx last slice -> no timer\n", 566 SLMCurAddr, SLMEndAddr ); 567#endif 568 } 569 else { 570 /* not last slice */ 571 SLMEndAddr = SLMCurAddr + SLMSliceSize + SLM_DMA_INT_OFFSET; 572 START_TIMER( DMA_TIME_FOR( SLMSliceSize )); 573#ifdef DEBUG 574 printk( "SLM: CurAddr=%#lx EndAddr=%#lx timer=%ld\n", 575 SLMCurAddr, SLMEndAddr, DMA_TIME_FOR( SLMSliceSize ) ); 576#endif 577 } 578#endif /* SLM_CONT_CNT_REPROG */ 579} 580 581 582static void set_dma_addr( unsigned long paddr ) 583 584{ unsigned long flags; 585 586 local_irq_save(flags); 587 dma_wd.dma_lo = (unsigned char)paddr; 588 paddr >>= 8; 589 MFPDELAY(); 590 dma_wd.dma_md = (unsigned char)paddr; 591 paddr >>= 8; 592 MFPDELAY(); 593 if (ATARIHW_PRESENT( EXTD_DMA )) 594 st_dma_ext_dmahi = (unsigned short)paddr; 595 else 596 dma_wd.dma_hi = (unsigned char)paddr; 597 MFPDELAY(); 598 local_irq_restore(flags); 599} 600 601 602static unsigned long get_dma_addr( void ) 603 604{ unsigned long addr; 605 606 addr = dma_wd.dma_lo & 0xff; 607 MFPDELAY(); 608 addr |= (dma_wd.dma_md & 0xff) << 8; 609 MFPDELAY(); 610 addr |= (dma_wd.dma_hi & 0xff) << 16; 611 MFPDELAY(); 612 613 return( addr ); 614} 615 616 617static ssize_t slm_write( struct file *file, const char *buf, size_t count, 618 loff_t *ppos ) 619 620{ 621 struct inode *node = file->f_path.dentry->d_inode; 622 int device = iminor(node); 623 int n, filled, w, h; 624 625 while( SLMState == PRINTING || 626 (SLMState == FILLING && SLMBufOwner != device) ) { 627 interruptible_sleep_on( &slm_wait ); 628 if (signal_pending(current)) 629 return( -ERESTARTSYS ); 630 } 631 if (SLMState == IDLE) { 632 /* first data of page: get current page size */ 633 if (slm_get_pagesize( device, &w, &h )) 634 return( -EIO ); 635 BufferSize = w*h/8; 636 if (BufferSize > SLM_BUFFER_SIZE) 637 return( -ENOMEM ); 638 639 SLMState = FILLING; 640 SLMBufOwner = device; 641 } 642 643 n = count; 644 filled = BufferP - SLMBuffer; 645 if (filled + n > BufferSize) 646 n = BufferSize - filled; 647 648 if (copy_from_user(BufferP, buf, n)) 649 return -EFAULT; 650 BufferP += n; 651 filled += n; 652 653 if (filled == BufferSize) { 654 /* Check the paper size again! The user may have switched it in the 655 * time between starting the data and finishing them. Would end up in 656 * a trashy page... */ 657 if (slm_get_pagesize( device, &w, &h )) 658 return( -EIO ); 659 if (BufferSize != w*h/8) { 660 printk( KERN_NOTICE "slm%d: page size changed while printing\n", 661 device ); 662 return( -EAGAIN ); 663 } 664 665 SLMState = PRINTING; 666 /* choose a slice size that is a multiple of the line size */ 667#ifndef SLM_CONT_CNT_REPROG 668 SLMSliceSize = SLM_SLICE_SIZE(w); 669#endif 670 671 start_print( device ); 672 sleep_on( &print_wait ); 673 if (SLMError && IS_REAL_ERROR(SLMError)) { 674 printk( KERN_ERR "slm%d: %s\n", device, slm_errstr(SLMError) ); 675 n = -EIO; 676 } 677 678 SLMState = IDLE; 679 BufferP = SLMBuffer; 680 wake_up_interruptible( &slm_wait ); 681 } 682 683 return( n ); 684} 685 686 687/* ---------------------------------------------------------------------- */ 688/* ioctl Functions */ 689 690 691static int slm_ioctl( struct inode *inode, struct file *file, 692 unsigned int cmd, unsigned long arg ) 693 694{ int device = iminor(inode), err; 695 696 /* I can think of setting: 697 * - manual feed 698 * - paper format 699 * - copy count 700 * - ... 701 * but haven't implemented that yet :-) 702 * BTW, has anybody better docs about the MODE SENSE/MODE SELECT data? 703 */ 704 switch( cmd ) { 705 706 case SLMIORESET: /* reset buffer, i.e. empty the buffer */ 707 if (!(file->f_mode & 2)) 708 return( -EINVAL ); 709 if (SLMState == PRINTING) 710 return( -EBUSY ); 711 SLMState = IDLE; 712 BufferP = SLMBuffer; 713 wake_up_interruptible( &slm_wait ); 714 return( 0 ); 715 716 case SLMIOGSTAT: { /* get status */ 717 int stat; 718 char *str; 719 720 stat = slm_req_sense( device ); 721 if (arg) { 722 str = slm_errstr( stat ); 723 if (put_user(stat, 724 (long *)&((struct SLM_status *)arg)->stat)) 725 return -EFAULT; 726 if (copy_to_user( ((struct SLM_status *)arg)->str, str, 727 strlen(str) + 1)) 728 return -EFAULT; 729 } 730 return( stat ); 731 } 732 733 case SLMIOGPSIZE: { /* get paper size */ 734 int w, h; 735 736 if ((err = slm_get_pagesize( device, &w, &h ))) return( err ); 737 738 if (put_user(w, (long *)&((struct SLM_paper_size *)arg)->width)) 739 return -EFAULT; 740 if (put_user(h, (long *)&((struct SLM_paper_size *)arg)->height)) 741 return -EFAULT; 742 return( 0 ); 743 } 744 745 case SLMIOGMFEED: /* get manual feed */ 746 return( -EINVAL ); 747 748 case SLMIOSPSIZE: /* set paper size */ 749 return( -EINVAL ); 750 751 case SLMIOSMFEED: /* set manual feed */ 752 return( -EINVAL ); 753 754 } 755 return( -EINVAL ); 756} 757 758 759/* ---------------------------------------------------------------------- */ 760/* Opening and Closing */ 761 762 763static int slm_open( struct inode *inode, struct file *file ) 764 765{ int device; 766 struct slm *sip; 767 768 device = iminor(inode); 769 if (device >= N_SLM_Printers) 770 return( -ENXIO ); 771 sip = &slm_info[device]; 772 773 if (file->f_mode & 2) { 774 /* open for writing is exclusive */ 775 if ( !atomic_dec_and_test(&sip->wr_ok) ) { 776 atomic_inc(&sip->wr_ok); 777 return( -EBUSY ); 778 } 779 } 780 if (file->f_mode & 1) { 781 /* open for reading is exclusive */ 782 if ( !atomic_dec_and_test(&sip->rd_ok) ) { 783 atomic_inc(&sip->rd_ok); 784 return( -EBUSY ); 785 } 786 } 787 788 return( 0 ); 789} 790 791 792static int slm_release( struct inode *inode, struct file *file ) 793 794{ int device; 795 struct slm *sip; 796 797 device = iminor(inode); 798 sip = &slm_info[device]; 799 800 if (file->f_mode & 2) 801 atomic_inc( &sip->wr_ok ); 802 if (file->f_mode & 1) 803 atomic_inc( &sip->rd_ok ); 804 805 return( 0 ); 806} 807 808 809/* ---------------------------------------------------------------------- */ 810/* ACSI Primitives for the SLM */ 811 812 813static int slm_req_sense( int device ) 814 815{ int stat, rv; 816 struct slm *sip = &slm_info[device]; 817 818 stdma_lock( NULL, NULL ); 819 820 CMDSET_TARG_LUN( slmreqsense_cmd, sip->target, sip->lun ); 821 if (!acsicmd_nodma( slmreqsense_cmd, 0 ) || 822 (stat = acsi_getstatus()) < 0) 823 rv = SLMSTAT_ACSITO; 824 else 825 rv = stat & 0x1f; 826 827 ENABLE_IRQ(); 828 stdma_release(); 829 return( rv ); 830} 831 832 833static int slm_mode_sense( int device, char *buffer, int abs_flag ) 834 835{ unsigned char stat, len; 836 int rv = 0; 837 struct slm *sip = &slm_info[device]; 838 839 stdma_lock( NULL, NULL ); 840 841 CMDSET_TARG_LUN( slmmsense_cmd, sip->target, sip->lun ); 842 slmmsense_cmd[5] = abs_flag ? 0x80 : 0; 843 if (!acsicmd_nodma( slmmsense_cmd, 0 )) { 844 rv = SLMSTAT_ACSITO; 845 goto the_end; 846 } 847 848 if (!acsi_extstatus( &stat, 1 )) { 849 acsi_end_extstatus(); 850 rv = SLMSTAT_ACSITO; 851 goto the_end; 852 } 853 854 if (!acsi_extstatus( &len, 1 )) { 855 acsi_end_extstatus(); 856 rv = SLMSTAT_ACSITO; 857 goto the_end; 858 } 859 buffer[0] = len; 860 if (!acsi_extstatus( buffer+1, len )) { 861 acsi_end_extstatus(); 862 rv = SLMSTAT_ACSITO; 863 goto the_end; 864 } 865 866 acsi_end_extstatus(); 867 rv = stat & 0x1f; 868 869 the_end: 870 ENABLE_IRQ(); 871 stdma_release(); 872 return( rv ); 873} 874 875 876#if 0 877/* currently unused */ 878static int slm_mode_select( int device, char *buffer, int len, 879 int default_flag ) 880 881{ int stat, rv; 882 struct slm *sip = &slm_info[device]; 883 884 stdma_lock( NULL, NULL ); 885 886 CMDSET_TARG_LUN( slmmselect_cmd, sip->target, sip->lun ); 887 slmmselect_cmd[5] = default_flag ? 0x80 : 0; 888 if (!acsicmd_nodma( slmmselect_cmd, 0 )) { 889 rv = SLMSTAT_ACSITO; 890 goto the_end; 891 } 892 893 if (!default_flag) { 894 unsigned char c = len; 895 if (!acsi_extcmd( &c, 1 )) { 896 rv = SLMSTAT_ACSITO; 897 goto the_end; 898 } 899 if (!acsi_extcmd( buffer, len )) { 900 rv = SLMSTAT_ACSITO; 901 goto the_end; 902 } 903 } 904 905 stat = acsi_getstatus(); 906 rv = (stat < 0 ? SLMSTAT_ACSITO : stat); 907 908 the_end: 909 ENABLE_IRQ(); 910 stdma_release(); 911 return( rv ); 912} 913#endif 914 915 916static int slm_get_pagesize( int device, int *w, int *h ) 917 918{ char buf[256]; 919 int stat; 920 921 stat = slm_mode_sense( device, buf, 0 ); 922 ENABLE_IRQ(); 923 stdma_release(); 924 925 if (stat != SLMSTAT_OK) 926 return( -EIO ); 927 928 *w = (buf[3] << 8) | buf[4]; 929 *h = (buf[1] << 8) | buf[2]; 930 return( 0 ); 931} 932 933 934/* ---------------------------------------------------------------------- */ 935/* Initialization */ 936 937 938int attach_slm( int target, int lun ) 939 940{ static int did_register; 941 int len; 942 943 if (N_SLM_Printers >= MAX_SLM) { 944 printk( KERN_WARNING "Too much SLMs\n" ); 945 return( 0 ); 946 } 947 948 /* do an INQUIRY */ 949 udelay(100); 950 CMDSET_TARG_LUN( slminquiry_cmd, target, lun ); 951 if (!acsicmd_nodma( slminquiry_cmd, 0 )) { 952 inq_timeout: 953 printk( KERN_ERR "SLM inquiry command timed out.\n" ); 954 inq_fail: 955 acsi_end_extstatus(); 956 return( 0 ); 957 } 958 /* read status and header of return data */ 959 if (!acsi_extstatus( SLMBuffer, 6 )) 960 goto inq_timeout; 961 962 if (SLMBuffer[1] != 2) { /* device type == printer? */ 963 printk( KERN_ERR "SLM inquiry returned device type != printer\n" ); 964 goto inq_fail; 965 } 966 len = SLMBuffer[5]; 967 968 /* read id string */ 969 if (!acsi_extstatus( SLMBuffer, len )) 970 goto inq_timeout; 971 acsi_end_extstatus(); 972 SLMBuffer[len] = 0; 973 974 if (!did_register) { 975 did_register = 1; 976 } 977 978 slm_info[N_SLM_Printers].target = target; 979 slm_info[N_SLM_Printers].lun = lun; 980 atomic_set(&slm_info[N_SLM_Printers].wr_ok, 1 ); 981 atomic_set(&slm_info[N_SLM_Printers].rd_ok, 1 ); 982 983 printk( KERN_INFO " Printer: %s\n", SLMBuffer ); 984 printk( KERN_INFO "Detected slm%d at id %d lun %d\n", 985 N_SLM_Printers, target, lun ); 986 N_SLM_Printers++; 987 return( 1 ); 988} 989 990int slm_init( void ) 991 992{ 993 int i; 994 if (register_chrdev( ACSI_MAJOR, "slm", &slm_fops )) { 995 printk( KERN_ERR "Unable to get major %d for ACSI SLM\n", ACSI_MAJOR ); 996 return -EBUSY; 997 } 998 999 if (!(SLMBuffer = atari_stram_alloc( SLM_BUFFER_SIZE, "SLM" ))) { 1000 printk( KERN_ERR "Unable to get SLM ST-Ram buffer.\n" ); 1001 unregister_chrdev( ACSI_MAJOR, "slm" ); 1002 return -ENOMEM; 1003 } 1004 BufferP = SLMBuffer; 1005 SLMState = IDLE; 1006 1007 return 0; 1008} 1009 1010#ifdef MODULE 1011 1012/* from acsi.c */ 1013void acsi_attach_SLMs( int (*attach_func)( int, int ) ); 1014 1015int init_module(void) 1016{ 1017 int err; 1018 1019 if ((err = slm_init())) 1020 return( err ); 1021 /* This calls attach_slm() for every target/lun where acsi.c detected a 1022 * printer */ 1023 acsi_attach_SLMs( attach_slm ); 1024 return( 0 ); 1025} 1026 1027void cleanup_module(void) 1028{ 1029 if (unregister_chrdev( ACSI_MAJOR, "slm" ) != 0) 1030 printk( KERN_ERR "acsi_slm: cleanup_module failed\n"); 1031 atari_stram_free( SLMBuffer ); 1032} 1033#endif