source: trunk/minix/drivers/ti1225/ti1225.c@ 10

Last change on this file since 10 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 10.0 KB
Line 
1/*
2ti1225.c
3
4Created: Dec 2005 by Philip Homburg
5*/
6
7#include "../drivers.h"
8#include <ibm/pci.h>
9#include <sys/vm.h>
10
11#include "ti1225.h"
12#include "i82365.h"
13
14/* The use of interrupts is not yet ready for prime time */
15#define USE_INTS 0
16
17#define MICROS_TO_TICKS(m) (((m)*HZ/1000000)+1)
18
19#define NR_PORTS 2
20
21PRIVATE struct port
22{
23 unsigned p_flags;
24 int p_devind;
25 u8_t p_cb_busnr;
26 u16_t p_exca_port;
27#if USE_INTS
28 int p_irq;
29 int p_hook;
30#endif
31 char *base_ptr;
32 volatile struct csr *csr_ptr;
33
34 char buffer[2*PAGE_SIZE];
35} ports[NR_PORTS];
36
37#define PF_PRESENT 1
38
39struct pcitab
40{
41 u16_t vid;
42 u16_t did;
43 int checkclass;
44};
45
46PRIVATE struct pcitab pcitab_ti[]=
47{
48 { 0x104C, 0xAC1C, 0 }, /* TI PCI1225 */
49
50 { 0x0000, 0x0000, 0 }
51};
52PRIVATE char *progname;
53PRIVATE int debug;
54
55FORWARD _PROTOTYPE( void init, (void) );
56FORWARD _PROTOTYPE( void hw_init, (struct port *pp) );
57FORWARD _PROTOTYPE( void map_regs, (struct port *pp, u32_t base) );
58FORWARD _PROTOTYPE( void do_int, (struct port *pp) );
59FORWARD _PROTOTYPE( u8_t read_exca, (struct port *pp, int socket, int reg) );
60FORWARD _PROTOTYPE( void do_outb, (port_t port, u8_t value) );
61FORWARD _PROTOTYPE( u8_t do_inb, (port_t port) );
62FORWARD _PROTOTYPE( void micro_delay, (unsigned long usecs) );
63
64int main(int argc, char *argv[])
65{
66 int c, r;
67 message m;
68
69 (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
70
71 debug= 0;
72 while (c= getopt(argc, argv, "d?"), c != -1)
73 {
74 switch(c)
75 {
76 case '?': panic("ti1225", "Usage: ti1225 [-d]", NO_NUM);
77 case 'd': debug++; break;
78 default: panic("ti1225", "getopt failed", NO_NUM);
79 }
80 }
81
82 init();
83
84 for (;;)
85 {
86 r= receive(ANY, &m);
87 if (r != OK)
88 panic("ti1225", "receive failed", r);
89 printf("ti1225: got message %u from %d\n",
90 m.m_type, m.m_source);
91 }
92 return 0;
93}
94
95PRIVATE void init()
96{
97 int i, r, first, devind, port;
98 u16_t vid, did;
99
100 pci_init1(progname);
101
102 first= 1;
103 port= 0;
104 for (;;)
105 {
106 if (first)
107 {
108 first= 0;
109 r= pci_first_dev(&devind, &vid, &did);
110 }
111 else
112 r= pci_next_dev(&devind, &vid, &did);
113 if (r != 1)
114 break;
115
116 for (i= 0; pcitab_ti[i].vid != 0; i++)
117 {
118 if (pcitab_ti[i].vid != vid)
119 continue;
120 if (pcitab_ti[i].did != did)
121 continue;
122 if (pcitab_ti[i].checkclass)
123 {
124 panic("ti1225",
125 "fxp_probe: class check not implemented",
126 NO_NUM);
127 }
128 break;
129 }
130 if (pcitab_ti[i].vid == 0)
131 continue;
132
133 pci_reserve(devind);
134
135 if (debug)
136 printf("ti1225: found device %04x/%04x\n", vid, did);
137 ports[port].p_devind= devind;
138 ports[port].p_flags |= PF_PRESENT;
139 port++;
140 if (port >= NR_PORTS)
141 break;
142 }
143
144 for (i= 0; i<NR_PORTS; i++)
145 {
146 if (!(ports[i].p_flags & PF_PRESENT))
147 continue;
148 hw_init(&ports[i]);
149 }
150}
151
152PRIVATE void hw_init(pp)
153struct port *pp;
154{
155 int i, r, devind, irq, socket;
156 u8_t v8;
157 u16_t v16;
158 u32_t v32;
159
160 devind= pp->p_devind;
161 if (debug)
162 printf("hw_init: devind = %d\n", devind);
163
164 if (debug)
165 {
166 v16= pci_attr_r16(devind, PCI_CR);
167 printf("ti1225: command register 0x%x\n", v16);
168 }
169
170 v32= pci_attr_r32(devind, TI_CB_BASEADDR);
171 if (debug)
172 printf("ti1225: Cardbus/ExCA base address 0x%x\n", v32);
173 map_regs(pp, v32);
174 pp->csr_ptr= (struct csr *)pp->base_ptr;
175
176 if (debug)
177 {
178 v8= pci_attr_r8(devind, TI_PCI_BUS_NR);
179 printf("ti1225: PCI bus number %d\n", v8);
180 }
181 v8= pci_attr_r8(devind, TI_CB_BUS_NR);
182 pp->p_cb_busnr= v8;
183 if (debug)
184 {
185 printf("ti1225: CardBus bus number %d\n", v8);
186 v8= pci_attr_r8(devind, TI_SO_BUS_NR);
187 printf("ti1225: Subordinate bus number %d\n", v8);
188 }
189
190#if USE_INTS
191 irq= pci_attr_r8(devind, PCI_ILR);
192 pp->p_irq= irq;
193 printf("ti1225 using IRQ %d\n", irq);
194#endif
195
196 v32= pci_attr_r32(devind, TI_LEGACY_BA);
197 v32 &= ~1;
198 if (debug)
199 {
200 printf("ti1225: PC Card 16-bit legacy-mode base address 0x%x\n",
201 v32);
202 }
203
204 if (v32 == 0)
205 panic("ti1225", "bad lagacy-mode base address 0x%x\n", v32);
206 pp->p_exca_port= v32;
207
208 if (debug)
209 {
210 v32= pci_attr_r32(devind, TI_MF_ROUTE);
211 printf("ti1225: Multifunction routing 0x%08x\n", v32);
212 }
213
214#if USE_INTS
215 pp->p_hook = pp->p_irq;
216 r= sys_irqsetpolicy(pp->p_irq, 0, &pp->p_hook);
217 if (r != OK)
218 panic("ti1225","sys_irqsetpolicy failed", r);
219#endif
220
221 /* Clear CBB_BC_INTEXCA */
222 v16= pci_attr_r16(devind, CBB_BRIDGECTRL);
223 if (debug)
224 printf("ti1225: Bridge control 0x%04x\n", v16);
225 v16 &= ~CBB_BC_INTEXCA;
226 pci_attr_w16(devind, CBB_BRIDGECTRL, v16);
227
228 if (debug)
229 {
230 v32= pci_attr_r32(devind, TI_SYSCTRL);
231 printf("ti1225: System Control Register 0x%08x\n", v32);
232
233 v8= pci_attr_r8(devind, TI_CARD_CTRL);
234 printf("ti1225: Card Control 0x%02x\n", v8);
235
236 v8= pci_attr_r8(devind, TI_DEV_CTRL);
237 printf("ti1225: Device Control 0x%02x\n", v8);
238 }
239
240 /* Enable socket interrupts */
241 pp->csr_ptr->csr_mask |= CM_PWRMASK | CM_CDMASK | CM_CSTSMASK;
242
243 do_int(pp);
244
245#if USE_INTS
246 r= sys_irqenable(&pp->p_hook);
247 if (r != OK)
248 panic("ti1225","unable enable interrupts", r);
249#endif
250}
251
252PRIVATE void map_regs(pp, base)
253struct port *pp;
254u32_t base;
255{
256 int r;
257 vir_bytes buf_base;
258
259 buf_base= (vir_bytes)pp->buffer;
260 if (buf_base % PAGE_SIZE)
261 buf_base += PAGE_SIZE-(buf_base % PAGE_SIZE);
262 pp->base_ptr= (char *)buf_base;
263 if (debug)
264 {
265 printf("ti1225: map_regs: using %p for %p\n",
266 pp->base_ptr, pp->buffer);
267 }
268
269 /* Clear low order bits in base */
270 base &= ~(u32_t)0xF;
271
272 r= sys_vm_map(SELF, 1 /* map */, (vir_bytes)pp->base_ptr,
273 PAGE_SIZE, (phys_bytes)base);
274 if (r != OK)
275 panic("ti1225", "map_regs: sys_vm_map failed", r);
276}
277
278PRIVATE void do_int(pp)
279struct port *pp;
280{
281 int i, r, devind, vcc_5v, vcc_3v, vcc_Xv, vcc_Yv,
282 socket_5v, socket_3v, socket_Xv, socket_Yv;
283 clock_t t0, t1;
284 u32_t csr_event, csr_present, csr_control;
285 u8_t v8;
286 u16_t v16;
287
288 devind= pp->p_devind;
289 v8= pci_attr_r8(devind, TI_CARD_CTRL);
290 if (v8 & TI_CCR_IFG)
291 {
292 printf("ti1225: got functional interrupt\n", v8);
293 pci_attr_w8(devind, TI_CARD_CTRL, v8);
294 }
295
296 if (debug)
297 {
298 printf("Socket event: 0x%x\n", pp->csr_ptr->csr_event);
299 printf("Socket mask: 0x%x\n", pp->csr_ptr->csr_mask);
300 }
301
302 csr_present= pp->csr_ptr->csr_present;
303 csr_control= pp->csr_ptr->csr_control;
304
305 if ((csr_present & (CP_CDETECT1|CP_CDETECT2)) != 0)
306 {
307 if (debug)
308 printf("do_int: no card present\n");
309 return;
310 }
311 if (csr_present & CP_BADVCCREQ)
312 {
313 printf("do_int: Bad Vcc request\n");
314 /* return; */
315 }
316 if (csr_present & CP_DATALOST)
317 {
318 /* Do we care? */
319 if (debug)
320 printf("do_int: Data lost\n");
321 /* return; */
322 }
323 if (csr_present & CP_NOTACARD)
324 {
325 printf("do_int: Not a card\n");
326 return;
327 }
328 if (debug)
329 {
330 if (csr_present & CP_CBCARD)
331 printf("do_int: Cardbus card detected\n");
332 if (csr_present & CP_16BITCARD)
333 printf("do_int: 16-bit card detected\n");
334 }
335 if (csr_present & CP_PWRCYCLE)
336 {
337 if (debug)
338 printf("do_int: powered up\n");
339 return;
340 }
341 vcc_5v= !!(csr_present & CP_5VCARD);
342 vcc_3v= !!(csr_present & CP_3VCARD);
343 vcc_Xv= !!(csr_present & CP_XVCARD);
344 vcc_Yv= !!(csr_present & CP_YVCARD);
345 if (debug)
346 {
347 printf("do_int: card supports:%s%s%s%s\n",
348 vcc_5v ? " 5V" : "", vcc_3v ? " 3V" : "",
349 vcc_Xv ? " X.X V" : "", vcc_Yv ? " Y.Y V" : "");
350 }
351 socket_5v= !!(csr_present & CP_5VSOCKET);
352 socket_3v= !!(csr_present & CP_3VSOCKET);
353 socket_Xv= !!(csr_present & CP_XVSOCKET);
354 socket_Yv= !!(csr_present & CP_YVSOCKET);
355 if (debug)
356 {
357 printf("do_int: socket supports:%s%s%s%s\n",
358 socket_5v ? " 5V" : "", socket_3v ? " 3V" : "",
359 socket_Xv ? " X.X V" : "", socket_Yv ? " Y.Y V" : "");
360 }
361 if (vcc_5v && socket_5v)
362 {
363 csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_5V;
364 pp->csr_ptr->csr_control= csr_control;
365 if (debug)
366 printf("do_int: applying 5V\n");
367 }
368 else if (vcc_3v && socket_3v)
369 {
370 csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_3V;
371 pp->csr_ptr->csr_control= csr_control;
372 if (debug)
373 printf("do_int: applying 3V\n");
374 }
375 else if (vcc_Xv && socket_Xv)
376 {
377 csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_XV;
378 pp->csr_ptr->csr_control= csr_control;
379 printf("do_int: applying X.X V\n");
380 }
381 else if (vcc_Yv && socket_Yv)
382 {
383 csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_YV;
384 pp->csr_ptr->csr_control= csr_control;
385 printf("do_int: applying Y.Y V\n");
386 }
387 else
388 {
389 printf("do_int: socket and card are not compatible\n");
390 return;
391 }
392
393 csr_event= pp->csr_ptr->csr_event;
394 if (csr_event)
395 {
396 if (debug)
397 printf("clearing socket event\n");
398 pp->csr_ptr->csr_event= csr_event;
399 if (debug)
400 {
401 printf("Socket event (cleared): 0x%x\n",
402 pp->csr_ptr->csr_event);
403 }
404 }
405
406 devind= pp->p_devind;
407 v8= pci_attr_r8(devind, TI_CARD_CTRL);
408 if (v8 & TI_CCR_IFG)
409 {
410 printf("ti1225: got functional interrupt\n", v8);
411 pci_attr_w8(devind, TI_CARD_CTRL, v8);
412 }
413
414 if (debug)
415 {
416 v8= pci_attr_r8(devind, TI_CARD_CTRL);
417 printf("TI_CARD_CTRL: 0x%02x\n", v8);
418 }
419
420 getuptime(&t0);
421 do {
422 csr_present= pp->csr_ptr->csr_present;
423 if (csr_present & CP_PWRCYCLE)
424 break;
425 } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(100000));
426
427 if (!(csr_present & CP_PWRCYCLE))
428 {
429 printf("do_int: not powered up?\n");
430 return;
431 }
432
433 /* Reset device */
434 v16= pci_attr_r16(devind, CBB_BRIDGECTRL);
435 v16 |= CBB_BC_CRST;
436 pci_attr_w16(devind, CBB_BRIDGECTRL, v16);
437
438 /* Wait one microsecond. Is this correct? What are the specs? */
439 micro_delay(1);
440
441 /* Clear CBB_BC_CRST */
442 v16= pci_attr_r16(devind, CBB_BRIDGECTRL);
443 v16 &= ~CBB_BC_CRST;
444 pci_attr_w16(devind, CBB_BRIDGECTRL, v16);
445
446 /* Wait one microsecond after clearing the reset line. Is this
447 * correct? What are the specs?
448 */
449 micro_delay(1);
450
451 pci_rescan_bus(pp->p_cb_busnr);
452
453#if USE_INTS
454 r= sys_irqenable(&pp->p_hook);
455 if (r != OK)
456 panic("ti1225","unable enable interrupts", r);
457#endif
458
459}
460
461PRIVATE u8_t read_exca(pp, socket, reg)
462struct port *pp;
463int socket;
464int reg;
465{
466 u16_t port;
467
468 port= pp->p_exca_port;
469 if (port == 0)
470 panic("ti1225", "read_exca: bad port", NO_NUM);
471 do_outb(port, socket * 0x40 + reg);
472 return do_inb(port+1);
473}
474
475PRIVATE u8_t do_inb(port_t port)
476{
477 int r;
478 u32_t value;
479
480 r= sys_inb(port, &value);
481 if (r != OK)
482 panic("ti1225","sys_inb failed", r);
483 return value;
484}
485
486PRIVATE void do_outb(port_t port, u8_t value)
487{
488 int r;
489
490 r= sys_outb(port, value);
491 if (r != OK)
492 panic("ti1225","sys_outb failed", r);
493}
494
495PRIVATE void micro_delay(unsigned long usecs)
496{
497 tickdelay(MICROS_TO_TICKS(usecs));
498}
499
Note: See TracBrowser for help on using the repository browser.