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

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