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

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