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

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