pccardvar.h revision 82781
138032Speter/*	$NetBSD: pcmciavar.h,v 1.12 2000/02/08 12:51:31 enami Exp $	*/
273188Sgshapiro/* $FreeBSD: head/sys/dev/pccard/pccardvar.h 82781 2001-09-02 06:37:41Z shiba $ */
364562Sgshapiro
438032Speter/*
538032Speter * Copyright (c) 1997 Marc Horowitz.  All rights reserved.
638032Speter *
738032Speter * Redistribution and use in source and binary forms, with or without
838032Speter * modification, are permitted provided that the following conditions
938032Speter * are met:
1038032Speter * 1. Redistributions of source code must retain the above copyright
1138032Speter *    notice, this list of conditions and the following disclaimer.
1238032Speter * 2. Redistributions in binary form must reproduce the above copyright
1338032Speter *    notice, this list of conditions and the following disclaimer in the
1438032Speter *    documentation and/or other materials provided with the distribution.
1573188Sgshapiro * 3. All advertising materials mentioning features or use of this software
1664562Sgshapiro *    must display the following acknowledgement:
1738032Speter *	This product includes software developed by Marc Horowitz.
1864562Sgshapiro * 4. The name of the author may not be used to endorse or promote products
1938032Speter *    derived from this software without specific prior written permission.
2064562Sgshapiro *
2164562Sgshapiro * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2264562Sgshapiro * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2364562Sgshapiro * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2464562Sgshapiro * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2564562Sgshapiro * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2638032Speter * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2738032Speter * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2838032Speter * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2938032Speter * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3038032Speter * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3138032Speter */
3238032Speter
3338032Speter#include <sys/types.h>
3438032Speter#include <sys/queue.h>
3538032Speter
3638032Speter#include <machine/bus.h>
3738032Speter#include "card_if.h"
3838032Speter
3938032Speterextern int	pccard_verbose;
4038032Speter
4138032Speter/*
4238032Speter * Contains information about mapped/allocated i/o spaces.
4338032Speter */
4438032Speterstruct pccard_io_handle {
4538032Speter	bus_space_tag_t iot;		/* bus space tag (from chipset) */
4638032Speter	bus_space_handle_t ioh;		/* mapped space handle */
4738032Speter	bus_addr_t      addr;		/* resulting address in bus space */
4838032Speter	bus_size_t      size;		/* size of i/o space */
4938032Speter	int             flags;		/* misc. information */
5038032Speter	int		width;
5138032Speter};
5238032Speter
5338032Speter#define	PCCARD_IO_ALLOCATED	0x01	/* i/o space was allocated */
5438032Speter
5538032Speter/*
5638032Speter * Contains information about allocated memory space.
5738032Speter */
5838032Speterstruct pccard_mem_handle {
5938032Speter	bus_space_tag_t memt;		/* bus space tag (from chipset) */
6038032Speter	bus_space_handle_t memh;	/* mapped space handle */
6138032Speter	bus_addr_t      addr;		/* resulting address in bus space */
6238032Speter	bus_size_t      size;		/* size of mem space */
6338032Speter	bus_size_t      realsize;	/* how much we really allocated */
6443148Speter	long		offset;
6538032Speter	int		kind;
6638032Speter};
6738032Speter
6838032Speter/* pccard itself */
6938032Speter
7038032Speter#define PCCARD_CFE_MWAIT_REQUIRED	0x0001
7138032Speter#define PCCARD_CFE_RDYBSY_ACTIVE	0x0002
7238032Speter#define PCCARD_CFE_WP_ACTIVE		0x0004
7364562Sgshapiro#define PCCARD_CFE_BVD_ACTIVE		0x0008
7438032Speter#define PCCARD_CFE_IO8			0x0010
7538032Speter#define PCCARD_CFE_IO16			0x0020
7638032Speter#define PCCARD_CFE_IRQSHARE		0x0040
7738032Speter#define PCCARD_CFE_IRQPULSE		0x0080
7838032Speter#define PCCARD_CFE_IRQLEVEL		0x0100
7938032Speter#define PCCARD_CFE_POWERDOWN		0x0200
8038032Speter#define PCCARD_CFE_READONLY		0x0400
8138032Speter#define PCCARD_CFE_AUDIO		0x0800
8238032Speter
8338032Speterstruct pccard_config_entry {
8464562Sgshapiro	int		number;
8564562Sgshapiro	u_int32_t	flags;
8664562Sgshapiro	int		iftype;
8764562Sgshapiro	int		num_iospace;
8838032Speter
8938032Speter	/*
9064562Sgshapiro	 * The card will only decode this mask in any case, so we can
9164562Sgshapiro	 * do dynamic allocation with this in mind, in case the suggestions
9264562Sgshapiro	 * below are no good.
9338032Speter	 */
9438032Speter	u_long		iomask;
9538032Speter	struct {
9638032Speter		u_long	length;
9738032Speter		u_long	start;
9838032Speter	} iospace[4];		/* XXX this could be as high as 16 */
9938032Speter	u_int16_t	irqmask;
10038032Speter	int		num_memspace;
10138032Speter	struct {
10238032Speter		u_long	length;
10338032Speter		u_long	cardaddr;
10473188Sgshapiro		u_long	hostaddr;
10538032Speter	} memspace[2];		/* XXX this could be as high as 8 */
10673188Sgshapiro	int		maxtwins;
10764562Sgshapiro	struct resource *iores[4];
10864562Sgshapiro	int		iorid[4];
10938032Speter	struct resource *irqres;
11064562Sgshapiro	int		irqrid;
11164562Sgshapiro	struct resource *memres[2];
11264562Sgshapiro	int		memrid[2];
11364562Sgshapiro	STAILQ_ENTRY(pccard_config_entry) cfe_list;
11473188Sgshapiro};
11573188Sgshapiro
11664562Sgshapirostruct pccard_funce_disk {
11764562Sgshapiro	int pfd_interface;
11864562Sgshapiro};
11964562Sgshapiro
12073188Sgshapirostruct pccard_funce_lan {
12164562Sgshapiro	int pfl_nidlen;
12264562Sgshapiro	u_int8_t pfl_nid[8];
12364562Sgshapiro};
12473188Sgshapiro
12573188Sgshapirounion pccard_funce {
12673188Sgshapiro	struct pccard_funce_disk pfv_disk;
12773188Sgshapiro	struct pccard_funce_lan pfv_lan;
12873188Sgshapiro};
12938032Speter
13042575Speterstruct pccard_function {
13164562Sgshapiro	/* read off the card */
13238032Speter	int		number;
13364562Sgshapiro	int		function;
13464562Sgshapiro	int		last_config_index;
13538032Speter	u_long		ccr_base;
13638032Speter	u_long		ccr_mask;
13738032Speter	struct resource *ccr_res;
13838032Speter	int		ccr_rid;
13938032Speter	STAILQ_HEAD(, pccard_config_entry) cfe_head;
14038032Speter	STAILQ_ENTRY(pccard_function) pf_list;
14138032Speter	/* run-time state */
14238032Speter	struct pccard_softc *sc;
14338032Speter	struct pccard_config_entry *cfe;
14438032Speter	struct pccard_mem_handle pf_pcmh;
14538032Speter	device_t	dev;
14638032Speter#define	pf_ccrt		pf_pcmh.memt
14738032Speter#define	pf_ccrh		pf_pcmh.memh
14838032Speter#define	pf_ccr_realsize	pf_pcmh.realsize
14938032Speter	bus_addr_t	pf_ccr_offset;
15038032Speter	int		pf_ccr_window;
15138032Speter	long		pf_mfc_iobase;
15238032Speter	long		pf_mfc_iomax;
15338032Speter	int		pf_flags;
15464562Sgshapiro	driver_intr_t	*intr_handler;
15538032Speter	void		*intr_handler_arg;
15638032Speter	void		*intr_handler_cookie;
15738032Speter
15838032Speter	union pccard_funce pf_funce; /* CISTPL_FUNCE */
15938032Speter#define pf_funce_disk_interface pf_funce.pfv_disk.pfd_interface
16038032Speter#define pf_funce_lan_nid pf_funce.pfv_lan.pfl_nid
16138032Speter#define pf_funce_lan_nidlen pf_funce.pfv_lan.pfl_nidlen
16238032Speter};
16338032Speter
16438032Speter/* pf_flags */
16538032Speter#define	PFF_ENABLED	0x0001		/* function is enabled */
16638032Speter
16738032Speterstruct pccard_card {
16838032Speter	int		cis1_major;
16938032Speter	int		cis1_minor;
17038032Speter	/* XXX waste of space? */
17138032Speter	char		cis1_info_buf[256];
17238032Speter	char		*cis1_info[4];
17338032Speter	/*
17438032Speter	 * Use int32_t for manufacturer and product so that they can
17538032Speter	 * hold the id value found in card CIS and special value that
17638032Speter	 * indicates no id was found.
17738032Speter	 */
17838032Speter	int32_t		manufacturer;
17938032Speter#define	PCCARD_VENDOR_INVALID	-1
18038032Speter	int32_t		product;
18138032Speter#define	PCCARD_PRODUCT_INVALID		-1
18264562Sgshapiro	u_int16_t	error;
18338032Speter#define	PCCARD_CIS_INVALID		{ NULL, NULL, NULL, NULL }
18438032Speter	STAILQ_HEAD(, pccard_function) pf_head;
18538032Speter};
18638032Speter
18738032Speter#define	PCCARD_MEM_ATTR		1
18838032Speter#define	PCCARD_MEM_COMMON	2
18938032Speter
19038032Speter#define	PCCARD_WIDTH_AUTO	0
19164562Sgshapiro#define	PCCARD_WIDTH_IO8	1
19238032Speter#define	PCCARD_WIDTH_IO16	2
19338032Speter
19438032Speter/* More later? */
19538032Speterstruct pccard_ivar {
19638032Speter	struct resource_list resources;
19738032Speter	struct pccard_function *fcn;
19838032Speter};
19938032Speter
20038032Speterstruct pccard_softc {
20138032Speter	device_t		dev;
20266494Sgshapiro	/* this stuff is for the socket */
20366494Sgshapiro
20466494Sgshapiro	/* this stuff is for the card */
20566494Sgshapiro	struct pccard_card card;
20666494Sgshapiro	int		sc_enabled_count;	/* num functions enabled */
20766494Sgshapiro};
20866494Sgshapiro
20966494Sgshapirovoid
21038032Speterpccardbus_if_setup(struct pccard_softc*);
21138032Speter
21238032Speterstruct pccard_cis_quirk {
21338032Speter	int32_t manufacturer;
21438032Speter	int32_t product;
21564562Sgshapiro	char *cis1_info[4];
21638032Speter	struct pccard_function *pf;
21738032Speter	struct pccard_config_entry *cfe;
21864562Sgshapiro};
21938032Speter
22064562Sgshapirostruct pccard_tuple {
22138032Speter	unsigned int	code;
22238032Speter	unsigned int	length;
22338032Speter	u_long		mult;
22438032Speter	bus_addr_t	ptr;
22538032Speter	bus_space_tag_t	memt;
22638032Speter	bus_space_handle_t memh;
22738032Speter};
22838032Speter
22938032Speterstruct pccard_product {
23064562Sgshapiro	const char	*pp_name;		/* NULL if end of table */
23164562Sgshapiro#define PCCARD_VENDOR_ANY ((u_int32_t) -1)
23238032Speter	u_int32_t	pp_vendor;
23338032Speter#define PCCARD_PRODUCT_ANY ((u_int32_t) -1)
23438032Speter	u_int32_t	pp_product;
23538032Speter	int		pp_expfunc;
23638032Speter	const char	*pp_cis[4];
23738032Speter};
23838032Speter
23938032Spetertypedef int (*pccard_product_match_fn) (device_t dev,
24038032Speter    const struct pccard_product *ent, int vpfmatch);
24138032Speter
24238032Speterconst struct pccard_product
24338032Speter	*pccard_product_lookup(device_t dev, const struct pccard_product *tab,
24438032Speter	    size_t ent_size, pccard_product_match_fn matchfn);
24538032Speter
24638032Spetervoid	pccard_read_cis(struct pccard_softc *);
24738032Spetervoid	pccard_check_cis_quirks(device_t);
24838032Spetervoid	pccard_print_cis(device_t);
24938032Speterint	pccard_scan_cis(device_t,
25038032Speter		int (*) (struct pccard_tuple *, void *), void *);
25138032Speter
25238032Speter#define	pccard_cis_read_1(tuple, idx0)					\
25338032Speter	(bus_space_read_1((tuple)->memt, (tuple)->memh, (tuple)->mult*(idx0)))
25438032Speter
25538032Speter#define	pccard_tuple_read_1(tuple, idx1)				\
25638032Speter	(pccard_cis_read_1((tuple), ((tuple)->ptr+(2+(idx1)))))
25738032Speter
25838032Speter#define	pccard_tuple_read_2(tuple, idx2)				\
25938032Speter	(pccard_tuple_read_1((tuple), (idx2)) |				\
26038032Speter	 (pccard_tuple_read_1((tuple), (idx2)+1)<<8))
26138032Speter
26238032Speter#define	pccard_tuple_read_3(tuple, idx3)				\
26338032Speter	(pccard_tuple_read_1((tuple), (idx3)) |				\
26438032Speter	 (pccard_tuple_read_1((tuple), (idx3)+1)<<8) |			\
26538032Speter	 (pccard_tuple_read_1((tuple), (idx3)+2)<<16))
26638032Speter
26738032Speter#define	pccard_tuple_read_4(tuple, idx4)				\
26838032Speter	(pccard_tuple_read_1((tuple), (idx4)) |				\
26938032Speter	 (pccard_tuple_read_1((tuple), (idx4)+1)<<8) |			\
27038032Speter	 (pccard_tuple_read_1((tuple), (idx4)+2)<<16) |			\
27138032Speter	 (pccard_tuple_read_1((tuple), (idx4)+3)<<24))
27238032Speter
27338032Speter#define	pccard_tuple_read_n(tuple, n, idxn)				\
27438032Speter	(((n)==1)?pccard_tuple_read_1((tuple), (idxn)) :		\
27538032Speter	 (((n)==2)?pccard_tuple_read_2((tuple), (idxn)) :		\
27638032Speter	  (((n)==3)?pccard_tuple_read_3((tuple), (idxn)) :		\
27738032Speter	   /* n == 4 */ pccard_tuple_read_4((tuple), (idxn)))))
27838032Speter
27964562Sgshapiro#define	PCCARD_SPACE_MEMORY	1
28038032Speter#define	PCCARD_SPACE_IO		2
28138032Speter
28238032Speter#define	pccard_mfc(sc)	(STAILQ_FIRST(&(sc)->card.pf_head) &&		\
28338032Speter		 STAILQ_NEXT(STAILQ_FIRST(&(sc)->card.pf_head),pf_list))
28438032Speter
28538032Speter#define	pccard_io_alloc(pf, start, size, align, pciop)			\
28638032Speter	(pccard_chip_io_alloc((pf)->sc->pct, pf->sc->pch, (start),	\
28738032Speter	 (size), (align), (pciop)))
28838032Speter
28938032Speter#define	pccard_io_free(pf, pciohp)					\
29038032Speter	(pccard_chip_io_free((pf)->sc->pct, (pf)->sc->pch, (pciohp)))
29138032Speter
29238032Speterint	pccard_io_map(struct pccard_function *, int, bus_addr_t,
29338032Speter	    bus_size_t, struct pccard_io_handle *, int *);
29438032Spetervoid	pccard_io_unmap(struct pccard_function *, int);
29538032Speter
29638032Speter#define pccard_mem_alloc(pf, size, pcmhp)				\
29738032Speter	(pccard_chip_mem_alloc((pf)->sc->pct, (pf)->sc->pch, (size), (pcmhp)))
29866494Sgshapiro#define pccard_mem_free(pf, pcmhp)					\
29966494Sgshapiro	(pccard_chip_mem_free((pf)->sc->pct, (pf)->sc->pch, (pcmhp)))
30066494Sgshapiro#define pccard_mem_map(pf, kind, card_addr, size, pcmhp, offsetp, windowp) \
30166494Sgshapiro	(pccard_chip_mem_map((pf)->sc->pct, (pf)->sc->pch, (kind),	\
30266494Sgshapiro	 (card_addr), (size), (pcmhp), (offsetp), (windowp)))
30366494Sgshapiro#define	pccard_mem_unmap(pf, window)					\
30466494Sgshapiro	(pccard_chip_mem_unmap((pf)->sc->pct, (pf)->sc->pch, (window)))
30566494Sgshapiro
30666494Sgshapiro/* compat layer */
30766494Sgshapirostatic __inline int
30866494Sgshapiropccard_compat_probe(device_t dev)
30943148Speter{
31038032Speter	return (CARD_COMPAT_DO_PROBE(device_get_parent(dev), dev));
31143148Speter}
31238032Speter
31366494Sgshapirostatic __inline int
31464562Sgshapiropccard_compat_attach(device_t dev)
31543148Speter{
31664562Sgshapiro	return (CARD_COMPAT_DO_ATTACH(device_get_parent(dev), dev));
31743148Speter}
31843148Speter
31938032Speter/* ivar interface */
32038032Speterenum {
32138032Speter	PCCARD_IVAR_ETHADDR,	/* read ethernet address from CIS tupple */
32238032Speter	PCCARD_IVAR_VENDOR,
32338032Speter	PCCARD_IVAR_PRODUCT,
32438032Speter	PCCARD_IVAR_FUNCTION_NUMBER,
32538032Speter	PCCARD_IVAR_VENDOR_STR,	/* CIS string for "Manufacturer" */
32638032Speter	PCCARD_IVAR_PRODUCT_STR,/* CIS strnig for "Product" */
32738032Speter	PCCARD_IVAR_CIS3_STR,
32838032Speter	PCCARD_IVAR_CIS4_STR,
32938032Speter	PCCARD_IVAR_FUNCTION
33038032Speter};
33138032Speter
33238032Speter#define PCCARD_ACCESSOR(A, B, T)					\
33338032Speter__inline static int							\
33438032Speterpccard_get_ ## A(device_t dev, T *t)					\
33538032Speter{									\
33638032Speter	return BUS_READ_IVAR(device_get_parent(dev), dev,		\
33764562Sgshapiro	    PCCARD_IVAR_ ## B, (uintptr_t *) t);			\
33838032Speter}
33938032Speter
34038032SpeterPCCARD_ACCESSOR(ether,		ETHADDR,		u_int8_t)
34138032SpeterPCCARD_ACCESSOR(vendor,		VENDOR,			u_int32_t)
34238032SpeterPCCARD_ACCESSOR(product,	PRODUCT,		u_int32_t)
34338032SpeterPCCARD_ACCESSOR(function_number,FUNCTION_NUMBER,	u_int32_t)
34464562SgshapiroPCCARD_ACCESSOR(function,	FUNCTION,		u_int32_t)
34538032SpeterPCCARD_ACCESSOR(vendor_str,	VENDOR_STR,		char *)
34664562SgshapiroPCCARD_ACCESSOR(product_str,	PRODUCT_STR,		char *)
34764562SgshapiroPCCARD_ACCESSOR(cis3_str,	CIS3_STR,		char *)
34864562Sgshapiro
34938032Speter/* shared memory flags */
35038032Speterenum {
35143148Speter	PCCARD_A_MEM_COM,       /* common */
35238032Speter	PCCARD_A_MEM_ATTR,      /* attribute */
35373188Sgshapiro	PCCARD_A_MEM_8BIT,      /* 8 bit */
35443730Speter	PCCARD_A_MEM_16BIT      /* 16 bit */
35573188Sgshapiro};
35643148Speter
35743148Speter#define PCCARD_SOFTC(d) (struct pccard_softc *) device_get_softc(d)
35843730Speter#define PCCARD_IVAR(d) (struct pccard_ivar *) device_get_ivars(d)
35943730Speter