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

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