"Fossies" - the Fresh Open Source Software Archive

Member "cdfs-2.6.27/toc.c" (21 Dec 2009, 6940 Bytes) of package /linux/misc/old/cdfs-2.6.27.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "toc.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2 
    3   File toc.c - superblock and module routines for cdfs
    4 
    5   
    6   Copyright (c) 2003 by Laurent Pinchart
    7 
    8   
    9   This program is free software; you can redistribute it and/or modify
   10   it under the terms of the GNU General Public License as published by
   11   the Free Software Foundation; either version 2, or (at your option)
   12   any later version.
   13   
   14   This program is distributed in the hope that it will be useful,
   15   but WITHOUT ANY WARRANTY; without even the implied warranty of
   16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17   GNU General Public License for more details.
   18   
   19   You should have received a copy of the GNU General Public License
   20   along with this program; if not, write to the Free Software
   21   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
   22   
   23 */
   24 
   25 #include "cdfs.h"
   26 #include <scsi/scsi.h>
   27 
   28 /*
   29  * Send a SCSI command
   30  */
   31 static int cdfs_scsi_send_command( struct super_block *sb,
   32     char *cmd, int dir, void *buffer, int buflen )
   33 {
   34     struct cdrom_generic_command cd_cmd;
   35     struct request_sense sense;
   36 
   37     /* No need to zero the request sense as we don't use it anyway */
   38     memset( &cd_cmd, 0, sizeof( cd_cmd ) );
   39     memcpy( cd_cmd.cmd, cmd, CDROM_PACKET_SIZE );
   40 
   41     cd_cmd.data_direction = dir;
   42     cd_cmd.buffer = buffer;
   43     cd_cmd.buflen = buflen;
   44     cd_cmd.timeout = 20000;
   45     cd_cmd.sense = &sense;
   46     cd_cmd.quiet = 0;
   47     cd_cmd.stat = GOOD;
   48 
   49     if ( cdfs_ioctl( sb, CDROM_SEND_PACKET, (unsigned long)&cd_cmd ) < 0 || cd_cmd.stat != GOOD )
   50     {
   51         PRINT( "cdfs_scsi_send_command: CDROM_SEND_PACKET ioctl failed (status %d)\n", cd_cmd.stat );
   52         return -1;
   53     }
   54 
   55     return 0;
   56 }
   57 
   58 #define TIME2LBA(min, sec, frame) ((((min)*60)+(sec))*75+(frame))
   59 
   60 int cdfs_toc_read_full( struct super_block *sb )
   61 {
   62     unsigned char cmd[CDROM_PACKET_SIZE];
   63     unsigned char toc[12];
   64     int first_session, last_session;
   65     int sess, cur_track;
   66     int lead_out;
   67     cd * this_cd = cdfs_info( sb );
   68 
   69     /* Get the number of sessions */
   70     memset( cmd, 0, sizeof( cmd ) );
   71     memset( toc, 0, sizeof( toc ) );
   72     cmd[0] = READ_TOC;
   73     cmd[2] = 1;             /* Format : Session Info    */
   74     cmd[8] = sizeof( toc );
   75     if ( cdfs_scsi_send_command( sb, cmd, CGC_DATA_READ, toc, sizeof( toc ) ) < 0 )
   76         return -1;
   77 
   78     first_session = toc[2];
   79     last_session = toc[3];
   80     PRINT( "cdfs_toc_read_full: CD contains %d sessions\n", last_session - first_session + 1 ); 
   81 
   82     cur_track = T2I(0);
   83     this_cd->track[0].start_lba  = 0;
   84     this_cd->track[1].start_lba  = 0;
   85     this_cd->track[2].start_lba  = 0;
   86 
   87     /* Iterate through the sessions */
   88     cmd[1] = 2;             /* Addresses in TIME format */
   89     cmd[2] = 2;             /* Format : Full TOC        */
   90     lead_out = 0;
   91     for ( sess = first_session; sess <= last_session; ++sess )
   92     {
   93         unsigned char *stoc;
   94         int toc_size, tracks, j;
   95 
   96         /* Read the first 4 bytes of the full TOC to get the TOC length */
   97         cmd[6] = sess;          /* Session number           */
   98     cmd[7] = 0;         /* Allocation length MSB    */
   99     cmd[8] = 4;         /* Allocation length LSB    */
  100 
  101         if ( cdfs_scsi_send_command( sb, cmd, CGC_DATA_READ, toc, sizeof( toc ) ) < 0 )
  102     {
  103         printk( "cdfs_read_toc: unable to read session %d toc header, skipping\n", sess );
  104         continue;
  105     }
  106 
  107         /* Allocate memory for the session TOC */
  108         toc_size = ( toc[0] << 8 ) + toc[1] + 2;
  109     tracks = ( toc_size - 4 ) / 11;
  110         PRINT( "cdfs_toc_read_full: session %d contains %d track descriptors\n", sess, tracks ); 
  111     if ( tracks == 0 )
  112         continue;
  113 
  114         if ( ! ( stoc = kmalloc( toc_size, GFP_KERNEL ) ) )
  115     {
  116         printk( "cdfs_read_toc: unable to allocate memory for session %d toc, skipping\n", sess );
  117         continue;
  118     }
  119 
  120         /* Read the full session TOC */
  121         cmd[7] = toc_size >> 8;
  122     cmd[8] = toc_size & 0xff;
  123         if ( cdfs_scsi_send_command( sb, cmd, CGC_DATA_READ, stoc, toc_size ) < 0 )
  124     {
  125         printk( "cdfs_read_toc: unable to read session %d toc, skipping\n", sess );
  126         kfree( stoc );
  127         continue;
  128     }
  129 
  130         /* Iterate through the tracks descriptors */
  131     lead_out = 0;
  132         for ( j = 0; j < tracks; ++j )
  133     {
  134         struct track_descriptor
  135         {
  136             unsigned char session;
  137         unsigned char adr_control;
  138         unsigned char tno;
  139         unsigned char point;
  140         unsigned char min;
  141         unsigned char sec;
  142         unsigned char frame;
  143         unsigned char zero;
  144         unsigned char pmin;
  145         unsigned char psec;
  146         unsigned char pframe;
  147         } *track = (struct track_descriptor*)&stoc[11*j+4];
  148 
  149         if ( ( track->adr_control >> 4 ) != 1 )
  150             continue;
  151 
  152         if ( track->point == 0xa2 )
  153             /* Lead out start. Needed to compute the size of the last track */
  154         lead_out = TIME2LBA( track->pmin, track->psec, track->pframe ) - 150;
  155         else if ( track->point <= 0x63 )
  156         {
  157             /* This is a true track descriptor */
  158         this_cd->track[cur_track].type = ( track->adr_control & 0x04 ) ? DATA : AUDIO;
  159         this_cd->track[cur_track].time = get_seconds();
  160         this_cd->track[cur_track].start_lba = TIME2LBA( track->pmin, track->psec, track->pframe ) - 150;
  161         this_cd->track[cur_track-1].stop_lba = this_cd->track[cur_track].start_lba - 1;
  162                 PRINT("Start[%d]: %d\n", cur_track, this_cd->track[cur_track].start_lba);
  163         ++cur_track;
  164         }
  165     }
  166     this_cd->track[cur_track-1].stop_lba = lead_out - 1;
  167 
  168     kfree( stoc );
  169     break; ////////////
  170     }
  171 
  172     this_cd->track[cur_track].start_lba = lead_out;
  173     this_cd->tracks = cur_track-T2I(0);
  174     return 0;
  175 }
  176 
  177 int cdfs_toc_read( struct super_block *sb )
  178 {
  179     int i, t;
  180     struct cdrom_tochdr hdr;
  181     struct cdrom_tocentry entry;   
  182     cd * this_cd = cdfs_info( sb );
  183 
  184     if ( cdfs_ioctl( sb, CDROMREADTOCHDR, (unsigned long)&hdr ) )
  185     {
  186         printk( "ioctl(CDROMREADTOCHDR) failed\n" );
  187         return -1;
  188     }
  189 
  190     this_cd->tracks = hdr.cdth_trk1 - hdr.cdth_trk0 + 1;
  191     PRINT( "CD contains %d tracks: %d-%d\n", this_cd->tracks, hdr.cdth_trk0, hdr.cdth_trk1 );
  192 
  193     /* Collect track info */
  194     entry.cdte_format = CDROM_LBA;
  195 
  196     this_cd->track[0].start_lba  = 0;
  197     this_cd->track[1].start_lba  = 0;
  198     this_cd->track[2].start_lba  = 0;
  199     for ( t = this_cd->tracks; t >= 0; --t )
  200     {
  201         i = T2I(t);
  202 
  203         entry.cdte_track = ( t == this_cd->tracks ) ? CDROM_LEADOUT : t+1;
  204         PRINT( "Read track %d/%d/%d\n", entry.cdte_track, t, i );
  205 
  206         if ( cdfs_ioctl( sb, CDROMREADTOCENTRY, (unsigned long)&entry ) )
  207     {
  208             printk( "ioctl(CDROMREADTOCENTRY) failed\n" );
  209             return -1;
  210         }
  211 
  212         this_cd->track[i].start_lba  = entry.cdte_addr.lba;
  213         this_cd->track[i].stop_lba   = this_cd->track[i+1].start_lba - 1;
  214 
  215         PRINT("Start[%d]: %d\n", i, this_cd->track[i].start_lba);
  216 
  217         if ( t != this_cd->tracks ) /* all tracks but the LEADOUT */
  218     {
  219             this_cd->track[i].type = ( entry.cdte_ctrl & CDROM_DATA_TRACK ) ? DATA : AUDIO;
  220             this_cd->track[i].time = get_seconds();
  221         }
  222     }
  223 
  224     return 0;
  225 }