[BACK]Return to driver.h CVS log [TXT][DIR] Up to [local] / prex-old / dev / include

File: [local] / prex-old / dev / include / driver.h (download)

Revision 1.2, Fri Aug 8 12:37:11 2008 UTC (15 years, 8 months ago) by nbrk
Changes since 1.1: +54 -0 lines

Heads up! Implement universal device attachment and autoconfiguration machinery.
This is somewhat similar to traditional BSD autoconf but much more simple.
Three basic data structures involved in autoconfiguration process are:
struct device, which represents abstract device and its private (driver softc) data;
struct driver, which holds {attach,match,detach} entries, name and softc size;
struct attachment, which tells us how drivers are interacted with each other.
Attachment basically describes how to attach devices in system.
Machine specified part should export arrays config_table[] and *drivers[] for config.

This might have broken i386 & gba tree, but there is only a question of time.

/*
 * Copyright (c) 2005-2007, Kohsuke Ohtani
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the author nor the names of any co-contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * driver.h - Kernel Interface for device driver
 */

#ifndef _DRIVER_H
#define _DRIVER_H

#include <conf/config.h>
#include <sys/cdefs.h>
#include <sys/param.h>
#include <sys/null.h>
#include <sys/types.h>
#include <sys/errno.h>
#include <sys/list.h>
#include <prex/bootinfo.h>
#include <queue.h>
#include <drvlib.h>

/*
 * Kernel types
 */
typedef unsigned long	device_t;
typedef unsigned long	task_t;

#define NULL_DEVICE	((device_t)0)
#define NULL_TASK	((task_t)0)

#ifndef CONFIG_AUTOCONF


/*
 * Driver structure
 *
 * "order" is initialize order which must be between 0 and 15.
 * The driver with order 0 is called first.
 */
struct driver {
	const char	*name;		/* Name of device driver */
	const int	order;		/* Initialize order */
	int		(*init)(void);	/* Initialize routine */
};
#else /* CONFIG_AUTOCONF */

#define CONFIG_XNAMELEN	16	/* maximum name for device (name+unit) */

/*
 * Generic information that is held for every attached device.
 */
struct device {
	void			*dv_data;	/* private data */
	int				dv_unit;	/* unit number (starting from 0) */
	char			*dv_xname;	/* name */
	unsigned long	dv_flags;

	struct device	*dv_parent;	/* parent device */
};

/*
 * Data structure that describes device driver.
 */
struct driver {
	char	*dr_name;	/* abstract name for a device */
	int		dr_datasize;/* sizeof private data structure */

	int		(*dr_match)(struct device *parent, void *aux);
	int		(*dr_attach)(struct device *parent, struct device *self, void *aux);
	int		(*dr_detach)(struct device *parent, struct device *self, void *aux);
	/* XXX dr_search() ? */
	int		dr_nunits;	/* number of attached units */
};

/*
 * Autoconf prototypes.
 */
void	config_attach_rootdev(void);
int	config_search_children(struct device *self, void *aux);
struct driver	*config_find_driver(const char *name);
struct device	*config_alloc_device(struct driver *drv);
void	config_free_device(struct device *dev);

/*
 * Attachment information.
 */
struct attachment {
	const char	*at_childname;
	const char	*at_parentname;
	const int	at_parentunit;	/* -1 for ALL */
	const char	*at_helpername;
	const unsigned long	at_flags;
};

#endif /* !CONFIG_AUTOCONF */

/*
 * Device I/O table
 */
struct devio {
	int (*open)	(device_t dev, int mode);
	int (*close)	(device_t dev);
	int (*read)	(device_t dev, char *buf, size_t *nbyte, int blkno);
	int (*write)	(device_t dev, char *buf, size_t *nbyte, int blkno);
	int (*ioctl)	(device_t dev, int cmd, u_long arg);
	int (*event)	(int event);
};

/*
 * Flags for device_create()
 */
#define DF_CHR		0x00000001	/* Character device */
#define DF_BLK		0x00000002	/* Block device */
#define DF_RDONLY	0x00000004	/* Read only device */
#define DF_REM		0x00000008	/* Removable device */

/*
 * Device open mode
 */
#define DO_RDONLY	0x0
#define DO_WRONLY	0x1
#define DO_RDWR		0x2
#define DO_RWMASK	0x3

/*
 * Return value of ISR
 */
#define INT_DONE	0
#define INT_ERROR	1
#define INT_CONTINUE	2

/*
 * Interrupt priority levels
 */
