sbpcd.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:164k
- drvcmd[3]=(block>>8)&0xFF;
- drvcmd[4]=block&0xFF;
- #endif /* TEST_UPC */
- response_count=0;
- flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
- }
- else if (fam2_drive)
- {
- return (-1);
- }
- else if (famT_drive)
- {
- return (-1);
- }
- i=cmd_out();
- if (i<0)
- {
- msg(DBG_000,"cc_ReadUPC cmd_out: err %dn", i);
- return (i);
- }
- if (fam0L_drive)
- {
- response_count=16;
- if (famL_drive) flags_cmd_out=f_putcmd;
- i=cc_ReadPacket();
- if (i<0)
- {
- msg(DBG_000,"cc_ReadUPC ReadPacket: err %dn", i);
- return (i);
- }
- }
- #if TEST_UPC
- checksum=0;
- #endif /* TEST_UPC */
- for (i=0;i<(fam1_drive?8:16);i++)
- {
- #if TEST_UPC
- checksum |= infobuf[i];
- #endif /* TEST_UPC */
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- }
- msgbuf[i*3]=0;
- msg(DBG_UPC,"UPC info:%sn", msgbuf);
- #if TEST_UPC
- if ((checksum&0x7F)!=0) break;
- }
- #endif /* TEST_UPC */
- D_S[d].UPC_ctl_adr=0;
- if (fam1_drive) i=0;
- else i=2;
- if ((infobuf[i]&0x80)!=0)
- {
- convert_UPC(&infobuf[i]);
- D_S[d].UPC_ctl_adr = (D_S[d].TocEnt_ctl_adr & 0xF0) | 0x02;
- }
- for (i=0;i<7;i++)
- sprintf(&msgbuf[i*3], " %02X", D_S[d].UPC_buf[i]);
- sprintf(&msgbuf[i*3], " (%02X)", D_S[d].UPC_ctl_adr);
- msgbuf[i*3+5]=0;
- msg(DBG_UPC,"UPC code:%sn", msgbuf);
- D_S[d].diskstate_flags |= upc_bit;
- return (0);
- }
- static int sbpcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
- {
- int i;
- unsigned char *mcnp = mcn->medium_catalog_number;
- unsigned char *resp;
- D_S[d].diskstate_flags &= ~upc_bit;
- clr_cmdbuf();
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_READ_UPC;
- response_count=8;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam0L_drive)
- {
- drvcmd[0]=CMD0_READ_UPC;
- response_count=0;
- flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
- }
- else if (fam2_drive)
- {
- return (-1);
- }
- else if (famT_drive)
- {
- return (-1);
- }
- i=cmd_out();
- if (i<0)
- {
- msg(DBG_000,"cc_ReadUPC cmd_out: err %dn", i);
- return (i);
- }
- if (fam0L_drive)
- {
- response_count=16;
- if (famL_drive) flags_cmd_out=f_putcmd;
- i=cc_ReadPacket();
- if (i<0)
- {
- msg(DBG_000,"cc_ReadUPC ReadPacket: err %dn", i);
- return (i);
- }
- }
- D_S[d].UPC_ctl_adr=0;
- if (fam1_drive) i=0;
- else i=2;
- resp = infobuf + i;
- if (*resp++ == 0x80) {
- /* packed bcd to single ASCII digits */
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- }
- *mcnp = ' ';
- D_S[d].diskstate_flags |= upc_bit;
- return (0);
- }
- /*==========================================================================*/
- static int cc_CheckMultiSession(void)
- {
- int i;
-
- if (fam2_drive) return (0);
- D_S[d].f_multisession=0;
- D_S[d].lba_multi=0;
- if (fam0_drive) return (0);
- clr_cmdbuf();
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_MULTISESS;
- response_count=6;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- i=cmd_out();
- if (i<0) return (i);
- if ((infobuf[0]&0x80)!=0)
- {
- D_S[d].f_multisession=1;
- D_S[d].lba_multi=msf2blk(make32(make16(0,infobuf[1]),
- make16(infobuf[2],infobuf[3])));
- }
- }
- else if (famLV_drive)
- {
- drvcmd[0]=CMDL_MULTISESS;
- drvcmd[1]=3;
- drvcmd[2]=1;
- response_count=8;
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- if (i<0) return (i);
- D_S[d].lba_multi=msf2blk(make32(make16(0,infobuf[5]),
- make16(infobuf[6],infobuf[7])));
- }
- else if (famT_drive)
- {
- response_count=12;
- drvcmd[0]=CMDT_DISKINFO;
- drvcmd[1]=0x02;
- drvcmd[6]=0;
- drvcmd[8]=response_count;
- drvcmd[9]=0x40;
- i=cmd_out();
- if (i<0) return (i);
- if (i<response_count) return (-100-i);
- D_S[d].first_session=infobuf[2];
- D_S[d].last_session=infobuf[3];
- D_S[d].track_of_last_session=infobuf[6];
- if (D_S[d].first_session!=D_S[d].last_session)
- {
- D_S[d].f_multisession=1;
- D_S[d].lba_multi=msf2blk(make32(make16(0,infobuf[9]),make16(infobuf[10],infobuf[11])));
- }
- }
- for (i=0;i<response_count;i++)
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_MUL,"MultiSession Info:%s (%d)n", msgbuf, D_S[d].lba_multi);
- if (D_S[d].lba_multi>200)
- {
- D_S[d].f_multisession=1;
- msg(DBG_MUL,"MultiSession base: %06Xn", D_S[d].lba_multi);
- }
- return (0);
- }
- /*==========================================================================*/
- #if FUTURE
- static int cc_SubChanInfo(int frame, int count, u_char *buffer)
- /* "frame" is a RED BOOK (msf-bin) address */
- {
- int i;
-
- if (fam0LV_drive) return (-ENOSYS); /* drive firmware lacks it */
- if (famT_drive)
- {
- return (-1);
- }
- #if 0
- if (D_S[d].audio_state!=audio_playing) return (-ENODATA);
- #endif
- clr_cmdbuf();
- drvcmd[0]=CMD1_SUBCHANINF;
- drvcmd[1]=(frame>>16)&0xFF;
- drvcmd[2]=(frame>>8)&0xFF;
- drvcmd[3]=frame&0xFF;
- drvcmd[5]=(count>>8)&0xFF;
- drvcmd[6]=count&0xFF;
- flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
- cmd_type=READ_SC;
- D_S[d].frame_size=CD_FRAMESIZE_SUB;
- i=cmd_out(); /* which buffer to use? */
- return (i);
- }
- #endif /* FUTURE */
- /*==========================================================================*/
- static void __init check_datarate(void)
- {
- int i=0;
-
- msg(DBG_IOX,"check_datarate entered.n");
- datarate=0;
- #if TEST_STI
- for (i=0;i<=1000;i++) printk(".");
- #endif
- /* set a timer to make (timed_out_delay!=0) after 1.1 seconds */
- #if 1
- del_timer(&delay_timer);
- #endif
- delay_timer.expires=jiffies+11*HZ/10;
- timed_out_delay=0;
- add_timer(&delay_timer);
- #if 0
- msg(DBG_TIM,"delay timer started (11*HZ/10).n");
- #endif
- do
- {
- i=inb(CDi_status);
- datarate++;
- #if 1
- if (datarate>0x6FFFFFFF) break;
- #endif
- }
- while (!timed_out_delay);
- del_timer(&delay_timer);
- #if 0
- msg(DBG_TIM,"datarate: %04Xn", datarate);
- #endif
- if (datarate<65536) datarate=65536;
- maxtim16=datarate*16;
- maxtim04=datarate*4;
- maxtim02=datarate*2;
- maxtim_8=datarate/32;
- #if LONG_TIMING
- maxtim_data=datarate/100;
- #else
- maxtim_data=datarate/300;
- #endif /* LONG_TIMING */
- #if 0
- msg(DBG_TIM,"maxtim_8 %d, maxtim_data %d.n", maxtim_8, maxtim_data);
- #endif
- }
- /*==========================================================================*/
- #if 0
- static int c2_ReadError(int fam)
- {
- int i;
-
- clr_cmdbuf();
- response_count=9;
- clr_respo_buf(9);
- if (fam==1)
- {
- drvcmd[0]=CMD0_READ_ERR; /* same as CMD1_ and CMDL_ */
- i=do_cmd(f_putcmd|f_lopsta|f_getsta|f_ResponseStatus);
- }
- else if (fam==2)
- {
- drvcmd[0]=CMD2_READ_ERR;
- i=do_cmd(f_putcmd);
- }
- else return (-1);
- return (i);
- }
- #endif
- /*==========================================================================*/
- static void __init ask_mail(void)
- {
- int i;
-
- msg(DBG_INF, "please mail the following lines to emoenke@gwdg.den");
- msg(DBG_INF, "(don't mail if you are not using the actual kernel):n");
- msg(DBG_INF, "%sn", VERSION);
- msg(DBG_INF, "address %03X, type %s, drive %s (ID %d)n",
- CDo_command, type, D_S[d].drive_model, D_S[d].drv_id);
- for (i=0;i<12;i++)
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_INF,"infobuf =%sn", msgbuf);
- for (i=0;i<12;i++)
- sprintf(&msgbuf[i*3], " %c ", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_INF,"infobuf =%sn", msgbuf);
- }
- /*==========================================================================*/
- static int __init check_version(void)
- {
- int i, j, l;
- int teac_possible=0;
-
- msg(DBG_INI,"check_version: id=%d, d=%d.n", D_S[d].drv_id, d);
- D_S[d].drv_type=0;
- /* check for CR-52x, CR-56x, LCS-7260 and ECS-AT */
- /* clear any pending error state */
- clr_cmdbuf();
- drvcmd[0]=CMD0_READ_ERR; /* same as CMD1_ and CMDL_ */
- response_count=9;
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- if (i<0) msg(DBG_INI,"CMD0_READ_ERR returns %d (ok anyway).n",i);
- /* read drive version */
- clr_cmdbuf();
- for (i=0;i<12;i++) infobuf[i]=0;
- drvcmd[0]=CMD0_READ_VER; /* same as CMD1_ and CMDL_ */
- response_count=12; /* fam1: only 11 */
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- if (i<-1) msg(DBG_INI,"CMD0_READ_VER returns %dn",i);
- if (i==-11) teac_possible++;
- j=0;
- for (i=0;i<12;i++) j+=infobuf[i];
- if (j)
- {
- for (i=0;i<12;i++)
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_ECS,"infobuf =%sn", msgbuf);
- for (i=0;i<12;i++)
- sprintf(&msgbuf[i*3], " %c ", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_ECS,"infobuf =%sn", msgbuf);
- }
- for (i=0;i<4;i++) if (infobuf[i]!=family1[i]) break;
- if (i==4)
- {
- D_S[d].drive_model[0]='C';
- D_S[d].drive_model[1]='R';
- D_S[d].drive_model[2]='-';
- D_S[d].drive_model[3]='5';
- D_S[d].drive_model[4]=infobuf[i++];
- D_S[d].drive_model[5]=infobuf[i++];
- D_S[d].drive_model[6]=0;
- D_S[d].drv_type=drv_fam1;
- }
- if (!D_S[d].drv_type)
- {
- for (i=0;i<8;i++) if (infobuf[i]!=family0[i]) break;
- if (i==8)
- {
- D_S[d].drive_model[0]='C';
- D_S[d].drive_model[1]='R';
- D_S[d].drive_model[2]='-';
- D_S[d].drive_model[3]='5';
- D_S[d].drive_model[4]='2';
- D_S[d].drive_model[5]='x';
- D_S[d].drive_model[6]=0;
- D_S[d].drv_type=drv_fam0;
- }
- }
- if (!D_S[d].drv_type)
- {
- for (i=0;i<8;i++) if (infobuf[i]!=familyL[i]) break;
- if (i==8)
- {
- for (j=0;j<8;j++)
- D_S[d].drive_model[j]=infobuf[j];
- D_S[d].drive_model[8]=0;
- D_S[d].drv_type=drv_famL;
- }
- }
- if (!D_S[d].drv_type)
- {
- for (i=0;i<6;i++) if (infobuf[i]!=familyV[i]) break;
- if (i==6)
- {
- for (j=0;j<6;j++)
- D_S[d].drive_model[j]=infobuf[j];
- D_S[d].drive_model[6]=0;
- D_S[d].drv_type=drv_famV;
- i+=2; /* 2 blanks before version */
- }
- }
- if (!D_S[d].drv_type)
- {
- /* check for CD200 */
- clr_cmdbuf();
- drvcmd[0]=CMD2_READ_ERR;
- response_count=9;
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- if (i<0) msg(DBG_INI,"CMD2_READERR returns %d (ok anyway).n",i);
- if (i<0) msg(DBG_000,"CMD2_READERR returns %d (ok anyway).n",i);
- /* read drive version */
- clr_cmdbuf();
- for (i=0;i<12;i++) infobuf[i]=0;
- if (sbpro_type==1) OUT(CDo_sel_i_d,0);
- #if 0
- OUT(CDo_reset,0);
- sbp_sleep(6*HZ);
- OUT(CDo_enable,D_S[d].drv_sel);
- #endif
- drvcmd[0]=CMD2_READ_VER;
- response_count=12;
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- if (i<0) msg(DBG_INI,"CMD2_READ_VER returns %dn",i);
- if (i==-7) teac_possible++;
- j=0;
- for (i=0;i<12;i++) j+=infobuf[i];
- if (j)
- {
- for (i=0;i<12;i++)
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_IDX,"infobuf =%sn", msgbuf);
- for (i=0;i<12;i++)
- sprintf(&msgbuf[i*3], " %c ", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_IDX,"infobuf =%sn", msgbuf);
- }
- if (i>=0)
- {
- for (i=0;i<5;i++) if (infobuf[i]!=family2[i]) break;
- if (i==5)
- {
- D_S[d].drive_model[0]='C';
- D_S[d].drive_model[1]='D';
- D_S[d].drive_model[2]='2';
- D_S[d].drive_model[3]='0';
- D_S[d].drive_model[4]='0';
- D_S[d].drive_model[5]=infobuf[i++];
- D_S[d].drive_model[6]=infobuf[i++];
- D_S[d].drive_model[7]=0;
- D_S[d].drv_type=drv_fam2;
- }
- }
- }
- if (!D_S[d].drv_type)
- {
- /* check for TEAC CD-55A */
- msg(DBG_TEA,"teac_possible: %dn",teac_possible);
- for (j=1;j<=((D_S[d].drv_id==0)?3:1);j++)
- {
- for (l=1;l<=((D_S[d].drv_id==0)?10:1);l++)
- {
- msg(DBG_TEA,"TEAC reset #%d-%d.n", j, l);
- if (sbpro_type==1) OUT(CDo_reset,0);
- else
- {
- OUT(CDo_enable,D_S[d].drv_sel);
- OUT(CDo_sel_i_d,0);
- OUT(CDo_command,CMDT_RESET);
- for (i=0;i<9;i++) OUT(CDo_command,0);
- }
- sbp_sleep(5*HZ/10);
- OUT(CDo_enable,D_S[d].drv_sel);
- OUT(CDo_sel_i_d,0);
- i=inb(CDi_status);
- msg(DBG_TEA,"TEAC CDi_status: %02X.n",i);
- #if 0
- if (i&s_not_result_ready) continue; /* drive not present or ready */
- #endif
- i=inb(CDi_info);
- msg(DBG_TEA,"TEAC CDi_info: %02X.n",i);
- if (i==0x55) break; /* drive found */
- }
- if (i==0x55) break; /* drive found */
- }
- if (i==0x55) /* drive found */
- {
- msg(DBG_TEA,"TEAC drive found.n");
- clr_cmdbuf();
- flags_cmd_out=f_putcmd;
- response_count=12;
- drvcmd[0]=CMDT_READ_VER;
- drvcmd[4]=response_count;
- for (i=0;i<12;i++) infobuf[i]=0;
- i=cmd_out_T();
- if (i!=0) msg(DBG_TEA,"cmd_out_T(CMDT_READ_VER) returns %d.n",i);
- for (i=1;i<6;i++) if (infobuf[i]!=familyT[i-1]) break;
- if (i==6)
- {
- D_S[d].drive_model[0]='C';
- D_S[d].drive_model[1]='D';
- D_S[d].drive_model[2]='-';
- D_S[d].drive_model[3]='5';
- D_S[d].drive_model[4]='5';
- D_S[d].drive_model[5]=0;
- D_S[d].drv_type=drv_famT;
- }
- }
- }
- if (!D_S[d].drv_type)
- {
- msg(DBG_TEA,"no drive found at address %03X under ID %d.n",CDo_command,D_S[d].drv_id);
- return (-522);
- }
- for (j=0;j<4;j++) D_S[d].firmware_version[j]=infobuf[i+j];
- if (famL_drive)
- {
- u_char lcs_firm_e1[]="A E1";
- u_char lcs_firm_f4[]="A4F4";
-
- for (j=0;j<4;j++)
- if (D_S[d].firmware_version[j]!=lcs_firm_e1[j]) break;
- if (j==4) D_S[d].drv_type=drv_e1;
-
- for (j=0;j<4;j++)
- if (D_S[d].firmware_version[j]!=lcs_firm_f4[j]) break;
- if (j==4) D_S[d].drv_type=drv_f4;
- if (D_S[d].drv_type==drv_famL) ask_mail();
- }
- else if (famT_drive)
- {
- j=infobuf[4]; /* one-byte version??? - here: 0x15 */
- if (j=='5')
- {
- D_S[d].firmware_version[0]=infobuf[7];
- D_S[d].firmware_version[1]=infobuf[8];
- D_S[d].firmware_version[2]=infobuf[10];
- D_S[d].firmware_version[3]=infobuf[11];
- }
- else
- {
- if (j!=0x15) ask_mail();
- D_S[d].firmware_version[0]='0';
- D_S[d].firmware_version[1]='.';
- D_S[d].firmware_version[2]='0'+(j>>4);
- D_S[d].firmware_version[3]='0'+(j&0x0f);
- }
- }
- else /* CR-52x, CR-56x, CD200, ECS-AT */
- {
- j = (D_S[d].firmware_version[0] & 0x0F) * 100 +
- (D_S[d].firmware_version[2] & 0x0F) *10 +
- (D_S[d].firmware_version[3] & 0x0F);
- if (fam0_drive)
- {
- if (j<200) D_S[d].drv_type=drv_199;
- else if (j<201) D_S[d].drv_type=drv_200;
- else if (j<210) D_S[d].drv_type=drv_201;
- else if (j<211) D_S[d].drv_type=drv_210;
- else if (j<300) D_S[d].drv_type=drv_211;
- else if (j>=300) D_S[d].drv_type=drv_300;
- }
- else if (fam1_drive)
- {
- if (j<100) D_S[d].drv_type=drv_099;
- else
- {
- D_S[d].drv_type=drv_100;
- if ((j!=500)&&(j!=102)) ask_mail();
- }
- }
- else if (fam2_drive)
- {
- if (D_S[d].drive_model[5]=='F')
- {
- if ((j!=1)&&(j!=35)&&(j!=200)&&(j!=210))
- ask_mail(); /* unknown version at time */
- }
- else
- {
- msg(DBG_INF,"this CD200 drive is not fully supported yet - only audio will work.n");
- if ((j!=101)&&(j!=35))
- ask_mail(); /* unknown version at time */
- }
- }
- else if (famV_drive)
- {
- if ((j==100)||(j==150)) D_S[d].drv_type=drv_at;
- ask_mail(); /* hopefully we get some feedback by this */
- }
- }
- msg(DBG_LCS,"drive type %02Xn",D_S[d].drv_type);
- msg(DBG_INI,"check_version done.n");
- return (0);
- }
- /*==========================================================================*/
- static void switch_drive(int i)
- {
- d=i;
- OUT(CDo_enable,D_S[d].drv_sel);
- msg(DBG_DID,"drive %d (ID=%d) activated.n", i, D_S[d].drv_id);
- return;
- }
- /*==========================================================================*/
- #ifdef PATH_CHECK
- /*
- * probe for the presence of an interface card
- */
- static int __init check_card(int port)
- {
- #undef N_RESPO
- #define N_RESPO 20
- int i, j, k;
- u_char response[N_RESPO];
- u_char save_port0;
- u_char save_port3;
-
- msg(DBG_INI,"check_card entered.n");
- save_port0=inb(port+0);
- save_port3=inb(port+3);
-
- for (j=0;j<NR_SBPCD;j++)
- {
- OUT(port+3,j) ; /* enable drive #j */
- OUT(port+0,CMD0_PATH_CHECK);
- for (i=10;i>0;i--) OUT(port+0,0);
- for (k=0;k<N_RESPO;k++) response[k]=0;
- for (k=0;k<N_RESPO;k++)
- {
- for (i=10000;i>0;i--)
- {
- if (inb(port+1)&s_not_result_ready) continue;
- response[k]=inb(port+0);
- break;
- }
- }
- for (i=0;i<N_RESPO;i++)
- sprintf(&msgbuf[i*3], " %02X", response[i]);
- msgbuf[i*3]=0;
- msg(DBG_TEA,"path check 00 (%d): %sn", j, msgbuf);
- OUT(port+0,CMD0_PATH_CHECK);
- for (i=10;i>0;i--) OUT(port+0,0);
- for (k=0;k<N_RESPO;k++) response[k]=0xFF;
- for (k=0;k<N_RESPO;k++)
- {
- for (i=10000;i>0;i--)
- {
- if (inb(port+1)&s_not_result_ready) continue;
- response[k]=inb(port+0);
- break;
- }
- }
- for (i=0;i<N_RESPO;i++)
- sprintf(&msgbuf[i*3], " %02X", response[i]);
- msgbuf[i*3]=0;
- msg(DBG_TEA,"path check 00 (%d): %sn", j, msgbuf);
- if (response[0]==0xAA)
- if (response[1]==0x55)
- return (0);
- }
- for (j=0;j<NR_SBPCD;j++)
- {
- OUT(port+3,j) ; /* enable drive #j */
- OUT(port+0,CMD2_READ_VER);
- for (i=10;i>0;i--) OUT(port+0,0);
- for (k=0;k<N_RESPO;k++) response[k]=0;
- for (k=0;k<N_RESPO;k++)
- {
- for (i=1000000;i>0;i--)
- {
- if (inb(port+1)&s_not_result_ready) continue;
- response[k]=inb(port+0);
- break;
- }
- }
- for (i=0;i<N_RESPO;i++)
- sprintf(&msgbuf[i*3], " %02X", response[i]);
- msgbuf[i*3]=0;
- msg(DBG_TEA,"path check 12 (%d): %sn", j, msgbuf);
- OUT(port+0,CMD2_READ_VER);
- for (i=10;i>0;i--) OUT(port+0,0);
- for (k=0;k<N_RESPO;k++) response[k]=0xFF;
- for (k=0;k<N_RESPO;k++)
- {
- for (i=1000000;i>0;i--)
- {
- if (inb(port+1)&s_not_result_ready) continue;
- response[k]=inb(port+0);
- break;
- }
- }
- for (i=0;i<N_RESPO;i++)
- sprintf(&msgbuf[i*3], " %02X", response[i]);
- msgbuf[i*3]=0;
- msg(DBG_TEA,"path check 12 (%d): %sn", j, msgbuf);
- if (response[0]==0xAA)
- if (response[1]==0x55)
- return (0);
- }
- OUT(port+0,save_port0);
- OUT(port+3,save_port3);
- return (0); /* in any case - no real "function" at time */
- }
- #endif /* PATH_CHECK */
- /*==========================================================================*/
- /*==========================================================================*/
- /*
- * probe for the presence of drives on the selected controller
- */
- static int __init check_drives(void)
- {
- int i, j;
-
- msg(DBG_INI,"check_drives entered.n");
- ndrives=0;
- for (j=0;j<max_drives;j++)
- {
- D_S[ndrives].drv_id=j;
- if (sbpro_type==1) D_S[ndrives].drv_sel=(j&0x01)<<1|(j&0x02)>>1;
- else D_S[ndrives].drv_sel=j;
- switch_drive(ndrives);
- msg(DBG_INI,"check_drives: drive %d (ID=%d) activated.n",ndrives,j);
- msg(DBG_000,"check_drives: drive %d (ID=%d) activated.n",ndrives,j);
- i=check_version();
- if (i<0) msg(DBG_INI,"check_version returns %d.n",i);
- else
- {
- D_S[d].drv_options=drv_pattern[j];
- if (fam0L_drive) D_S[d].drv_options&=~(speed_auto|speed_300|speed_150);
- msg(DBG_INF, "Drive %d (ID=%d): %.9s (%.4s) at 0x%03X (type %d)n",
- d,
- D_S[d].drv_id,
- D_S[d].drive_model,
- D_S[d].firmware_version,
- CDo_command,
- sbpro_type);
- ndrives++;
- }
- }
- for (j=ndrives;j<NR_SBPCD;j++) D_S[j].drv_id=-1;
- if (ndrives==0) return (-1);
- return (0);
- }
- /*==========================================================================*/
- #if FUTURE
- /*
- * obtain if requested service disturbs current audio state
- */
- static int obey_audio_state(u_char audio_state, u_char func,u_char subfunc)
- {
- switch (audio_state) /* audio status from controller */
- {
- case aud_11: /* "audio play in progress" */
- case audx11:
- switch (func) /* DOS command code */
- {
- case cmd_07: /* input flush */
- case cmd_0d: /* open device */
- case cmd_0e: /* close device */
- case cmd_0c: /* ioctl output */
- return (1);
- case cmd_03: /* ioctl input */
- switch (subfunc)
- /* DOS ioctl input subfunction */
- {
- case cxi_00:
- case cxi_06:
- case cxi_09:
- return (1);
- default:
- return (ERROR15);
- }
- return (1);
- default:
- return (ERROR15);
- }
- return (1);
- case aud_12: /* "audio play paused" */
- case audx12:
- return (1);
- default:
- return (2);
- }
- }
- /*==========================================================================*/
- /* allowed is only
- * ioctl_o, flush_input, open_device, close_device,
- * tell_address, tell_volume, tell_capabiliti,
- * tell_framesize, tell_CD_changed, tell_audio_posi
- */
- static int check_allowed1(u_char func1, u_char func2)
- {
- #if 000
- if (func1==ioctl_o) return (0);
- if (func1==read_long) return (-1);
- if (func1==read_long_prefetch) return (-1);
- if (func1==seek) return (-1);
- if (func1==audio_play) return (-1);
- if (func1==audio_pause) return (-1);
- if (func1==audio_resume) return (-1);
- if (func1!=ioctl_i) return (0);
- if (func2==tell_SubQ_run_tot) return (-1);
- if (func2==tell_cdsize) return (-1);
- if (func2==tell_TocDescrip) return (-1);
- if (func2==tell_TocEntry) return (-1);
- if (func2==tell_subQ_info) return (-1);
- if (fam1_drive) if (func2==tell_SubChanInfo) return (-1);
- if (func2==tell_UPC) return (-1);
- #else
- return (0);
- #endif
- }
- /*==========================================================================*/
- static int check_allowed2(u_char func1, u_char func2)
- {
- #if 000
- if (func1==read_long) return (-1);
- if (func1==read_long_prefetch) return (-1);
- if (func1==seek) return (-1);
- if (func1==audio_play) return (-1);
- if (func1!=ioctl_o) return (0);
- if (fam1_drive)
- {
- if (func2==EjectDisk) return (-1);
- if (func2==CloseTray) return (-1);
- }
- #else
- return (0);
- #endif
- }
- /*==========================================================================*/
- static int check_allowed3(u_char func1, u_char func2)
- {
- #if 000
- if (func1==ioctl_i)
- {
- if (func2==tell_address) return (0);
- if (func2==tell_capabiliti) return (0);
- if (func2==tell_CD_changed) return (0);
- if (fam0L_drive) if (func2==tell_SubChanInfo) return (0);
- return (-1);
- }
- if (func1==ioctl_o)
- {
- if (func2==DriveReset) return (0);
- if (fam0L_drive)
- {
- if (func2==EjectDisk) return (0);
- if (func2==LockDoor) return (0);
- if (func2==CloseTray) return (0);
- }
- return (-1);
- }
- if (func1==flush_input) return (-1);
- if (func1==read_long) return (-1);
- if (func1==read_long_prefetch) return (-1);
- if (func1==seek) return (-1);
- if (func1==audio_play) return (-1);
- if (func1==audio_pause) return (-1);
- if (func1==audio_resume) return (-1);
- #else
- return (0);
- #endif
- }
- /*==========================================================================*/
- static int seek_pos_audio_end(void)
- {
- int i;
- i=msf2blk(D_S[d].pos_audio_end)-1;
- if (i<0) return (-1);
- i=cc_Seek(i,0);
- return (i);
- }
- #endif /* FUTURE */
- /*==========================================================================*/
- static int ReadToC(void)
- {
- int i, j;
- D_S[d].diskstate_flags &= ~toc_bit;
- D_S[d].ored_ctl_adr=0;
- /* special handling of CD-I HE */
- if ((D_S[d].n_first_track == 2 && D_S[d].n_last_track == 2) ||
- D_S[d].xa_byte == 0x10)
- {
- D_S[d].TocBuffer[1].nixbyte=0;
- D_S[d].TocBuffer[1].ctl_adr=0x40;
- D_S[d].TocBuffer[1].number=1;
- D_S[d].TocBuffer[1].format=0;
- D_S[d].TocBuffer[1].address=blk2msf(0);
- D_S[d].ored_ctl_adr |= 0x40;
- D_S[d].n_first_track = 1;
- D_S[d].n_last_track = 1;
- D_S[d].xa_byte = 0x10;
- j = 2;
- } else
- for (j=D_S[d].n_first_track;j<=D_S[d].n_last_track;j++)
- {
- i=cc_ReadTocEntry(j);
- if (i<0)
- {
- msg(DBG_INF,"cc_ReadTocEntry(%d) returns %d.n",j,i);
- return (i);
- }
- D_S[d].TocBuffer[j].nixbyte=D_S[d].TocEnt_nixbyte;
- D_S[d].TocBuffer[j].ctl_adr=D_S[d].TocEnt_ctl_adr;
- D_S[d].TocBuffer[j].number=D_S[d].TocEnt_number;
- D_S[d].TocBuffer[j].format=D_S[d].TocEnt_format;
- D_S[d].TocBuffer[j].address=D_S[d].TocEnt_address;
- D_S[d].ored_ctl_adr |= D_S[d].TocEnt_ctl_adr;
- }
- /* fake entry for LeadOut Track */
- D_S[d].TocBuffer[j].nixbyte=0;
- D_S[d].TocBuffer[j].ctl_adr=0;
- D_S[d].TocBuffer[j].number=CDROM_LEADOUT;
- D_S[d].TocBuffer[j].format=0;
- D_S[d].TocBuffer[j].address=D_S[d].size_msf;
-
- D_S[d].diskstate_flags |= toc_bit;
- return (0);
- }
- /*==========================================================================*/
- static int DiskInfo(void)
- {
- int i, j;
-
- D_S[d].mode=READ_M1;
-
- #undef LOOP_COUNT
- #define LOOP_COUNT 10 /* needed for some "old" drives */
-
- msg(DBG_000,"DiskInfo entered.n");
- for (j=1;j<LOOP_COUNT;j++)
- {
- #if 0
- i=SetSpeed();
- if (i<0)
- {
- msg(DBG_INF,"DiskInfo: SetSpeed returns %dn", i);
- continue;
- }
- i=cc_ModeSense();
- if (i<0)
- {
- msg(DBG_INF,"DiskInfo: cc_ModeSense returns %dn", i);
- continue;
- }
- #endif
- i=cc_ReadCapacity();
- if (i>=0) break;
- msg(DBG_INF,"DiskInfo: ReadCapacity #%d returns %dn", j, i);
- #if 0
- i=cc_DriveReset();
- #endif
- if (!fam0_drive && j == 2) break;
- }
- if (j==LOOP_COUNT) return (-33); /* give up */
-
- i=cc_ReadTocDescr();
- if (i<0)
- {
- msg(DBG_INF,"DiskInfo: ReadTocDescr returns %dn", i);
- return (i);
- }
- i=ReadToC();
- if (i<0)
- {
- msg(DBG_INF,"DiskInfo: ReadToC returns %dn", i);
- return (i);
- }
- i=cc_CheckMultiSession();
- if (i<0)
- {
- msg(DBG_INF,"DiskInfo: cc_CheckMultiSession returns %dn", i);
- return (i);
- }
- if (D_S[d].f_multisession) D_S[d].sbp_bufsiz=1; /* possibly a weird PhotoCD */
- else D_S[d].sbp_bufsiz=buffers;
- i=cc_ReadTocEntry(D_S[d].n_first_track);
- if (i<0)
- {
- msg(DBG_INF,"DiskInfo: cc_ReadTocEntry(1) returns %dn", i);
- return (i);
- }
- i=cc_ReadUPC();
- if (i<0) msg(DBG_INF,"DiskInfo: cc_ReadUPC returns %dn", i);
- if ((fam0L_drive) && (D_S[d].xa_byte==0x20 || D_S[d].xa_byte == 0x10))
- {
- /* XA disk with old drive */
- cc_ModeSelect(CD_FRAMESIZE_RAW1);
- cc_ModeSense();
- }
- if (famT_drive) cc_prep_mode_T();
- msg(DBG_000,"DiskInfo done.n");
- return (0);
- }
- static int sbpcd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
- {
- int st;
- if (CDSL_CURRENT != slot_nr) {
- /* we have no changer support */
- return -EINVAL;
- }
- cc_ReadStatus();
- st=ResponseStatus();
- if (st<0)
- {
- msg(DBG_INF,"sbpcd_drive_status: timeout.n");
- return (0);
- }
- msg(DBG_000,"Drive Status: door_locked =%d.n", st_door_locked);
- msg(DBG_000,"Drive Status: door_closed =%d.n", st_door_closed);
- msg(DBG_000,"Drive Status: caddy_in =%d.n", st_caddy_in);
- msg(DBG_000,"Drive Status: disk_ok =%d.n", st_diskok);
- msg(DBG_000,"Drive Status: spinning =%d.n", st_spinning);
- msg(DBG_000,"Drive Status: busy =%d.n", st_busy);
- #if 0
- if (!(D_S[MINOR(cdi->dev)].status_bits & p_door_closed)) return CDS_TRAY_OPEN;
- if (D_S[MINOR(cdi->dev)].status_bits & p_disk_ok) return CDS_DISC_OK;
- if (D_S[MINOR(cdi->dev)].status_bits & p_disk_in) return CDS_DRIVE_NOT_READY;
- return CDS_NO_DISC;
- #else
- if (D_S[MINOR(cdi->dev)].status_bits & p_spinning) return CDS_DISC_OK;
- /* return CDS_TRAY_OPEN; */
- return CDS_NO_DISC;
-
- #endif
- }
- /*==========================================================================*/
- #if FUTURE
- /*
- * called always if driver gets entered
- * returns 0 or ERROR2 or ERROR15
- */
- static int prepare(u_char func, u_char subfunc)
- {
- int i;
-
- if (fam0L_drive)
- {
- i=inb(CDi_status);
- if (i&s_attention) GetStatus();
- }
- else if (fam1_drive) GetStatus();
- else if (fam2_drive) GetStatus();
- else if (famT_drive) GetStatus();
- if (D_S[d].CD_changed==0xFF)
- {
- D_S[d].diskstate_flags=0;
- D_S[d].audio_state=0;
- if (!st_diskok)
- {
- i=check_allowed1(func,subfunc);
- if (i<0) return (-2);
- }
- else
- {
- i=check_allowed3(func,subfunc);
- if (i<0)
- {
- D_S[d].CD_changed=1;
- return (-15);
- }
- }
- }
- else
- {
- if (!st_diskok)
- {
- D_S[d].diskstate_flags=0;
- D_S[d].audio_state=0;
- i=check_allowed1(func,subfunc);
- if (i<0) return (-2);
- }
- else
- {
- if (st_busy)
- {
- if (D_S[d].audio_state!=audio_pausing)
- {
- i=check_allowed2(func,subfunc);
- if (i<0) return (-2);
- }
- }
- else
- {
- if (D_S[d].audio_state==audio_playing) seek_pos_audio_end();
- D_S[d].audio_state=0;
- }
- if (!frame_size_valid)
- {
- i=DiskInfo();
- if (i<0)
- {
- D_S[d].diskstate_flags=0;
- D_S[d].audio_state=0;
- i=check_allowed1(func,subfunc);
- if (i<0) return (-2);
- }
- }
- }
- }
- return (0);
- }
- #endif /* FUTURE */
- /*==========================================================================*/
- /*==========================================================================*/
- /*
- * Check the results of the "get status" command.
- */
- static int sbp_status(void)
- {
- int st;
-
- st=ResponseStatus();
- if (st<0)
- {
- msg(DBG_INF,"sbp_status: timeout.n");
- return (0);
- }
-
- if (!st_spinning) msg(DBG_SPI,"motor got off - ignoring.n");
-
- if (st_check)
- {
- msg(DBG_INF,"st_check detected - retrying.n");
- return (0);
- }
- if (!st_door_closed)
- {
- msg(DBG_INF,"door is open - retrying.n");
- return (0);
- }
- if (!st_caddy_in)
- {
- msg(DBG_INF,"disk removed - retrying.n");
- return (0);
- }
- if (!st_diskok)
- {
- msg(DBG_INF,"!st_diskok detected - retrying.n");
- return (0);
- }
- if (st_busy)
- {
- msg(DBG_INF,"st_busy detected - retrying.n");
- return (0);
- }
- return (1);
- }
- /*==========================================================================*/
-
- static int sbpcd_get_last_session(struct cdrom_device_info *cdi, struct cdrom_multisession *ms_infp)
- {
- ms_infp->addr_format = CDROM_LBA;
- ms_infp->addr.lba = D_S[MINOR(cdi->dev)].lba_multi;
- if (D_S[MINOR(cdi->dev)].f_multisession)
- ms_infp->xa_flag=1; /* valid redirection address */
- else
- ms_infp->xa_flag=0; /* invalid redirection address */
- return 0;
- }
- /*==========================================================================*/
- /*==========================================================================*/
- /*
- * ioctl support
- */
- static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd,
- u_long arg)
- {
- int i;
-
- msg(DBG_IO2,"ioctl(%d, 0x%08lX, 0x%08lX)n",
- MINOR(cdi->dev), cmd, arg);
- i=MINOR(cdi->dev);
- if ((i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1))
- {
- msg(DBG_INF, "ioctl: bad device: %04Xn", cdi->dev);
- return (-ENXIO); /* no such drive */
- }
- down(&ioctl_read_sem);
- if (d!=i) switch_drive(i);
-
- msg(DBG_IO2,"ioctl: device %d, request %04Xn",i,cmd);
- switch (cmd) /* Sun-compatible */
- {
- case DDIOCSDBG: /* DDI Debug */
- if (!capable(CAP_SYS_ADMIN)) RETURN_UP(-EPERM);
- i=sbpcd_dbg_ioctl(arg,1);
- RETURN_UP(i);
- case CDROMRESET: /* hard reset the drive */
- msg(DBG_IOC,"ioctl: CDROMRESET entered.n");
- i=DriveReset();
- D_S[d].audio_state=0;
- RETURN_UP(i);
-
- case CDROMREADMODE1:
- msg(DBG_IOC,"ioctl: CDROMREADMODE1 requested.n");
- #if SAFE_MIXED
- if (D_S[d].has_data>1) RETURN_UP(-EBUSY);
- #endif /* SAFE_MIXED */
- cc_ModeSelect(CD_FRAMESIZE);
- cc_ModeSense();
- D_S[d].mode=READ_M1;
- RETURN_UP(0);
-
- case CDROMREADMODE2: /* not usable at the moment */
- msg(DBG_IOC,"ioctl: CDROMREADMODE2 requested.n");
- #if SAFE_MIXED
- if (D_S[d].has_data>1) RETURN_UP(-EBUSY);
- #endif /* SAFE_MIXED */
- cc_ModeSelect(CD_FRAMESIZE_RAW1);
- cc_ModeSense();
- D_S[d].mode=READ_M2;
- RETURN_UP(0);
-
- case CDROMAUDIOBUFSIZ: /* configure the audio buffer size */
- msg(DBG_IOC,"ioctl: CDROMAUDIOBUFSIZ entered.n");
- if (D_S[d].sbp_audsiz>0) vfree(D_S[d].aud_buf);
- D_S[d].aud_buf=NULL;
- D_S[d].sbp_audsiz=arg;
-
- if (D_S[d].sbp_audsiz>16)
- {
- D_S[d].sbp_audsiz = 0;
- RETURN_UP(D_S[d].sbp_audsiz);
- }
-
- if (D_S[d].sbp_audsiz>0)
- {
- D_S[d].aud_buf=(u_char *) vmalloc(D_S[d].sbp_audsiz*CD_FRAMESIZE_RAW);
- if (D_S[d].aud_buf==NULL)
- {
- msg(DBG_INF,"audio buffer (%d frames) not available.n",D_S[d].sbp_audsiz);
- D_S[d].sbp_audsiz=0;
- }
- else msg(DBG_INF,"audio buffer size: %d frames.n",D_S[d].sbp_audsiz);
- }
- RETURN_UP(D_S[d].sbp_audsiz);
- case CDROMREADAUDIO:
- { /* start of CDROMREADAUDIO */
- int i=0, j=0, frame, block=0;
- u_int try=0;
- u_long timeout;
- u_char *p;
- u_int data_tries = 0;
- u_int data_waits = 0;
- u_int data_retrying = 0;
- int status_tries;
- int error_flag;
-
- msg(DBG_IOC,"ioctl: CDROMREADAUDIO entered.n");
- if (fam0_drive) RETURN_UP(-EINVAL);
- if (famL_drive) RETURN_UP(-EINVAL);
- if (famV_drive) RETURN_UP(-EINVAL);
- if (famT_drive) RETURN_UP(-EINVAL);
- #if SAFE_MIXED
- if (D_S[d].has_data>1) RETURN_UP(-EBUSY);
- #endif /* SAFE_MIXED */
- if (D_S[d].aud_buf==NULL) RETURN_UP(-EINVAL);
- i=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_read_audio));
- if (i) RETURN_UP(i);
- copy_from_user(&read_audio, (void *) arg, sizeof(struct cdrom_read_audio));
- if (read_audio.nframes < 0 || read_audio.nframes>D_S[d].sbp_audsiz) RETURN_UP(-EINVAL);
- i=verify_area(VERIFY_WRITE, read_audio.buf,
- read_audio.nframes*CD_FRAMESIZE_RAW);
- if (i) RETURN_UP(i);
-
- if (read_audio.addr_format==CDROM_MSF) /* MSF-bin specification of where to start */
- block=msf2lba(&read_audio.addr.msf.minute);
- else if (read_audio.addr_format==CDROM_LBA) /* lba specification of where to start */
- block=read_audio.addr.lba;
- else RETURN_UP(-EINVAL);
- #if 000
- i=cc_SetSpeed(speed_150,0,0);
- if (i) msg(DBG_AUD,"read_audio: SetSpeed error %dn", i);
- #endif
- msg(DBG_AUD,"read_audio: lba: %d, msf: %06Xn",
- block, blk2msf(block));
- msg(DBG_AUD,"read_audio: before cc_ReadStatus.n");
- #if OLD_BUSY
- while (busy_data) sbp_sleep(HZ/10); /* wait a bit */
- busy_audio=1;
- #endif /* OLD_BUSY */
- error_flag=0;
- for (data_tries=5; data_tries>0; data_tries--)
- {
- msg(DBG_AUD,"data_tries=%d ...n", data_tries);
- D_S[d].mode=READ_AU;
- cc_ModeSelect(CD_FRAMESIZE_RAW);
- cc_ModeSense();
- for (status_tries=3; status_tries > 0; status_tries--)
- {
- flags_cmd_out |= f_respo3;
- cc_ReadStatus();
- if (sbp_status() != 0) break;
- if (st_check) cc_ReadError();
- sbp_sleep(1); /* wait a bit, try again */
- }
- if (status_tries == 0)
- {
- msg(DBG_AUD,"read_audio: sbp_status: failed after 3 tries in line %d.n", __LINE__);
- continue;
- }
- msg(DBG_AUD,"read_audio: sbp_status: ok.n");
-
- flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check;
- if (fam0L_drive)
- {
- flags_cmd_out |= f_lopsta | f_getsta | f_bit1;
- cmd_type=READ_M2;
- drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */
- drvcmd[1]=(block>>16)&0x000000ff;
- drvcmd[2]=(block>>8)&0x000000ff;
- drvcmd[3]=block&0x000000ff;
- drvcmd[4]=0;
- drvcmd[5]=read_audio.nframes; /* # of frames */
- drvcmd[6]=0;
- }
- else if (fam1_drive)
- {
- drvcmd[0]=CMD1_READ; /* "read frames", new drives */
- lba2msf(block,&drvcmd[1]); /* msf-bin format required */
- drvcmd[4]=0;
- drvcmd[5]=0;
- drvcmd[6]=read_audio.nframes; /* # of frames */
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_READ_XA2;
- lba2msf(block,&drvcmd[1]); /* msf-bin format required */
- drvcmd[4]=0;
- drvcmd[5]=read_audio.nframes; /* # of frames */
- drvcmd[6]=0x11; /* raw mode */
- }
- else if (famT_drive) /* CD-55A: not tested yet */
- {
- }
- msg(DBG_AUD,"read_audio: before giving "read" command.n");
- flags_cmd_out=f_putcmd;
- response_count=0;
- i=cmd_out();
- if (i<0) msg(DBG_INF,"error giving READ AUDIO command: %0dn", i);
- sbp_sleep(0);
- msg(DBG_AUD,"read_audio: after giving "read" command.n");
- for (frame=1;frame<2 && !error_flag; frame++)
- {
- try=maxtim_data;
- for (timeout=jiffies+9*HZ; ; )
- {
- for ( ; try!=0;try--)
- {
- j=inb(CDi_status);
- if (!(j&s_not_data_ready)) break;
- if (!(j&s_not_result_ready)) break;
- if (fam0L_drive) if (j&s_attention) break;
- }
- if (try != 0 || time_after_eq(jiffies, timeout)) break;
- if (data_retrying == 0) data_waits++;
- data_retrying = 1;
- sbp_sleep(1);
- try = 1;
- }
- if (try==0)
- {
- msg(DBG_INF,"read_audio: sbp_data: CDi_status timeout.n");
- error_flag++;
- break;
- }
- msg(DBG_AUD,"read_audio: sbp_data: CDi_status ok.n");
- if (j&s_not_data_ready)
- {
- msg(DBG_INF, "read_audio: sbp_data: DATA_READY timeout.n");
- error_flag++;
- break;
- }
- msg(DBG_AUD,"read_audio: before reading data.n");
- error_flag=0;
- p = D_S[d].aud_buf;
- if (sbpro_type==1) OUT(CDo_sel_i_d,1);
- if (do_16bit)
- {
- u_short *p2 = (u_short *) p;
- for (; (u_char *) p2 < D_S[d].aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;)
- {
- if ((inb_p(CDi_status)&s_not_data_ready)) continue;
- /* get one sample */
- *p2++ = inw_p(CDi_data);
- *p2++ = inw_p(CDi_data);
- }
- } else {
- for (; p < D_S[d].aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;)
- {
- if ((inb_p(CDi_status)&s_not_data_ready)) continue;
- /* get one sample */
- *p++ = inb_p(CDi_data);
- *p++ = inb_p(CDi_data);
- *p++ = inb_p(CDi_data);
- *p++ = inb_p(CDi_data);
- }
- }
- if (sbpro_type==1) OUT(CDo_sel_i_d,0);
- data_retrying = 0;
- }
- msg(DBG_AUD,"read_audio: after reading data.n");
- if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */
- {
- msg(DBG_AUD,"read_audio: read aborted by driven");
- #if 0000
- i=cc_DriveReset(); /* ugly fix to prevent a hang */
- #else
- i=cc_ReadError();
- #endif
- continue;
- }
- if (fam0L_drive)
- {
- i=maxtim_data;
- for (timeout=jiffies+9*HZ; time_before(jiffies, timeout); timeout--)
- {
- for ( ;i!=0;i--)
- {
- j=inb(CDi_status);
- if (!(j&s_not_data_ready)) break;
- if (!(j&s_not_result_ready)) break;
- if (j&s_attention) break;
- }
- if (i != 0 || time_after_eq(jiffies, timeout)) break;
- sbp_sleep(0);
- i = 1;
- }
- if (i==0) msg(DBG_AUD,"read_audio: STATUS TIMEOUT AFTER READ");
- if (!(j&s_attention))
- {
- msg(DBG_AUD,"read_audio: sbp_data: timeout waiting DRV_ATTN - retryingn");
- i=cc_DriveReset(); /* ugly fix to prevent a hang */
- continue;
- }
- }
- do
- {
- if (fam0L_drive) cc_ReadStatus();
- i=ResponseStatus(); /* builds status_bits, returns orig. status (old) or faked p_success (new) */
- if (i<0) { msg(DBG_AUD,
- "read_audio: cc_ReadStatus error after read: %02Xn",
- D_S[d].status_bits);
- continue; /* FIXME */
- }
- }
- while ((fam0L_drive)&&(!st_check)&&(!(i&p_success)));
- if (st_check)
- {
- i=cc_ReadError();
- msg(DBG_AUD,"read_audio: cc_ReadError was necessary after read: %02Xn",i);
- continue;
- }
- copy_to_user((u_char *) read_audio.buf,
- (u_char *) D_S[d].aud_buf,
- read_audio.nframes*CD_FRAMESIZE_RAW);
- msg(DBG_AUD,"read_audio: copy_to_user done.n");
- break;
- }
- cc_ModeSelect(CD_FRAMESIZE);
- cc_ModeSense();
- D_S[d].mode=READ_M1;
- #if OLD_BUSY
- busy_audio=0;
- #endif /* OLD_BUSY */
- if (data_tries == 0)
- {
- msg(DBG_AUD,"read_audio: failed after 5 tries in line %d.n", __LINE__);
- RETURN_UP(-EIO);
- }
- msg(DBG_AUD,"read_audio: successful return.n");
- RETURN_UP(0);
- } /* end of CDROMREADAUDIO */
-
- case BLKRASET:
- if(!capable(CAP_SYS_ADMIN)) RETURN_UP(-EACCES);
- if(!(cdi->dev)) RETURN_UP(-EINVAL);
- if(arg > 0xff) RETURN_UP(-EINVAL);
- read_ahead[MAJOR(cdi->dev)] = arg;
- RETURN_UP(0);
- default:
- msg(DBG_IOC,"ioctl: unknown function request %04Xn", cmd);
- RETURN_UP(-EINVAL);
- } /* end switch(cmd) */
- }
- static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
- void * arg)
- {
- int i, st, j;
-
- msg(DBG_IO2,"ioctl(%d, 0x%08lX, 0x%08p)n",
- MINOR(cdi->dev), cmd, arg);
- i=MINOR(cdi->dev);
- if ((i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1))
- {
- msg(DBG_INF, "ioctl: bad device: %04Xn", cdi->dev);
- return (-ENXIO); /* no such drive */
- }
- down(&ioctl_read_sem);
- if (d!=i) switch_drive(i);
-
- msg(DBG_IO2,"ioctl: device %d, request %04Xn",i,cmd);
- switch (cmd) /* Sun-compatible */
- {
-
- case CDROMPAUSE: /* Pause the drive */
- msg(DBG_IOC,"ioctl: CDROMPAUSE entered.n");
- /* pause the drive unit when it is currently in PLAY mode, */
- /* or reset the starting and ending locations when in PAUSED mode. */
- /* If applicable, at the next stopping point it reaches */
- /* the drive will discontinue playing. */
- switch (D_S[d].audio_state)
- {
- case audio_playing:
- if (famL_drive) i=cc_ReadSubQ();
- else i=cc_Pause_Resume(1);
- if (i<0) RETURN_UP(-EIO);
- if (famL_drive) i=cc_Pause_Resume(1);
- else i=cc_ReadSubQ();
- if (i<0) RETURN_UP(-EIO);
- D_S[d].pos_audio_start=D_S[d].SubQ_run_tot;
- D_S[d].audio_state=audio_pausing;
- RETURN_UP(0);
- case audio_pausing:
- i=cc_Seek(D_S[d].pos_audio_start,1);
- if (i<0) RETURN_UP(-EIO);
- RETURN_UP(0);
- default:
- RETURN_UP(-EINVAL);
- }
-
- case CDROMRESUME: /* resume paused audio play */
- msg(DBG_IOC,"ioctl: CDROMRESUME entered.n");
- /* resume playing audio tracks when a previous PLAY AUDIO call has */
- /* been paused with a PAUSE command. */
- /* It will resume playing from the location saved in SubQ_run_tot. */
- if (D_S[d].audio_state!=audio_pausing) RETURN_UP(-EINVAL);
- if (famL_drive)
- i=cc_PlayAudio(D_S[d].pos_audio_start,
- D_S[d].pos_audio_end);
- else i=cc_Pause_Resume(3);
- if (i<0) RETURN_UP(-EIO);
- D_S[d].audio_state=audio_playing;
- RETURN_UP(0);
-
- case CDROMPLAYMSF:
- msg(DBG_IOC,"ioctl: CDROMPLAYMSF entered.n");
- #if SAFE_MIXED
- if (D_S[d].has_data>1) RETURN_UP(-EBUSY);
- #endif /* SAFE_MIXED */
- if (D_S[d].audio_state==audio_playing)
- {
- i=cc_Pause_Resume(1);
- if (i<0) RETURN_UP(-EIO);
- i=cc_ReadSubQ();
- if (i<0) RETURN_UP(-EIO);
- D_S[d].pos_audio_start=D_S[d].SubQ_run_tot;
- i=cc_Seek(D_S[d].pos_audio_start,1);
- }
- memcpy(&msf, (void *) arg, sizeof(struct cdrom_msf));
- /* values come as msf-bin */
- D_S[d].pos_audio_start = (msf.cdmsf_min0<<16) |
- (msf.cdmsf_sec0<<8) |
- msf.cdmsf_frame0;
- D_S[d].pos_audio_end = (msf.cdmsf_min1<<16) |
- (msf.cdmsf_sec1<<8) |
- msf.cdmsf_frame1;
- msg(DBG_IOX,"ioctl: CDROMPLAYMSF %08X %08Xn",
- D_S[d].pos_audio_start,D_S[d].pos_audio_end);
- i=cc_PlayAudio(D_S[d].pos_audio_start,D_S[d].pos_audio_end);
- if (i<0)
- {
- msg(DBG_INF,"ioctl: cc_PlayAudio returns %dn",i);
- DriveReset();
- D_S[d].audio_state=0;
- RETURN_UP(-EIO);
- }
- D_S[d].audio_state=audio_playing;
- RETURN_UP(0);
-
- case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */
- msg(DBG_IOC,"ioctl: CDROMPLAYTRKIND entered.n");
- #if SAFE_MIXED
- if (D_S[d].has_data>1) RETURN_UP(-EBUSY);
- #endif /* SAFE_MIXED */
- if (D_S[d].audio_state==audio_playing)
- {
- msg(DBG_IOX,"CDROMPLAYTRKIND: already audio_playing.n");
- #if 1
- RETURN_UP(0); /* just let us play on */
- #else
- RETURN_UP(-EINVAL); /* play on, but say "error" */
- #endif
- }
- memcpy(&ti,(void *) arg,sizeof(struct cdrom_ti));
- msg(DBG_IOX,"ioctl: trk0: %d, ind0: %d, trk1:%d, ind1:%dn",
- ti.cdti_trk0,ti.cdti_ind0,ti.cdti_trk1,ti.cdti_ind1);
- if (ti.cdti_trk0<D_S[d].n_first_track) RETURN_UP(-EINVAL);
- if (ti.cdti_trk0>D_S[d].n_last_track) RETURN_UP(-EINVAL);
- if (ti.cdti_trk1<ti.cdti_trk0) ti.cdti_trk1=ti.cdti_trk0;
- if (ti.cdti_trk1>D_S[d].n_last_track) ti.cdti_trk1=D_S[d].n_last_track;
- D_S[d].pos_audio_start=D_S[d].TocBuffer[ti.cdti_trk0].address;
- D_S[d].pos_audio_end=D_S[d].TocBuffer[ti.cdti_trk1+1].address;
- i=cc_PlayAudio(D_S[d].pos_audio_start,D_S[d].pos_audio_end);
- if (i<0)
- {
- msg(DBG_INF,"ioctl: cc_PlayAudio returns %dn",i);
- DriveReset();
- D_S[d].audio_state=0;
- RETURN_UP(-EIO);
- }
- D_S[d].audio_state=audio_playing;
- RETURN_UP(0);
-
- case CDROMREADTOCHDR: /* Read the table of contents header */
- msg(DBG_IOC,"ioctl: CDROMREADTOCHDR entered.n");
- tochdr.cdth_trk0=D_S[d].n_first_track;
- tochdr.cdth_trk1=D_S[d].n_last_track;
- memcpy((void *) arg, &tochdr, sizeof(struct cdrom_tochdr));
- RETURN_UP(0);
-
- case CDROMREADTOCENTRY: /* Read an entry in the table of contents */
- msg(DBG_IOC,"ioctl: CDROMREADTOCENTRY entered.n");
- memcpy(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry));
- i=tocentry.cdte_track;
- if (i==CDROM_LEADOUT) i=D_S[d].n_last_track+1;
- else if (i<D_S[d].n_first_track||i>D_S[d].n_last_track)
- RETURN_UP(-EINVAL);
- tocentry.cdte_adr=D_S[d].TocBuffer[i].ctl_adr&0x0F;
- tocentry.cdte_ctrl=(D_S[d].TocBuffer[i].ctl_adr>>4)&0x0F;
- tocentry.cdte_datamode=D_S[d].TocBuffer[i].format;
- if (tocentry.cdte_format==CDROM_MSF) /* MSF-bin required */
- {
- tocentry.cdte_addr.msf.minute=(D_S[d].TocBuffer[i].address>>16)&0x00FF;
- tocentry.cdte_addr.msf.second=(D_S[d].TocBuffer[i].address>>8)&0x00FF;
- tocentry.cdte_addr.msf.frame=D_S[d].TocBuffer[i].address&0x00FF;
- }
- else if (tocentry.cdte_format==CDROM_LBA) /* blk required */
- tocentry.cdte_addr.lba=msf2blk(D_S[d].TocBuffer[i].address);
- else RETURN_UP(-EINVAL);
- memcpy((void *) arg, &tocentry, sizeof(struct cdrom_tocentry));
- RETURN_UP(0);
-
- case CDROMSTOP: /* Spin down the drive */
- msg(DBG_IOC,"ioctl: CDROMSTOP entered.n");
- #if SAFE_MIXED
- if (D_S[d].has_data>1) RETURN_UP(-EBUSY);
- #endif /* SAFE_MIXED */
- i=cc_Pause_Resume(1);
- D_S[d].audio_state=0;
- #if 0
- cc_DriveReset();
- #endif
- RETURN_UP(i);
-
- case CDROMSTART: /* Spin up the drive */
- msg(DBG_IOC,"ioctl: CDROMSTART entered.n");
- cc_SpinUp();
- D_S[d].audio_state=0;
- RETURN_UP(0);
-
- case CDROMVOLCTRL: /* Volume control */
- msg(DBG_IOC,"ioctl: CDROMVOLCTRL entered.n");
- memcpy(&volctrl,(char *) arg,sizeof(volctrl));
- D_S[d].vol_chan0=0;
- D_S[d].vol_ctrl0=volctrl.channel0;
- D_S[d].vol_chan1=1;
- D_S[d].vol_ctrl1=volctrl.channel1;
- i=cc_SetVolume();
- RETURN_UP(0);
-
- case CDROMVOLREAD: /* read Volume settings from drive */
- msg(DBG_IOC,"ioctl: CDROMVOLREAD entered.n");
- st=cc_GetVolume();
- if (st<0) RETURN_UP(st);
- volctrl.channel0=D_S[d].vol_ctrl0;
- volctrl.channel1=D_S[d].vol_ctrl1;
- volctrl.channel2=0;
- volctrl.channel2=0;
- memcpy((void *)arg,&volctrl,sizeof(volctrl));
- RETURN_UP(0);
- case CDROMSUBCHNL: /* Get subchannel info */
- msg(DBG_IOS,"ioctl: CDROMSUBCHNL entered.n");
- /* Bogus, I can do better than this! --AJK
- if ((st_spinning)||(!subq_valid)) {
- i=cc_ReadSubQ();
- if (i<0) RETURN_UP(-EIO);
- }
- */
- i=cc_ReadSubQ();
- if (i<0) {
- j=cc_ReadError(); /* clear out error status from drive */
- D_S[d].audio_state=CDROM_AUDIO_NO_STATUS;
- /* get and set the disk state here,
- probably not the right place, but who cares!
- It makes it work properly! --AJK */
- if (D_S[d].CD_changed==0xFF) {
- msg(DBG_000,"Disk changed detectn");
- D_S[d].diskstate_flags &= ~cd_size_bit;
- }
- RETURN_UP(-EIO);
- }
- if (D_S[d].CD_changed==0xFF) {
- /* reread the TOC because the disk has changed! --AJK */
- msg(DBG_000,"Disk changed STILL detected, rereading TOC!n");
- i=DiskInfo();
- if(i==0) {
- D_S[d].CD_changed=0x00; /* cd has changed, procede, */
- RETURN_UP(-EIO); /* and get TOC, etc on next try! --AJK */
- } else {
- RETURN_UP(-EIO); /* we weren't ready yet! --AJK */
- }
- }
- memcpy(&SC, (void *) arg, sizeof(struct cdrom_subchnl));
- /*
- This virtual crap is very bogus!
- It doesn't detect when the cd is done playing audio!
- Lets do this right with proper hardware register reading!
- */
- cc_ReadStatus();
- i=ResponseStatus();
- msg(DBG_000,"Drive Status: door_locked =%d.n", st_door_locked);
- msg(DBG_000,"Drive Status: door_closed =%d.n", st_door_closed);
- msg(DBG_000,"Drive Status: caddy_in =%d.n", st_caddy_in);
- msg(DBG_000,"Drive Status: disk_ok =%d.n", st_diskok);
- msg(DBG_000,"Drive Status: spinning =%d.n", st_spinning);
- msg(DBG_000,"Drive Status: busy =%d.n", st_busy);
- /* st_busy indicates if it's _ACTUALLY_ playing audio */
- switch (D_S[d].audio_state)
- {
- case audio_playing:
- if(st_busy==0) {
- /* CD has stopped playing audio --AJK */
- D_S[d].audio_state=audio_completed;
- SC.cdsc_audiostatus=CDROM_AUDIO_COMPLETED;
- } else {
- SC.cdsc_audiostatus=CDROM_AUDIO_PLAY;
- }
- break;
- case audio_pausing:
- SC.cdsc_audiostatus=CDROM_AUDIO_PAUSED;
- break;
- case audio_completed:
- SC.cdsc_audiostatus=CDROM_AUDIO_COMPLETED;
- break;
- default:
- SC.cdsc_audiostatus=CDROM_AUDIO_NO_STATUS;
- break;
- }
- SC.cdsc_adr=D_S[d].SubQ_ctl_adr;
- SC.cdsc_ctrl=D_S[d].SubQ_ctl_adr>>4;
- SC.cdsc_trk=bcd2bin(D_S[d].SubQ_trk);
- SC.cdsc_ind=bcd2bin(D_S[d].SubQ_pnt_idx);
- if (SC.cdsc_format==CDROM_LBA)
- {
- SC.cdsc_absaddr.lba=msf2blk(D_S[d].SubQ_run_tot);
- SC.cdsc_reladdr.lba=msf2blk(D_S[d].SubQ_run_trk);
- }
- else /* not only if (SC.cdsc_format==CDROM_MSF) */
- {
- SC.cdsc_absaddr.msf.minute=(D_S[d].SubQ_run_tot>>16)&0x00FF;
- SC.cdsc_absaddr.msf.second=(D_S[d].SubQ_run_tot>>8)&0x00FF;
- SC.cdsc_absaddr.msf.frame=D_S[d].SubQ_run_tot&0x00FF;
- SC.cdsc_reladdr.msf.minute=(D_S[d].SubQ_run_trk>>16)&0x00FF;
- SC.cdsc_reladdr.msf.second=(D_S[d].SubQ_run_trk>>8)&0x00FF;
- SC.cdsc_reladdr.msf.frame=D_S[d].SubQ_run_trk&0x00FF;
- }
- memcpy((void *) arg, &SC, sizeof(struct cdrom_subchnl));
- msg(DBG_IOS,"CDROMSUBCHNL: %1X %02X %08X %08X %02X %02X %06X %06Xn",
- SC.cdsc_format,SC.cdsc_audiostatus,
- SC.cdsc_adr,SC.cdsc_ctrl,
- SC.cdsc_trk,SC.cdsc_ind,
- SC.cdsc_absaddr,SC.cdsc_reladdr);
- RETURN_UP(0);
-
- default:
- msg(DBG_IOC,"ioctl: unknown function request %04Xn", cmd);
- RETURN_UP(-EINVAL);
- } /* end switch(cmd) */
- }
- /*==========================================================================*/
- /*
- * Take care of the different block sizes between cdrom and Linux.
- */
- static void sbp_transfer(struct request *req)
- {
- long offs;
-
- while ( (req->nr_sectors > 0) &&
- (req->sector/4 >= D_S[d].sbp_first_frame) &&
- (req->sector/4 <= D_S[d].sbp_last_frame) )
- {
- offs = (req->sector - D_S[d].sbp_first_frame * 4) * 512;
- memcpy(req->buffer, D_S[d].sbp_buf + offs, 512);
- req->nr_sectors--;
- req->sector++;
- req->buffer += 512;
- }
- }
- /*==========================================================================*/
- /*
- * special end_request for sbpcd to solve CURRENT==NULL bug. (GTL)
- * GTL = Gonzalo Tornaria <tornaria@cmat.edu.uy>
- *
- * This is a kludge so we don't need to modify end_request.
- * We put the req we take out after INIT_REQUEST in the requests list,
- * so that end_request will discard it.
- *
- * The bug could be present in other block devices, perhaps we
- * should modify INIT_REQUEST and end_request instead, and
- * change every block device..
- *
- * Could be a race here?? Could e.g. a timer interrupt schedule() us?
- * If so, we should copy end_request here, and do it right.. (or
- * modify end_request and the block devices).
- *
- * In any case, the race here would be much small than it was, and
- * I couldn't reproduce..
- *
- * The race could be: suppose CURRENT==NULL. We put our req in the list,
- * and we are scheduled. Other process takes over, and gets into
- * do_sbpcd_request. It sees CURRENT!=NULL (it is == to our req), so
- * proceeds. It ends, so CURRENT is now NULL.. Now we awake somewhere in
- * end_request, but now CURRENT==NULL... oops!
- *
- */
- #undef DEBUG_GTL
- static inline void sbpcd_end_request(struct request *req, int uptodate) {
- list_add(&req->queue, &req->q->queue_head);
- end_request(uptodate);
- }
- /*==========================================================================*/
- /*
- * I/O request routine, called from Linux kernel.
- */
- static void DO_SBPCD_REQUEST(request_queue_t * q)
- {
- u_int block;
- u_int nsect;
- int i, status_tries, data_tries;
- struct request *req;
- #ifdef DEBUG_GTL
- static int xx_nr=0;
- int xnr;
- #endif
- request_loop:
- #ifdef DEBUG_GTL
- xnr=++xx_nr;
- if(QUEUE_EMPTY)
- {
- printk( "do_sbpcd_request[%di](NULL), Pid:%d, Time:%lin",
- xnr, current->pid, jiffies);
- printk( "do_sbpcd_request[%do](NULL) end 0 (null), Time:%lin",
- xnr, jiffies);
- CLEAR_INTR;
- return;
- }
- printk(" do_sbpcd_request[%di](%p:%ld+%ld), Pid:%d, Time:%lin",
- xnr, CURRENT, CURRENT->sector, CURRENT->nr_sectors, current->pid, jiffies);
- #endif
- INIT_REQUEST;
- req=CURRENT; /* take out our request so no other */
- blkdev_dequeue_request(req); /* task can fuck it up GTL */
-
- if (req->rq_status == RQ_INACTIVE)
- sbpcd_end_request(req, 0);
- if (req -> sector == -1)
- sbpcd_end_request(req, 0);
- spin_unlock_irq(&io_request_lock);
- down(&ioctl_read_sem);
- if (req->cmd != READ)
- {
- msg(DBG_INF, "bad cmd %dn", req->cmd);
- goto err_done;
- }
- i = MINOR(req->rq_dev);
- if ( (i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1))
- {
- msg(DBG_INF, "do_request: bad device: %sn",
- kdevname(req->rq_dev));
- goto err_done;
- }
- #if OLD_BUSY
- while (busy_audio) sbp_sleep(HZ); /* wait a bit */
- busy_data=1;
- #endif /* OLD_BUSY */
-
- if (D_S[i].audio_state==audio_playing) goto err_done;
- if (d!=i) switch_drive(i);
-
- block = req->sector; /* always numbered as 512-byte-pieces */
- nsect = req->nr_sectors; /* always counted as 512-byte-pieces */
-
- msg(DBG_BSZ,"read sector %d (%d sectors)n", block, nsect);
- #if 0
- msg(DBG_MUL,"read LBA %dn", block/4);
- #endif
-
- sbp_transfer(req);
- /* if we satisfied the request from the buffer, we're done. */
- if (req->nr_sectors == 0)
- {
- #ifdef DEBUG_GTL
- printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 2, Time:%lin",
- xnr, req, req->sector, req->nr_sectors, jiffies);
- #endif
- up(&ioctl_read_sem);
- spin_lock_irq(&io_request_lock);
- sbpcd_end_request(req, 1);
- goto request_loop;
- }
- #if FUTURE
- i=prepare(0,0); /* at moment not really a hassle check, but ... */
- if (i!=0)
- msg(DBG_INF,""prepare" tells error %d -- ignoredn", i);
- #endif /* FUTURE */
-
- if (!st_spinning) cc_SpinUp();
-
- for (data_tries=n_retries; data_tries > 0; data_tries--)
- {
- for (status_tries=3; status_tries > 0; status_tries--)
- {
- flags_cmd_out |= f_respo3;
- cc_ReadStatus();
- if (sbp_status() != 0) break;
- if (st_check) cc_ReadError();
- sbp_sleep(1); /* wait a bit, try again */
- }
- if (status_tries == 0)
- {
- msg(DBG_INF,"sbp_status: failed after 3 tries in line %dn", __LINE__);
- break;
- }
-
- sbp_read_cmd(req);
- sbp_sleep(0);
- if (sbp_data(req) != 0)
- {
- #if SAFE_MIXED
- D_S[d].has_data=2; /* is really a data disk */
- #endif /* SAFE_MIXED */
- #ifdef DEBUG_GTL
- printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 3, Time:%lin",
- xnr, req, req->sector, req->nr_sectors, jiffies);
- #endif
- up(&ioctl_read_sem);
- spin_lock_irq(&io_request_lock);
- sbpcd_end_request(req, 1);
- goto request_loop;
- }
- }
-
- err_done:
- #if OLD_BUSY
- busy_data=0;
- #endif /* OLD_BUSY */
- #ifdef DEBUG_GTL
- printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 4 (error), Time:%lin",
- xnr, req, req->sector, req->nr_sectors, jiffies);
- #endif
- up(&ioctl_read_sem);
- sbp_sleep(0); /* wait a bit, try again */
- spin_lock_irq(&io_request_lock);
- sbpcd_end_request(req, 0);
- goto request_loop;
- }
- /*==========================================================================*/
- /*
- * build and send the READ command.
- */
- static void sbp_read_cmd(struct request *req)
- {
- #undef OLD
- int i;
- int block;
-
- D_S[d].sbp_first_frame=D_S[d].sbp_last_frame=-1; /* purge buffer */
- D_S[d].sbp_current = 0;
- block=req->sector/4;
- if (block+D_S[d].sbp_bufsiz <= D_S[d].CDsize_frm)
- D_S[d].sbp_read_frames = D_S[d].sbp_bufsiz;
- else
- {
- D_S[d].sbp_read_frames=D_S[d].CDsize_frm-block;
- /* avoid reading past end of data */
- if (D_S[d].sbp_read_frames < 1)
- {
- msg(DBG_INF,"requested frame %d, CD size %d ???n",
- block, D_S[d].CDsize_frm);
- D_S[d].sbp_read_frames=1;
- }
- }
-
- flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check;
- clr_cmdbuf();
- if (famV_drive)
- {
- drvcmd[0]=CMDV_READ;
- lba2msf(block,&drvcmd[1]); /* msf-bcd format required */
- bin2bcdx(&drvcmd[1]);
- bin2bcdx(&drvcmd[2]);
- bin2bcdx(&drvcmd[3]);
- drvcmd[4]=D_S[d].sbp_read_frames>>8;
- drvcmd[5]=D_S[d].sbp_read_frames&0xff;
- drvcmd[6]=0x02; /* flag "msf-bcd" */
- }
- else if (fam0L_drive)
- {
- flags_cmd_out |= f_lopsta | f_getsta | f_bit1;
- if (D_S[d].xa_byte==0x20)
- {
- cmd_type=READ_M2;
- drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */
- drvcmd[1]=(block>>16)&0x0ff;
- drvcmd[2]=(block>>8)&0x0ff;
- drvcmd[3]=block&0x0ff;
- drvcmd[4]=(D_S[d].sbp_read_frames>>8)&0x0ff;
- drvcmd[5]=D_S[d].sbp_read_frames&0x0ff;
- }
- else
- {
- drvcmd[0]=CMD0_READ; /* "read frames", old drives */
- if (D_S[d].drv_type>=drv_201)
- {
- lba2msf(block,&drvcmd[1]); /* msf-bcd format required */
- bin2bcdx(&drvcmd[1]);
- bin2bcdx(&drvcmd[2]);
- bin2bcdx(&drvcmd[3]);
- }
- else
- {
- drvcmd[1]=(block>>16)&0x0ff;
- drvcmd[2]=(block>>8)&0x0ff;
- drvcmd[3]=block&0x0ff;
- }
- drvcmd[4]=(D_S[d].sbp_read_frames>>8)&0x0ff;
- drvcmd[5]=D_S[d].sbp_read_frames&0x0ff;
- drvcmd[6]=(D_S[d].drv_type<drv_201)?0:2; /* flag "lba or msf-bcd format" */
- }
- }
- else if (fam1_drive)
- {
- drvcmd[0]=CMD1_READ;
- lba2msf(block,&drvcmd[1]); /* msf-bin format required */
- drvcmd[5]=(D_S[d].sbp_read_frames>>8)&0x0ff;
- drvcmd[6]=D_S[d].sbp_read_frames&0x0ff;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_READ;
- lba2msf(block,&drvcmd[1]); /* msf-bin format required */
- drvcmd[4]=(D_S[d].sbp_read_frames>>8)&0x0ff;
- drvcmd[5]=D_S[d].sbp_read_frames&0x0ff;
- drvcmd[6]=0x02;
- }
- else if (famT_drive)
- {
- drvcmd[0]=CMDT_READ;
- drvcmd[2]=(block>>24)&0x0ff;
- drvcmd[3]=(block>>16)&0x0ff;
- drvcmd[4]=(block>>8)&0x0ff;
- drvcmd[5]=block&0x0ff;
- drvcmd[7]=(D_S[d].sbp_read_frames>>8)&0x0ff;
- drvcmd[8]=D_S[d].sbp_read_frames&0x0ff;
- }
- flags_cmd_out=f_putcmd;
- response_count=0;
- i=cmd_out();
- if (i<0) msg(DBG_INF,"error giving READ command: %0dn", i);
- return;
- }
- /*==========================================================================*/
- /*
- * Check the completion of the read-data command. On success, read
- * the D_S[d].sbp_bufsiz * 2048 bytes of data from the disk into buffer.
- */
- static int sbp_data(struct request *req)
- {
- int i=0, j=0, l, frame;
- u_int try=0;
- u_long timeout;
- u_char *p;
- u_int data_tries = 0;
- u_int data_waits = 0;
- u_int data_retrying = 0;
- int error_flag;
- int xa_count;
- int max_latency;
- int success;
- int wait;
- int duration;
-
- error_flag=0;
- success=0;
- #if LONG_TIMING
- max_latency=9*HZ;
- #else
- if (D_S[d].f_multisession) max_latency=15*HZ;
- else max_latency=5*HZ;
- #endif
- duration=jiffies;
- for (frame=0;frame<D_S[d].sbp_read_frames&&!error_flag; frame++)
- {
- SBPCD_CLI;
-
- del_timer(&data_timer);
- data_timer.expires=jiffies+max_latency;
- timed_out_data=0;
- add_timer(&data_timer);
- while (!timed_out_data)
- {
- if (D_S[d].f_multisession) try=maxtim_data*4;
- else try=maxtim_data;
- msg(DBG_000,"sbp_data: CDi_status loop: try=%d.n",try);
- for ( ; try!=0;try--)
- {
- j=inb(CDi_status);
- if (!(j&s_not_data_ready)) break;;
- if (!(j&s_not_result_ready)) break;
- if (fam0LV_drive) if (j&s_attention) break;
- }
- if (!(j&s_not_data_ready)) goto data_ready;
- if (try==0)
- {
- if (data_retrying == 0) data_waits++;
- data_retrying = 1;
- msg(DBG_000,"sbp_data: CDi_status loop: sleeping.n");
- sbp_sleep(1);
- try = 1;
- }
- }
- msg(DBG_INF,"sbp_data: CDi_status loop expired.n");
- data_ready:
- del_timer(&data_timer);
- if (timed_out_data)
- {
- msg(DBG_INF,"sbp_data: CDi_status timeout (timed_out_data) (%02X).n", j);
- error_flag++;
- }
- if (try==0)
- {
- msg(DBG_INF,"sbp_data: CDi_status timeout (try=0) (%02X).n", j);
- error_flag++;
- }
- if (!(j&s_not_result_ready))
- {
- msg(DBG_INF, "sbp_data: RESULT_READY where DATA_READY awaited (%02X).n", j);
- response_count=20;
- j=ResponseInfo();
- j=inb(CDi_status);
- }
- if (j&s_not_data_ready)
- {
- if ((D_S[d].ored_ctl_adr&0x40)==0)
- msg(DBG_INF, "CD contains no data tracks.n");
- else msg(DBG_INF, "sbp_data: DATA_READY timeout (%02X).n", j);
- error_flag++;
- }
- SBPCD_STI;
- if (error_flag) break;
- msg(DBG_000, "sbp_data: beginning to read.n");
- p = D_S[d].sbp_buf + frame * CD_FRAMESIZE;
- if (sbpro_type==1) OUT(CDo_sel_i_d,1);
- if (cmd_type==READ_M2) {
- if (do_16bit) insw(CDi_data, xa_head_buf, CD_XA_HEAD>>1);
- else insb(CDi_data, xa_head_buf, CD_XA_HEAD);
- }
- if (do_16bit) insw(CDi_data, p, CD_FRAMESIZE>>1);
- else insb(CDi_data, p, CD_FRAMESIZE);
- if (cmd_type==READ_M2) {
- if (do_16bit) insw(CDi_data, xa_tail_buf, CD_XA_TAIL>>1);
- else insb(CDi_data, xa_tail_buf, CD_XA_TAIL);
- }
- D_S[d].sbp_current++;
- if (sbpro_type==1) OUT(CDo_sel_i_d,0);
- if (cmd_type==READ_M2)
- {
- for (xa_count=0;xa_count<CD_XA_HEAD;xa_count++)
- sprintf(&msgbuf[xa_count*3], " %02X", xa_head_buf[xa_count]);
- msgbuf[xa_count*3]=0;
- msg(DBG_XA1,"xa head:%sn", msgbuf);
- }
- data_retrying = 0;
- data_tries++;
- if (data_tries >= 1000)
- {
- msg(DBG_INF,"sbp_data() statistics: %d waits in %d frames.n", data_waits, data_tries);
- data_waits = data_tries = 0;
- }
- }
- duration=jiffies-duration;
- msg(DBG_TEA,"time to read %d frames: %d jiffies .n",frame,duration);
- if (famT_drive)
- {
- wait=8;
- do
- {
- if (teac==2)
- {
- if ((i=CDi_stat_loop_T()) == -1) break;
- }
- else
- {
- sbp_sleep(1);
- OUT(CDo_sel_i_d,0);
- i=inb(CDi_status);
- }
- if (!(i&s_not_data_ready))
- {
- OUT(CDo_sel_i_d,1);
- j=0;
- do
- {
- if (do_16bit) i=inw(CDi_data);
- else i=inb(CDi_data);
- j++;
- i=inb(CDi_status);
- }
- while (!(i&s_not_data_ready));
- msg(DBG_TEA, "==========too much data (%d bytes/words)==============.n", j);
- }
- if (!(i&s_not_result_ready))
- {
- OUT(CDo_sel_i_d,0);
- l=0;
- do
- {
- infobuf[l++]=inb(CDi_info);
- i=inb(CDi_status);
- }
- while (!(i&s_not_result_ready));
- if (infobuf[0]==0x00) success=1;
- #if 1
- for (j=0;j<l;j++) sprintf(&msgbuf[j*3], " %02X", infobuf[j]);
- msgbuf[j*3]=0;
- msg(DBG_TEA,"sbp_data info response:%sn", msgbuf);
- #endif
- if (infobuf[0]==0x02)
- {
- error_flag++;
- do
- {
- ++recursion;
- if (recursion>1) msg(DBG_TEA,"cmd_out_T READ_ERR recursion (sbp_data): %d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!n",recursion);
- else msg(DBG_TEA,"sbp_data: CMDT_READ_ERR necessary.n");
- clr_cmdbuf();
- drvcmd[0]=CMDT_READ_ERR;
- j=cmd_out_T(); /* !!! recursive here !!! */
- --recursion;
- sbp_sleep(1);
- }
- while (j<0);
- D_S[d].error_state=infobuf[2];
- D_S[d].b3=infobuf[3];
- D_S[d].b4=infobuf[4];
- }
- break;
- }
- else
- {
- #if 0
- msg(DBG_TEA, "============= waiting for result=================.n");
- sbp_sleep(1);
- #endif
- }
- }
- while (wait--);
- }
- if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */
- {
- msg(DBG_TEA, "================error flag: %d=================.n", error_flag);
- msg(DBG_INF,"sbp_data: read aborted by drive.n");
- #if 1
- i=cc_DriveReset(); /* ugly fix to prevent a hang */
- #else
- i=cc_ReadError();
- #endif
- return (0);
- }
-
- if (fam0LV_drive)
- {
- SBPCD_CLI;
- i=maxtim_data;
- for (timeout=jiffies+HZ; time_before(jiffies, timeout); timeout--)
- {
- for ( ;i!=0;i--)
- {
- j=inb(CDi_status);
- if (!(j&s_not_data_ready)) break;
- if (!(j&s_not_result_ready)) break;
- if (j&s_attention) break;
- }
- if (i != 0 || time_after_eq(jiffies, timeout)) break;
- sbp_sleep(0);
- i = 1;
- }
- if (i==0) msg(DBG_INF,"status timeout after READ.n");
- if (!(j&s_attention))
- {
- msg(DBG_INF,"sbp_data: timeout waiting DRV_ATTN - retrying.n");
- i=cc_DriveReset(); /* ugly fix to prevent a hang */
- SBPCD_STI;
- return (0);
- }
- SBPCD_STI;
- }
-
- #if 0
- if (!success)
- #endif
- do
- {
- if (fam0LV_drive) cc_ReadStatus();
- #if 1
- if (famT_drive) msg(DBG_TEA, "================before ResponseStatus=================.n", i);
- #endif
- i=ResponseStatus(); /* builds status_bits, returns orig. status (old) or faked p_success (new) */
- #if 1
- if (famT_drive) msg(DBG_TEA, "================ResponseStatus: %d=================.n", i);
- #endif
- if (i<0)
- {
- msg(DBG_INF,"bad cc_ReadStatus after read: %02Xn", D_S[d].status_bits);
- return (0);
- }
- }
- while ((fam0LV_drive)&&(!st_check)&&(!(i&p_success)));
- if (st_check)
- {
- i=cc_ReadError();
- msg(DBG_INF,"cc_ReadError was necessary after read: %dn",i);
- return (0);
- }
- if (fatal_err)
- {
- fatal_err=0;
- D_S[d].sbp_first_frame=D_S[d].sbp_last_frame=-1; /* purge buffer */
- D_S[d].sbp_current = 0;
- msg(DBG_INF,"sbp_data: fatal_err - retrying.n");
- return (0);
- }
-
- D_S[d].sbp_first_frame = req -> sector / 4;
- D_S[d].sbp_last_frame = D_S[d].sbp_first_frame + D_S[d].sbp_read_frames - 1;
- sbp_transfer(req);
- return (1);
- }
- /*==========================================================================*/
- static struct block_device_operations sbpcd_bdops =
- {
- owner: THIS_MODULE,
- open: cdrom_open,
- release: cdrom_release,
- ioctl: cdrom_ioctl,
- check_media_change: cdrom_media_changed,
- };
- /*==========================================================================*/
- /*
- * Open the device special file. Check that a disk is in. Read TOC.
- */
- static int sbpcd_open(struct cdrom_device_info *cdi, int purpose)
- {
- int i;
- i = MINOR(cdi->dev);
- down(&ioctl_read_sem);
- switch_drive(i);
- /*
- * try to keep an "open" counter here and lock the door if 0->1.
- */
- msg(DBG_LCK,"open_count: %d -> %dn",
- D_S[d].open_count,D_S[d].open_count+1);
- if (++D_S[d].open_count<=1)
- {
- i=LockDoor();
- D_S[d].open_count=1;
- if (famT_drive) msg(DBG_TEA,"sbpcd_open: before i=DiskInfo();.n");
- i=DiskInfo();
- if (famT_drive) msg(DBG_TEA,"sbpcd_open: after i=DiskInfo();.n");
- if ((D_S[d].ored_ctl_adr&0x40)==0)
- {
- msg(DBG_INF,"CD contains no data tracks.n");
- #if SAFE_MIXED
- D_S[d].has_data=0;
- #endif /* SAFE_MIXED */
- }
- #if SAFE_MIXED
- else if (D_S[d].has_data<1) D_S[d].has_data=1;
- #endif /* SAFE_MIXED */
- }
- if (!st_spinning) cc_SpinUp();
- RETURN_UP(0);
- }
- /*==========================================================================*/
- /*
- * On close, we flush all sbp blocks from the buffer cache.
- */
- static void sbpcd_release(struct cdrom_device_info * cdi)
- {
- int i;
-
- i = MINOR(cdi->dev);
- if ((i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1))
- {
- msg(DBG_INF, "release: bad device: %04Xn", cdi->dev);
- return ;
- }
- down(&ioctl_read_sem);
- switch_drive(i);
- /*
- * try to keep an "open" counter here and unlock the door if 1->0.
- */
- msg(DBG_LCK,"open_count: %d -> %dn",
- D_S[d].open_count,D_S[d].open_count-1);
- if (D_S[d].open_count>-2) /* CDROMEJECT may have been done */
- {
- if (--D_S[d].open_count<=0)
- {
- D_S[d].sbp_first_frame=D_S[d].sbp_last_frame=-1;
- invalidate_buffers(cdi->dev);
- if (D_S[d].audio_state!=audio_playing)
- if (D_S[d].f_eject) cc_SpinDown();
- D_S[d].diskstate_flags &= ~cd_size_bit;
- D_S[d].open_count=0;
- #if SAFE_MIXED
- D_S[d].has_data=0;
- #endif /* SAFE_MIXED */
- }
- }
- up(&ioctl_read_sem);
- return ;
- }
- /*==========================================================================*/
- /*
- *
- */
- static int sbpcd_media_changed( struct cdrom_device_info *cdi, int disc_nr);
- static struct cdrom_device_ops sbpcd_dops = {
- open: sbpcd_open,
- release: sbpcd_release,
- drive_status: sbpcd_drive_status,
- media_changed: sbpcd_media_changed,
- tray_move: sbpcd_tray_move,
- lock_door: sbpcd_lock_door,
- select_speed: sbpcd_select_speed,
- get_last_session: sbpcd_get_last_session,
- get_mcn: sbpcd_get_mcn,
- reset: sbpcd_reset,
- audio_ioctl: sbpcd_audio_ioctl,
- dev_ioctl: sbpcd_dev_ioctl,
- capability: CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
- CDC_MULTI_SESSION | CDC_MEDIA_CHANGED |
- CDC_MCN | CDC_PLAY_AUDIO | CDC_IOCTLS,
- n_minors: 1,
- };
- static struct cdrom_device_info sbpcd_info = {
- ops: &sbpcd_dops,
- speed: 2,
- capacity: 1,
- name: "sbpcd",
- };
- /*==========================================================================*/
- /*
- * accept "kernel command line" parameters
- * (suggested by Peter MacDonald with SLS 1.03)
- *
- * This is only implemented for the first controller. Should be enough to
- * allow installing with a "strange" distribution kernel.
- *
- * use: tell LILO:
- * sbpcd=0x230,SoundBlaster
- * or
- * sbpcd=0x300,LaserMate
- * or
- * sbpcd=0x338,SoundScape
- * or
- * sbpcd=0x2C0,Teac16bit
- *
- * (upper/lower case sensitive here - but all-lowercase is ok!!!).
- *
- * the address value has to be the CDROM PORT ADDRESS -
- * not the soundcard base address.
- * For the SPEA/SoundScape setup, DO NOT specify the "configuration port"
- * address, but the address which is really used for the CDROM (usually 8
- * bytes above).
- *
- */
- #if (SBPCD_ISSUE-1)
- static int sbpcd_setup(char *s)
- #else
- int sbpcd_setup(char *s)
- #endif
- {
- #ifndef MODULE
- int p[4];
- (void)get_options(s, ARRAY_SIZE(p), p);
- setup_done++;
- msg(DBG_INI,"sbpcd_setup called with %04X,%sn",p[1], s);
- sbpro_type=0; /* default: "LaserMate" */
- if (p[0]>1) sbpro_type=p[2];
- else if (!strcmp(s,str_sb)) sbpro_type=1;
- else if (!strcmp(s,str_sb_l)) sbpro_type=1;
- else if (!strcmp(s,str_sp)) sbpro_type=2;
- else if (!strcmp(s,str_sp_l)) sbpro_type=2;
- else if (!strcmp(s,str_ss)) sbpro_type=2;
- else if (!strcmp(s,str_ss_l)) sbpro_type=2;
- else if (!strcmp(s,str_t16)) sbpro_type=3;
- else if (!strcmp(s,str_t16_l)) sbpro_type=3;
- if (p[0]>0) sbpcd_ioaddr=p[1];
- if (p[0]>2) max_drives=p[3];
- #else
- sbpcd_ioaddr = sbpcd[0];
- sbpro_type = sbpcd[1];
- #endif
-
- CDo_command=sbpcd_ioaddr;
- CDi_info=sbpcd_ioaddr;
- CDi_status=sbpcd_ioaddr+1;
- CDo_sel_i_d=sbpcd_ioaddr+1;
- CDo_reset=sbpcd_ioaddr+2;
- CDo_enable=sbpcd_ioaddr+3;
- f_16bit=0;
- if ((sbpro_type==1)||(sbpro_type==3))
- {
- CDi_data=sbpcd_ioaddr;
- if (sbpro_type==3)
- {
- f_16bit=1;
- sbpro_type=1;
- }
- }
- else CDi_data=sbpcd_ioaddr+2;
- return 1;
- }
- __setup("sbpcd=", sbpcd_setup);
- /*==========================================================================*/
- /*
- * Sequoia S-1000 CD-ROM Interface Configuration
- * as used within SPEA Media FX, Ensonic SoundScape and some Reveal cards
- * The soundcard has to get jumpered for the interface type "Panasonic"
- * (not Sony or Mitsumi) and to get soft-configured for
- * -> configuration port address
- * -> CDROM port offset (num_ports): has to be 8 here. Possibly this
- * offset value determines the interface type (none, Panasonic,
- * Mitsumi, Sony).
- * The interface uses a configuration port (0x320, 0x330, 0x340, 0x350)
- * some bytes below the real CDROM address.
- *
- * For the Panasonic style (LaserMate) interface and the configuration
- * port 0x330, we have to use an offset of 8; so, the real CDROM port
- * address is 0x338.
- */
- static int __init config_spea(void)
- {
- /*
- * base address offset between configuration port and CDROM port,
- * this probably defines the interface type
- * 2 (type=??): 0x00
- * 8 (type=LaserMate):0x10
- * 16 (type=??):0x20
- * 32 (type=??):0x30
- */
- int n_ports=0x10;
- int irq_number=0; /* off:0x00, 2/9:0x01, 7:0x03, 12:0x05, 15:0x07 */
- int dma_channel=0; /* off: 0x00, 0:0x08, 1:0x18, 3:0x38, 5:0x58, 6:0x68 */
- int dack_polarity=0; /* L:0x00, H:0x80 */
- int drq_polarity=0x40; /* L:0x00, H:0x40 */
- int i;
- #define SPEA_REG_1 sbpcd_ioaddr-0x08+4
- #define SPEA_REG_2 sbpcd_ioaddr-0x08+5
-
- OUT(SPEA_REG_1,0xFF);
- i=inb(SPEA_REG_1);
- if (i!=0x0F)
- {
- msg(DBG_SEQ,"no SPEA interface at %04X present.n", sbpcd_ioaddr);
- return (-1); /* no interface found */
- }
- OUT(SPEA_REG_1,0x04);
- OUT(SPEA_REG_2,0xC0);
-
- OUT(SPEA_REG_1,0x05);
- OUT(SPEA_REG_2,0x10|drq_polarity|dack_polarity);
-
- #if 1
- #define SPEA_PATTERN 0x80
- #else
- #define SPEA_PATTERN 0x00
- #endif
- OUT(SPEA_REG_1,0x06);
- OUT(SPEA_REG_2,dma_channel|irq_number|SPEA_PATTERN);
- OUT(SPEA_REG_2,dma_channel|irq_number|SPEA_PATTERN);
-
- OUT(SPEA_REG_1,0x09);
- i=(inb(SPEA_REG_2)&0xCF)|n_ports;
- OUT(SPEA_REG_2,i);
-
- sbpro_type = 0; /* acts like a LaserMate interface now */
- msg(DBG_SEQ,"found SoundScape interface at %04X.n", sbpcd_ioaddr);
- return (0);
- }
- #ifdef DONT_MERGE_REQUESTS
- static int dont_merge_requests_fn(request_queue_t *q, struct request *req,
- struct request *next, int max_segments)
- {
- return 0;
- }
- static int dont_bh_merge_fn(request_queue_t *q, struct request *req,
- struct buffer_head *bh, int max_segments)
- {
- return 0;
- }
- #endif
- /*==========================================================================*/
- /*
- * Test for presence of drive and initialize it.
- * Called once at boot or load time.
- */
- static devfs_handle_t devfs_handle;
- #ifdef MODULE
- int __init __SBPCD_INIT(void)
- #else
- int __init SBPCD_INIT(void)
- #endif /* MODULE */
- {
- char nbuff[16];
- int i=0, j=0;
- int addr[2]={1, CDROM_PORT};
- int port_index;
- sti();
-
- msg(DBG_INF,"sbpcd.c %sn", VERSION);
- #ifndef MODULE
- #if DISTRIBUTION
- if (!setup_done)
- {
- msg(DBG_INF,"Looking for Matsushita/Panasonic, CreativeLabs, Longshine, TEAC CD-ROM drivesn");
- msg(DBG_INF,"= = = = = = = = = = W A R N I N G = = = = = = = = = =n");
- msg(DBG_INF,"Auto-Probing can cause a hang (f.e. touching an NE2000 card).n");
- msg(DBG_INF,"If that happens, you have to reboot and use then");
- msg(DBG_INF,"LILO (kernel) command line feature like:n");
- msg(DBG_INF," LILO boot: ... sbpcd=0x230,SoundBlastern");
- msg(DBG_INF,"or like:n");
- msg(DBG_INF," LILO boot: ... sbpcd=0x300,LaserMaten");
- msg(DBG_INF,"or like:n");
- msg(DBG_INF," LILO boot: ... sbpcd=0x338,SoundScapen");
- msg(DBG_INF,"with your REAL address.n");
- msg(DBG_INF,"= = = = = = = = = = END of WARNING = = = = = == = = =n");
- }
- #endif /* DISTRIBUTION */
- sbpcd[0]=sbpcd_ioaddr; /* possibly changed by kernel command line */
- sbpcd[1]=sbpro_type; /* possibly changed by kernel command line */
- #endif /* MODULE */
-
- for (port_index=0;port_index<NUM_PROBE;port_index+=2)
- {
- addr[1]=sbpcd[port_index];
- if (addr[1]==0) break;
- if (check_region(addr[1],4))
- {
- msg(DBG_INF,"check_region: %03X is not free.n",addr[1]);
- continue;
- }
- if (sbpcd[port_index+1]==2) type=str_sp;
- else if (sbpcd[port_index+1]==1) type=str_sb;
- else if (sbpcd[port_index+1]==3) type=str_t16;
- else type=str_lm;
- sbpcd_setup((char *)type);
- #if DISTRIBUTION
- msg(DBG_INF,"Scanning 0x%X (%s)...n", CDo_command, type);
- #endif /* DISTRIBUTION */
- if (sbpcd[port_index+1]==2)
- {
- i=config_spea();
- if (i<0) continue;
- }
- #ifdef PATH_CHECK
- if (check_card(addr[1])) continue;
- #endif /* PATH_CHECK */
- i=check_drives();
- msg(DBG_INI,"check_drives done.n");
- if (i>=0) break; /* drive found */
- } /* end of cycling through the set of possible I/O port addresses */
-
- if (ndrives==0)
- {
- msg(DBG_INF, "No drive found.n");
- #ifdef MODULE
- return -EIO;
- #else
- goto init_done;
- #endif /* MODULE */
- }
-
- if (port_index>0)
- {
- msg(DBG_INF, "You should read linux/Documentation/cdrom/sbpcdn");
- msg(DBG_INF, "and then configure sbpcd.h for your hardware.n");
- }
- check_datarate();
- msg(DBG_INI,"check_datarate done.n");
-
- for (j=0;j<NR_SBPCD;j++)
- {
- if (D_S[j].drv_id==-1) continue;
- switch_drive(j);
- #if 1
- if (!famL_drive) cc_DriveReset();
- #endif
- if (!st_spinning) cc_SpinUp();
- D_S[j].sbp_first_frame = -1; /* First frame in buffer */
- D_S[j].sbp_last_frame = -1; /* Last frame in buffer */
- D_S[j].sbp_read_frames = 0; /* Number of frames being read to buffer */
- D_S[j].sbp_current = 0; /* Frame being currently read */
- D_S[j].CD_changed=1;
- D_S[j].frame_size=CD_FRAMESIZE;
- D_S[j].f_eject=0;
- #if EJECT
- if (!fam0_drive) D_S[j].f_eject=1;
- #endif /* EJECT */
- cc_ReadStatus();
- i=ResponseStatus(); /* returns orig. status or p_busy_new */
- if (famT_drive) i=ResponseStatus(); /* returns orig. status or p_busy_new */
- if (i<0)
- {
- if (i!=-402)
- msg(DBG_INF,"init: ResponseStatus returns %d.n",i);
- }
- else
- {
- if (st_check)
- {
- i=cc_ReadError();
- msg(DBG_INI,"init: cc_ReadError returns %dn",i);
- }
- }
- msg(DBG_INI,"init: first GetStatus: %dn",i);
- msg(DBG_LCS,"init: first GetStatus: error_byte=%dn",
- D_S[j].error_byte);
- if (D_S[j].error_byte==aud_12)
- {
- timeout=jiffies+2*HZ;
- do
- {
- i=GetStatus();
- msg(DBG_INI,"init: second GetStatus: %02Xn",i);
- msg(DBG_LCS,
- "init: second GetStatus: error_byte=%dn",
- D_S[j].error_byte);
- if (i<0) break;
- if (!st_caddy_in) break;
- }
- while ((!st_diskok)||time_after(jiffies, timeout));
- }
- i=SetSpeed();
- if (i>=0) D_S[j].CD_changed=1;
- }
-
- /*
- * Turn on the CD audio channels.
- * The addresses are obtained from SOUND_BASE (see sbpcd.h).
- */
- #if SOUND_BASE
- OUT(MIXER_addr,MIXER_CD_Volume); /* select SB Pro mixer register */
- OUT(MIXER_data,0xCC); /* one nibble per channel, max. value: 0xFF */
- #endif /* SOUND_BASE */
-
- if (devfs_register_blkdev(MAJOR_NR, major_name, &sbpcd_bdops) != 0)
- {
- msg(DBG_INF, "Can't get MAJOR %d for Matsushita CDROMn", MAJOR_NR);
- #ifdef MODULE
- return -EIO;
- #else
- goto init_done;
- #endif /* MODULE */
- }
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
- #ifdef DONT_MERGE_REQUESTS
- (BLK_DEFAULT_QUEUE(MAJOR_NR))->back_merge_fn = dont_bh_merge_fn;
- (BLK_DEFAULT_QUEUE(MAJOR_NR))->front_merge_fn = dont_bh_merge_fn;
- (BLK_DEFAULT_QUEUE(MAJOR_NR))->merge_requests_fn = dont_merge_requests_fn;
- #endif
- blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR), 0);
- read_ahead[MAJOR_NR] = buffers * (CD_FRAMESIZE / 512);
-
- request_region(CDo_command,4,major_name);
-
- devfs_handle = devfs_mk_dir (NULL, "sbp", NULL);
- for (j=0;j<NR_SBPCD;j++)
- {
- struct cdrom_device_info * sbpcd_infop;
- if (D_S[j].drv_id==-1) continue;
- switch_drive(j);
- #if SAFE_MIXED
- D_S[j].has_data=0;
- #endif /* SAFE_MIXED */
- /*
- * allocate memory for the frame buffers
- */
- D_S[j].aud_buf=NULL;
- D_S[j].sbp_audsiz=0;
- D_S[j].sbp_bufsiz=buffers;
- if (D_S[j].drv_type&drv_fam1)
- if (READ_AUDIO>0) D_S[j].sbp_audsiz=READ_AUDIO;
- D_S[j].sbp_buf=(u_char *) vmalloc(D_S[j].sbp_bufsiz*CD_FRAMESIZE);
- if (D_S[j].sbp_buf==NULL)
- {
- msg(DBG_INF,"data buffer (%d frames) not available.n",D_S[j].sbp_bufsiz);
- if ((devfs_unregister_blkdev(MAJOR_NR, major_name) == -EINVAL))
- {
- printk("Can't unregister %sn", major_name);
- }
- release_region(CDo_command,4);
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
- return -EIO;
- }
- #ifdef MODULE
- msg(DBG_INF,"data buffer size: %d frames.n",buffers);
- #endif /* MODULE */
- if (D_S[j].sbp_audsiz>0)
- {
- D_S[j].aud_buf=(u_char *) vmalloc(D_S[j].sbp_audsiz*CD_FRAMESIZE_RAW);
- if (D_S[j].aud_buf==NULL) msg(DBG_INF,"audio buffer (%d frames) not available.n",D_S[j].sbp_audsiz);
- else msg(DBG_INF,"audio buffer size: %d frames.n",D_S[j].sbp_audsiz);
- }
- sbpcd_infop = vmalloc(sizeof (struct cdrom_device_info));
- if (sbpcd_infop == NULL)
- {
- release_region(CDo_command,4);
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
- return -ENOMEM;
- }
- D_S[j].sbpcd_infop = sbpcd_infop;
- memcpy (sbpcd_infop, &sbpcd_info, sizeof(struct cdrom_device_info));
- sbpcd_infop->dev = MKDEV(MAJOR_NR, j);
- strncpy(sbpcd_infop->name,major_name, sizeof(sbpcd_infop->name));
- sprintf (nbuff, "c%dt%d/cd", SBPCD_ISSUE - 1, D_S[j].drv_id);
- sbpcd_infop->de =
- devfs_register (devfs_handle, nbuff, DEVFS_FL_DEFAULT,
- MAJOR_NR, j, S_IFBLK | S_IRUGO | S_IWUGO,
- &sbpcd_bdops, NULL);
- if (register_cdrom(sbpcd_infop))
- {
- printk(" sbpcd: Unable to register with Uniform CD-ROm drivern");
- }
- /*
- * set the block size
- */
- sbpcd_blocksizes[j]=CD_FRAMESIZE;
- }
- blksize_size[MAJOR_NR]=sbpcd_blocksizes;
- #ifndef MODULE
- init_done:
- #if !(SBPCD_ISSUE-1)
- #ifdef CONFIG_SBPCD2
- sbpcd2_init();
- #endif /* CONFIG_SBPCD2 */
- #ifdef CONFIG_SBPCD3
- sbpcd3_init();
- #endif /* CONFIG_SBPCD3 */
- #ifdef CONFIG_SBPCD4
- sbpcd4_init();
- #endif /* CONFIG_SBPCD4 */
- #endif /* !(SBPCD_ISSUE-1) */
- #endif /* MODULE */
- return 0;
- }
- /*==========================================================================*/
- #ifdef MODULE
- void sbpcd_exit(void)
- {
- int j;
-
- if ((devfs_unregister_blkdev(MAJOR_NR, major_name) == -EINVAL))
- {
- msg(DBG_INF, "What's that: can't unregister %s.n", major_name);
- return;
- }
- release_region(CDo_command,4);
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
- devfs_unregister (devfs_handle);
- for (j=0;j<NR_SBPCD;j++)
- {
- if (D_S[j].drv_id==-1) continue;
- vfree(D_S[j].sbp_buf);
- if (D_S[j].sbp_audsiz>0) vfree(D_S[j].aud_buf);
- if ((unregister_cdrom(D_S[j].sbpcd_infop) == -EINVAL))
- {
- msg(DBG_INF, "What's that: can't unregister info %s.n", major_name);
- return;
- }
- vfree(D_S[j].sbpcd_infop);
- }
- msg(DBG_INF, "%s module released.n", major_name);
- }
- #ifdef MODULE
- module_init(__SBPCD_INIT) /*HACK!*/;
- #endif
- module_exit(sbpcd_exit);
- #endif /* MODULE */
- /*==========================================================================*/
- /*
- * Check if the media has changed in the CD-ROM drive.
- * used externally (isofs/inode.c, fs/buffer.c)
- */
- static int sbpcd_chk_disk_change(kdev_t full_dev)
- {
- int i;
-
- msg(DBG_CHK,"media_check (%d) calledn", MINOR(full_dev));
- i=MINOR(full_dev);
-
- if (D_S[i].CD_changed==0xFF)
- {
- D_S[i].CD_changed=0;
- msg(DBG_CHK,"medium changed (drive %d)n", i);
- /* BUG! Should invalidate buffers! --AJK */
- invalidate_buffers(full_dev);
- D_S[d].diskstate_flags &= ~toc_bit;
- D_S[d].diskstate_flags &= ~cd_size_bit;
- #if SAFE_MIXED
- D_S[d].has_data=0;
- #endif /* SAFE_MIXED */
- return (1);
- }
- else
- return (0);
- }
- static int sbpcd_media_changed( struct cdrom_device_info *cdi, int disc_nr)
- {
- return sbpcd_chk_disk_change(cdi->dev);
- }
- MODULE_LICENSE("GPL");
- /*==========================================================================*/
- /*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 8
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -8
- * c-argdecl-indent: 8
- * c-label-offset: -8
- * c-continued-statement-offset: 8
- * c-continued-brace-offset: 0
- * End:
- */