root/kernel/blk_drv/scsi/sr.c

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

DEFINITIONS

This source file includes following definitions.
  1. sr_release
  2. check_cdrom_media_change
  3. rw_intr
  4. sr_open
  5. do_sr_request
  6. requeue_sr_request
  7. sr_init1
  8. sr_attach
  9. sr_init

   1 /*
   2  *      sr.c by David Giller
   3  *
   4  *      adapted from:
   5  *      sd.c Copyright (C) 1992 Drew Eckhardt 
   6  *      Linux scsi disk driver by
   7  *              Drew Eckhardt 
   8  *
   9  *      <drew@colorado.edu>
  10  *
  11  *       Modified by Eric Youngdale eric@tantalus.nrl.navy.mil to
  12  *       add scatter-gather, multiple outstanding request, and other
  13  *       enhancements.
  14  */
  15 
  16 #include <linux/fs.h>
  17 #include <linux/kernel.h>
  18 #include <linux/sched.h>
  19 #include <linux/string.h>
  20 #include <linux/errno.h>
  21 #include <asm/system.h>
  22 
  23 #define MAJOR_NR 11
  24 
  25 #include "../blk.h"
  26 #include "scsi.h"
  27 #include "hosts.h"
  28 #include "sr.h"
  29 #include "scsi_ioctl.h"   /* For the door lock/unlock commands */
  30 
  31 #define MAX_RETRIES 0
  32 #define SR_TIMEOUT 250
  33 
  34 int NR_SR=0;
  35 int MAX_SR=0;
  36 Scsi_CD * scsi_CDs;
  37 static int * sr_sizes;
  38 
  39 static int sr_open(struct inode *, struct file *);
  40 
  41 extern int sr_ioctl(struct inode *, struct file *, unsigned int, unsigned int);
  42 
  43 void requeue_sr_request (Scsi_Cmnd * SCpnt);
  44 
  45 static void sr_release(struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
  46 {
  47         sync_dev(inode->i_rdev);
  48         if(! --scsi_CDs[MINOR(inode->i_rdev)].device->access_count)
  49           sr_ioctl(inode, NULL, SCSI_IOCTL_DOORUNLOCK, 0);
  50 }
  51 
  52 static struct file_operations sr_fops = 
  53 {
  54         NULL,                   /* lseek - default */
  55         block_read,             /* read - general block-dev read */
  56         block_write,            /* write - general block-dev write */
  57         NULL,                   /* readdir - bad */
  58         NULL,                   /* select */
  59         sr_ioctl,               /* ioctl */
  60         NULL,                   /* mmap */
  61         sr_open,                /* no special open code */
  62         sr_release              /* release */
  63 };
  64 
  65 /*
  66  * This function checks to see if the media has been changed in the
  67  * CDROM drive.  It is possible that we have already sensed a change,
  68  * or the drive may have sensed one and not yet reported it.  We must
  69  * be ready for either case. This function always reports the current
  70  * value of the changed bit.  If flag is 0, then the changed bit is reset.
  71  * This function could be done as an ioctl, but we would need to have
  72  * an inode for that to work, and we do not always have one.
  73  */
  74 
  75 int check_cdrom_media_change(int full_dev, int flag){
     /* [previous][next][first][last][top][bottom][index][help] */
  76         int retval, target;
  77         struct inode inode;
  78 
  79         target =  MINOR(full_dev);
  80 
  81         if (target >= NR_SR) {
  82                 printk("CD-ROM request error: invalid device.\n");
  83                 return 0;
  84         };
  85 
  86         inode.i_rdev = full_dev;  /* This is all we really need here */
  87         retval = sr_ioctl(&inode, NULL, SCSI_IOCTL_TEST_UNIT_READY, 0);
  88 
  89         if(retval){ /* Unable to test, unit probably not ready.  This usually
  90                      means there is no disc in the drive.  Mark as changed,
  91                      and we will figure it out later once the drive is
  92                      available again.  */
  93 
  94           scsi_CDs[target].device->changed = 1;
  95           return 1; /* This will force a flush, if called from
  96                        check_disk_change */
  97         };
  98 
  99         retval = scsi_CDs[target].device->changed;
 100         if(!flag) scsi_CDs[target].device->changed = 0;
 101         return retval;
 102 }
 103 
 104 /*
 105  * rw_intr is the interrupt routine for the device driver.  It will be notified on the 
 106  * end of a SCSI read / write, and will take on of several actions based on success or failure.
 107  */
 108 
 109 static void rw_intr (Scsi_Cmnd * SCpnt)
     /* [previous][next][first][last][top][bottom][index][help] */
 110 {
 111         int result = SCpnt->result;
 112         int this_count = SCpnt->this_count;
 113 
 114 #ifdef DEBUG
 115         printk("sr.c done: %x %x\n",result, SCpnt->request.bh->b_data);
 116 #endif
 117         if (!result)
 118                 { /* No error */
 119                   if (SCpnt->use_sg == 0) {
 120                     if (SCpnt->buffer != SCpnt->request.buffer)
 121                       {
 122                         int offset;
 123                         offset = (SCpnt->request.sector % 4) << 9;
 124                         memcpy((char *)SCpnt->request.buffer, 
 125                                SCpnt->buffer + offset, 
 126                                this_count << 9);
 127                         /* Even though we are not using scatter-gather, we look
 128                            ahead and see if there is a linked request for the
 129                            other half of this buffer.  If there is, then satisfy
 130                            it. */
 131                         if((offset == 0) && this_count == 2 &&
 132                            SCpnt->request.nr_sectors > this_count && 
 133                            SCpnt->request.bh &&
 134                            SCpnt->request.bh->b_reqnext &&
 135                            SCpnt->request.bh->b_reqnext->b_size == 1024) {
 136                           memcpy((char *)SCpnt->request.bh->b_reqnext->b_data, 
 137                                  SCpnt->buffer + 1024, 
 138                                  1024);
 139                           this_count += 2;
 140                         };
 141                         
 142                         scsi_free(SCpnt->buffer, 2048);
 143                       }
 144                   } else {
 145                     struct scatterlist * sgpnt;
 146                     int i;
 147                     sgpnt = (struct scatterlist *) SCpnt->buffer;
 148                     for(i=0; i<SCpnt->use_sg; i++) {
 149                       if (sgpnt[i].alt_address) {
 150                         if (sgpnt[i].alt_address != sgpnt[i].address) {
 151                           memcpy(sgpnt[i].alt_address, sgpnt[i].address, sgpnt[i].length);
 152                         };
 153                         scsi_free(sgpnt[i].address, sgpnt[i].length);
 154                       };
 155                     };
 156                     scsi_free(SCpnt->buffer, SCpnt->sglist_len);  /* Free list of scatter-gather pointers */
 157                     if(SCpnt->request.sector % 4) this_count -= 2;
 158 /* See   if there is a padding record at the end that needs to be removed */
 159                     if(this_count > SCpnt->request.nr_sectors)
 160                       this_count -= 2;
 161                   };
 162 
 163 #ifdef DEBUG
 164                 printk("(%x %x %x) ",SCpnt->request.bh, SCpnt->request.nr_sectors, 
 165                        this_count);
 166 #endif
 167                 if (SCpnt->request.nr_sectors > this_count)
 168                         {        
 169                         SCpnt->request.errors = 0;
 170                         if (!SCpnt->request.bh)
 171                           {
 172                             printk("sr.c: linked page request. (%x %x)",
 173                                   SCpnt->request.sector, this_count);
 174                             panic("Aiiiiiiiiiiiieeeeeeeee");
 175                           }
 176                         }
 177 
 178                   end_scsi_request(SCpnt, 1, this_count);  /* All done */
 179                   requeue_sr_request(SCpnt);
 180                   return;
 181                 } /* Normal completion */
 182 
 183         /* We only come through here if we have an error of some kind */
 184 
 185 /* Free up any indirection buffers we allocated for DMA purposes. */
 186         if (SCpnt->use_sg) {
 187           struct scatterlist * sgpnt;
 188           int i;
 189           sgpnt = (struct scatterlist *) SCpnt->buffer;
 190           for(i=0; i<SCpnt->use_sg; i++) {
 191             if (sgpnt[i].alt_address) {
 192               scsi_free(sgpnt[i].address, sgpnt[i].length);
 193             };
 194           };
 195           scsi_free(SCpnt->buffer, SCpnt->sglist_len);  /* Free list of scatter-gather pointers */
 196         } else {
 197           if (SCpnt->buffer != SCpnt->request.buffer)
 198             scsi_free(SCpnt->buffer, SCpnt->bufflen);
 199         };
 200 
 201         if (driver_byte(result) != 0) {
 202                 if ((SCpnt->sense_buffer[0] & 0x7f) == 0x70) {
 203                         if ((SCpnt->sense_buffer[2] & 0xf) == UNIT_ATTENTION) {
 204                                 /* detected disc change.  set a bit and quietly refuse  */
 205                                 /* further access.                                      */
 206                     
 207                                 scsi_CDs[DEVICE_NR(SCpnt->request.dev)].device->changed = 1;
 208                                 end_scsi_request(SCpnt, 0, this_count);
 209                                 requeue_sr_request(SCpnt);
 210                                 return;
 211                         }
 212                 }
 213             
 214                 if (SCpnt->sense_buffer[2] == ILLEGAL_REQUEST) {
 215                         printk("CD-ROM error: Drive reports ILLEGAL REQUEST.\n");
 216                         if (scsi_CDs[DEVICE_NR(SCpnt->request.dev)].ten) {
 217                                 scsi_CDs[DEVICE_NR(SCpnt->request.dev)].ten = 0;
 218                                 requeue_sr_request(SCpnt);
 219                                 result = 0;
 220                                 return;
 221                         } else {
 222                           printk("CD-ROM error: Drive reports %d.\n", SCpnt->sense_buffer[2]);                          
 223                           end_scsi_request(SCpnt, 0, this_count);
 224                           requeue_sr_request(SCpnt); /* Do next request */
 225                           return;
 226                         }
 227 
 228                 }
 229 
 230                 if (SCpnt->sense_buffer[2] == NOT_READY) {
 231                         printk("CDROM not ready.  Make sure you have a disc in the drive.\n");
 232                         end_scsi_request(SCpnt, 0, this_count);
 233                         requeue_sr_request(SCpnt); /* Do next request */
 234                         return;
 235                 };
 236               }
 237         
 238         /* We only get this far if we have an error we have not recognized */
 239         if(result) {
 240           printk("SCSI CD error : host %d id %d lun %d return code = %03x\n", 
 241                  scsi_CDs[DEVICE_NR(SCpnt->request.dev)].device->host_no, 
 242                  scsi_CDs[DEVICE_NR(SCpnt->request.dev)].device->id,
 243                  scsi_CDs[DEVICE_NR(SCpnt->request.dev)].device->lun,
 244                  result);
 245             
 246         if (status_byte(result) == CHECK_CONDITION)
 247             printk("\tSense class %x, sense error %x, extended sense %x\n",
 248                  sense_class(SCpnt->sense_buffer[0]), 
 249                  sense_error(SCpnt->sense_buffer[0]),
 250                  SCpnt->sense_buffer[2] & 0xf);
 251         
 252         end_scsi_request(SCpnt, 0, SCpnt->request.current_nr_sectors);
 253         requeue_sr_request(SCpnt);
 254         }
 255 }
 256 
 257 static int sr_open(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 258 {
 259         if(MINOR(inode->i_rdev) >= NR_SR || 
 260            !scsi_CDs[MINOR(inode->i_rdev)].device) return -ENODEV;   /* No such device */
 261 
 262         check_disk_change(inode->i_rdev);
 263 
 264         if(!scsi_CDs[MINOR(inode->i_rdev)].device->access_count++)
 265           sr_ioctl(inode, NULL, SCSI_IOCTL_DOORLOCK, 0);
 266         return 0;
 267 }
 268 
 269 
 270 /*
 271  * do_sr_request() is the request handler function for the sr driver.  Its function in life 
 272  * is to take block device requests, and translate them to SCSI commands.
 273  */
 274         
 275 static void do_sr_request (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 276 {
 277   Scsi_Cmnd * SCpnt = NULL;
 278   struct request * req = NULL;
 279   int flag = 0;
 280 
 281   while (1==1){
 282     if (CURRENT != NULL && CURRENT->dev == -1) return;
 283 
 284     INIT_REQUEST;
 285 
 286     if (flag++ == 0)
 287       SCpnt = allocate_device(&CURRENT,
 288                               scsi_CDs[DEVICE_NR(MINOR(CURRENT->dev))].device->index, 0); 
 289     else SCpnt = NULL;
 290 
 291 
 292 /* This is a performance enhancement.  We dig down into the request list and
 293    try and find a queueable request (i.e. device not busy, and host able to
 294    accept another command.  If we find one, then we queue it. This can
 295    make a big difference on systems with more than one disk drive.  We want
 296    to have the interrupts off when monkeying with the request list, because
 297    otherwise the kernel might try and slip in a request inbetween somewhere. */
 298 
 299     if (!SCpnt && NR_SR > 1){
 300       struct request *req1;
 301       req1 = NULL;
 302       cli();
 303       req = CURRENT;
 304       while(req){
 305         SCpnt = request_queueable(req,
 306                                   scsi_CDs[DEVICE_NR(MINOR(req->dev))].device->index);
 307         if(SCpnt) break;
 308         req1 = req;
 309         req = req->next;
 310       };
 311       if (SCpnt) {
 312         if (req == CURRENT) 
 313           CURRENT = CURRENT->next;
 314         else
 315           req1->next = req->next;
 316       };
 317       sti();
 318     };
 319     
 320     if (!SCpnt)
 321       return; /* Could not find anything to do */
 322     
 323   wake_up(&wait_for_request);
 324 
 325 /* Queue command */
 326   requeue_sr_request(SCpnt);
 327   };  /* While */
 328 }    
 329 
 330 void requeue_sr_request (Scsi_Cmnd * SCpnt)
     /* [previous][next][first][last][top][bottom][index][help] */
 331 {
 332         unsigned int dev, block, realcount;
 333         unsigned char cmd[10], *buffer, tries;
 334         int this_count, start, end_rec;
 335 
 336         tries = 2;
 337 
 338       repeat:
 339         if(SCpnt->request.dev <= 0)
 340           return do_sr_request();
 341 
 342         dev =  MINOR(SCpnt->request.dev);
 343         block = SCpnt->request.sector;  
 344         buffer = NULL;
 345         this_count = 0;
 346 
 347         if (dev >= NR_SR)
 348                 {
 349                 /* printk("CD-ROM request error: invalid device.\n");                   */
 350                 end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
 351                 tries = 2;
 352                 goto repeat;
 353                 }
 354 
 355         if (!scsi_CDs[dev].use)
 356                 {
 357                 /* printk("CD-ROM request error: device marked not in use.\n");         */
 358                 end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
 359                 tries = 2;
 360                 goto repeat;
 361                 }
 362 
 363         if (scsi_CDs[dev].device->changed)
 364                 {
 365 /* 
 366  * quietly refuse to do anything to a changed disc until the changed bit has been reset
 367  */
 368                 /* printk("CD-ROM has been changed.  Prohibiting further I/O.\n");      */
 369                 end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
 370                 tries = 2;
 371                 goto repeat;
 372                 }
 373         
 374         switch (SCpnt->request.cmd)
 375                 {
 376                 case WRITE:             
 377                         end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
 378                         goto repeat;
 379                         break;
 380                 case READ : 
 381                         cmd[0] = READ_6;
 382                         break;
 383                 default : 
 384                         printk ("Unknown sr command %d\r\n", SCpnt->request.cmd);
 385                         panic("");
 386                 }
 387         
 388         cmd[1] = (SCpnt->lun << 5) & 0xe0;
 389 
 390 /*
 391            Now do the grungy work of figuring out which sectors we need, and
 392            where in memory we are going to put them.
 393 
 394            The variables we need are:
 395 
 396            this_count= number of 512 byte sectors being read 
 397            block     = starting cdrom sector to read.
 398            realcount = # of cdrom sectors to read
 399 
 400            The major difference between a scsi disk and a scsi cdrom
 401 is that we will always use scatter-gather if we can, because we can
 402 work around the fact that the buffer cache has a block size of 1024,
 403 and we have 2048 byte sectors.  This code should work for buffers that
 404 are any multiple of 512 bytes long.  */
 405 
 406         SCpnt->use_sg = 0;
 407 
 408         if (scsi_hosts[SCpnt->host].sg_tablesize > 0 &&
 409             (!need_isa_buffer ||
 410             dma_free_sectors >= 10)) {
 411           struct buffer_head * bh;
 412           struct scatterlist * sgpnt;
 413           int count, this_count_max;
 414           bh = SCpnt->request.bh;
 415           this_count = 0;
 416           count = 0;
 417           this_count_max = (scsi_CDs[dev].ten ? 0xffff : 0xff) << 4;
 418           /* Calculate how many links we can use.  First see if we need
 419            a padding record at the start */
 420           this_count = SCpnt->request.sector % 4;
 421           if(this_count) count++;
 422           while(bh && count < scsi_hosts[SCpnt->host].sg_tablesize) {
 423             if ((this_count + (bh->b_size >> 9)) > this_count_max) break;
 424             this_count += (bh->b_size >> 9);
 425             count++;
 426             bh = bh->b_reqnext;
 427           };
 428           /* Fix up in case of an odd record at the end */
 429           end_rec = 0;
 430           if(this_count % 4) {
 431             if (count < scsi_hosts[SCpnt->host].sg_tablesize) {
 432               count++;
 433               end_rec = (4 - (this_count % 4)) << 9;
 434               this_count += 4 - (this_count % 4);
 435             } else {
 436               count--;
 437               this_count -= (this_count % 4);
 438             };
 439           };
 440           SCpnt->use_sg = count;  /* Number of chains */
 441           count = 512;/* scsi_malloc can only allocate in chunks of 512 bytes*/
 442           while( count < (SCpnt->use_sg * sizeof(struct scatterlist))) 
 443             count = count << 1;
 444           SCpnt->sglist_len = count;
 445           sgpnt = (struct scatterlist * ) scsi_malloc(count);
 446           if (!sgpnt) {
 447             printk("Warning - running *really* short on DMA buffers\n");
 448             SCpnt->use_sg = 0;  /* No memory left - bail out */
 449           } else {
 450             buffer = (char *) sgpnt;
 451             count = 0;
 452             bh = SCpnt->request.bh;
 453             if(SCpnt->request.sector % 4) {
 454               sgpnt[count].length = (SCpnt->request.sector % 4) << 9;
 455               sgpnt[count].address = scsi_malloc(sgpnt[count].length);
 456               if(!sgpnt[count].address) panic("SCSI DMA pool exhausted.");
 457               sgpnt[count].alt_address = sgpnt[count].address; /* Flag to delete
 458                                                                   if needed */
 459               count++;
 460             };
 461             for(bh = SCpnt->request.bh; count < SCpnt->use_sg; 
 462                 count++, bh = bh->b_reqnext) {
 463               if (bh) { /* Need a placeholder at the end of the record? */
 464                 sgpnt[count].address = bh->b_data;
 465                 sgpnt[count].length = bh->b_size;
 466                 sgpnt[count].alt_address = NULL;
 467               } else {
 468                 sgpnt[count].address = scsi_malloc(end_rec);
 469                 if(!sgpnt[count].address) panic("SCSI DMA pool exhausted.");
 470                 sgpnt[count].length = end_rec;
 471                 sgpnt[count].alt_address = sgpnt[count].address;
 472                 if (count+1 != SCpnt->use_sg) panic("Bad sr request list");
 473                 break;
 474               };
 475               if (((int) sgpnt[count].address) + sgpnt[count].length > 
 476                   ISA_DMA_THRESHOLD & (scsi_hosts[SCpnt->host].unchecked_isa_dma)) {
 477                 sgpnt[count].alt_address = sgpnt[count].address;
 478                 /* We try and avoid exhausting the DMA pool, since it is easier
 479                    to control usage here.  In other places we might have a more
 480                    pressing need, and we would be screwed if we ran out */
 481                 if(dma_free_sectors < (sgpnt[count].length >> 9) + 5) {
 482                   sgpnt[count].address = NULL;
 483                 } else {
 484                   sgpnt[count].address = scsi_malloc(sgpnt[count].length);
 485                 };
 486 /* If we start running low on DMA buffers, we abort the scatter-gather
 487    operation, and free all of the memory we have allocated.  We want to
 488    ensure that all scsi operations are able to do at least a non-scatter/gather
 489    operation */
 490                 if(sgpnt[count].address == NULL){ /* Out of dma memory */
 491                   printk("Warning: Running low on SCSI DMA buffers");
 492                   /* Try switching back to a non scatter-gather operation. */
 493                   while(--count){
 494                     if(sgpnt[count].alt_address) 
 495                       scsi_free(sgpnt[count].address, sgpnt[count].length);
 496                   };
 497                   SCpnt->use_sg = 0;
 498                   scsi_free(buffer, SCpnt->sglist_len);
 499                   break;
 500                 }; /* if address == NULL */
 501               };  /* if need DMA fixup */
 502             };  /* for loop to fill list */
 503 #ifdef DEBUG
 504             printk("SG: %d %d %d %d %d *** ",SCpnt->use_sg, SCpnt->request.sector,
 505                    this_count, 
 506                    SCpnt->request.current_nr_sectors,
 507                    SCpnt->request.nr_sectors);
 508             for(count=0; count<SCpnt->use_sg; count++)
 509               printk("SGlist: %d %x %x %x\n", count,
 510                      sgpnt[count].address, 
 511                      sgpnt[count].alt_address, 
 512                      sgpnt[count].length);
 513 #endif
 514           };  /* Able to allocate scatter-gather list */
 515         };
 516         
 517         if (SCpnt->use_sg == 0){
 518           /* We cannot use scatter-gather.  Do this the old fashion way */
 519           if (!SCpnt->request.bh)       
 520             this_count = SCpnt->request.nr_sectors;
 521           else
 522             this_count = (SCpnt->request.bh->b_size >> 9);
 523           
 524           start = block % 4;
 525           if (start)
 526             {                             
 527               this_count = ((this_count > 4 - start) ? 
 528                             (4 - start) : (this_count));
 529               buffer = scsi_malloc(2048);
 530             } 
 531           else if (this_count < 4)
 532             {
 533               buffer = scsi_malloc(2048);
 534             }
 535           else
 536             {
 537               this_count -= this_count % 4;
 538               buffer = SCpnt->request.buffer;
 539               if (((int) buffer) + (this_count << 9) > ISA_DMA_THRESHOLD & 
 540                   (scsi_hosts[SCpnt->host].unchecked_isa_dma))
 541                 buffer = scsi_malloc(this_count << 9);
 542             }
 543         };
 544 
 545         block = block >> 2; /* These are the sectors that the cdrom uses */
 546         realcount = (this_count + 3) / 4;
 547 
 548         if (((realcount > 0xff) || (block > 0x1fffff)) && scsi_CDs[dev].ten) 
 549                 {
 550                 if (realcount > 0xffff)
 551                         {
 552                         realcount = 0xffff;
 553                         this_count = realcount * 4;
 554                         }
 555 
 556                 cmd[0] += READ_10 - READ_6 ;
 557                 cmd[2] = (unsigned char) (block >> 24) & 0xff;
 558                 cmd[3] = (unsigned char) (block >> 16) & 0xff;
 559                 cmd[4] = (unsigned char) (block >> 8) & 0xff;
 560                 cmd[5] = (unsigned char) block & 0xff;
 561                 cmd[6] = cmd[9] = 0;
 562                 cmd[7] = (unsigned char) (realcount >> 8) & 0xff;
 563                 cmd[8] = (unsigned char) realcount & 0xff;
 564                 }
 565         else
 566                 {
 567                 if (realcount > 0xff)
 568                         {
 569                         realcount = 0xff;
 570                         this_count = realcount * 4;
 571                         }
 572         
 573                 cmd[1] |= (unsigned char) ((block >> 16) & 0x1f);
 574                 cmd[2] = (unsigned char) ((block >> 8) & 0xff);
 575                 cmd[3] = (unsigned char) block & 0xff;
 576                 cmd[4] = (unsigned char) realcount;
 577                 cmd[5] = 0;
 578                 }   
 579 
 580 #ifdef DEBUG
 581         printk("ReadCD: %d %d %d\n",block, realcount, buffer);
 582 #endif
 583 
 584         SCpnt->this_count = this_count;
 585         scsi_do_cmd (SCpnt, (void *) cmd, buffer, realcount << 11, 
 586                      rw_intr, SR_TIMEOUT, MAX_RETRIES);
 587 }
 588 
 589 unsigned long sr_init1(unsigned long mem_start, unsigned long mem_end){
     /* [previous][next][first][last][top][bottom][index][help] */
 590   scsi_CDs = (Scsi_CD *) mem_start;
 591   mem_start += MAX_SR * sizeof(Scsi_CD);
 592   return mem_start;
 593 };
 594 
 595 void sr_attach(Scsi_Device * SDp){
     /* [previous][next][first][last][top][bottom][index][help] */
 596   scsi_CDs[NR_SR++].device = SDp;
 597   if(NR_SR > MAX_SR) panic ("scsi_devices corrupt (sr)");
 598 };
 599 
 600 unsigned long sr_init(unsigned long memory_start, unsigned long memory_end)
     /* [previous][next][first][last][top][bottom][index][help] */
 601 {
 602         int i;
 603 
 604         if (register_blkdev(MAJOR_NR,"sr",&sr_fops)) {
 605                 printk("Unable to get major %d for SCSI-CD\n",MAJOR_NR);
 606                 return memory_start;
 607         }
 608         if(MAX_SR == 0) return memory_start;
 609 
 610         sr_sizes = (int *) memory_start;
 611         memory_start += MAX_SR * sizeof(int);
 612         memset(sr_sizes, 0, MAX_SR * sizeof(int));
 613 
 614         for (i = 0; i < NR_SR; ++i)
 615                 {
 616                 scsi_CDs[i].capacity = 0x1fffff;
 617                 scsi_CDs[i].sector_size = 2048;
 618                 scsi_CDs[i].use = 1;
 619                 scsi_CDs[i].ten = 1;
 620                 scsi_CDs[i].remap = 1;
 621                 sr_sizes[i] = scsi_CDs[i].capacity;
 622                 }
 623 
 624         blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
 625         blk_size[MAJOR_NR] = sr_sizes;  
 626 
 627         /* If our host adapter is capable of scatter-gather, then we increase
 628            the read-ahead to 8 blocks (16 sectors).  If not, we use
 629            a two block (4 sector) read ahead. */
 630         if(scsi_hosts[scsi_CDs[0].device->host_no].sg_tablesize)
 631           read_ahead[MAJOR_NR] = 16;  /* 16 sector read-ahead */
 632         else
 633           read_ahead[MAJOR_NR] = 4;  /* 4 sector read-ahead */
 634 
 635         return memory_start;
 636 }       

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