root/kernel/blk_drv/scsi/sr.c

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

DEFINITIONS

This source file includes following definitions.
  1. sr_release
  2. check_cdrom_media_change
  3. rw_intr
  4. sr_open
  5. do_sr_request
  6. requeue_sr_request
  7. sr_init1
  8. sr_attach
  9. sr_init_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 11
  24 
  25 #include "../blk.h"
  26 #include "scsi.h"
  27 #include "hosts.h"
  28 #include "sr.h"
  29 #include "scsi_ioctl.h"   /* For the door lock/unlock commands */
  30 #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) scsi_CDs[target].device->changed = 0;
 106         return retval;
 107 }
 108 
 109 /*
 110  * rw_intr is the interrupt routine for the device driver.  It will be notified on the 
 111  * end of a SCSI read / write, and will take on of several actions based on success or failure.
 112  */
 113 
 114 static void rw_intr (Scsi_Cmnd * SCpnt)
     /* [previous][next][first][last][top][bottom][index][help] */
 115 {
 116         int result = SCpnt->result;
 117         int this_count = SCpnt->this_count;
 118 
 119 #ifdef DEBUG
 120         printk("sr.c done: %x %x\n",result, SCpnt->request.bh->b_data);
 121 #endif
 122         if (!result)
 123                 { /* No error */
 124                   if (SCpnt->use_sg == 0) {
 125                     if (SCpnt->buffer != SCpnt->request.buffer)
 126                       {
 127                         int offset;
 128                         offset = (SCpnt->request.sector % 4) << 9;
 129                         memcpy((char *)SCpnt->request.buffer, 
 130                                SCpnt->buffer + offset, 
 131                                this_count << 9);
 132                         /* Even though we are not using scatter-gather, we look
 133                            ahead and see if there is a linked request for the
 134                            other half of this buffer.  If there is, then satisfy
 135                            it. */
 136                         if((offset == 0) && this_count == 2 &&
 137                            SCpnt->request.nr_sectors > this_count && 
 138                            SCpnt->request.bh &&
 139                            SCpnt->request.bh->b_reqnext &&
 140                            SCpnt->request.bh->b_reqnext->b_size == 1024) {
 141                           memcpy((char *)SCpnt->request.bh->b_reqnext->b_data, 
 142                                  SCpnt->buffer + 1024, 
 143                                  1024);
 144                           this_count += 2;
 145                         };
 146                         
 147                         scsi_free(SCpnt->buffer, 2048);
 148                       }
 149                   } else {
 150                     struct scatterlist * sgpnt;
 151                     int i;
 152                     sgpnt = (struct scatterlist *) SCpnt->buffer;
 153                     for(i=0; i<SCpnt->use_sg; i++) {
 154                       if (sgpnt[i].alt_address) {
 155                         if (sgpnt[i].alt_address != sgpnt[i].address) {
 156                           memcpy(sgpnt[i].alt_address, sgpnt[i].address, sgpnt[i].length);
 157                         };
 158                         scsi_free(sgpnt[i].address, sgpnt[i].length);
 159                       };
 160                     };
 161                     scsi_free(SCpnt->buffer, SCpnt->sglist_len);  /* Free list of scatter-gather pointers */
 162                     if(SCpnt->request.sector % 4) this_count -= 2;
 163 /* See   if there is a padding record at the end that needs to be removed */
 164                     if(this_count > SCpnt->request.nr_sectors)
 165                       this_count -= 2;
 166                   };
 167 
 168 #ifdef DEBUG
 169                 printk("(%x %x %x) ",SCpnt->request.bh, SCpnt->request.nr_sectors, 
 170                        this_count);
 171 #endif
 172                 if (SCpnt->request.nr_sectors > this_count)
 173                         {        
 174                         SCpnt->request.errors = 0;
 175                         if (!SCpnt->request.bh)
 176                           {
 177                             printk("sr.c: linked page request. (%x %x)",
 178                                   SCpnt->request.sector, this_count);
 179                             panic("Aiiiiiiiiiiiieeeeeeeee");
 180                           }
 181                         }
 182 
 183                   end_scsi_request(SCpnt, 1, this_count);  /* All done */
 184                   requeue_sr_request(SCpnt);
 185                   return;
 186                 } /* Normal completion */
 187 
 188         /* We only come through here if we have an error of some kind */
 189 
 190 /* Free up any indirection buffers we allocated for DMA purposes. */
 191         if (SCpnt->use_sg) {
 192           struct scatterlist * sgpnt;
 193           int i;
 194           sgpnt = (struct scatterlist *) SCpnt->buffer;
 195           for(i=0; i<SCpnt->use_sg; i++) {
 196             if (sgpnt[i].alt_address) {
 197               scsi_free(sgpnt[i].address, sgpnt[i].length);
 198             };
 199           };
 200           scsi_free(SCpnt->buffer, SCpnt->sglist_len);  /* Free list of scatter-gather pointers */
 201         } else {
 202           if (SCpnt->buffer != SCpnt->request.buffer)
 203             scsi_free(SCpnt->buffer, SCpnt->bufflen);
 204         };
 205 
 206         if (driver_byte(result) != 0) {
 207                 if ((SCpnt->sense_buffer[0] & 0x7f) == 0x70) {
 208                         if ((SCpnt->sense_buffer[2] & 0xf) == UNIT_ATTENTION) {
 209                                 /* detected disc change.  set a bit and quietly refuse  */
 210                                 /* further access.                                      */
 211                     
 212                                 scsi_CDs[DEVICE_NR(SCpnt->request.dev)].device->changed = 1;
 213                                 end_scsi_request(SCpnt, 0, this_count);
 214                                 requeue_sr_request(SCpnt);
 215                                 return;
 216                         }
 217                 }
 218             
 219                 if (SCpnt->sense_buffer[2] == ILLEGAL_REQUEST) {
 220                         printk("CD-ROM error: Drive reports ILLEGAL REQUEST.\n");
 221                         if (scsi_CDs[DEVICE_NR(SCpnt->request.dev)].ten) {
 222                                 scsi_CDs[DEVICE_NR(SCpnt->request.dev)].ten = 0;
 223                                 requeue_sr_request(SCpnt);
 224                                 result = 0;
 225                                 return;
 226                         } else {
 227                           printk("CD-ROM error: Drive reports %d.\n", SCpnt->sense_buffer[2]);                          
 228                           end_scsi_request(SCpnt, 0, this_count);
 229                           requeue_sr_request(SCpnt); /* Do next request */
 230                           return;
 231                         }
 232 
 233                 }
 234 
 235                 if (SCpnt->sense_buffer[2] == NOT_READY) {
 236                         printk("CDROM not ready.  Make sure you have a disc in the drive.\n");
 237                         end_scsi_request(SCpnt, 0, this_count);
 238                         requeue_sr_request(SCpnt); /* Do next request */
 239                         return;
 240                 };
 241               }
 242         
 243         /* We only get this far if we have an error we have not recognized */
 244         if(result) {
 245           printk("SCSI CD error : host %d id %d lun %d return code = %03x\n", 
 246                  scsi_CDs[DEVICE_NR(SCpnt->request.dev)].device->host_no, 
 247                  scsi_CDs[DEVICE_NR(SCpnt->request.dev)].device->id,
 248                  scsi_CDs[DEVICE_NR(SCpnt->request.dev)].device->lun,
 249                  result);
 250             
 251           if (status_byte(result) == CHECK_CONDITION)
 252                   print_sense("sr", SCpnt);
 253           
 254           end_scsi_request(SCpnt, 0, SCpnt->request.current_nr_sectors);
 255           requeue_sr_request(SCpnt);
 256   }
 257 }
 258 
 259 static int sr_open(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 260 {
 261         if(MINOR(inode->i_rdev) >= NR_SR || 
 262            !scsi_CDs[MINOR(inode->i_rdev)].device) return -ENODEV;   /* No such device */
 263 
 264         check_disk_change(inode->i_rdev);
 265 
 266         if(!scsi_CDs[MINOR(inode->i_rdev)].device->access_count++)
 267           sr_ioctl(inode, NULL, SCSI_IOCTL_DOORLOCK, 0);
 268 
 269         /* If this device did not have media in the drive at boot time, then
 270            we would have been unable to get the sector size.  Check to see if
 271            this is the case, and try again.
 272            */
 273 
 274         if(scsi_CDs[MINOR(inode->i_rdev)].needs_sector_size)
 275           get_sectorsize(MINOR(inode->i_rdev));
 276 
 277         return 0;
 278 }
 279 
 280 
 281 /*
 282  * do_sr_request() is the request handler function for the sr driver.  Its function in life 
 283  * is to take block device requests, and translate them to SCSI commands.
 284  */
 285         
 286 static void do_sr_request (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 287 {
 288   Scsi_Cmnd * SCpnt = NULL;
 289   struct request * req = NULL;
 290   int flag = 0;
 291 
 292   while (1==1){
 293     cli();
 294     if (CURRENT != NULL && CURRENT->dev == -1) {
 295       sti();
 296       return;
 297     };
 298 
 299     INIT_SCSI_REQUEST;
 300 
 301     if (flag++ == 0)
 302       SCpnt = allocate_device(&CURRENT,
 303                               scsi_CDs[DEVICE_NR(MINOR(CURRENT->dev))].device->index, 0); 
 304     else SCpnt = NULL;
 305     sti();
 306 
 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) {
 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                         printk ("Unknown sr command %d\n", SCpnt->request.cmd);
 403                         panic("");
 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 (scsi_hosts[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 < scsi_hosts[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 < scsi_hosts[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 & (scsi_hosts[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                   (scsi_hosts[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         printk("ReadCD: %d %d %d %d\n",block, realcount, buffer, this_count);
 606 #endif
 607 
 608         SCpnt->this_count = this_count;
 609         scsi_do_cmd (SCpnt, (void *) cmd, buffer, 
 610                      realcount * scsi_CDs[dev].sector_size, 
 611                      rw_intr, SR_TIMEOUT, MAX_RETRIES);
 612 }
 613 
 614 unsigned long sr_init1(unsigned long mem_start, unsigned long mem_end){
     /* [previous][next][first][last][top][bottom][index][help] */
 615   scsi_CDs = (Scsi_CD *) mem_start;
 616   mem_start += MAX_SR * sizeof(Scsi_CD);
 617   return mem_start;
 618 };
 619 
 620 void sr_attach(Scsi_Device * SDp){
     /* [previous][next][first][last][top][bottom][index][help] */
 621   scsi_CDs[NR_SR++].device = SDp;
 622   if(NR_SR > MAX_SR) panic ("scsi_devices corrupt (sr)");
 623 };
 624 
 625 static void sr_init_done (Scsi_Cmnd * SCpnt)
     /* [previous][next][first][last][top][bottom][index][help] */
 626 {
 627   struct request * req;
 628   struct task_struct * p;
 629   
 630   req = &SCpnt->request;
 631   req->dev = 0xfffe; /* Busy, but indicate request done */
 632   
 633   if ((p = req->waiting) != NULL) {
 634     req->waiting = NULL;
 635     p->state = TASK_RUNNING;
 636     if (p->counter > current->counter)
 637       need_resched = 1;
 638   }
 639 }
 640 
 641 static void get_sectorsize(int i){
     /* [previous][next][first][last][top][bottom][index][help] */
 642   unsigned char cmd[10];
 643   unsigned char buffer[513];
 644   int the_result, retries;
 645   Scsi_Cmnd * SCpnt;
 646   
 647   SCpnt = allocate_device(NULL, scsi_CDs[i].device->index, 1);
 648 
 649   retries = 3;
 650   do {
 651     cmd[0] = READ_CAPACITY;
 652     cmd[1] = (scsi_CDs[i].device->lun << 5) & 0xe0;
 653     memset ((void *) &cmd[2], 0, 8);
 654     SCpnt->request.dev = 0xffff;  /* Mark as really busy */
 655     
 656     scsi_do_cmd (SCpnt,
 657                  (void *) cmd, (void *) buffer,
 658                  512, sr_init_done,  SR_TIMEOUT,
 659                  MAX_RETRIES);
 660     
 661     if (current == task[0])
 662       while(SCpnt->request.dev != 0xfffe);
 663     else
 664       if (SCpnt->request.dev != 0xfffe){
 665         SCpnt->request.waiting = current;
 666         current->state = TASK_UNINTERRUPTIBLE;
 667         while (SCpnt->request.dev != 0xfffe) schedule();
 668       };
 669     
 670     the_result = SCpnt->result;
 671     retries--;
 672     
 673   } while(the_result && retries);
 674   
 675   SCpnt->request.dev = -1;  /* Mark as not busy */
 676   
 677   wake_up(&scsi_devices[SCpnt->index].device_wait); 
 678 
 679   if (the_result) {
 680     scsi_CDs[i].capacity = 0x1fffff;
 681     scsi_CDs[i].sector_size = 2048;  /* A guess, just in case */
 682     scsi_CDs[i].needs_sector_size = 1;
 683   } else {
 684     scsi_CDs[i].capacity = (buffer[0] << 24) |
 685       (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
 686     scsi_CDs[i].sector_size = (buffer[4] << 24) |
 687       (buffer[5] << 16) | (buffer[6] << 8) | buffer[7];
 688     if(scsi_CDs[i].sector_size == 0) scsi_CDs[i].sector_size = 2048;
 689     if(scsi_CDs[i].sector_size != 2048 && 
 690        scsi_CDs[i].sector_size != 512) {
 691       printk ("scd%d : unsupported sector size %d.\n",
 692               i, scsi_CDs[i].sector_size);
 693       scsi_CDs[i].capacity = 0;
 694     };
 695     if(scsi_CDs[i].sector_size == 2048)
 696       scsi_CDs[i].capacity *= 4;
 697     scsi_CDs[i].needs_sector_size = 0;
 698   };
 699 }
 700 
 701 unsigned long sr_init(unsigned long memory_start, unsigned long memory_end)
     /* [previous][next][first][last][top][bottom][index][help] */
 702 {
 703         int i;
 704 
 705         if (register_blkdev(MAJOR_NR,"sr",&sr_fops)) {
 706                 printk("Unable to get major %d for SCSI-CD\n",MAJOR_NR);
 707                 return memory_start;
 708         }
 709         if(MAX_SR == 0) return memory_start;
 710 
 711         sr_sizes = (int *) memory_start;
 712         memory_start += MAX_SR * sizeof(int);
 713         memset(sr_sizes, 0, MAX_SR * sizeof(int));
 714 
 715         sr_blocksizes = (int *) memory_start;
 716         memory_start += MAX_SR * sizeof(int);
 717         for(i=0;i<MAX_SR;i++) sr_blocksizes[i] = 2048;
 718         blksize_size[MAJOR_NR] = sr_blocksizes;
 719 
 720         for (i = 0; i < NR_SR; ++i)
 721                 {
 722                   get_sectorsize(i);
 723                   printk("Scd sectorsize = %d bytes\n", scsi_CDs[i].sector_size);
 724                   scsi_CDs[i].use = 1;
 725                   scsi_CDs[i].ten = 1;
 726                   scsi_CDs[i].remap = 1;
 727                   sr_sizes[i] = scsi_CDs[i].capacity;
 728                 }
 729 
 730         blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
 731         blk_size[MAJOR_NR] = sr_sizes;  
 732 
 733         /* If our host adapter is capable of scatter-gather, then we increase
 734            the read-ahead to 8 blocks (16 sectors).  If not, we use
 735            a two block (4 sector) read ahead. */
 736         if(scsi_hosts[scsi_CDs[0].device->host_no].sg_tablesize)
 737           read_ahead[MAJOR_NR] = 16;  /* 16 sector read-ahead */
 738         else
 739           read_ahead[MAJOR_NR] = 4;  /* 4 sector read-ahead */
 740 
 741         return memory_start;
 742 }       

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