drivers/s390/char/sclp_vt220.c

Source file repositories/reference/linux-study-clean/drivers/s390/char/sclp_vt220.c

File Facts

System
Linux kernel
Corpus path
drivers/s390/char/sclp_vt220.c
Extension
.c
Size
22289 bytes
Lines
846
Domain
Driver Families
Bucket
drivers/s390
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct sclp_vt220_request {
	struct list_head list;
	struct sclp_req sclp_req;
	int retry_count;
};

/* VT220 SCCB */
struct sclp_vt220_sccb {
	struct sccb_header header;
	struct evbuf_header evbuf;
};

#define SCLP_VT220_MAX_CHARS_PER_BUFFER	(PAGE_SIZE - \
					 sizeof(struct sclp_vt220_request) - \
					 sizeof(struct sclp_vt220_sccb))

/* Structures and data needed to register tty driver */
static struct tty_driver *sclp_vt220_driver;

static struct tty_port sclp_vt220_port;

/* Lock to protect internal data from concurrent access */
static DEFINE_SPINLOCK(sclp_vt220_lock);

/* List of empty pages to be used as write request buffers */
static LIST_HEAD(sclp_vt220_empty);

/* List of pending requests */
static LIST_HEAD(sclp_vt220_outqueue);

/* Flag that output queue is currently running */
static int sclp_vt220_queue_running;

/* Timer used for delaying write requests to merge subsequent messages into
 * a single buffer */
static struct timer_list sclp_vt220_timer;

/* Pointer to current request buffer which has been partially filled but not
 * yet sent */
static struct sclp_vt220_request *sclp_vt220_current_request;

/* Counter controlling core driver initialization. */
static int __initdata sclp_vt220_init_count;

/* Flag indicating that sclp_vt220_current_request should really
 * have been already queued but wasn't because the SCLP was processing
 * another buffer */
static int sclp_vt220_flush_later;

static void sclp_vt220_receiver_fn(struct evbuf_header *evbuf);
static int __sclp_vt220_emit(struct sclp_vt220_request *request);
static void sclp_vt220_emit_current(void);

/* Registration structure for SCLP output event buffers */
static struct sclp_register sclp_vt220_register = {
	.send_mask		= EVTYP_VT220MSG_MASK,
};

/* Registration structure for SCLP input event buffers */
static struct sclp_register sclp_vt220_register_input = {
	.receive_mask		= EVTYP_VT220MSG_MASK,
	.receiver_fn		= sclp_vt220_receiver_fn,
};


/*
 * Put provided request buffer back into queue and check emit pending
 * buffers if necessary.
 */
static void
sclp_vt220_process_queue(struct sclp_vt220_request *request)
{
	unsigned long flags;
	void *page;

	do {
		/* Put buffer back to list of empty buffers */
		page = request->sclp_req.sccb;
		spin_lock_irqsave(&sclp_vt220_lock, flags);
		/* Move request from outqueue to empty queue */
		list_del(&request->list);
		list_add_tail((struct list_head *) page, &sclp_vt220_empty);
		/* Check if there is a pending buffer on the out queue. */
		request = NULL;
		if (!list_empty(&sclp_vt220_outqueue))
			request = list_entry(sclp_vt220_outqueue.next,
					     struct sclp_vt220_request, list);
		if (!request) {
			sclp_vt220_queue_running = 0;
			spin_unlock_irqrestore(&sclp_vt220_lock, flags);

Annotation

Implementation Notes