⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cdu31a.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
         {            end_request(1);         }         break;                  case WRITE:         end_request(0);         break;                  default:         panic("CDU31A: Unknown cmd");      }   }end_do_cdu31a_request:   spin_lock_irq(&io_request_lock);#if 0   /* After finished, cancel any pending operations. */   abort_read();#else   /* Start a timer to time out after a while to disable      the read. */   cdu31a_abort_timer.expires = jiffies + 2*HZ; /* Wait 2 seconds */   add_timer(&cdu31a_abort_timer);#endif   has_cd_task = NULL;   sony_inuse = 0;   wake_up_interruptible(&sony_wait);   restore_flags(flags);#if DEBUG   printk("Leaving do_cdu31a_request at %d\n", __LINE__);#endif}/* * Read the table of contents from the drive and set up TOC if * successful. */static voidsony_get_toc(void){   unsigned char res_reg[2];   unsigned int res_size;   unsigned char parms[1];   int session;   int num_spin_ups;   int totaltracks = 0;   int mint = 99;   int maxt = 0;#if DEBUG   printk("Entering sony_get_toc\n");#endif   num_spin_ups = 0;   if (!sony_toc_read)   {respinup_on_gettoc:      /* Ignore the result, since it might error if spinning already. */      do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);      do_sony_cd_cmd(SONY_READ_TOC_CMD, NULL, 0, res_reg, &res_size);      /* The drive sometimes returns error 0.  I don't know why, but ignore         it.  It seems to mean the drive has already done the operation. */      if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0)))      {         /* If the drive is already playing, it's ok.  */         if ((res_reg[1] == SONY_AUDIO_PLAYING_ERR) || (res_reg[1] == 0))         {            goto gettoc_drive_spinning;         }         /* If the drive says it is not spun up (even though we just did it!)            then retry the operation at least a few times. */         if (   (res_reg[1] == SONY_NOT_SPIN_ERR)             && (num_spin_ups < MAX_CDU31A_RETRIES))         {            num_spin_ups++;            goto respinup_on_gettoc;         }         printk("cdu31a: Error reading TOC: %x %s\n",                res_reg[0], translate_error(res_reg[1]));	 return;      }gettoc_drive_spinning:      /* The idea here is we keep asking for sessions until the command	 fails.  Then we know what the last valid session on the disk is.	 No need to check session 0, since session 0 is the same as session         1; the command returns different information if you give it 0.         */#if DEBUG      memset(&sony_toc, 0x0e, sizeof(sony_toc));      memset(&single_toc, 0x0f, sizeof(single_toc));#endif      session = 1;      while (1)      {/* This seems to slow things down enough to make it work.  This * appears to be a problem in do_sony_cd_cmd.  This printk seems  * to address the symptoms...  -Erik */#if 1         printk("cdu31a: Trying session %d\n", session);#endif	 parms[0] = session;	 do_sony_cd_cmd(SONY_READ_TOC_SPEC_CMD,			parms,			1, 			res_reg,			&res_size);#if DEBUG         printk("%2.2x %2.2x\n", res_reg[0], res_reg[1]);#endif	 if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20))	 {	    /* An error reading the TOC, this must be past the last session. */	     if (session == 1)		    printk("Yikes! Couldn't read any sessions!");	    break;         }#if DEBUG         printk("Reading session %d\n", session);#endif         parms[0] = session;         do_sony_cd_cmd(SONY_REQ_TOC_DATA_SPEC_CMD,		     parms,		     1, 		     (unsigned char *) &single_toc, 		     &res_size);         if ((res_size < 2) || ((single_toc.exec_status[0] & 0xf0) == 0x20))         {            printk("cdu31a: Error reading session %d: %x %s\n",                session,                single_toc.exec_status[0],                translate_error(single_toc.exec_status[1]));	    /* An error reading the TOC.  Return without sony_toc_read	       set. */	    return;         }#if DEBUG      printk("add0 %01x, con0 %01x, poi0 %02x, 1st trk %d, dsktyp %x, dum0 %x\n",              single_toc.address0, single_toc.control0, single_toc.point0,              bcd_to_int(single_toc.first_track_num), single_toc.disk_type, single_toc.dummy0);      printk("add1 %01x, con1 %01x, poi1 %02x, lst trk %d, dummy1 %x, dum2 %x\n",              single_toc.address1, single_toc.control1, single_toc.point1,              bcd_to_int(single_toc.last_track_num), single_toc.dummy1, single_toc.dummy2);      printk("add2 %01x, con2 %01x, poi2 %02x leadout start min %d, sec %d, frame %d\n",              single_toc.address2, single_toc.control2, single_toc.point2,              bcd_to_int(single_toc.lead_out_start_msf[0]),              bcd_to_int(single_toc.lead_out_start_msf[1]),              bcd_to_int(single_toc.lead_out_start_msf[2]));      if (res_size > 18 && single_toc.pointb0 > 0xaf)      printk("addb0 %01x, conb0 %01x, poib0 %02x, nextsession min %d, sec %d, frame %d\n"             "#mode5_ptrs %02d, max_start_outer_leadout_msf min %d, sec %d, frame %d\n",              single_toc.addressb0, single_toc.controlb0, single_toc.pointb0,              bcd_to_int(single_toc.next_poss_prog_area_msf[0]),              bcd_to_int(single_toc.next_poss_prog_area_msf[1]),              bcd_to_int(single_toc.next_poss_prog_area_msf[2]),              single_toc.num_mode_5_pointers,              bcd_to_int(single_toc.max_start_outer_leadout_msf[0]),              bcd_to_int(single_toc.max_start_outer_leadout_msf[1]),              bcd_to_int(single_toc.max_start_outer_leadout_msf[2]));      if (res_size > 27 && single_toc.pointb1 > 0xaf)      printk("addb1 %01x, conb1 %01x, poib1 %02x, %x %x %x %x #skipint_ptrs %d, #skiptrkassign %d %x\n",              single_toc.addressb1, single_toc.controlb1, single_toc.pointb1,              single_toc.dummyb0_1[0],              single_toc.dummyb0_1[1],              single_toc.dummyb0_1[2],              single_toc.dummyb0_1[3],              single_toc.num_skip_interval_pointers,              single_toc.num_skip_track_assignments,              single_toc.dummyb0_2);      if (res_size > 36 && single_toc.pointb2 > 0xaf)      printk("addb2 %01x, conb2 %01x, poib2 %02x, %02x %02x %02x %02x %02x %02x %02x\n",              single_toc.addressb2, single_toc.controlb2, single_toc.pointb2,              single_toc.tracksb2[0],              single_toc.tracksb2[1],              single_toc.tracksb2[2],              single_toc.tracksb2[3],              single_toc.tracksb2[4],              single_toc.tracksb2[5],              single_toc.tracksb2[6]);      if (res_size > 45 && single_toc.pointb3 > 0xaf)      printk("addb3 %01x, conb3 %01x, poib3 %02x, %02x %02x %02x %02x %02x %02x %02x\n",              single_toc.addressb3, single_toc.controlb3, single_toc.pointb3,              single_toc.tracksb3[0],              single_toc.tracksb3[1],              single_toc.tracksb3[2],              single_toc.tracksb3[3],              single_toc.tracksb3[4],              single_toc.tracksb3[5],              single_toc.tracksb3[6]);      if (res_size > 54 && single_toc.pointb4 > 0xaf)      printk("addb4 %01x, conb4 %01x, poib4 %02x, %02x %02x %02x %02x %02x %02x %02x\n",              single_toc.addressb4, single_toc.controlb4, single_toc.pointb4,              single_toc.tracksb4[0],              single_toc.tracksb4[1],              single_toc.tracksb4[2],              single_toc.tracksb4[3],              single_toc.tracksb4[4],              single_toc.tracksb4[5],              single_toc.tracksb4[6]);      if (res_size > 63 && single_toc.pointc0 > 0xaf)      printk("addc0 %01x, conc0 %01x, poic0 %02x, %02x %02x %02x %02x %02x %02x %02x\n",              single_toc.addressc0, single_toc.controlc0, single_toc.pointc0,              single_toc.dummyc0[0],              single_toc.dummyc0[1],              single_toc.dummyc0[2],              single_toc.dummyc0[3],              single_toc.dummyc0[4],              single_toc.dummyc0[5],              single_toc.dummyc0[6]);#endif#undef DEBUG#define DEBUG 0      sony_toc.lead_out_start_msf[0] = bcd_to_int(single_toc.lead_out_start_msf[0]);      sony_toc.lead_out_start_msf[1] = bcd_to_int(single_toc.lead_out_start_msf[1]);      sony_toc.lead_out_start_msf[2] = bcd_to_int(single_toc.lead_out_start_msf[2]);      sony_toc.lead_out_start_lba = single_toc.lead_out_start_lba =                    msf_to_log(sony_toc.lead_out_start_msf);      /* For points that do not exist, move the data over them	 to the right location. */      if (single_toc.pointb0 != 0xb0)      {	 memmove(((char *) &single_toc) + 27,		 ((char *) &single_toc) + 18,		 res_size - 18);	 res_size += 9;      }      else if (res_size > 18) {        sony_toc.lead_out_start_msf[0] = bcd_to_int(single_toc.max_start_outer_leadout_msf[0]);        sony_toc.lead_out_start_msf[1] = bcd_to_int(single_toc.max_start_outer_leadout_msf[1]);        sony_toc.lead_out_start_msf[2] = bcd_to_int(single_toc.max_start_outer_leadout_msf[2]);        sony_toc.lead_out_start_lba = msf_to_log(sony_toc.lead_out_start_msf);      }      if (single_toc.pointb1 != 0xb1)      {	 memmove(((char *) &single_toc) + 36,		((char *) &single_toc) + 27,		res_size - 27);	 res_size += 9;      }      if (single_toc.pointb2 != 0xb2)      {	 memmove(((char *) &single_toc) + 45,		((char *) &single_toc) + 36,		res_size - 36);	 res_size += 9;      }      if (single_toc.pointb3 != 0xb3)      {	 memmove(((char *) &single_toc) + 54,		((char *) &single_toc) + 45,		res_size - 45);	 res_size += 9;      }      if (single_toc.pointb4 != 0xb4)      {	 memmove(((char *) &single_toc) + 63,		((char *) &single_toc) + 54,		res_size - 54);	 res_size += 9;      }      if (single_toc.pointc0 != 0xc0)      {	 memmove(((char *) &single_toc) + 72,		((char *) &single_toc) + 63,		res_size - 63);	 res_size += 9;      }#if DEBUG      printk("start track lba %u,  leadout start lba %u\n",              single_toc.start_track_lba, single_toc.lead_out_start_lba);      { int i;        for (i = 0; i < 1 + bcd_to_int(single_toc.last_track_num)                          - bcd_to_int(single_toc.first_track_num); i++) {          printk("trk %02d: add 0x%01x, con 0x%01x,  track %02d, start min %02d, sec %02d, frame %02d\n",                 i, single_toc.tracks[i].address, single_toc.tracks[i].control,                 bcd_to_int(single_toc.tracks[i].track),                 bcd_to_int(single_toc.tracks[i].track_start_msf[0]),                 bcd_to_int(single_toc.tracks[i].track_start_msf[1]),                 bcd_to_int(single_toc.tracks[i].track_start_msf[2]));          if (mint > bcd_to_int(single_toc.tracks[i].track))            mint = bcd_to_int(single_toc.tracks[i].track);          if (maxt < bcd_to_int(single_toc.tracks[i].track))            maxt = bcd_to_int(single_toc.tracks[i].track);        }        printk("min track number %d,   max track number %d\n", mint, maxt);      }#endif         /* prepare a special table of contents for a CD-I disc. They don't have one. */         if (single_toc.disk_type == 0x10 &&             single_toc.first_track_num == 2 &&             single_toc.last_track_num == 2 /* CD-I */)         {            sony_toc.tracks[totaltracks].address = 1;	    sony_toc.tracks[totaltracks].control = 4; /* force data tracks */            sony_toc.tracks[totaltracks].track = 1;            sony_toc.tracks[totaltracks].track_start_msf[0] = 0;            sony_toc.tracks[totaltracks].track_start_msf[1] = 2;            sony_toc.tracks[totaltracks].track_start_msf[2] = 0;            mint = maxt = 1;            totaltracks++;         } else         /* gather track entries from this session */         { int i;	   for (i = 0; i < 1 + bcd_to_int(single_toc.last_track_num)                          - bcd_to_int(single_toc.first_track_num); i++, totaltracks++) {             sony_toc.tracks[totaltracks].address = single_toc.tracks[i].address;             sony_toc.tracks[totaltracks].control = single_toc.tracks[i].control;             sony_toc.tracks[totaltracks].track = bcd_to_int(single_toc.tracks[i].track);             sony_toc.tracks[totaltracks].track_start_msf[0] =                   bcd_to_int(single_toc.tracks[i].track_start_msf[0]);             sony_toc.tracks[totaltracks].track_start_msf[1] =                   bcd_to_int(single_toc.tracks[i].track_start_msf[1]);             sony_toc.tracks[totaltracks].track_start_msf[2] =                   bcd_to_int(single_toc.tracks[i].track_start_msf[2]);             if (i == 0)               single_toc.start_track_lba = msf_to_log(sony_toc.tracks[totaltracks].track_start_msf);             if (mint > sony_toc.tracks[totaltracks].track)               mint = sony_toc.tracks[totaltracks].track;             if (maxt < sony_toc.tracks[totaltracks].track)               maxt = sony_toc.tracks[totaltracks].track;           }         }         sony_toc.first_track_num = mint;         sony_toc.last_track_num = maxt;         /* Disk type of last session wins. For example:            CD-Extra has disk type 0 for the first session, so            a dumb HiFi CD player thinks it is a plain audio CD.	    We are interested in the disk type of the last session,            which is 0x20 (XA) for CD-Extra, so we can access the            data track ... */         sony_toc.disk_type = single_toc.disk_type;         sony_toc.sessions = session;         /* don't believe everything :-) */         if (session == 1)            single_toc.start_track_lba = 0;         sony_toc.start_track_lba = single_toc.start_track_lba;         if (session > 1 && single_toc.pointb0 == 0xb0 &&             sony_toc.lead_out_start_lba == single_toc.lead_out_start_lba)	 {            break;         }         /* Let's not get carried away... */         if (session > 40)         {            printk("cdu31a: too many sessions: %d\n", session);            break;         }         session++;      }      sony_toc.track_entries = totaltracks;      /* add one entry for the LAST track with track number CDROM_LEADOUT */       sony_toc.tracks[totaltracks].address = single_toc.address2;      sony_toc.tracks[totaltracks].control = single_toc.control2;      sony_toc.tracks[totaltracks].track = CDROM_LEADOUT;      sony_toc.tracks[totaltracks].track_start_msf[0] =              sony_toc.lead_out_start_msf[0];      sony_toc.tracks[totaltracks].track_start_msf[1] =              sony_toc.lead_out_start_msf[1];      sony_toc.tracks[totaltracks].track_start_msf[2] =              sony_toc.lead_out_start_msf[2];      sony_toc_read = 1;#undef DEBUG#if DEBUG   printk("Disk session %d, start track: %d, stop track: %d\n",	  session,	  single_toc.start_track_lba,	  single_toc.lead_out_start_lba);#endif   }#if DEBUG   printk("Leaving sony_get_toc\n");#endif}/* * Uniform cdrom interface function * return multisession offset and sector information */static int scd_get_last_session(struct cdrom_device_info *cdi,                                 struct cdrom_multisession *ms_info){   if (ms_info == NULL)      return 1;   if (!sony_toc_read)      sony_get_toc();   ms_info->addr_format = CDROM_LBA;   ms_info->addr.lba    = sony_toc.start_track_lba;   ms_info->xa_flag     = sony_toc.disk_type == SONY_XA_DISK_TYPE ||                          sony_toc.disk_type == 0x10 /* CDI */;   return 0;}/* * Search for a specific track in the table of contents. */static intfind_track(int track){   int i;   for (i = 0; i <= sony_toc.track_entries; i++)   {      if (sony_toc.tracks[i].track == track)      {         return i;      }   }   return -1;}/* * Read the subcode and put it in last_sony_subcode for future use. */static intread_subcode(void){   unsigned int res_size;   do_sony_cd_cmd(SONY_REQ_SUBCODE_ADDRESS_CMD,                  NULL,                  0,                   (unsigned char *) &last_sony_subcode,                   &res_size);   if ((res_size < 2) || ((last_sony_subcode.exec_status[0] & 0xf0) == 0x20))   {      printk("Sony CDROM error %s (read_subcode)\n",             translate_error(last_sony_subcode.exec_status[1]));      return -EIO;   }   last_sony_subcode.track_num = bcd_to_int(last_sony_subcode.track_num);   last_sony_subcode.index_num = bcd_to_int(last_sony_subcode.index_num);   last_sony_subcode.abs_msf[0] = bcd_to_int(last_sony_subcode.abs_msf[0]);   last_sony_subcode.abs_msf[1] = bcd_to_int(l

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -