/* This function calibrates the datarate (i.e. determines the maximal * usable data rate) and sets the global variable ft_qic_std to qic_std * */ int ftape_calibrate_data_rate(unsigned int qic_std) { int rate = ft_fdc_rate_limit; int result; TRACE_FUN(ft_t_flow); ft_qic_std = qic_std; if (ft_qic_std == -1) { TRACE_ABORT(-EIO, ft_t_err, "Unable to determine data rate if QIC standard is unknown"); } /* Select highest rate supported by both fdc and drive. * Start with highest rate supported by the fdc. */ while (fdc_set_data_rate(rate) < 0 && rate > 250) { rate /= 2; } TRACE(ft_t_info, "Highest FDC supported data rate: %d Kbps", rate); ft_fdc_max_rate = rate; do { result = ftape_set_data_rate(rate, ft_qic_std); } while (result == -EINVAL && (rate /= 2) > 250); if (result < 0) { TRACE_ABORT(-EIO, ft_t_err, "set datarate failed"); } ft_data_rate = rate; TRACE_EXIT 0; }
int ftape_set_data_rate(unsigned int new_rate /* Kbps */, unsigned int qic_std) { int status; int result = 0; unsigned int data_rate = new_rate; static int supported; int rate_changed = 0; qic_model dummy_model; unsigned int dummy_qic_std, dummy_tape_len; TRACE_FUN(ft_t_any); if (ft_drive_max_rate == 0) { /* first time */ supported = ftape_set_rate_test(&ft_drive_max_rate); } if (supported) { ftape_command(QIC_SELECT_RATE); result = ftape_parameter_wait(qic_rate_code(new_rate), 1 * FT_SECOND, &status); if (result >= 0 && !(status & QIC_STATUS_ERROR)) { rate_changed = 1; } } TRACE_CATCH(result = ftape_report_configuration(&dummy_model, &data_rate, &dummy_qic_std, &dummy_tape_len),); if (data_rate != new_rate) { if (!supported) { TRACE(ft_t_warn, "Rate change not supported!"); } else if (rate_changed) { TRACE(ft_t_warn, "Requested: %d, got %d", new_rate, data_rate); } else { TRACE(ft_t_warn, "Rate change failed!"); } result = -EINVAL; } /* * Set data rate and write precompensation as specified: * * | QIC-40/80 | QIC-3010/3020 * rate | precomp | precomp * ----------+-------------+-------------- * 250 Kbps. | 250 ns. | 0 ns. * 500 Kbps. | 125 ns. | 0 ns. * 1 Mbps. | 42 ns. | 0 ns. * 2 Mbps | N/A | 0 ns. */ if ((qic_std == QIC_TAPE_QIC40 && data_rate > 500) || (qic_std == QIC_TAPE_QIC80 && data_rate > 1000)) { TRACE_ABORT(-EINVAL, ft_t_warn, "Datarate too high for QIC-mode"); } TRACE_CATCH(fdc_set_data_rate(data_rate),_res = -EINVAL); ft_data_rate = data_rate; if (qic_std == QIC_TAPE_QIC40 || qic_std == QIC_TAPE_QIC80) { switch (data_rate) { case 250: fdc_set_write_precomp(250); break; default: case 500: fdc_set_write_precomp(125); break; case 1000: fdc_set_write_precomp(42); break; } } else { fdc_set_write_precomp(0); } TRACE_EXIT result; }