Line data Source code
1 : /* $OpenBSD: jmb.c,v 1.9 2015/03/14 03:38:48 jsg 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/buf.h>
22 : #include <sys/kernel.h>
23 : #include <sys/malloc.h>
24 : #include <sys/device.h>
25 : #include <sys/queue.h>
26 :
27 : #include <dev/pci/pcireg.h>
28 : #include <dev/pci/pcivar.h>
29 : #include <dev/pci/pcidevs.h>
30 :
31 : /* JMicron registers */
32 : #define JM_PCI_CTL0 0x40 /* control register 0 */
33 : #define JM_PCI_CTL0_ROM_EN (1<<31) /* External Option ROM */
34 : #define JM_PCI_CTL0_IDWR_EN (1<<30) /* Device ID Write */
35 : #define JM_PCI_CTL0_MSI64_EN (1<<25) /* 64bit MSI Addr Mode */
36 : #define JM_PCI_CTL0_MSI_EN (1<<24) /* MSI Addr Mode */
37 : #define JM_PCI_CTL0_IDEDMA_CFG (1<<23) /* PCIIDE DMA Chan Cfg */
38 : #define JM_PCI_CTL0_PCIIDE_CS (1<<22) /* PCIIDE channels Swap */
39 : #define JM_PCI_CTL0_SATA_PS (1<<21) /* SATA channel M/S swap */
40 : #define JM_PCI_CTL0_AHCI_PS (1<<20) /* SATA AHCI ports swap */
41 : #define JM_PCI_CTL0_F1_SUBCLASS_M 0xc0000 /* subclass for func 1 */
42 : #define JM_PCI_CTL0_F0_SUBCLASS_M 0x30000 /* subclass for func 0 */
43 : #define JM_PCI_CTL0_SUBCLASS_IDE 0x0 /* IDE Controller */
44 : #define JM_PCI_CTL0_SUBCLASS_RAID 0x1 /* RAID Controller */
45 : #define JM_PCI_CTL0_SUBCLASS_AHCI 0x2 /* AHCI Controller */
46 : #define JM_PCI_CTL0_SUBCLASS_OTHER 0x3 /* Other Mass Storage */
47 : #define JM_PCI_CTL0_F1_SUBCLASS(_m) ((_m)<<18) /* subclass for func 1 */
48 : #define JM_PCI_CTL0_F0_SUBCLASS(_m) ((_m)<<16) /* subclass for func 0 */
49 : #define JM_PCI_CTL0_SATA1_AHCI (1<<15) /* SATA port 1 AHCI enable */
50 : #define JM_PCI_CTL0_SATA1_IDE (1<<14) /* SATA port 1 IDE enable */
51 : #define JM_PCI_CTL0_SATA0_AHCI (1<<13) /* SATA port 0 AHCI enable */
52 : #define JM_PCI_CTL0_SATA0_IDE (1<<12) /* SATA port 0 PCIIDE enable */
53 : #define JM_PCI_CTL0_AHCI_F1 (1<<9) /* AHCI on function 1 */
54 : #define JM_PCI_CTL0_AHCI_EN (1<<8) /* ACHI enable */
55 : #define JM_PCI_CTL0_PATA0_RST (1<<6) /* PATA port 0 reset */
56 : #define JM_PCI_CTL0_PATA0_EN (1<<5) /* PATA port 0 enable */
57 : #define JM_PCI_CTL0_PATA0_SEC (1<<4) /* PATA 0 enable on 2nd chan */
58 : #define JM_PCI_CTL0_PATA0_40P (1<<3) /* PATA 0 40pin cable */
59 : #define JM_PCI_CTL0_PCIIDE_F1 (1<<1) /* PCIIDE on function 1 */
60 : #define JM_PCI_CTL0_PATA0_PRI (1<<0) /* PATA 0 enable on 1st chan */
61 :
62 : #define JM_PCI_CTL5 0x80 /* control register 8 */
63 : #define JM_PCI_CTL5_PATA1_PRI (1<<24) /* force PATA 1 on chan0 */
64 :
65 : int jmb_match(struct device *, void *, void *);
66 : void jmb_attach(struct device *, struct device *, void *);
67 : int jmb_print(void *, const char *);
68 :
69 : struct jmb_softc {
70 : struct device sc_dev;
71 : };
72 :
73 : struct cfattach jmb_ca = {
74 : sizeof(struct jmb_softc),
75 : jmb_match,
76 : jmb_attach,
77 : config_detach_children
78 : };
79 :
80 : struct cfdriver jmb_cd = {
81 : NULL, "jmb", DV_DULL
82 : };
83 :
84 : static const struct pci_matchid jmb_devices[] = {
85 : { PCI_VENDOR_JMICRON, PCI_PRODUCT_JMICRON_JMB360 },
86 : { PCI_VENDOR_JMICRON, PCI_PRODUCT_JMICRON_JMB361 },
87 : { PCI_VENDOR_JMICRON, PCI_PRODUCT_JMICRON_JMB362 },
88 : { PCI_VENDOR_JMICRON, PCI_PRODUCT_JMICRON_JMB363 },
89 : { PCI_VENDOR_JMICRON, PCI_PRODUCT_JMICRON_JMB365 },
90 : { PCI_VENDOR_JMICRON, PCI_PRODUCT_JMICRON_JMB366 },
91 : { PCI_VENDOR_JMICRON, PCI_PRODUCT_JMICRON_JMB368 }
92 : };
93 :
94 : int
95 0 : jmb_match(struct device *parent, void *match, void *aux)
96 : {
97 0 : struct pci_attach_args *pa = aux;
98 :
99 0 : return (pci_matchbyid(pa, jmb_devices,
100 0 : sizeof(jmb_devices) / sizeof(jmb_devices[0])) * 3);
101 : }
102 :
103 : void
104 0 : jmb_attach(struct device *parent, struct device *self, void *aux)
105 : {
106 0 : struct pci_attach_args *pa = aux, jpa;
107 : u_int32_t ctl0, ctl5;
108 : int sata = 0, pata = 0;
109 :
110 0 : ctl0 = pci_conf_read(pa->pa_pc, pa->pa_tag, JM_PCI_CTL0);
111 0 : ctl5 = pci_conf_read(pa->pa_pc, pa->pa_tag, JM_PCI_CTL5);
112 :
113 : /* configure sata bits if it is on this function */
114 0 : if (pa->pa_function == (ISSET(ctl0, JM_PCI_CTL0_AHCI_F1) ? 1 : 0)) {
115 0 : ctl0 &= ~(JM_PCI_CTL0_AHCI_EN | JM_PCI_CTL0_SATA0_IDE |
116 : JM_PCI_CTL0_SATA0_AHCI | JM_PCI_CTL0_SATA1_IDE |
117 : JM_PCI_CTL0_SATA1_AHCI);
118 :
119 0 : switch (PCI_PRODUCT(pa->pa_id)) {
120 : case PCI_PRODUCT_JMICRON_JMB360:
121 : case PCI_PRODUCT_JMICRON_JMB361:
122 : case PCI_PRODUCT_JMICRON_JMB362:
123 : case PCI_PRODUCT_JMICRON_JMB363:
124 : case PCI_PRODUCT_JMICRON_JMB365:
125 : case PCI_PRODUCT_JMICRON_JMB366:
126 : /* enable AHCI */
127 0 : ctl0 |= JM_PCI_CTL0_AHCI_EN | JM_PCI_CTL0_SATA0_AHCI |
128 : JM_PCI_CTL0_SATA1_AHCI;
129 : sata = 1;
130 0 : break;
131 : }
132 : }
133 :
134 : /* configure pata bits if it is on this function */
135 0 : if (pa->pa_function == (ISSET(ctl0, JM_PCI_CTL0_PCIIDE_F1) ? 1 : 0)) {
136 0 : ctl0 &= ~(JM_PCI_CTL0_PCIIDE_CS | JM_PCI_CTL0_IDEDMA_CFG);
137 0 : ctl5 &= ~JM_PCI_CTL5_PATA1_PRI;
138 :
139 0 : switch (PCI_PRODUCT(pa->pa_id)) {
140 : case PCI_PRODUCT_JMICRON_JMB366:
141 : case PCI_PRODUCT_JMICRON_JMB365:
142 : /* wire the second PATA port in the right place */
143 0 : ctl5 |= JM_PCI_CTL5_PATA1_PRI;
144 : /* FALLTHROUGH */
145 : case PCI_PRODUCT_JMICRON_JMB363:
146 : case PCI_PRODUCT_JMICRON_JMB361:
147 : case PCI_PRODUCT_JMICRON_JMB368:
148 0 : ctl0 |= JM_PCI_CTL0_PCIIDE_CS | JM_PCI_CTL0_IDEDMA_CFG;
149 : pata = 1;
150 0 : break;
151 : }
152 : }
153 :
154 0 : pci_conf_write(pa->pa_pc, pa->pa_tag, JM_PCI_CTL0, ctl0);
155 0 : pci_conf_write(pa->pa_pc, pa->pa_tag, JM_PCI_CTL5, ctl5);
156 :
157 0 : printf("\n");
158 :
159 0 : jpa = *pa;
160 :
161 0 : if (sata) {
162 : /* tweak the class to look like ahci, then try to attach it */
163 0 : jpa.pa_class = (PCI_CLASS_MASS_STORAGE << PCI_CLASS_SHIFT) |
164 : (PCI_SUBCLASS_MASS_STORAGE_SATA << PCI_SUBCLASS_SHIFT) |
165 : (0x01 << PCI_INTERFACE_SHIFT); /* AHCI_PCI_INTERFACE */
166 0 : config_found(self, &jpa, jmb_print);
167 0 : }
168 :
169 0 : if (pata) {
170 : /* set things up for pciide */
171 0 : jpa.pa_class = (PCI_CLASS_MASS_STORAGE << PCI_CLASS_SHIFT) |
172 : (PCI_SUBCLASS_MASS_STORAGE_IDE << PCI_SUBCLASS_SHIFT) |
173 : (0x85 << PCI_INTERFACE_SHIFT);
174 0 : config_found(self, &jpa, jmb_print);
175 0 : }
176 0 : }
177 :
178 : int
179 0 : jmb_print(void *aux, const char *pnp)
180 : {
181 0 : struct pci_attach_args *pa = aux;
182 0 : char devinfo[256];
183 :
184 0 : if (pnp != NULL) {
185 0 : pci_devinfo(pa->pa_id, pa->pa_class, 1, devinfo,
186 : sizeof(devinfo));
187 0 : printf("%s at %s", devinfo, pnp);
188 0 : }
189 :
190 0 : return (UNCONF);
191 0 : }
|