pccard_cis_quirks.c revision 53813
153813Simp/*	$NetBSD: pcmcia_cis_quirks.c,v 1.5 1999/10/11 17:50:21 thorpej Exp $	*/
252506Simp/* $FreeBSD: head/sys/dev/pccard/pccard_cis_quirks.c 53813 1999-11-28 05:49:27Z imp $ */
352506Simp
452506Simp#define	PCCARDDEBUG
552506Simp
652506Simp/*
752506Simp * Copyright (c) 1998 Marc Horowitz.  All rights reserved.
852506Simp *
952506Simp * Redistribution and use in source and binary forms, with or without
1052506Simp * modification, are permitted provided that the following conditions
1152506Simp * are met:
1252506Simp * 1. Redistributions of source code must retain the above copyright
1352506Simp *    notice, this list of conditions and the following disclaimer.
1452506Simp * 2. Redistributions in binary form must reproduce the above copyright
1552506Simp *    notice, this list of conditions and the following disclaimer in the
1652506Simp *    documentation and/or other materials provided with the distribution.
1752506Simp * 3. All advertising materials mentioning features or use of this software
1852506Simp *    must display the following acknowledgement:
1952506Simp *	This product includes software developed by Marc Horowitz.
2052506Simp * 4. The name of the author may not be used to endorse or promote products
2152506Simp *    derived from this software without specific prior written permission.
2252506Simp *
2352506Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2452506Simp * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2552506Simp * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2652506Simp * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2752506Simp * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2852506Simp * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2952506Simp * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3052506Simp * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3152506Simp * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3252506Simp * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3352506Simp */
3452506Simp
3552506Simp#include <sys/param.h>
3652506Simp#include <sys/systm.h>
3752506Simp#include <sys/malloc.h>
3852506Simp#include <sys/module.h>
3952506Simp#include <sys/kernel.h>
4052506Simp#include <sys/queue.h>
4152506Simp#include <sys/types.h>
4252506Simp
4352506Simp#include <sys/bus.h>
4452506Simp#include <machine/bus.h>
4552506Simp#include <sys/rman.h>
4652506Simp#include <machine/resource.h>
4752506Simp
4852506Simp#include <dev/pccard/pccarddevs.h>
4952506Simp#include <dev/pccard/pccardreg.h>
5052506Simp#include <dev/pccard/pccardchip.h>
5152506Simp#include <dev/pccard/pccardvar.h>
5252506Simp
5352506Simp/* There are cards out there whose CIS flat-out lies.  This file
5452506Simp   contains struct pccard_function chains for those devices. */
5552506Simp
5652506Simp/* these structures are just static templates which are then copied
5752506Simp   into "live" allocated structures */
5852506Simp
5952506Simpstruct pccard_function pccard_3cxem556_func0 = {
6052506Simp	0,			/* function number */
6152506Simp	PCCARD_FUNCTION_NETWORK,
6252506Simp	0x07,			/* last cfe number */
6352506Simp	0x800,			/* ccr_base */
6452506Simp	0x63,			/* ccr_mask */
6552506Simp};
6652506Simp
6752506Simpstruct pccard_config_entry pccard_3cxem556_func0_cfe0 = {
6852506Simp	0x07,			/* cfe number */
6952506Simp	PCCARD_CFE_IO8 | PCCARD_CFE_IO16 | PCCARD_CFE_IRQLEVEL,
7052506Simp	PCCARD_IFTYPE_IO,
7152506Simp	1,			/* num_iospace */
7252506Simp	4,			/* iomask */
7352506Simp	{ { 0x0010, 0 } },	/* iospace */
7452506Simp	0xffff,			/* irqmask */
7552506Simp	0,			/* num_memspace */
7652506Simp	{ },			/* memspace */
7752506Simp	0,			/* maxtwins */
7852506Simp};
7952506Simp
8052506Simpstatic struct pccard_function pccard_3cxem556_func1 = {
8152506Simp	1,			/* function number */
8252506Simp	PCCARD_FUNCTION_SERIAL,
8352506Simp	0x27,			/* last cfe number */
8452506Simp	0x900,			/* ccr_base */
8552506Simp	0x63,			/* ccr_mask */
8652506Simp};
8752506Simp
8852506Simpstatic struct pccard_config_entry pccard_3cxem556_func1_cfe0 = {
8952506Simp	0x27,			/* cfe number */
9052506Simp	PCCARD_CFE_IO8 | PCCARD_CFE_IRQLEVEL,
9152506Simp	PCCARD_IFTYPE_IO,
9252506Simp	1,			/* num_iospace */
9352506Simp	3,			/* iomask */
9452506Simp	{ { 0x0008, 0 } },	/* iospace */
9552506Simp	0xffff,			/* irqmask */
9652506Simp	0,			/* num_memspace */
9752506Simp	{ },			/* memspace */
9852506Simp	0,			/* maxtwins */
9952506Simp};
10052506Simp
10153813Simpstatic struct pccard_function pccard_3ccfem556bi_func0 = {
10253813Simp	0,			/* function number */
10353813Simp	PCCARD_FUNCTION_NETWORK,
10453813Simp	0x07,			/* last cfe number */
10553813Simp	0x1000,			/* ccr_base */
10653813Simp	0x267,			/* ccr_mask */
10753813Simp};
10853813Simp
10953813Simpstatic struct pccard_config_entry pccard_3ccfem556bi_func0_cfe0 = {
11053813Simp	0x07,			/* cfe number */
11153813Simp	PCCARD_CFE_IO8 | PCCARD_CFE_IO16 | PCCARD_CFE_IRQLEVEL,
11253813Simp	PCCARD_IFTYPE_IO,
11353813Simp	1,			/* num_iospace */
11453813Simp	5,			/* iomask */
11553813Simp	{ { 0x0020, 0 } },	/* iospace */
11653813Simp	0xffff,			/* irqmask */
11753813Simp	0,			/* num_memspace */
11853813Simp	{ },			/* memspace */
11953813Simp	0,			/* maxtwins */
12053813Simp};
12153813Simp
12253813Simpstatic struct pccard_function pccard_3ccfem556bi_func1 = {
12353813Simp	1,			/* function number */
12453813Simp	PCCARD_FUNCTION_SERIAL,
12553813Simp	0x27,			/* last cfe number */
12653813Simp	0x1100,			/* ccr_base */
12753813Simp	0x277,			/* ccr_mask */
12853813Simp};
12953813Simp
13053813Simpstatic struct pccard_config_entry pccard_3ccfem556bi_func1_cfe0 = {
13153813Simp	0x27,			/* cfe number */
13253813Simp	PCCARD_CFE_IO8 | PCCARD_CFE_IRQLEVEL,
13353813Simp	PCCARD_IFTYPE_IO,
13453813Simp	1,			/* num_iospace */
13553813Simp	3,			/* iomask */
13653813Simp	{ { 0x0008, 0 } },	/* iospace */
13753813Simp	0xffff,			/* irqmask */
13853813Simp	0,			/* num_memspace */
13953813Simp	{ },			/* memspace */
14053813Simp	0,			/* maxtwins */
14153813Simp};
14253813Simp
14352506Simpstatic struct pccard_function pccard_sveclancard_func0 = {
14452506Simp	0,			/* function number */
14552506Simp	PCCARD_FUNCTION_NETWORK,
14652506Simp	0x1,			/* last cfe number */
14752506Simp	0x100,			/* ccr_base */
14852506Simp	0x1,			/* ccr_mask */
14952506Simp};
15052506Simp
15152506Simpstatic struct pccard_config_entry pccard_sveclancard_func0_cfe0 = {
15252506Simp	0x1,			/* cfe number */
15352506Simp	PCCARD_CFE_MWAIT_REQUIRED | PCCARD_CFE_RDYBSY_ACTIVE |
15452506Simp	PCCARD_CFE_WP_ACTIVE | PCCARD_CFE_BVD_ACTIVE | PCCARD_CFE_IO16,
15552506Simp	PCCARD_IFTYPE_IO,
15652506Simp	1,			/* num_iospace */
15752506Simp	5,			/* iomask */
15852506Simp	{ { 0x20, 0x300 } },	/* iospace */
15952506Simp	0xdeb8,			/* irqmask */
16052506Simp	0,			/* num_memspace */
16152506Simp	{ },			/* memspace */
16252506Simp	0,			/* maxtwins */
16352506Simp};
16452506Simp
16552506Simpstatic struct pccard_cis_quirk pccard_cis_quirks[] = {
16652506Simp	{ PCCARD_VENDOR_3COM, PCCARD_PRODUCT_3COM_3CXEM556, PCCARD_CIS_INVALID,
16752506Simp	  &pccard_3cxem556_func0, &pccard_3cxem556_func0_cfe0 },
16852506Simp	{ PCCARD_VENDOR_3COM, PCCARD_PRODUCT_3COM_3CXEM556, PCCARD_CIS_INVALID,
16952506Simp	  &pccard_3cxem556_func1, &pccard_3cxem556_func1_cfe0 },
17053813Simp	{ PCCARD_VENDOR_3COM, PCCARD_PRODUCT_3COM_3CXEM556INT, PCCARD_CIS_INVALID,
17153813Simp	  &pccard_3cxem556_func0, &pccard_3cxem556_func0_cfe0 },
17253813Simp	{ PCCARD_VENDOR_3COM, PCCARD_PRODUCT_3COM_3CXEM556INT, PCCARD_CIS_INVALID,
17353813Simp	  &pccard_3cxem556_func1, &pccard_3cxem556_func1_cfe0 },
17453813Simp	{ PCCARD_VENDOR_3COM, PCCARD_PRODUCT_3COM_3CCFEM556BI,
17553813Simp	  PCCARD_CIS_INVALID,
17653813Simp	  &pccard_3ccfem556bi_func0, &pccard_3ccfem556bi_func0_cfe0 },
17753813Simp	{ PCCARD_VENDOR_3COM, PCCARD_PRODUCT_3COM_3CCFEM556BI,
17853813Simp	  PCCARD_CIS_INVALID,
17953813Simp	  &pccard_3ccfem556bi_func1, &pccard_3ccfem556bi_func1_cfe0 },
18052506Simp	{ PCCARD_VENDOR_INVALID, PCCARD_PRODUCT_INVALID, PCCARD_CIS_SVEC_LANCARD,
18152506Simp	  &pccard_sveclancard_func0, &pccard_sveclancard_func0_cfe0 },
18252506Simp};
18352506Simp
18452506Simpstatic int n_pccard_cis_quirks =
18552506Simp	sizeof(pccard_cis_quirks)/sizeof(pccard_cis_quirks[0]);
18652506Simp
18752506Simpvoid pccard_check_cis_quirks(device_t dev)
18852506Simp{
18952506Simp	struct pccard_softc *sc = (struct pccard_softc *)
19052506Simp	    device_get_softc(dev);
19152506Simp	int wiped = 0;
19252506Simp	int i, j;
19352506Simp	struct pccard_function *pf, *pf_next, *pf_last;
19452506Simp	struct pccard_config_entry *cfe, *cfe_next;
19552506Simp
19652506Simp	pf = NULL;
19752506Simp	pf_last = NULL;
19852506Simp
19952506Simp	for (i=0; i<n_pccard_cis_quirks; i++) {
20052506Simp		if ((sc->card.manufacturer == pccard_cis_quirks[i].manufacturer) &&
20152506Simp			(sc->card.product == pccard_cis_quirks[i].product) &&
20252506Simp			(((sc->card.manufacturer != PCCARD_VENDOR_INVALID) &&
20352506Simp			  (sc->card.product != PCCARD_PRODUCT_INVALID)) ||
20452506Simp			 ((sc->card.manufacturer == PCCARD_VENDOR_INVALID) &&
20552506Simp			  (sc->card.product == PCCARD_PRODUCT_INVALID) &&
20652506Simp			  sc->card.cis1_info[0] &&
20752506Simp			  (strcmp(sc->card.cis1_info[0],
20852506Simp					  pccard_cis_quirks[i].cis1_info[0]) == 0) &&
20952506Simp			  sc->card.cis1_info[1] &&
21052506Simp			  (strcmp(sc->card.cis1_info[1],
21152506Simp					  pccard_cis_quirks[i].cis1_info[1]) == 0)))) {
21252506Simp			if (!wiped) {
21352506Simp				if (pccard_verbose) {
21452506Simp					device_printf(dev, "using CIS quirks for ");
21552506Simp					for (j = 0; j < 4; j++) {
21652506Simp						if (sc->card.cis1_info[j] == NULL)
21752506Simp							break;
21852506Simp						if (j)
21952506Simp							printf(", ");
22052506Simp						printf("%s", sc->card.cis1_info[j]);
22152506Simp					}
22252506Simp					printf("\n");
22352506Simp				}
22452506Simp
22552506Simp				for (pf = STAILQ_FIRST(&sc->card.pf_head); pf != NULL;
22652506Simp				     pf = pf_next) {
22752506Simp					for (cfe = STAILQ_FIRST(&pf->cfe_head); cfe != NULL;
22852506Simp					     cfe = cfe_next) {
22952506Simp						cfe_next = STAILQ_NEXT(cfe, cfe_list);
23052506Simp						free(cfe, M_DEVBUF);
23152506Simp					}
23252506Simp					pf_next = STAILQ_NEXT(pf, pf_list);
23352506Simp					free(pf, M_DEVBUF);
23452506Simp				}
23552506Simp
23652506Simp				STAILQ_INIT(&sc->card.pf_head);
23752506Simp				wiped = 1;
23852506Simp			}
23952506Simp
24052506Simp			if (pf_last == pccard_cis_quirks[i].pf) {
24152506Simp				cfe = malloc(sizeof(*cfe), M_DEVBUF, M_NOWAIT);
24252506Simp				*cfe = *pccard_cis_quirks[i].cfe;
24352506Simp
24452506Simp				STAILQ_INSERT_TAIL(&pf->cfe_head, cfe, cfe_list);
24552506Simp			} else {
24652506Simp				pf = malloc(sizeof(*pf), M_DEVBUF, M_NOWAIT);
24752506Simp				*pf = *pccard_cis_quirks[i].pf;
24852506Simp				STAILQ_INIT(&pf->cfe_head);
24952506Simp
25052506Simp				cfe = malloc(sizeof(*cfe), M_DEVBUF, M_NOWAIT);
25152506Simp				*cfe = *pccard_cis_quirks[i].cfe;
25252506Simp
25352506Simp				STAILQ_INSERT_TAIL(&pf->cfe_head, cfe, cfe_list);
25452506Simp				STAILQ_INSERT_TAIL(&sc->card.pf_head, pf, pf_list);
25552506Simp
25652506Simp				pf_last = pccard_cis_quirks[i].pf;
25752506Simp			}
25852506Simp		}
25952506Simp	}
26052506Simp}
261