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

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