📄 sbpcd.c
字号:
#endif/*==========================================================================*//* * Wait a little while (used for polling the drive). */static void sbp_sleep(u_int time){ sti(); current->state = TASK_INTERRUPTIBLE; schedule_timeout(time); sti();}/*==========================================================================*/#define RETURN_UP(rc) {up(&ioctl_read_sem); return(rc);}/*==========================================================================*//* * convert logical_block_address to m-s-f_number (3 bytes only) */static INLINE void lba2msf(int lba, u_char *msf){ lba += CD_MSF_OFFSET; msf[0] = lba / (CD_SECS*CD_FRAMES); lba %= CD_SECS*CD_FRAMES; msf[1] = lba / CD_FRAMES; msf[2] = lba % CD_FRAMES;}/*==========================================================================*//*==========================================================================*//* * convert msf-bin to msf-bcd */static INLINE void bin2bcdx(u_char *p) /* must work only up to 75 or 99 */{ *p=((*p/10)<<4)|(*p%10);}/*==========================================================================*/static INLINE u_int blk2msf(u_int blk){ MSF msf; u_int mm; msf.c[3] = 0; msf.c[2] = (blk + CD_MSF_OFFSET) / (CD_SECS * CD_FRAMES); mm = (blk + CD_MSF_OFFSET) % (CD_SECS * CD_FRAMES); msf.c[1] = mm / CD_FRAMES; msf.c[0] = mm % CD_FRAMES; return (msf.n);}/*==========================================================================*/static INLINE u_int make16(u_char rh, u_char rl){ return ((rh<<8)|rl);}/*==========================================================================*/static INLINE u_int make32(u_int rh, u_int rl){ return ((rh<<16)|rl);}/*==========================================================================*/static INLINE u_char swap_nibbles(u_char i){ return ((i<<4)|(i>>4));}/*==========================================================================*/static INLINE u_char byt2bcd(u_char i){ return (((i/10)<<4)+i%10);}/*==========================================================================*/static INLINE u_char bcd2bin(u_char bcd){ return ((bcd>>4)*10+(bcd&0x0F));}/*==========================================================================*/static INLINE int msf2blk(int msfx){ MSF msf; int i; msf.n=msfx; i=(msf.c[2] * CD_SECS + msf.c[1]) * CD_FRAMES + msf.c[0] - CD_MSF_OFFSET; if (i<0) return (0); return (i);}/*==========================================================================*//* * convert m-s-f_number (3 bytes only) to logical_block_address */static INLINE int msf2lba(u_char *msf){ int i; i=(msf[0] * CD_SECS + msf[1]) * CD_FRAMES + msf[2] - CD_MSF_OFFSET; if (i<0) return (0); return (i);}/*==========================================================================*//* evaluate cc_ReadError code */ static int sta2err(int sta){ if (famT_drive) { if (sta==0x00) return (0); if (sta==0x01) return (-604); /* CRC error */ if (sta==0x02) return (-602); /* drive not ready */ if (sta==0x03) return (-607); /* unknown media */ if (sta==0x04) return (-612); /* general failure */ if (sta==0x05) return (0); if (sta==0x06) return (-ERR_DISKCHANGE); /* disk change */ if (sta==0x0b) return (-612); /* general failure */ if (sta==0xff) return (-612); /* general failure */ return (0); } else { if (sta<=2) return (sta); if (sta==0x05) return (-604); /* CRC error */ if (sta==0x06) return (-606); /* seek error */ if (sta==0x0d) return (-606); /* seek error */ if (sta==0x0e) return (-603); /* unknown command */ if (sta==0x14) return (-603); /* unknown command */ if (sta==0x0c) return (-611); /* read fault */ if (sta==0x0f) return (-611); /* read fault */ if (sta==0x10) return (-611); /* read fault */ if (sta>=0x16) return (-612); /* general failure */ if (sta==0x11) return (-ERR_DISKCHANGE); /* disk change (LCS: removed) */ if (famL_drive) if (sta==0x12) return (-ERR_DISKCHANGE); /* disk change (inserted) */ return (-602); /* drive not ready */ }}/*==========================================================================*/static INLINE void clr_cmdbuf(void){ int i; for (i=0;i<10;i++) drvcmd[i]=0; cmd_type=0;}/*==========================================================================*/static void flush_status(void){ int i; sbp_sleep(15*HZ/10); for (i=maxtim_data;i!=0;i--) inb(CDi_status);}/*====================================================================*//* * CDi status loop for Teac CD-55A (Rob Riggs) * * This is needed because for some strange reason * the CD-55A can take a real long time to give a * status response. This seems to happen after we * issue a READ command where a long seek is involved. * * I tried to ensure that we get max throughput with * minimal busy waiting. We busy wait at first, then * "switch gears" and start sleeping. We sleep for * longer periods of time the longer we wait. * */static int CDi_stat_loop_T(void){ int i, gear=1; u_long timeout_1, timeout_2, timeout_3, timeout_4; timeout_1 = jiffies + HZ / 50; /* sbp_sleep(0) for a short period */ timeout_2 = jiffies + HZ / 5; /* nap for no more than 200ms */ timeout_3 = jiffies + 5 * HZ; /* sleep for up to 5s */ timeout_4 = jiffies + 45 * HZ; /* long sleep for up to 45s. */ do { i = inb(CDi_status); if (!(i&s_not_data_ready)) return (i); if (!(i&s_not_result_ready)) return (i); switch(gear) { case 4: sbp_sleep(HZ); if (time_after(jiffies, timeout_4)) gear++; msg(DBG_TEA, "CDi_stat_loop_T: long sleep active.\n"); break; case 3: sbp_sleep(HZ/10); if (time_after(jiffies, timeout_3)) gear++; break; case 2: sbp_sleep(HZ/100); if (time_after(jiffies, timeout_2)) gear++; break; case 1: sbp_sleep(0); if (time_after(jiffies, timeout_1)) gear++; } } while (gear < 5); return -1;}/*==========================================================================*/static int CDi_stat_loop(void){ int i,j; for(timeout = jiffies + 10*HZ, i=maxtim_data; time_before(jiffies, timeout); ) { for ( ;i!=0;i--) { j=inb(CDi_status); if (!(j&s_not_data_ready)) return (j); if (!(j&s_not_result_ready)) return (j); if (fam0L_drive) if (j&s_attention) return (j); } sbp_sleep(1); i = 1; } msg(DBG_LCS,"CDi_stat_loop failed in line %d\n", __LINE__); return (-1);}/*==========================================================================*/#if 00000/*==========================================================================*/static int tst_DataReady(void){ int i; i=inb(CDi_status); if (i&s_not_data_ready) return (0); return (1);}/*==========================================================================*/static int tst_ResultReady(void){ int i; i=inb(CDi_status); if (i&s_not_result_ready) return (0); return (1);}/*==========================================================================*/static int tst_Attention(void){ int i; i=inb(CDi_status); if (i&s_attention) return (1); return (0);}/*==========================================================================*/#endif 00000/*==========================================================================*/static int ResponseInfo(void){ int i,j,st=0; u_long timeout; for (i=0,timeout=jiffies+HZ;i<response_count;i++) { for (j=maxtim_data; ; ) { for ( ;j!=0;j-- ) { st=inb(CDi_status); if (!(st&s_not_result_ready)) break; } if ((j!=0)||time_after_eq(jiffies, timeout)) break; sbp_sleep(1); j = 1; } if (time_after_eq(jiffies, timeout)) break; infobuf[i]=inb(CDi_info); }#if 000 while (!(inb(CDi_status)&s_not_result_ready)) { infobuf[i++]=inb(CDi_info); } j=i-response_count; if (j>0) msg(DBG_INF,"ResponseInfo: got %d trailing bytes.\n",j);#endif 000 for (j=0;j<i;j++) sprintf(&msgbuf[j*3]," %02X",infobuf[j]); msgbuf[j*3]=0; msg(DBG_CMD,"ResponseInfo:%s (%d,%d)\n",msgbuf,response_count,i); j=response_count-i; if (j>0) return (-j); else return (i);}/*==========================================================================*/static void EvaluateStatus(int st){ D_S[d].status_bits=0; if (fam1_drive) D_S[d].status_bits=st|p_success; else if (fam0_drive) { if (st&p_caddin_old) D_S[d].status_bits |= p_door_closed|p_caddy_in; if (st&p_spinning) D_S[d].status_bits |= p_spinning; if (st&p_check) D_S[d].status_bits |= p_check; if (st&p_success_old) D_S[d].status_bits |= p_success; if (st&p_busy_old) D_S[d].status_bits |= p_busy_new; if (st&p_disk_ok) D_S[d].status_bits |= p_disk_ok; } else if (famLV_drive) { D_S[d].status_bits |= p_success; if (st&p_caddin_old) D_S[d].status_bits |= p_disk_ok|p_caddy_in; if (st&p_spinning) D_S[d].status_bits |= p_spinning; if (st&p_check) D_S[d].status_bits |= p_check; if (st&p_busy_old) D_S[d].status_bits |= p_busy_new; if (st&p_lcs_door_closed) D_S[d].status_bits |= p_door_closed; if (st&p_lcs_door_locked) D_S[d].status_bits |= p_door_locked; } else if (fam2_drive) { D_S[d].status_bits |= p_success; if (st&p2_check) D_S[d].status_bits |= p1_check; if (st&p2_door_closed) D_S[d].status_bits |= p1_door_closed; if (st&p2_disk_in) D_S[d].status_bits |= p1_disk_in; if (st&p2_busy1) D_S[d].status_bits |= p1_busy; if (st&p2_busy2) D_S[d].status_bits |= p1_busy; if (st&p2_spinning) D_S[d].status_bits |= p1_spinning; if (st&p2_door_locked) D_S[d].status_bits |= p1_door_locked; if (st&p2_disk_ok) D_S[d].status_bits |= p1_disk_ok; } else if (famT_drive) { return; /* still needs to get coded */ D_S[d].status_bits |= p_success; if (st&p2_check) D_S[d].status_bits |= p1_check; if (st&p2_door_closed) D_S[d].status_bits |= p1_door_closed; if (st&p2_disk_in) D_S[d].status_bits |= p1_disk_in; if (st&p2_busy1) D_S[d].status_bits |= p1_busy; if (st&p2_busy2) D_S[d].status_bits |= p1_busy; if (st&p2_spinning) D_S[d].status_bits |= p1_spinning; if (st&p2_door_locked) D_S[d].status_bits |= p1_door_locked; if (st&p2_disk_ok) D_S[d].status_bits |= p1_disk_ok; } return;}/*==========================================================================*/static int get_state_T(void){ int i; static int cmd_out_T(void); clr_cmdbuf(); D_S[d].n_bytes=1; drvcmd[0]=CMDT_STATUS; i=cmd_out_T(); if (i>=0) i=infobuf[0]; else { msg(DBG_TEA,"get_state_T error %d\n", i); return (i); } if (i>=0) /* 2: closed, disk in */ D_S[d].status_bits=p1_door_closed|p1_disk_in|p1_spinning|p1_disk_ok; else if (D_S[d].error_state==6) { /* 3: closed, disk in, changed ("06 xx xx") */ D_S[d].status_bits=p1_door_closed|p1_disk_in; D_S[d].CD_changed=0xFF; D_S[d].diskstate_flags &= ~toc_bit; } else if ((D_S[d].error_state!=2)||(D_S[d].b3!=0x3A)||(D_S[d].b4==0x00)) { /* 1: closed, no disk ("xx yy zz"or "02 3A 00") */ D_S[d].status_bits=p1_door_closed; D_S[d].open_count=0; } else if (D_S[d].b4==0x01) { /* 0: open ("02 3A 01") */ D_S[d].status_bits=0; D_S[d].open_count=0; } else { /* 1: closed, no disk ("02 3A xx") */ D_S[d].status_bits=p1_door_closed; D_S[d].open_count=0; } return (D_S[d].status_bits);}/*==========================================================================*/static int ResponseStatus(void){ int i,j; u_long timeout; msg(DBG_STA,"doing ResponseStatus...\n"); if (famT_drive) return (get_state_T()); if (flags_cmd_out & f_respo3) timeout = jiffies; else if (flags_cmd_out & f_respo2) timeout = jiffies + 16*HZ; else timeout = jiffies + 4*HZ; j=maxtim_8; do { for ( ;j!=0;j--) { i=inb(CDi_status); if (!(i&s_not_result_ready)) break; } if ((j!=0)||time_after(jiffies, timeout)) break; sbp_sleep(1); j = 1; } while (1); if (j==0) { if ((flags_cmd_out & f_respo3) == 0) msg(DBG_STA,"ResponseStatus: timeout.\n"); D_S[d].status_bits=0; return (-401); } i=inb(CDi_info); msg(DBG_STA,"ResponseStatus: response %02X.\n", i); EvaluateStatus(i); msg(DBG_STA,"status_bits=%02X, i=%02X\n",D_S[d].status_bits,i); return (D_S[d].status_bits);}/*==========================================================================*/static void cc_ReadStatus(void){ int i; msg(DBG_STA,"giving cc_ReadStatus command\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -