/* Called by modules package when installing the driver * or by kernel during the initialization phase */ static int __init ftape_init(void) { TRACE_FUN(ft_t_flow); #ifdef MODULE #ifndef CONFIG_FT_NO_TRACE_AT_ALL if (ft_tracing != -1) { ftape_tracing = ft_tracing; } #endif printk(KERN_INFO FTAPE_VERSION "\n"); if (TRACE_LEVEL >= ft_t_info) { printk( KERN_INFO "(c) 1993-1996 Bas Laarhoven ([email protected])\n" KERN_INFO "(c) 1995-1996 Kai Harrekilde-Petersen ([email protected])\n" KERN_INFO "(c) 1996-1997 Claus-Justus Heine ([email protected])\n" KERN_INFO "QIC-117 driver for QIC-40/80/3010/3020 floppy tape drives\n" KERN_INFO "Compiled for Linux version %s\n", UTS_RELEASE); } #else /* !MODULE */ /* print a short no-nonsense boot message */ printk(KERN_INFO FTAPE_VERSION " for Linux " UTS_RELEASE "\n"); #endif /* MODULE */ TRACE(ft_t_info, "installing QIC-117 floppy tape hardware drive ... "); TRACE(ft_t_info, "ftape_init @ 0x%p", ftape_init); /* Allocate the DMA buffers. They are deallocated at cleanup() time. */ #if TESTING #ifdef MODULE while (ftape_set_nr_buffers(CONFIG_FT_NR_BUFFERS) < 0) { ftape_sleep(FT_SECOND/20); if (signal_pending(current)) { (void)ftape_set_nr_buffers(0); TRACE(ft_t_bug, "Killed by signal while allocating buffers."); TRACE_ABORT(-EINTR, ft_t_bug, "Free up memory and retry"); } } #else TRACE_CATCH(ftape_set_nr_buffers(CONFIG_FT_NR_BUFFERS), (void)ftape_set_nr_buffers(0)); #endif #else TRACE_CATCH(ftape_set_nr_buffers(CONFIG_FT_NR_BUFFERS), (void)ftape_set_nr_buffers(0)); #endif ft_drive_sel = -1; ft_failure = 1; /* inhibit any operation but open */ ftape_udelay_calibrate(); /* must be before fdc_wait_calibrate ! */ fdc_wait_calibrate(); #if defined(CONFIG_PROC_FS) && defined(CONFIG_FT_PROC_FS) (void)ftape_proc_init(); #endif #ifdef CONFIG_ZFTAPE (void)zft_init(); #endif TRACE_EXIT 0; }
/* Issue a tape command: */ int ftape_command(qic117_cmd_t command) { int result = 0; static int level; TRACE_FUN(ft_t_any); if ((unsigned int)command > NR_ITEMS(qic117_cmds)) { /* This is a bug we'll want to know about too. */ TRACE_ABORT(-EIO, ft_t_bug, "bug - bad command: %d", command); } if (++level > 5) { /* This is a bug we'll want to know about. */ --level; TRACE_ABORT(-EIO, ft_t_bug, "bug - recursion for command: %d", command); } /* disable logging and restriction check for some commands, * check all other commands that have a prescribed starting * status. */ if (diagnostic_mode) { TRACE(ft_t_flow, "diagnostic command %d", command); } else if (command == QIC_REPORT_DRIVE_STATUS || command == QIC_REPORT_NEXT_BIT) { TRACE(ft_t_any, "%s", qic117_cmds[command].name); } else { TRACE_CATCH(ft_check_cmd_restrictions(command), --level); } /* Now all conditions are met or result was < 0. */ result = ft_send_to_drive((unsigned int)command); if (qic117_cmds[command].cmd_type == motion && command != QIC_LOGICAL_FORWARD && command != QIC_STOP_TAPE) { ft_location.known = 0; } ftape_current_command = command; --level; TRACE_EXIT result; }
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; }