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