/*  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;
}
Exemple #2
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;
}
Exemple #3
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;
}