root/drivers/char/lp.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. lp_reset
  2. lp_char_polled
  3. lp_char_interrupt
  4. lp_interrupt
  5. lp_write_interrupt
  6. lp_write_polled
  7. lp_write
  8. lp_lseek
  9. lp_open
  10. lp_release
  11. lp_ioctl
  12. init_module
  13. cleanup_module

   1 /*
   2  * Copyright (C) 1992 by Jim Weigand and Linus Torvalds
   3  * Copyright (C) 1992,1993 by Michael K. Johnson
   4  * - Thanks much to Gunter Windau for pointing out to me where the error
   5  *   checking ought to be.
   6  * Copyright (C) 1993 by Nigel Gamble (added interrupt code)
   7  * Copyright (C) 1994 by Alan Cox (Modularised it)
   8  * LPCAREFUL, LPABORT, LPGETSTATUS added by Chris Metcalf, metcalf@lcs.mit.edu
   9  */
  10 
  11 #ifdef MODULE
  12 #include <linux/module.h>
  13 #include <linux/version.h>
  14 #else
  15 #define MOD_INC_USE_COUNT
  16 #define MOD_DEC_USE_COUNT
  17 #endif
  18 
  19 #include <linux/errno.h>
  20 #include <linux/kernel.h>
  21 #include <linux/major.h>
  22 #include <linux/sched.h>
  23 #include <linux/lp.h>
  24 #include <linux/malloc.h>
  25 #include <linux/ioport.h>
  26 #include <linux/fcntl.h>
  27 
  28 #include <asm/io.h>
  29 #include <asm/segment.h>
  30 #include <asm/system.h>
  31 
  32 /* the BIOS manuals say there can be up to 4 lpt devices
  33  * but I have not seen a board where the 4th address is listed
  34  * if you have different hardware change the table below 
  35  * please let me know if you have different equipment
  36  * if you have more than 3 printers, remember to increase LP_NO
  37  */
  38 struct lp_struct lp_table[] = {
  39         { 0x3bc, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, },
  40         { 0x378, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, },
  41         { 0x278, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, },
  42 }; 
  43 #define LP_NO 3
  44 
  45 /* Test if printer is ready (and optionally has no error conditions) */
  46 #define LP_READY(minor, status) \
  47   ((LP_F(minor) & LP_CAREFUL) ? _LP_CAREFUL_READY(status) : (status & LP_PBUSY))
  48 #define LP_CAREFUL_READY(minor, status) \
  49   ((LP_F(minor) & LP_CAREFUL) ? _LP_CAREFUL_READY(status) : 1)
  50 #define _LP_CAREFUL_READY(status) \
  51    (status & (LP_PBUSY|LP_POUTPA|LP_PSELECD|LP_PERRORP)) == \
  52       (LP_PBUSY|LP_PSELECD|LP_PERRORP) 
  53 
  54 /* Allow old versions of tunelp to continue to work */
  55 #define OLD_LPCHAR   0x0001
  56 #define OLD_LPTIME   0x0002
  57 #define OLD_LPABORT  0x0004
  58 #define OLD_LPSETIRQ 0x0005
  59 #define OLD_LPGETIRQ 0x0006
  60 #define OLD_LPWAIT   0x0008
  61 #define OLD_IOCTL_MAX 8
  62 
  63 /* 
  64  * All my debugging code assumes that you debug with only one printer at
  65  * a time. RWWH
  66  */
  67 
  68 #undef LP_DEBUG
  69 
  70 static int lp_reset(int minor)
     /* [previous][next][first][last][top][bottom][index][help] */
  71 {
  72         int testvalue;
  73         unsigned char command;
  74 
  75         command = LP_PSELECP | LP_PINITP;
  76 
  77         /* reset value */
  78         outb_p(0, LP_C(minor));
  79         for (testvalue = 0 ; testvalue < LP_DELAY ; testvalue++)
  80                 ;
  81         outb_p(command, LP_C(minor));
  82         return LP_S(minor);
  83 }
  84 
  85 #ifdef LP_DEBUG
  86 static int lp_max_count = 1;
  87 #endif
  88 
  89 static int lp_char_polled(char lpchar, int minor)
     /* [previous][next][first][last][top][bottom][index][help] */
  90 {
  91         int status = 0, wait = 0;
  92         unsigned long count  = 0; 
  93 
  94         do {
  95                 status = LP_S(minor);
  96                 count ++;
  97                 if(need_resched)
  98                         schedule();
  99         } while(!LP_READY(minor,status) && count < LP_CHAR(minor));
 100 
 101         if (count == LP_CHAR(minor)) {
 102                 return 0;
 103                 /* we timed out, and the character was /not/ printed */
 104         }
 105 #ifdef LP_DEBUG
 106         if (count > lp_max_count) {
 107                 printk("lp success after %d counts.\n",count);
 108                 lp_max_count=count;
 109         }
 110 #endif
 111         outb_p(lpchar, LP_B(minor));
 112         /* must wait before taking strobe high, and after taking strobe
 113            low, according spec.  Some printers need it, others don't. */
 114         while(wait != LP_WAIT(minor)) wait++;
 115         /* control port takes strobe high */
 116         outb_p(( LP_PSELECP | LP_PINITP | LP_PSTROBE ), ( LP_C( minor )));
 117         while(wait) wait--;
 118         /* take strobe low */
 119         outb_p(( LP_PSELECP | LP_PINITP ), ( LP_C( minor )));
 120 
 121         return 1;
 122 }
 123 
 124 static int lp_char_interrupt(char lpchar, int minor)
     /* [previous][next][first][last][top][bottom][index][help] */
 125 {
 126         int wait = 0;
 127         unsigned char status;
 128 
 129 
 130         if (!((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY)
 131         || !((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY)
 132         || !((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY)) {
 133 
 134                 if (!LP_CAREFUL_READY(minor, status))
 135                         return 0;
 136                 outb_p(lpchar, LP_B(minor));
 137                 /* must wait before taking strobe high, and after taking strobe
 138                    low, according spec.  Some printers need it, others don't. */
 139                 while(wait != LP_WAIT(minor)) wait++;
 140                 /* control port takes strobe high */
 141                 outb_p(( LP_PSELECP | LP_PINITP | LP_PSTROBE ), ( LP_C( minor )));
 142                 while(wait) wait--;
 143                 /* take strobe low */
 144                 outb_p(( LP_PSELECP | LP_PINITP ), ( LP_C( minor )));
 145                 return 1;
 146         }
 147 
 148         return 0;
 149 }
 150 
 151 #ifdef LP_DEBUG
 152         unsigned int lp_total_chars = 0;
 153         unsigned int lp_last_call = 0;
 154 #endif
 155 
 156 static void lp_interrupt(int irq, struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 157 {
 158         struct lp_struct *lp = &lp_table[0];
 159         struct lp_struct *lp_end = &lp_table[LP_NO];
 160 
 161         while (irq != lp->irq) {
 162                 if (++lp >= lp_end)
 163                         return;
 164         }
 165 
 166         wake_up(&lp->lp_wait_q);
 167 }
 168 
 169 static int lp_write_interrupt(struct inode * inode, struct file * file, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 170 {
 171         unsigned int minor = MINOR(inode->i_rdev);
 172         unsigned long copy_size;
 173         unsigned long total_bytes_written = 0;
 174         unsigned long bytes_written;
 175         struct lp_struct *lp = &lp_table[minor];
 176         unsigned char status;
 177 
 178         do {
 179                 bytes_written = 0;
 180                 copy_size = (count <= LP_BUFFER_SIZE ? count : LP_BUFFER_SIZE);
 181                 memcpy_fromfs(lp->lp_buffer, buf, copy_size);
 182 
 183                 while (copy_size) {
 184                         if (lp_char_interrupt(lp->lp_buffer[bytes_written], minor)) {
 185                                 --copy_size;
 186                                 ++bytes_written;
 187                         } else {
 188                                 int rc = total_bytes_written + bytes_written;
 189                                 status = LP_S(minor);
 190                                 if ((status & LP_POUTPA)) {
 191                                         printk(KERN_INFO "lp%d out of paper\n", minor);
 192                                         if (LP_F(minor) & LP_ABORT)
 193                                                 return rc?rc:-ENOSPC;
 194                                 } else if (!(status & LP_PSELECD)) {
 195                                         printk(KERN_INFO "lp%d off-line\n", minor);
 196                                         if (LP_F(minor) & LP_ABORT)
 197                                                 return rc?rc:-EIO;
 198                                 } else if (!(status & LP_PERRORP)) {
 199                                         printk(KERN_ERR "lp%d printer error\n", minor);
 200                                         if (LP_F(minor) & LP_ABORT)
 201                                                 return rc?rc:-EIO;
 202                                 }
 203                                 cli();
 204                                 outb_p((LP_PSELECP|LP_PINITP|LP_PINTEN), (LP_C(minor)));
 205                                 status = LP_S(minor);
 206                                 if ((!(status & LP_PACK) || (status & LP_PBUSY))
 207                                   && LP_CAREFUL_READY(minor, status)) {
 208                                         outb_p((LP_PSELECP|LP_PINITP), (LP_C(minor)));
 209                                         sti();
 210                                         continue;
 211                                 }
 212                                 current->timeout = jiffies + LP_TIMEOUT_INTERRUPT;
 213                                 interruptible_sleep_on(&lp->lp_wait_q);
 214                                 outb_p((LP_PSELECP|LP_PINITP), (LP_C(minor)));
 215                                 sti();
 216                                 if (current->signal & ~current->blocked) {
 217                                         if (total_bytes_written + bytes_written)
 218                                                 return total_bytes_written + bytes_written;
 219                                         else
 220                                                 return -EINTR;
 221                                 }
 222                         }
 223                 }
 224 
 225                 total_bytes_written += bytes_written;
 226                 buf += bytes_written;
 227                 count -= bytes_written;
 228 
 229         } while (count > 0);
 230 
 231         return total_bytes_written;
 232 }
 233 
 234 static int lp_write_polled(struct inode * inode, struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
 235                            char * buf, int count)
 236 {
 237         int  retval;
 238         unsigned int minor = MINOR(inode->i_rdev);
 239         char c, *temp = buf;
 240 
 241 #ifdef LP_DEBUG
 242         if (jiffies-lp_last_call > LP_TIME(minor)) {
 243                 lp_total_chars = 0;
 244                 lp_max_count = 1;
 245         }
 246         lp_last_call = jiffies;
 247 #endif
 248 
 249         temp = buf;
 250         while (count > 0) {
 251                 c = get_user(temp);
 252                 retval = lp_char_polled(c, minor);
 253                 /* only update counting vars if character was printed */
 254                 if (retval) { count--; temp++;
 255 #ifdef LP_DEBUG
 256                         lp_total_chars++;
 257 #endif
 258                 }
 259                 if (!retval) { /* if printer timed out */
 260                         int status = LP_S(minor);
 261 
 262                         if (status & LP_POUTPA) {
 263                                 printk(KERN_INFO "lp%d out of paper\n", minor);
 264                                 if(LP_F(minor) & LP_ABORT)
 265                                         return temp-buf?temp-buf:-ENOSPC;
 266                                 current->state = TASK_INTERRUPTIBLE;
 267                                 current->timeout = jiffies + LP_TIMEOUT_POLLED;
 268                                 schedule();
 269                         } else
 270                         if (!(status & LP_PSELECD)) {
 271                                 printk(KERN_INFO "lp%d off-line\n", minor);
 272                                 if(LP_F(minor) & LP_ABORT)
 273                                         return temp-buf?temp-buf:-EIO;
 274                                 current->state = TASK_INTERRUPTIBLE;
 275                                 current->timeout = jiffies + LP_TIMEOUT_POLLED;
 276                                 schedule();
 277                         } else
 278                         /* not offline or out of paper. on fire? */
 279                         if (!(status & LP_PERRORP)) {
 280                                 printk(KERN_ERR "lp%d reported invalid error status (on fire, eh?)\n", minor);
 281                                 if(LP_F(minor) & LP_ABORT)
 282                                         return temp-buf?temp-buf:-EIO;
 283                                 current->state = TASK_INTERRUPTIBLE;
 284                                 current->timeout = jiffies + LP_TIMEOUT_POLLED;
 285                                 schedule();
 286                         }
 287 
 288                         /* check for signals before going to sleep */
 289                         if (current->signal & ~current->blocked) {
 290                                 if (temp != buf)
 291                                         return temp-buf;
 292                                 else
 293                                         return -EINTR;
 294                         }
 295 #ifdef LP_DEBUG
 296                         printk("lp sleeping at %d characters for %d jiffies\n",
 297                                 lp_total_chars, LP_TIME(minor));
 298                         lp_total_chars=0;
 299 #endif
 300                         current->state = TASK_INTERRUPTIBLE;
 301                         current->timeout = jiffies + LP_TIME(minor);
 302                         schedule();
 303                 }
 304         }
 305         return temp-buf;
 306 }
 307 
 308 static int lp_write(struct inode * inode, struct file * file, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 309 {
 310         if (LP_IRQ(MINOR(inode->i_rdev)))
 311                 return lp_write_interrupt(inode, file, buf, count);
 312         else
 313                 return lp_write_polled(inode, file, buf, count);
 314 }
 315 
 316 static int lp_lseek(struct inode * inode, struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
 317                     off_t offset, int origin)
 318 {
 319         return -ESPIPE;
 320 }
 321 
 322 static int lp_open(struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
 323 {
 324         unsigned int minor = MINOR(inode->i_rdev);
 325         int ret;
 326         unsigned int irq;
 327 
 328         if (minor >= LP_NO)
 329                 return -ENODEV;
 330         if ((LP_F(minor) & LP_EXIST) == 0)
 331                 return -ENODEV;
 332         if (LP_F(minor) & LP_BUSY)
 333                 return -EBUSY;
 334 
 335         MOD_INC_USE_COUNT;
 336 
 337         /* If ABORTOPEN is set and the printer is offline or out of paper,
 338            we may still want to open it to perform ioctl()s.  Therefore we
 339            have commandeered O_NONBLOCK, even though it is being used in
 340            a non-standard manner.  This is strictly a Linux hack, and
 341            should most likely only ever be used by the tunelp application. */
 342         if ((LP_F(minor) & LP_ABORTOPEN) && !(file->f_flags & O_NONBLOCK)) {
 343                 int status = LP_S(minor);
 344                 if (status & LP_POUTPA) {
 345                         printk(KERN_INFO "lp%d out of paper\n", minor);
 346                         MOD_DEC_USE_COUNT;
 347                         return -ENOSPC;
 348                 } else if (!(status & LP_PSELECD)) {
 349                         printk(KERN_INFO "lp%d off-line\n", minor);
 350                         MOD_DEC_USE_COUNT;
 351                         return -EIO;
 352                 } else if (!(status & LP_PERRORP)) {
 353                         printk(KERN_ERR "lp%d printer error\n", minor);
 354                         MOD_DEC_USE_COUNT;
 355                         return -EIO;
 356                 }
 357         }
 358 
 359         if ((irq = LP_IRQ(minor))) {
 360                 lp_table[minor].lp_buffer = (char *) kmalloc(LP_BUFFER_SIZE, GFP_KERNEL);
 361                 if (!lp_table[minor].lp_buffer) {
 362                         MOD_DEC_USE_COUNT;
 363                         return -ENOMEM;
 364                 }
 365 
 366                 ret = request_irq(irq, lp_interrupt, SA_INTERRUPT, "printer");
 367                 if (ret) {
 368                         kfree_s(lp_table[minor].lp_buffer, LP_BUFFER_SIZE);
 369                         lp_table[minor].lp_buffer = NULL;
 370                         printk("lp%d unable to use interrupt %d, error %d\n", minor, irq, ret);
 371                         MOD_DEC_USE_COUNT;
 372                         return ret;
 373                 }
 374         }
 375 
 376         LP_F(minor) |= LP_BUSY;
 377         return 0;
 378 }
 379 
 380 static void lp_release(struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
 381 {
 382         unsigned int minor = MINOR(inode->i_rdev);
 383         unsigned int irq;
 384 
 385         if ((irq = LP_IRQ(minor))) {
 386                 free_irq(irq);
 387                 kfree_s(lp_table[minor].lp_buffer, LP_BUFFER_SIZE);
 388                 lp_table[minor].lp_buffer = NULL;
 389         }
 390 
 391         LP_F(minor) &= ~LP_BUSY;
 392         MOD_DEC_USE_COUNT;
 393 }
 394 
 395 
 396 static int lp_ioctl(struct inode *inode, struct file *file,
     /* [previous][next][first][last][top][bottom][index][help] */
 397                     unsigned int cmd, unsigned long arg)
 398 {
 399         unsigned int minor = MINOR(inode->i_rdev);
 400         int retval = 0;
 401 
 402 #ifdef LP_DEBUG
 403         printk("lp%d ioctl, cmd: 0x%x, arg: 0x%x\n", minor, cmd, arg);
 404 #endif
 405         if (minor >= LP_NO)
 406                 return -ENODEV;
 407         if ((LP_F(minor) & LP_EXIST) == 0)
 408                 return -ENODEV;
 409         if (cmd <= OLD_IOCTL_MAX)
 410                 printk(KERN_NOTICE "lp%d: warning: obsolete ioctl %#x (perhaps you need a new tunelp)\n",
 411                     minor, cmd);
 412         switch ( cmd ) {
 413                 case OLD_LPTIME:
 414                 case LPTIME:
 415                         LP_TIME(minor) = arg;
 416                         break;
 417                 case OLD_LPCHAR:
 418                 case LPCHAR:
 419                         LP_CHAR(minor) = arg;
 420                         break;
 421                 case OLD_LPABORT:
 422                 case LPABORT:
 423                         if (arg)
 424                                 LP_F(minor) |= LP_ABORT;
 425                         else
 426                                 LP_F(minor) &= ~LP_ABORT;
 427                         break;
 428                 case LPABORTOPEN:
 429                         if (arg)
 430                                 LP_F(minor) |= LP_ABORTOPEN;
 431                         else
 432                                 LP_F(minor) &= ~LP_ABORTOPEN;
 433                         break;
 434                 case LPCAREFUL:
 435                         if (arg)
 436                                 LP_F(minor) |= LP_CAREFUL;
 437                         else
 438                                 LP_F(minor) &= ~LP_CAREFUL;
 439                         break;
 440                 case OLD_LPWAIT:
 441                 case LPWAIT:
 442                         LP_WAIT(minor) = arg;
 443                         break;
 444                 case OLD_LPSETIRQ:
 445                 case LPSETIRQ: {
 446                         int oldirq;
 447                         int newirq = arg;
 448                         struct lp_struct *lp = &lp_table[minor];
 449 
 450                         if (!suser())
 451                                 return -EPERM;
 452 
 453                         oldirq = LP_IRQ(minor);
 454 
 455                         /* Allocate buffer now if we are going to need it */
 456                         if (!oldirq && newirq) {
 457                                 lp->lp_buffer = (char *) kmalloc(LP_BUFFER_SIZE, GFP_KERNEL);
 458                                 if (!lp->lp_buffer)
 459                                         return -ENOMEM;
 460                         }
 461 
 462                         if (oldirq) {
 463                                 free_irq(oldirq);
 464                         }
 465                         if (newirq) {
 466                                 /* Install new irq */
 467                                 if ((retval = request_irq(newirq, lp_interrupt, SA_INTERRUPT, "printer"))) {
 468                                         if (oldirq) {
 469                                                 /* restore old irq */
 470                                                 request_irq(oldirq, lp_interrupt, SA_INTERRUPT, "printer");
 471                                         } else {
 472                                                 /* We don't need the buffer */
 473                                                 kfree_s(lp->lp_buffer, LP_BUFFER_SIZE);
 474                                                 lp->lp_buffer = NULL;
 475                                         }
 476                                         return retval;
 477                                 }
 478                         }
 479                         if (oldirq && !newirq) {
 480                                 /* We don't need the buffer */
 481                                 kfree_s(lp->lp_buffer, LP_BUFFER_SIZE);
 482                                 lp->lp_buffer = NULL;
 483                         }
 484                         LP_IRQ(minor) = newirq;
 485                         lp_reset(minor);
 486                         break;
 487                 }
 488                 case OLD_LPGETIRQ:
 489                         retval = LP_IRQ(minor);
 490                         break;
 491                 case LPGETIRQ:
 492                         retval = verify_area(VERIFY_WRITE, (void *) arg,
 493                             sizeof(int));
 494                         if (retval)
 495                                 return retval;
 496                         memcpy_tofs((int *) arg, &LP_IRQ(minor), sizeof(int));
 497                         break;
 498                 case LPGETSTATUS:
 499                         retval = verify_area(VERIFY_WRITE, (void *) arg,
 500                             sizeof(int));
 501                         if (retval)
 502                                 return retval;
 503                         else {
 504                                 int status = LP_S(minor);
 505                                 memcpy_tofs((int *) arg, &status, sizeof(int));
 506                         }
 507                         break;
 508                 case LPRESET:
 509                         lp_reset(minor);
 510                         break;
 511                 default:
 512                         retval = -EINVAL;
 513         }
 514         return retval;
 515 }
 516 
 517 
 518 static struct file_operations lp_fops = {
 519         lp_lseek,
 520         NULL,           /* lp_read */
 521         lp_write,
 522         NULL,           /* lp_readdir */
 523         NULL,           /* lp_select */
 524         lp_ioctl,
 525         NULL,           /* lp_mmap */
 526         lp_open,
 527         lp_release
 528 };
 529 
 530 #ifdef MODULE
 531 char kernel_version[]=UTS_RELEASE;
 532 
 533 int init_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 534 #else
 535 long lp_init(long kmem_start)
 536 #endif
 537 {
 538         int offset = 0;
 539         unsigned int testvalue = 0;
 540         int count = 0;
 541 
 542         if (register_chrdev(LP_MAJOR,"lp",&lp_fops)) {
 543                 printk("lp: unable to get major %d\n", LP_MAJOR);
 544 #ifdef MODULE
 545                 return -EIO;
 546 #else           
 547                 return kmem_start;
 548 #endif
 549         }
 550         /* take on all known port values */
 551         for (offset = 0; offset < LP_NO; offset++) {
 552                 if (check_region(LP_B(offset), 3))
 553                         continue;
 554                 /* write to port & read back to check */
 555                 outb_p( LP_DUMMY, LP_B(offset));
 556                 for (testvalue = 0 ; testvalue < LP_DELAY ; testvalue++)
 557                         ;
 558                 testvalue = inb_p(LP_B(offset));
 559                 if (testvalue == LP_DUMMY) {
 560                         LP_F(offset) |= LP_EXIST;
 561                         lp_reset(offset);
 562                         printk("lp%d at 0x%04x, ", offset,LP_B(offset));
 563                         request_region(LP_B(offset), 3, "lp");
 564                         if (LP_IRQ(offset))
 565                                 printk("(irq = %d)\n", LP_IRQ(offset));
 566                         else
 567                                 printk("(polling)\n");
 568                         count++;
 569                 }
 570         }
 571         if (count == 0)
 572                 printk("lp: Driver configured but no interfaces found.\n");
 573 
 574 
 575 #ifdef MODULE
 576         return 0;
 577 #else   
 578         return kmem_start;
 579 #endif
 580 }
 581 
 582 #ifdef MODULE
 583 void cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 584 {
 585         int offset;
 586         if(MOD_IN_USE)
 587                printk("lp: busy - remove delayed\n");
 588         else {
 589                unregister_chrdev(LP_MAJOR,"lp");
 590                for (offset = 0; offset < LP_NO; offset++) 
 591                         if (LP_F(offset) & LP_EXIST) 
 592                                 release_region(LP_B(offset),3);
 593         }
 594 }
 595 
 596 #endif

/* [previous][next][first][last][top][bottom][index][help] */