Annotation of sys/dev/pci/sili_pci.c, Revision 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