162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Copyright (C) 2000 Jens Axboe <axboe@suse.de>
362306a36Sopenharmony_ci * Copyright (C) 2001-2004 Peter Osterlund <petero2@telia.com>
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * May be copied or modified under the terms of the GNU General Public
662306a36Sopenharmony_ci * License.  See linux/COPYING for more information.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * Packet writing layer for ATAPI and SCSI CD-R, CD-RW, DVD-R, and
962306a36Sopenharmony_ci * DVD-RW devices.
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci#ifndef __PKTCDVD_H
1362306a36Sopenharmony_ci#define __PKTCDVD_H
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include <linux/blkdev.h>
1662306a36Sopenharmony_ci#include <linux/completion.h>
1762306a36Sopenharmony_ci#include <linux/cdrom.h>
1862306a36Sopenharmony_ci#include <linux/kobject.h>
1962306a36Sopenharmony_ci#include <linux/sysfs.h>
2062306a36Sopenharmony_ci#include <linux/mempool.h>
2162306a36Sopenharmony_ci#include <uapi/linux/pktcdvd.h>
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci/* default bio write queue congestion marks */
2462306a36Sopenharmony_ci#define PKT_WRITE_CONGESTION_ON    10000
2562306a36Sopenharmony_ci#define PKT_WRITE_CONGESTION_OFF   9000
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_cistruct packet_settings
2962306a36Sopenharmony_ci{
3062306a36Sopenharmony_ci	__u32			size;		/* packet size in (512 byte) sectors */
3162306a36Sopenharmony_ci	__u8			fp;		/* fixed packets */
3262306a36Sopenharmony_ci	__u8			link_loss;	/* the rest is specified
3362306a36Sopenharmony_ci						 * as per Mt Fuji */
3462306a36Sopenharmony_ci	__u8			write_type;
3562306a36Sopenharmony_ci	__u8			track_mode;
3662306a36Sopenharmony_ci	__u8			block_mode;
3762306a36Sopenharmony_ci};
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci/*
4062306a36Sopenharmony_ci * Very crude stats for now
4162306a36Sopenharmony_ci */
4262306a36Sopenharmony_cistruct packet_stats
4362306a36Sopenharmony_ci{
4462306a36Sopenharmony_ci	unsigned long		pkt_started;
4562306a36Sopenharmony_ci	unsigned long		pkt_ended;
4662306a36Sopenharmony_ci	unsigned long		secs_w;
4762306a36Sopenharmony_ci	unsigned long		secs_rg;
4862306a36Sopenharmony_ci	unsigned long		secs_r;
4962306a36Sopenharmony_ci};
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_cistruct packet_cdrw
5262306a36Sopenharmony_ci{
5362306a36Sopenharmony_ci	struct list_head	pkt_free_list;
5462306a36Sopenharmony_ci	struct list_head	pkt_active_list;
5562306a36Sopenharmony_ci	spinlock_t		active_list_lock; /* Serialize access to pkt_active_list */
5662306a36Sopenharmony_ci	struct task_struct	*thread;
5762306a36Sopenharmony_ci	atomic_t		pending_bios;
5862306a36Sopenharmony_ci};
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci/*
6162306a36Sopenharmony_ci * Switch to high speed reading after reading this many kilobytes
6262306a36Sopenharmony_ci * with no interspersed writes.
6362306a36Sopenharmony_ci */
6462306a36Sopenharmony_ci#define HI_SPEED_SWITCH 512
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_cistruct packet_iosched
6762306a36Sopenharmony_ci{
6862306a36Sopenharmony_ci	atomic_t		attention;	/* Set to non-zero when queue processing is needed */
6962306a36Sopenharmony_ci	int			writing;	/* Non-zero when writing, zero when reading */
7062306a36Sopenharmony_ci	spinlock_t		lock;		/* Protecting read/write queue manipulations */
7162306a36Sopenharmony_ci	struct bio_list		read_queue;
7262306a36Sopenharmony_ci	struct bio_list		write_queue;
7362306a36Sopenharmony_ci	sector_t		last_write;	/* The sector where the last write ended */
7462306a36Sopenharmony_ci	int			successive_reads;
7562306a36Sopenharmony_ci};
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci/*
7862306a36Sopenharmony_ci * 32 buffers of 2048 bytes
7962306a36Sopenharmony_ci */
8062306a36Sopenharmony_ci#if (PAGE_SIZE % CD_FRAMESIZE) != 0
8162306a36Sopenharmony_ci#error "PAGE_SIZE must be a multiple of CD_FRAMESIZE"
8262306a36Sopenharmony_ci#endif
8362306a36Sopenharmony_ci#define PACKET_MAX_SIZE		128
8462306a36Sopenharmony_ci#define FRAMES_PER_PAGE		(PAGE_SIZE / CD_FRAMESIZE)
8562306a36Sopenharmony_ci#define PACKET_MAX_SECTORS	(PACKET_MAX_SIZE * CD_FRAMESIZE >> 9)
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_cienum packet_data_state {
8862306a36Sopenharmony_ci	PACKET_IDLE_STATE,			/* Not used at the moment */
8962306a36Sopenharmony_ci	PACKET_WAITING_STATE,			/* Waiting for more bios to arrive, so */
9062306a36Sopenharmony_ci						/* we don't have to do as much */
9162306a36Sopenharmony_ci						/* data gathering */
9262306a36Sopenharmony_ci	PACKET_READ_WAIT_STATE,			/* Waiting for reads to fill in holes */
9362306a36Sopenharmony_ci	PACKET_WRITE_WAIT_STATE,		/* Waiting for the write to complete */
9462306a36Sopenharmony_ci	PACKET_RECOVERY_STATE,			/* Recover after read/write errors */
9562306a36Sopenharmony_ci	PACKET_FINISHED_STATE,			/* After write has finished */
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	PACKET_NUM_STATES			/* Number of possible states */
9862306a36Sopenharmony_ci};
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci/*
10162306a36Sopenharmony_ci * Information needed for writing a single packet
10262306a36Sopenharmony_ci */
10362306a36Sopenharmony_cistruct pktcdvd_device;
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_cistruct packet_data
10662306a36Sopenharmony_ci{
10762306a36Sopenharmony_ci	struct list_head	list;
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	spinlock_t		lock;		/* Lock protecting state transitions and */
11062306a36Sopenharmony_ci						/* orig_bios list */
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	struct bio_list		orig_bios;	/* Original bios passed to pkt_make_request */
11362306a36Sopenharmony_ci						/* that will be handled by this packet */
11462306a36Sopenharmony_ci	int			write_size;	/* Total size of all bios in the orig_bios */
11562306a36Sopenharmony_ci						/* list, measured in number of frames */
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	struct bio		*w_bio;		/* The bio we will send to the real CD */
11862306a36Sopenharmony_ci						/* device once we have all data for the */
11962306a36Sopenharmony_ci						/* packet we are going to write */
12062306a36Sopenharmony_ci	sector_t		sector;		/* First sector in this packet */
12162306a36Sopenharmony_ci	int			frames;		/* Number of frames in this packet */
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	enum packet_data_state	state;		/* Current state */
12462306a36Sopenharmony_ci	atomic_t		run_sm;		/* Incremented whenever the state */
12562306a36Sopenharmony_ci						/* machine needs to be run */
12662306a36Sopenharmony_ci	long			sleep_time;	/* Set this to non-zero to make the state */
12762306a36Sopenharmony_ci						/* machine run after this many jiffies. */
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci	atomic_t		io_wait;	/* Number of pending IO operations */
13062306a36Sopenharmony_ci	atomic_t		io_errors;	/* Number of read/write errors during IO */
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci	struct bio		*r_bios[PACKET_MAX_SIZE]; /* bios to use during data gathering */
13362306a36Sopenharmony_ci	struct page		*pages[PACKET_MAX_SIZE / FRAMES_PER_PAGE];
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	int			cache_valid;	/* If non-zero, the data for the zone defined */
13662306a36Sopenharmony_ci						/* by the sector variable is completely cached */
13762306a36Sopenharmony_ci						/* in the pages[] vector. */
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	int			id;		/* ID number for debugging */
14062306a36Sopenharmony_ci	struct pktcdvd_device	*pd;
14162306a36Sopenharmony_ci};
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_cistruct pkt_rb_node {
14462306a36Sopenharmony_ci	struct rb_node		rb_node;
14562306a36Sopenharmony_ci	struct bio		*bio;
14662306a36Sopenharmony_ci};
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_cistruct packet_stacked_data
14962306a36Sopenharmony_ci{
15062306a36Sopenharmony_ci	struct bio		*bio;		/* Original read request bio */
15162306a36Sopenharmony_ci	struct pktcdvd_device	*pd;
15262306a36Sopenharmony_ci};
15362306a36Sopenharmony_ci#define PSD_POOL_SIZE		64
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_cistruct pktcdvd_device
15662306a36Sopenharmony_ci{
15762306a36Sopenharmony_ci	struct block_device	*bdev;		/* dev attached */
15862306a36Sopenharmony_ci	dev_t			pkt_dev;	/* our dev */
15962306a36Sopenharmony_ci	struct packet_settings	settings;
16062306a36Sopenharmony_ci	struct packet_stats	stats;
16162306a36Sopenharmony_ci	int			refcnt;		/* Open count */
16262306a36Sopenharmony_ci	int			write_speed;	/* current write speed, kB/s */
16362306a36Sopenharmony_ci	int			read_speed;	/* current read speed, kB/s */
16462306a36Sopenharmony_ci	unsigned long		offset;		/* start offset */
16562306a36Sopenharmony_ci	__u8			mode_offset;	/* 0 / 8 */
16662306a36Sopenharmony_ci	__u8			type;
16762306a36Sopenharmony_ci	unsigned long		flags;
16862306a36Sopenharmony_ci	__u16			mmc3_profile;
16962306a36Sopenharmony_ci	__u32			nwa;		/* next writable address */
17062306a36Sopenharmony_ci	__u32			lra;		/* last recorded address */
17162306a36Sopenharmony_ci	struct packet_cdrw	cdrw;
17262306a36Sopenharmony_ci	wait_queue_head_t	wqueue;
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	spinlock_t		lock;		/* Serialize access to bio_queue */
17562306a36Sopenharmony_ci	struct rb_root		bio_queue;	/* Work queue of bios we need to handle */
17662306a36Sopenharmony_ci	int			bio_queue_size;	/* Number of nodes in bio_queue */
17762306a36Sopenharmony_ci	bool			congested;	/* Someone is waiting for bio_queue_size
17862306a36Sopenharmony_ci						 * to drop. */
17962306a36Sopenharmony_ci	sector_t		current_sector;	/* Keep track of where the elevator is */
18062306a36Sopenharmony_ci	atomic_t		scan_queue;	/* Set to non-zero when pkt_handle_queue */
18162306a36Sopenharmony_ci						/* needs to be run. */
18262306a36Sopenharmony_ci	mempool_t		rb_pool;	/* mempool for pkt_rb_node allocations */
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	struct packet_iosched   iosched;
18562306a36Sopenharmony_ci	struct gendisk		*disk;
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	int			write_congestion_off;
18862306a36Sopenharmony_ci	int			write_congestion_on;
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci	struct device		*dev;		/* sysfs pktcdvd[0-7] dev */
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	struct dentry		*dfs_d_root;	/* debugfs: devname directory */
19362306a36Sopenharmony_ci	struct dentry		*dfs_f_info;	/* debugfs: info file */
19462306a36Sopenharmony_ci};
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci#endif /* __PKTCDVD_H */
197