xref: /kernel/linux/linux-5.10/drivers/s390/char/tape.h (revision 8c2ecf20)
18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *    tape device driver for 3480/3490E/3590 tapes.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *  S390 and zSeries version
68c2ecf20Sopenharmony_ci *    Copyright IBM Corp. 2001, 2009
78c2ecf20Sopenharmony_ci *    Author(s): Carsten Otte <cotte@de.ibm.com>
88c2ecf20Sopenharmony_ci *		 Tuan Ngo-Anh <ngoanh@de.ibm.com>
98c2ecf20Sopenharmony_ci *		 Martin Schwidefsky <schwidefsky@de.ibm.com>
108c2ecf20Sopenharmony_ci *		 Stefan Bader <shbader@de.ibm.com>
118c2ecf20Sopenharmony_ci */
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#ifndef _TAPE_H
148c2ecf20Sopenharmony_ci#define _TAPE_H
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#include <asm/ccwdev.h>
178c2ecf20Sopenharmony_ci#include <asm/debug.h>
188c2ecf20Sopenharmony_ci#include <asm/idals.h>
198c2ecf20Sopenharmony_ci#include <linux/kernel.h>
208c2ecf20Sopenharmony_ci#include <linux/module.h>
218c2ecf20Sopenharmony_ci#include <linux/mtio.h>
228c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
238c2ecf20Sopenharmony_ci#include <linux/workqueue.h>
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_cistruct gendisk;
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci/*
288c2ecf20Sopenharmony_ci * Define DBF_LIKE_HELL for lots of messages in the debug feature.
298c2ecf20Sopenharmony_ci */
308c2ecf20Sopenharmony_ci#define DBF_LIKE_HELL
318c2ecf20Sopenharmony_ci#ifdef  DBF_LIKE_HELL
328c2ecf20Sopenharmony_ci#define DBF_LH(level, str, ...) \
338c2ecf20Sopenharmony_cido { \
348c2ecf20Sopenharmony_ci	debug_sprintf_event(TAPE_DBF_AREA, level, str, ## __VA_ARGS__); \
358c2ecf20Sopenharmony_ci} while (0)
368c2ecf20Sopenharmony_ci#else
378c2ecf20Sopenharmony_ci#define DBF_LH(level, str, ...) do {} while(0)
388c2ecf20Sopenharmony_ci#endif
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci/*
418c2ecf20Sopenharmony_ci * macros s390 debug feature (dbf)
428c2ecf20Sopenharmony_ci */
438c2ecf20Sopenharmony_ci#define DBF_EVENT(d_level, d_str...) \
448c2ecf20Sopenharmony_cido { \
458c2ecf20Sopenharmony_ci	debug_sprintf_event(TAPE_DBF_AREA, d_level, d_str); \
468c2ecf20Sopenharmony_ci} while (0)
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci#define DBF_EXCEPTION(d_level, d_str...) \
498c2ecf20Sopenharmony_cido { \
508c2ecf20Sopenharmony_ci	debug_sprintf_exception(TAPE_DBF_AREA, d_level, d_str); \
518c2ecf20Sopenharmony_ci} while (0)
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci#define TAPE_VERSION_MAJOR 2
548c2ecf20Sopenharmony_ci#define TAPE_VERSION_MINOR 0
558c2ecf20Sopenharmony_ci#define TAPE_MAGIC "tape"
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci#define TAPE_MINORS_PER_DEV 2	    /* two minors per device */
588c2ecf20Sopenharmony_ci#define TAPEBLOCK_HSEC_SIZE	2048
598c2ecf20Sopenharmony_ci#define TAPEBLOCK_HSEC_S2B	2
608c2ecf20Sopenharmony_ci#define TAPEBLOCK_RETRIES	5
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_cienum tape_medium_state {
638c2ecf20Sopenharmony_ci	MS_UNKNOWN,
648c2ecf20Sopenharmony_ci	MS_LOADED,
658c2ecf20Sopenharmony_ci	MS_UNLOADED,
668c2ecf20Sopenharmony_ci	MS_SIZE
678c2ecf20Sopenharmony_ci};
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_cienum tape_state {
708c2ecf20Sopenharmony_ci	TS_UNUSED=0,
718c2ecf20Sopenharmony_ci	TS_IN_USE,
728c2ecf20Sopenharmony_ci	TS_BLKUSE,
738c2ecf20Sopenharmony_ci	TS_INIT,
748c2ecf20Sopenharmony_ci	TS_NOT_OPER,
758c2ecf20Sopenharmony_ci	TS_SIZE
768c2ecf20Sopenharmony_ci};
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_cienum tape_op {
798c2ecf20Sopenharmony_ci	TO_BLOCK,	/* Block read */
808c2ecf20Sopenharmony_ci	TO_BSB,		/* Backward space block */
818c2ecf20Sopenharmony_ci	TO_BSF,		/* Backward space filemark */
828c2ecf20Sopenharmony_ci	TO_DSE,		/* Data security erase */
838c2ecf20Sopenharmony_ci	TO_FSB,		/* Forward space block */
848c2ecf20Sopenharmony_ci	TO_FSF,		/* Forward space filemark */
858c2ecf20Sopenharmony_ci	TO_LBL,		/* Locate block label */
868c2ecf20Sopenharmony_ci	TO_NOP,		/* No operation */
878c2ecf20Sopenharmony_ci	TO_RBA,		/* Read backward */
888c2ecf20Sopenharmony_ci	TO_RBI,		/* Read block information */
898c2ecf20Sopenharmony_ci	TO_RFO,		/* Read forward */
908c2ecf20Sopenharmony_ci	TO_REW,		/* Rewind tape */
918c2ecf20Sopenharmony_ci	TO_RUN,		/* Rewind and unload tape */
928c2ecf20Sopenharmony_ci	TO_WRI,		/* Write block */
938c2ecf20Sopenharmony_ci	TO_WTM,		/* Write tape mark */
948c2ecf20Sopenharmony_ci	TO_MSEN,	/* Medium sense */
958c2ecf20Sopenharmony_ci	TO_LOAD,	/* Load tape */
968c2ecf20Sopenharmony_ci	TO_READ_CONFIG, /* Read configuration data */
978c2ecf20Sopenharmony_ci	TO_READ_ATTMSG, /* Read attention message */
988c2ecf20Sopenharmony_ci	TO_DIS,		/* Tape display */
998c2ecf20Sopenharmony_ci	TO_ASSIGN,	/* Assign tape to channel path */
1008c2ecf20Sopenharmony_ci	TO_UNASSIGN,	/* Unassign tape from channel path */
1018c2ecf20Sopenharmony_ci	TO_CRYPT_ON,	/* Enable encrpytion */
1028c2ecf20Sopenharmony_ci	TO_CRYPT_OFF,	/* Disable encrpytion */
1038c2ecf20Sopenharmony_ci	TO_KEKL_SET,	/* Set KEK label */
1048c2ecf20Sopenharmony_ci	TO_KEKL_QUERY,	/* Query KEK label */
1058c2ecf20Sopenharmony_ci	TO_RDC,		/* Read device characteristics */
1068c2ecf20Sopenharmony_ci	TO_SIZE,	/* #entries in tape_op_t */
1078c2ecf20Sopenharmony_ci};
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci/* Forward declaration */
1108c2ecf20Sopenharmony_cistruct tape_device;
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci/* tape_request->status can be: */
1138c2ecf20Sopenharmony_cienum tape_request_status {
1148c2ecf20Sopenharmony_ci	TAPE_REQUEST_INIT,	/* request is ready to be processed */
1158c2ecf20Sopenharmony_ci	TAPE_REQUEST_QUEUED,	/* request is queued to be processed */
1168c2ecf20Sopenharmony_ci	TAPE_REQUEST_IN_IO,	/* request is currently in IO */
1178c2ecf20Sopenharmony_ci	TAPE_REQUEST_DONE,	/* request is completed. */
1188c2ecf20Sopenharmony_ci	TAPE_REQUEST_CANCEL,	/* request should be canceled. */
1198c2ecf20Sopenharmony_ci	TAPE_REQUEST_LONG_BUSY, /* request has to be restarted after long busy */
1208c2ecf20Sopenharmony_ci};
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci/* Tape CCW request */
1238c2ecf20Sopenharmony_cistruct tape_request {
1248c2ecf20Sopenharmony_ci	struct list_head list;		/* list head for request queueing. */
1258c2ecf20Sopenharmony_ci	struct tape_device *device;	/* tape device of this request */
1268c2ecf20Sopenharmony_ci	struct ccw1 *cpaddr;		/* address of the channel program. */
1278c2ecf20Sopenharmony_ci	void *cpdata;			/* pointer to ccw data. */
1288c2ecf20Sopenharmony_ci	enum tape_request_status status;/* status of this request */
1298c2ecf20Sopenharmony_ci	int options;			/* options for execution. */
1308c2ecf20Sopenharmony_ci	int retries;			/* retry counter for error recovery. */
1318c2ecf20Sopenharmony_ci	int rescnt;			/* residual count from devstat. */
1328c2ecf20Sopenharmony_ci	struct timer_list timer;	/* timer for std_assign_timeout(). */
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	/* Callback for delivering final status. */
1358c2ecf20Sopenharmony_ci	void (*callback)(struct tape_request *, void *);
1368c2ecf20Sopenharmony_ci	void *callback_data;
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci	enum tape_op op;
1398c2ecf20Sopenharmony_ci	int rc;
1408c2ecf20Sopenharmony_ci};
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci/* Function type for magnetic tape commands */
1438c2ecf20Sopenharmony_citypedef int (*tape_mtop_fn)(struct tape_device *, int);
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci/* Size of the array containing the mtops for a discipline */
1468c2ecf20Sopenharmony_ci#define TAPE_NR_MTOPS (MTMKPART+1)
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci/* Tape Discipline */
1498c2ecf20Sopenharmony_cistruct tape_discipline {
1508c2ecf20Sopenharmony_ci	struct module *owner;
1518c2ecf20Sopenharmony_ci	int  (*setup_device)(struct tape_device *);
1528c2ecf20Sopenharmony_ci	void (*cleanup_device)(struct tape_device *);
1538c2ecf20Sopenharmony_ci	int (*irq)(struct tape_device *, struct tape_request *, struct irb *);
1548c2ecf20Sopenharmony_ci	struct tape_request *(*read_block)(struct tape_device *, size_t);
1558c2ecf20Sopenharmony_ci	struct tape_request *(*write_block)(struct tape_device *, size_t);
1568c2ecf20Sopenharmony_ci	void (*process_eov)(struct tape_device*);
1578c2ecf20Sopenharmony_ci	/* ioctl function for additional ioctls. */
1588c2ecf20Sopenharmony_ci	int (*ioctl_fn)(struct tape_device *, unsigned int, unsigned long);
1598c2ecf20Sopenharmony_ci	/* Array of tape commands with TAPE_NR_MTOPS entries */
1608c2ecf20Sopenharmony_ci	tape_mtop_fn *mtop_array;
1618c2ecf20Sopenharmony_ci};
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci/*
1648c2ecf20Sopenharmony_ci * The discipline irq function either returns an error code (<0) which
1658c2ecf20Sopenharmony_ci * means that the request has failed with an error or one of the following:
1668c2ecf20Sopenharmony_ci */
1678c2ecf20Sopenharmony_ci#define TAPE_IO_SUCCESS		0	/* request successful */
1688c2ecf20Sopenharmony_ci#define TAPE_IO_PENDING		1	/* request still running */
1698c2ecf20Sopenharmony_ci#define TAPE_IO_RETRY		2	/* retry to current request */
1708c2ecf20Sopenharmony_ci#define TAPE_IO_STOP		3	/* stop the running request */
1718c2ecf20Sopenharmony_ci#define TAPE_IO_LONG_BUSY	4	/* delay the running request */
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci/* Char Frontend Data */
1748c2ecf20Sopenharmony_cistruct tape_char_data {
1758c2ecf20Sopenharmony_ci	struct idal_buffer *idal_buf;	/* idal buffer for user char data */
1768c2ecf20Sopenharmony_ci	int block_size;			/*   of size block_size. */
1778c2ecf20Sopenharmony_ci};
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci/* Tape Info */
1808c2ecf20Sopenharmony_cistruct tape_device {
1818c2ecf20Sopenharmony_ci	/* entry in tape_device_list */
1828c2ecf20Sopenharmony_ci	struct list_head		node;
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci	int				cdev_id;
1858c2ecf20Sopenharmony_ci	struct ccw_device *		cdev;
1868c2ecf20Sopenharmony_ci	struct tape_class_device *	nt;
1878c2ecf20Sopenharmony_ci	struct tape_class_device *	rt;
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	/* Device mutex to serialize tape commands. */
1908c2ecf20Sopenharmony_ci	struct mutex			mutex;
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	/* Device discipline information. */
1938c2ecf20Sopenharmony_ci	struct tape_discipline *	discipline;
1948c2ecf20Sopenharmony_ci	void *				discdata;
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	/* Generic status flags */
1978c2ecf20Sopenharmony_ci	long				tape_generic_status;
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	/* Device state information. */
2008c2ecf20Sopenharmony_ci	wait_queue_head_t		state_change_wq;
2018c2ecf20Sopenharmony_ci	enum tape_state			tape_state;
2028c2ecf20Sopenharmony_ci	enum tape_medium_state		medium_state;
2038c2ecf20Sopenharmony_ci	unsigned char *			modeset_byte;
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci	/* Reference count. */
2068c2ecf20Sopenharmony_ci	atomic_t			ref_count;
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci	/* Request queue. */
2098c2ecf20Sopenharmony_ci	struct list_head		req_queue;
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci	/* Request wait queue. */
2128c2ecf20Sopenharmony_ci	wait_queue_head_t		wait_queue;
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci	/* Each tape device has (currently) two minor numbers. */
2158c2ecf20Sopenharmony_ci	int				first_minor;
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	/* Number of tapemarks required for correct termination. */
2188c2ecf20Sopenharmony_ci	int				required_tapemarks;
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	/* Block ID of the BOF */
2218c2ecf20Sopenharmony_ci	unsigned int			bof;
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci	/* Character device frontend data */
2248c2ecf20Sopenharmony_ci	struct tape_char_data		char_data;
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	/* Function to start or stop the next request later. */
2278c2ecf20Sopenharmony_ci	struct delayed_work		tape_dnr;
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	/* Timer for long busy */
2308c2ecf20Sopenharmony_ci	struct timer_list		lb_timeout;
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci};
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci/* Externals from tape_core.c */
2358c2ecf20Sopenharmony_ciextern struct tape_request *tape_alloc_request(int cplength, int datasize);
2368c2ecf20Sopenharmony_ciextern void tape_free_request(struct tape_request *);
2378c2ecf20Sopenharmony_ciextern int tape_do_io(struct tape_device *, struct tape_request *);
2388c2ecf20Sopenharmony_ciextern int tape_do_io_async(struct tape_device *, struct tape_request *);
2398c2ecf20Sopenharmony_ciextern int tape_do_io_interruptible(struct tape_device *, struct tape_request *);
2408c2ecf20Sopenharmony_ciextern int tape_cancel_io(struct tape_device *, struct tape_request *);
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_cistatic inline int
2438c2ecf20Sopenharmony_citape_do_io_free(struct tape_device *device, struct tape_request *request)
2448c2ecf20Sopenharmony_ci{
2458c2ecf20Sopenharmony_ci	int rc;
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	rc = tape_do_io(device, request);
2488c2ecf20Sopenharmony_ci	tape_free_request(request);
2498c2ecf20Sopenharmony_ci	return rc;
2508c2ecf20Sopenharmony_ci}
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_cistatic inline void
2538c2ecf20Sopenharmony_citape_do_io_async_free(struct tape_device *device, struct tape_request *request)
2548c2ecf20Sopenharmony_ci{
2558c2ecf20Sopenharmony_ci	request->callback = (void *) tape_free_request;
2568c2ecf20Sopenharmony_ci	request->callback_data = NULL;
2578c2ecf20Sopenharmony_ci	tape_do_io_async(device, request);
2588c2ecf20Sopenharmony_ci}
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ciextern int tape_open(struct tape_device *);
2618c2ecf20Sopenharmony_ciextern int tape_release(struct tape_device *);
2628c2ecf20Sopenharmony_ciextern int tape_mtop(struct tape_device *, int, int);
2638c2ecf20Sopenharmony_ciextern void tape_state_set(struct tape_device *, enum tape_state);
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ciextern int tape_generic_online(struct tape_device *, struct tape_discipline *);
2668c2ecf20Sopenharmony_ciextern int tape_generic_offline(struct ccw_device *);
2678c2ecf20Sopenharmony_ciextern int tape_generic_pm_suspend(struct ccw_device *);
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci/* Externals from tape_devmap.c */
2708c2ecf20Sopenharmony_ciextern int tape_generic_probe(struct ccw_device *);
2718c2ecf20Sopenharmony_ciextern void tape_generic_remove(struct ccw_device *);
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ciextern struct tape_device *tape_find_device(int devindex);
2748c2ecf20Sopenharmony_ciextern struct tape_device *tape_get_device(struct tape_device *);
2758c2ecf20Sopenharmony_ciextern void tape_put_device(struct tape_device *);
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci/* Externals from tape_char.c */
2788c2ecf20Sopenharmony_ciextern int tapechar_init(void);
2798c2ecf20Sopenharmony_ciextern void tapechar_exit(void);
2808c2ecf20Sopenharmony_ciextern int  tapechar_setup_device(struct tape_device *);
2818c2ecf20Sopenharmony_ciextern void tapechar_cleanup_device(struct tape_device *);
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci/* tape initialisation functions */
2848c2ecf20Sopenharmony_ci#ifdef CONFIG_PROC_FS
2858c2ecf20Sopenharmony_ciextern void tape_proc_init (void);
2868c2ecf20Sopenharmony_ciextern void tape_proc_cleanup (void);
2878c2ecf20Sopenharmony_ci#else
2888c2ecf20Sopenharmony_cistatic inline void tape_proc_init (void) {;}
2898c2ecf20Sopenharmony_cistatic inline void tape_proc_cleanup (void) {;}
2908c2ecf20Sopenharmony_ci#endif
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci/* a function for dumping device sense info */
2938c2ecf20Sopenharmony_ciextern void tape_dump_sense_dbf(struct tape_device *, struct tape_request *,
2948c2ecf20Sopenharmony_ci				struct irb *);
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci/* functions for handling the status of a device */
2978c2ecf20Sopenharmony_ciextern void tape_med_state_set(struct tape_device *, enum tape_medium_state);
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci/* The debug area */
3008c2ecf20Sopenharmony_ciextern debug_info_t *TAPE_DBF_AREA;
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci/* functions for building ccws */
3038c2ecf20Sopenharmony_cistatic inline struct ccw1 *
3048c2ecf20Sopenharmony_citape_ccw_cc(struct ccw1 *ccw, __u8 cmd_code, __u16 memsize, void *cda)
3058c2ecf20Sopenharmony_ci{
3068c2ecf20Sopenharmony_ci	ccw->cmd_code = cmd_code;
3078c2ecf20Sopenharmony_ci	ccw->flags = CCW_FLAG_CC;
3088c2ecf20Sopenharmony_ci	ccw->count = memsize;
3098c2ecf20Sopenharmony_ci	ccw->cda = (__u32)(addr_t) cda;
3108c2ecf20Sopenharmony_ci	return ccw + 1;
3118c2ecf20Sopenharmony_ci}
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_cistatic inline struct ccw1 *
3148c2ecf20Sopenharmony_citape_ccw_end(struct ccw1 *ccw, __u8 cmd_code, __u16 memsize, void *cda)
3158c2ecf20Sopenharmony_ci{
3168c2ecf20Sopenharmony_ci	ccw->cmd_code = cmd_code;
3178c2ecf20Sopenharmony_ci	ccw->flags = 0;
3188c2ecf20Sopenharmony_ci	ccw->count = memsize;
3198c2ecf20Sopenharmony_ci	ccw->cda = (__u32)(addr_t) cda;
3208c2ecf20Sopenharmony_ci	return ccw + 1;
3218c2ecf20Sopenharmony_ci}
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_cistatic inline struct ccw1 *
3248c2ecf20Sopenharmony_citape_ccw_cmd(struct ccw1 *ccw, __u8 cmd_code)
3258c2ecf20Sopenharmony_ci{
3268c2ecf20Sopenharmony_ci	ccw->cmd_code = cmd_code;
3278c2ecf20Sopenharmony_ci	ccw->flags = 0;
3288c2ecf20Sopenharmony_ci	ccw->count = 0;
3298c2ecf20Sopenharmony_ci	ccw->cda = (__u32)(addr_t) &ccw->cmd_code;
3308c2ecf20Sopenharmony_ci	return ccw + 1;
3318c2ecf20Sopenharmony_ci}
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_cistatic inline struct ccw1 *
3348c2ecf20Sopenharmony_citape_ccw_repeat(struct ccw1 *ccw, __u8 cmd_code, int count)
3358c2ecf20Sopenharmony_ci{
3368c2ecf20Sopenharmony_ci	while (count-- > 0) {
3378c2ecf20Sopenharmony_ci		ccw->cmd_code = cmd_code;
3388c2ecf20Sopenharmony_ci		ccw->flags = CCW_FLAG_CC;
3398c2ecf20Sopenharmony_ci		ccw->count = 0;
3408c2ecf20Sopenharmony_ci		ccw->cda = (__u32)(addr_t) &ccw->cmd_code;
3418c2ecf20Sopenharmony_ci		ccw++;
3428c2ecf20Sopenharmony_ci	}
3438c2ecf20Sopenharmony_ci	return ccw;
3448c2ecf20Sopenharmony_ci}
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_cistatic inline struct ccw1 *
3478c2ecf20Sopenharmony_citape_ccw_cc_idal(struct ccw1 *ccw, __u8 cmd_code, struct idal_buffer *idal)
3488c2ecf20Sopenharmony_ci{
3498c2ecf20Sopenharmony_ci	ccw->cmd_code = cmd_code;
3508c2ecf20Sopenharmony_ci	ccw->flags    = CCW_FLAG_CC;
3518c2ecf20Sopenharmony_ci	idal_buffer_set_cda(idal, ccw);
3528c2ecf20Sopenharmony_ci	return ccw++;
3538c2ecf20Sopenharmony_ci}
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_cistatic inline struct ccw1 *
3568c2ecf20Sopenharmony_citape_ccw_end_idal(struct ccw1 *ccw, __u8 cmd_code, struct idal_buffer *idal)
3578c2ecf20Sopenharmony_ci{
3588c2ecf20Sopenharmony_ci	ccw->cmd_code = cmd_code;
3598c2ecf20Sopenharmony_ci	ccw->flags    = 0;
3608c2ecf20Sopenharmony_ci	idal_buffer_set_cda(idal, ccw);
3618c2ecf20Sopenharmony_ci	return ccw++;
3628c2ecf20Sopenharmony_ci}
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci/* Global vars */
3658c2ecf20Sopenharmony_ciextern const char *tape_state_verbose[];
3668c2ecf20Sopenharmony_ciextern const char *tape_op_verbose[];
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci#endif /* for ifdef tape.h */
369