Annotation of sys/dev/pci/sili_pci.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: sili_pci.c,v 1.7 2007/04/07 05:59:49 dlg Exp $ */
2:
3: /*
4: * Copyright (c) 2007 David Gwynne <dlg@openbsd.org>
5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18:
19: #include <sys/param.h>
20: #include <sys/systm.h>
21: #include <sys/kernel.h>
22: #include <sys/malloc.h>
23: #include <sys/device.h>
24: #include <sys/timeout.h>
25:
26: #include <machine/bus.h>
27:
28: #include <dev/pci/pcireg.h>
29: #include <dev/pci/pcivar.h>
30: #include <dev/pci/pcidevs.h>
31:
32: #include <dev/ata/atascsi.h>
33:
34: #include <dev/ic/silireg.h>
35: #include <dev/ic/silivar.h>
36:
37: int sili_pci_match(struct device *, void *, void *);
38: void sili_pci_attach(struct device *, struct device *, void *);
39: int sili_pci_detach(struct device *, int);
40:
41: struct sili_pci_softc {
42: struct sili_softc psc_sili;
43:
44: pci_chipset_tag_t psc_pc;
45: pcitag_t psc_tag;
46:
47: void *psc_ih;
48: };
49:
50: struct cfattach sili_pci_ca = {
51: sizeof(struct sili_pci_softc), sili_pci_match, sili_pci_attach,
52: sili_pci_detach
53: };
54:
55: struct sili_device {
56: pci_vendor_id_t sd_vendor;
57: pci_product_id_t sd_product;
58: u_int sd_nports;
59: };
60:
61: const struct sili_device *sili_lookup(struct pci_attach_args *);
62:
63: static const struct sili_device sili_devices[] = {
64: { PCI_VENDOR_CMDTECH, PCI_PRODUCT_CMDTECH_3124, 4 },
65: { PCI_VENDOR_CMDTECH, PCI_PRODUCT_CMDTECH_3131, 1 },
66: { PCI_VENDOR_CMDTECH, PCI_PRODUCT_CMDTECH_3132, 2 },
67: { PCI_VENDOR_CMDTECH, PCI_PRODUCT_CMDTECH_3531, 1 },
68: { PCI_VENDOR_CMDTECH, PCI_PRODUCT_CMDTECH_AAR_1220SA, 2 },
69: { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_3124, 4 }
70: };
71:
72: const struct sili_device *
73: sili_lookup(struct pci_attach_args *pa)
74: {
75: int i;
76: const struct sili_device *sd;
77:
78: for (i = 0; i < sizeofa(sili_devices); i++) {
79: sd = &sili_devices[i];
80: if (sd->sd_vendor == PCI_VENDOR(pa->pa_id) &&
81: sd->sd_product == PCI_PRODUCT(pa->pa_id))
82: return (sd);
83: }
84:
85: return (NULL);
86: }
87:
88: int
89: sili_pci_match(struct device *parent, void *match, void *aux)
90: {
91: return (sili_lookup((struct pci_attach_args *)aux) != NULL);
92: }
93:
94: void
95: sili_pci_attach(struct device *parent, struct device *self, void *aux)
96: {
97: struct sili_pci_softc *psc = (void *)self;
98: struct sili_softc *sc = &psc->psc_sili;
99: struct pci_attach_args *pa = aux;
100: const struct sili_device *sd;
101: pcireg_t memtype;
102: pci_intr_handle_t ih;
103: const char *intrstr;
104:
105: sd = sili_lookup(pa);
106:
107: psc->psc_pc = pa->pa_pc;
108: psc->psc_tag = pa->pa_tag;
109: psc->psc_ih = NULL;
110: sc->sc_dmat = pa->pa_dmat;
111: sc->sc_ios_global = 0;
112: sc->sc_ios_port = 0;
113: sc->sc_nports = sd->sd_nports;
114:
115: memtype = pci_mapreg_type(psc->psc_pc, psc->psc_tag,
116: SILI_PCI_BAR_GLOBAL);
117: if (pci_mapreg_map(pa, SILI_PCI_BAR_GLOBAL, memtype, 0,
118: &sc->sc_iot_global, &sc->sc_ioh_global,
119: NULL, &sc->sc_ios_global, 0) != 0) {
120: printf(": unable to map global registers\n");
121: return;
122: }
123:
124: memtype = pci_mapreg_type(psc->psc_pc, psc->psc_tag,
125: SILI_PCI_BAR_PORT);
126: if (pci_mapreg_map(pa, SILI_PCI_BAR_PORT, memtype, 0,
127: &sc->sc_iot_port, &sc->sc_ioh_port,
128: NULL, &sc->sc_ios_port, 0) != 0) {
129: printf(": unable to map port registers\n");
130: goto unmap_global;
131: }
132:
133: /* hook up the interrupt */
134: if (pci_intr_map(pa, &ih)) {
135: printf(": unable to map interrupt\n");
136: goto unmap_port;
137: }
138: intrstr = pci_intr_string(psc->psc_pc, ih);
139: psc->psc_ih = pci_intr_establish(psc->psc_pc, ih, IPL_BIO,
140: sili_intr, sc, sc->sc_dev.dv_xname);
141: if (psc->psc_ih == NULL) {
142: printf(": unable to map interrupt%s%s\n",
143: intrstr == NULL ? "" : " at ",
144: intrstr == NULL ? "" : intrstr);
145: goto unmap_port;
146: }
147: printf(": %s", intrstr);
148:
149: if (sili_attach(sc) != 0) {
150: /* error printed by sili_attach */
151: goto deintr;
152: }
153:
154: return;
155:
156: deintr:
157: pci_intr_disestablish(psc->psc_pc, psc->psc_ih);
158: psc->psc_ih = NULL;
159: unmap_port:
160: bus_space_unmap(sc->sc_iot_port, sc->sc_ioh_port, sc->sc_ios_port);
161: sc->sc_ios_port = 0;
162: unmap_global:
163: bus_space_unmap(sc->sc_iot_global, sc->sc_ioh_global,
164: sc->sc_ios_global);
165: sc->sc_ios_global = 0;
166: }
167:
168: int
169: sili_pci_detach(struct device *self, int flags)
170: {
171: struct sili_pci_softc *psc = (struct sili_pci_softc *)self;
172: struct sili_softc *sc = &psc->psc_sili;
173: int rv;
174:
175: rv = sili_detach(sc, flags);
176: if (rv != 0)
177: return (rv);
178:
179: if (psc->psc_ih != NULL) {
180: pci_intr_disestablish(psc->psc_pc, psc->psc_ih);
181: psc->psc_ih = NULL;
182: }
183: if (sc->sc_ios_port != 0) {
184: bus_space_unmap(sc->sc_iot_port, sc->sc_ioh_port,
185: sc->sc_ios_port);
186: sc->sc_ios_port = 0;
187: }
188: if (sc->sc_ios_global != 0) {
189: bus_space_unmap(sc->sc_iot_global, sc->sc_ioh_global,
190: sc->sc_ios_global);
191: sc->sc_ios_global = 0;
192: }
193:
194: return (0);
195: }
CVSweb