#define IPL_NONE	0	/* Nothing */
#define IPL_COMM	1	/* Serial, Parallel */
#define IPL_BLOCK	2	/* FDD, IDE */
#define IPL_NET		3	/* Network */
#define IPL_DISPLAY	4	/* Screen */
#define IPL_INPUT	5	/* Keyboard, Mouse */
#define IPL_AUDIO	6	/* Audio */
#define IPL_BUS		7	/* USB, PCCARD */
#define IPL_RTC		8	/* RTC Alarm */
#define IPL_PROFILE	9	/* Profiling timer */
#define IPL_CLOCK	10	/* System Clock Timer */
#define IPL_HIGH	11	/* Everything */

#define NIPL		12

/*
 * Event for sleep/wakeup
 */
struct event {
	struct queue	sleepq;		/* queue for waiting thread */
	const char	*name;		/* pointer to event name string */
};

#define EVENT_INIT(event, evt_name) \
    { {&(event).sleepq, &(event).sleepq}, evt_name}

#define event_init(event, evt_name) \
    do { list_init(&(event)->sleepq); (event)->name = evt_name; } while (0)

/*
 * Sleep result
 */
#define SLP_SUCCESS	0
#define SLP_BREAK	1
#define SLP_TIMEOUT	2
#define SLP_INVAL	3
#define SLP_INTR	4

/*
 * DPC (Deferred Procedure Call) object
 */
struct dpc {
	struct queue	link;		/* Linkage on DPC queue */
	int		state;
	void		(*func)(void *); /* Call back routine */
	void		*arg;		/* Argument to pass */
};

/*
 * Macro to convert milliseconds and tick.
 */
#define msec_to_tick(ms) (((ms) >= 0x20000) ? \
	    ((ms) / 1000UL) * HZ : \
	    ((ms) * HZ) / 1000UL)

#define tick_to_msec(tick) (((tick) * 1000) / HZ)

/*
 * Timer structure
 */
struct timer {
	struct list	link;		/* Linkage on timer chain */
	int		active;		/* True if active */
	u_long		expire;		/* Expire time (ticks) */
	u_long		interval;	/* Time interval */
	void		(*func)(void *); /* Function to call */
	void		*arg;		/* Function argument */
	struct event	event;		/* Event for this timer */
};

#define timer_init(tmr)     (tmr)->expire = 0;

/*
 * Items for debug_dump()
 */
#define DUMP_THREAD	1
#define DUMP_TASK	2
#define DUMP_OBJECT	3
#define DUMP_TIMER	4
#define DUMP_IRQ	5
#define DUMP_DEVICE	6
#define DUMP_VM		7
#define DUMP_MSGLOG	8
#define DUMP_TRACE	9

__BEGIN_DECLS
device_t device_create(struct devio *io, const char *name, int flags);
int	 device_destroy(device_t dev);
int	 device_broadcast(int event, int force);

int	 umem_copyin(void *uaddr, void *kaddr, size_t len);
int	 umem_copyout(void *kaddr, void *uaddr, size_t len);
int	 umem_strnlen(const char *uaddr, size_t maxlen, size_t *len);

void	*kmem_alloc(size_t size);
void	 kmem_free(void *ptr);
void	*kmem_map(void *addr, size_t size);

void	*page_alloc(size_t size);
void	 page_free(void *addr, size_t size);
int	 page_reserve(void *addr, size_t size);

int	 irq_attach(int irqno, int level, int shared, int (*isr)(int), void (*ist)(int));
void	 irq_detach(int handle);
void	 irq_lock(void);
void	 irq_unlock(void);

void	 timer_callout(struct timer *tmr, void (*func)(u_long), u_long arg, u_long msec);
void	 timer_stop(struct timer *tmr);
u_long	 timer_delay(u_long msec);
u_long	 timer_count(void);
int	 timer_hook(void (*func)(int));

void	 sched_lock(void);
void	 sched_unlock(void);
int	 sched_tsleep(struct event *evt, u_long timeout);
void	 sched_wakeup(struct event *evt);
void	 sched_dpc(struct dpc *dpc, void (*func)(void *), void *arg);
#define	 sched_sleep(event)  sched_tsleep((event), 0)

int	 exception_post(task_t task, int exc);
int	 task_capable(int cap);

void	*phys_to_virt(void *p_addr);
void	*virt_to_phys(void *v_addr);

void	 machine_reset(void);
void	 machine_idle(void);
void	 machine_bootinfo(struct boot_info **);

void	 debug_attach(void (*func)(char *));
int	 debug_dump(int index);

#ifdef DEBUG
void	 printk(const char *fmt, ...);
void	 panic(const char *fmt, ...);
void	 assert(const char *file, int line, const char *exp);
#define ASSERT(exp) do { if (!(exp)) \
	assert(__FILE__, __LINE__, #exp); } while (0)
#else
#define printk(fmt...)  do {} while (0)
#define panic(fmt...)  do { for (;;) ; } while (0)
#define ASSERT(exp)
#endif
__END_DECLS

#endif /* !_DRIVER_H */