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

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