1 /*        $NetBSD: sti_sgc.c,v 1.9 2025/05/01 06:11:21 tsutsui Exp $  */
2 /*        $OpenBSD: sti_sgc.c,v 1.14 2007/05/26 00:36:03 krw Exp $    */
3 
4 /*
5  * Copyright (c) 2005, Miodrag Vallat
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  *
28  */
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: sti_sgc.c,v 1.9 2025/05/01 06:11:21 tsutsui Exp $");
31 
32 #include <sys/param.h>
33 #include <sys/device.h>
34 #include <sys/bus.h>
35 
36 #include <uvm/uvm_extern.h>
37 
38 #include <hp300/dev/sgcvar.h>
39 #include <hp300/dev/sti_sgcvar.h>
40 #include <hp300/dev/sti_machdep.h>
41 
42 static int sticonslot = -1;
43 
44 static int sti_sgc_match(device_t, struct cfdata *, void *);
45 static void sti_sgc_attach(device_t, device_t, void *);
46 
47 static int sti_sgc_probe(bus_space_tag_t, int);
48 
49 CFATTACH_DECL_NEW(sti_sgc, sizeof(struct sti_machdep_softc),
50     sti_sgc_match, sti_sgc_attach, NULL, NULL);
51 
52 static int
sti_sgc_match(device_t parent,struct cfdata * cf,void * aux)53 sti_sgc_match(device_t parent, struct cfdata *cf, void *aux)
54 {
55           struct sgc_attach_args *saa = aux;
56 
57           /*
58            * If we already probed it successfully as a console device, go ahead,
59            * since we will not be able to bus_space_map() again.
60            */
61           if (saa->saa_slot == sticonslot)
62                     return 1;
63 
64           return sti_sgc_probe(saa->saa_iot, saa->saa_slot);
65 }
66 
67 static void
sti_sgc_attach(device_t parent,device_t self,void * aux)68 sti_sgc_attach(device_t parent, device_t self, void *aux)
69 {
70           struct sti_machdep_softc *sc = device_private(self);
71           struct sti_softc *ssc = &sc->sc_sti;
72           struct sgc_attach_args *saa = aux;
73           bus_space_tag_t bst;
74           bus_space_handle_t romh;
75           bus_addr_t base;
76           u_int romend;
77           int i;
78 
79           ssc->sc_dev = self;
80           bst = saa->saa_iot;
81           base = (bus_addr_t)sgc_slottopa(saa->saa_slot);
82           sc->sc_base = base;
83 
84           if (saa->saa_slot == sticonslot) {
85                     sti_machdep_attach_console(sc);
86           } else {
87                     if (bus_space_map(bst, base, PAGE_SIZE, 0, &romh)) {
88                               aprint_error(": can't map ROM");
89                               return;
90                     }
91                     /*
92                      * Compute real PROM size
93                      */
94                     romend = sti_rom_size(bst, romh);
95 
96                     bus_space_unmap(bst, romh, PAGE_SIZE);
97 
98                     if (bus_space_map(bst, base, romend, 0, &romh)) {
99                               aprint_error(": can't map frame buffer");
100                               return;
101                     }
102 
103                     ssc->bases[0] = romh;
104                     for (i = 0; i < STI_REGION_MAX; i++)
105                               ssc->bases[i] = base;
106 
107                     if (sti_attach_common(ssc, bst, bst, romh,
108                         STI_CODEBASE_ALT) != 0)
109                               return;
110           }
111 
112           sti_machdep_attach(sc);
113 }
114 
115 static int
sti_sgc_probe(bus_space_tag_t iot,int slot)116 sti_sgc_probe(bus_space_tag_t iot, int slot)
117 {
118           bus_space_handle_t ioh;
119           int devtype;
120 
121           if (bus_space_map(iot, (bus_addr_t)sgc_slottopa(slot),
122               PAGE_SIZE, 0, &ioh))
123                     return 0;
124 
125           devtype = bus_space_read_1(iot, ioh, 3);
126 
127           bus_space_unmap(iot, ioh, PAGE_SIZE);
128 
129           /*
130            * This might not be reliable enough. On the other hand, non-STI
131            * SGC cards will apparently not initialize in the hp300, to the
132            * point of not even answering bus probes (checked with an
133            * Harmony/FDDI SGC card).
134            */
135           if (devtype != STI_DEVTYPE1 && devtype != STI_DEVTYPE4)
136                     return 0;
137 
138           return 1;
139 }
140 
141 int
sti_sgc_cnprobe(bus_space_tag_t bst,int slot)142 sti_sgc_cnprobe(bus_space_tag_t bst, int slot)
143 {
144           void *va;
145           bus_space_handle_t romh;
146           bus_addr_t base;
147           int devtype, rv = 0;
148 
149           base = sgc_slottopa(slot);
150           if (bus_space_map(bst, base, PAGE_SIZE, 0, &romh))
151                     return 0;
152 
153           va = bus_space_vaddr(bst, romh);
154           if (badaddr(va))
155                     goto out;
156 
157           devtype = bus_space_read_1(bst, romh, 3);
158           if (devtype == STI_DEVTYPE1 || devtype == STI_DEVTYPE4)
159                     rv = 1;
160 
161  out:
162           bus_space_unmap(bst, romh, PAGE_SIZE);
163           return rv;
164 }
165 
166 void
sti_sgc_cnattach(bus_space_tag_t bst,int slot)167 sti_sgc_cnattach(bus_space_tag_t bst, int slot)
168 {
169           paddr_t base;
170 
171           base = sgc_slottopa(slot);
172 
173           sti_machdep_cnattach(bst, base);
174 
175           sticonslot = slot;
176 }
177