dec21140A ethernet driver for virtualpc, contributed by nicolas tittley.
[minix.git] / drivers / ti1225 / ti1225.c
blob9ada092e6c714603df4dee6e2c34c78f11a0f7f1
1 /*
2 ti1225.c
4 Created: Dec 2005 by Philip Homburg
5 */
7 #include "../drivers.h"
8 #include <ibm/pci.h>
9 #include <sys/vm.h>
10 #include <sys/vm_i386.h>
12 #include "ti1225.h"
13 #include "i82365.h"
15 /* The use of interrupts is not yet ready for prime time */
16 #define USE_INTS 0
18 #define NR_PORTS 2
20 PRIVATE struct port
22 unsigned p_flags;
23 int p_devind;
24 u8_t p_cb_busnr;
25 u16_t p_exca_port;
26 #if USE_INTS
27 int p_irq;
28 int p_hook;
29 #endif
30 char *base_ptr;
31 volatile struct csr *csr_ptr;
33 char buffer[2*I386_PAGE_SIZE];
34 } ports[NR_PORTS];
36 #define PF_PRESENT 1
38 struct pcitab
40 u16_t vid;
41 u16_t did;
42 int checkclass;
45 PRIVATE struct pcitab pcitab_ti[]=
47 { 0x104C, 0xAC1C, 0 }, /* TI PCI1225 */
49 { 0x0000, 0x0000, 0 }
51 PRIVATE char *progname;
52 PRIVATE int debug;
54 FORWARD _PROTOTYPE( void hw_init, (struct port *pp) );
55 FORWARD _PROTOTYPE( void map_regs, (struct port *pp, u32_t base) );
56 FORWARD _PROTOTYPE( void do_int, (struct port *pp) );
57 FORWARD _PROTOTYPE( u8_t read_exca, (struct port *pp, int socket, int reg) );
58 FORWARD _PROTOTYPE( void do_outb, (port_t port, u8_t value) );
59 FORWARD _PROTOTYPE( u8_t do_inb, (port_t port) );
61 /* SEF functions and variables. */
62 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
63 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
64 EXTERN int env_argc;
65 EXTERN char **env_argv;
67 /*===========================================================================*
68 * main *
69 *===========================================================================*/
70 int main(int argc, char *argv[])
72 int r;
73 message m;
75 /* SEF local startup. */
76 env_setargs(argc, argv);
77 sef_local_startup();
79 for (;;)
81 r= sef_receive(ANY, &m);
82 if (r != OK)
83 panic("ti1225", "sef_receive failed", r);
84 printf("ti1225: got message %u from %d\n",
85 m.m_type, m.m_source);
87 return 0;
90 /*===========================================================================*
91 * sef_local_startup *
92 *===========================================================================*/
93 PRIVATE void sef_local_startup()
95 /* Register init callbacks. */
96 sef_setcb_init_fresh(sef_cb_init_fresh);
97 sef_setcb_init_lu(sef_cb_init_fresh);
98 sef_setcb_init_restart(sef_cb_init_fresh);
100 /* Register live update callbacks. */
101 sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready);
102 sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_standard);
104 /* Let SEF perform startup. */
105 sef_startup();
108 /*===========================================================================*
109 * sef_cb_init_fresh *
110 *===========================================================================*/
111 PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
113 /* Initialize the ti1225 driver. */
114 int c, i, r, first, devind, port;
115 u16_t vid, did;
117 (progname=strrchr(env_argv[0],'/')) ? progname++
118 : (progname=env_argv[0]);
120 if((r=tsc_calibrate()) != OK)
121 panic("ti1225", "tsc_calibrate failed", r);
123 debug= 0;
124 while (c= getopt(env_argc, env_argv, "d?"), c != -1)
126 switch(c)
128 case '?': panic("ti1225", "Usage: ti1225 [-d]", NO_NUM);
129 case 'd': debug++; break;
130 default: panic("ti1225", "getopt failed", NO_NUM);
134 pci_init1(progname);
136 first= 1;
137 port= 0;
138 for (;;)
140 if (first)
142 first= 0;
143 r= pci_first_dev(&devind, &vid, &did);
145 else
146 r= pci_next_dev(&devind, &vid, &did);
147 if (r != 1)
148 break;
150 for (i= 0; pcitab_ti[i].vid != 0; i++)
152 if (pcitab_ti[i].vid != vid)
153 continue;
154 if (pcitab_ti[i].did != did)
155 continue;
156 if (pcitab_ti[i].checkclass)
158 panic("ti1225",
159 "fxp_probe: class check not implemented",
160 NO_NUM);
162 break;
164 if (pcitab_ti[i].vid == 0)
165 continue;
167 pci_reserve(devind);
169 if (debug)
170 printf("ti1225: found device %04x/%04x\n", vid, did);
171 ports[port].p_devind= devind;
172 ports[port].p_flags |= PF_PRESENT;
173 port++;
174 if (port >= NR_PORTS)
175 break;
178 for (i= 0; i<NR_PORTS; i++)
180 if (!(ports[i].p_flags & PF_PRESENT))
181 continue;
182 hw_init(&ports[i]);
185 return(OK);
188 PRIVATE void hw_init(pp)
189 struct port *pp;
191 int i, r, devind, irq, socket;
192 u8_t v8;
193 u16_t v16;
194 u32_t v32;
196 devind= pp->p_devind;
197 if (debug)
198 printf("hw_init: devind = %d\n", devind);
200 if (debug)
202 v16= pci_attr_r16(devind, PCI_CR);
203 printf("ti1225: command register 0x%x\n", v16);
206 v32= pci_attr_r32(devind, TI_CB_BASEADDR);
207 if (debug)
208 printf("ti1225: Cardbus/ExCA base address 0x%x\n", v32);
209 map_regs(pp, v32);
210 pp->csr_ptr= (struct csr *)pp->base_ptr;
212 if (debug)
214 v8= pci_attr_r8(devind, TI_PCI_BUS_NR);
215 printf("ti1225: PCI bus number %d\n", v8);
217 v8= pci_attr_r8(devind, TI_CB_BUS_NR);
218 pp->p_cb_busnr= v8;
219 if (debug)
221 printf("ti1225: CardBus bus number %d\n", v8);
222 v8= pci_attr_r8(devind, TI_SO_BUS_NR);
223 printf("ti1225: Subordinate bus number %d\n", v8);
226 #if USE_INTS
227 irq= pci_attr_r8(devind, PCI_ILR);
228 pp->p_irq= irq;
229 printf("ti1225 using IRQ %d\n", irq);
230 #endif
232 v32= pci_attr_r32(devind, TI_LEGACY_BA);
233 v32 &= ~1;
234 if (debug)
236 printf("ti1225: PC Card 16-bit legacy-mode base address 0x%x\n",
237 v32);
240 if (v32 == 0)
241 panic("ti1225", "bad lagacy-mode base address 0x%x\n", v32);
242 pp->p_exca_port= v32;
244 if (debug)
246 v32= pci_attr_r32(devind, TI_MF_ROUTE);
247 printf("ti1225: Multifunction routing 0x%08x\n", v32);
250 #if USE_INTS
251 pp->p_hook = pp->p_irq;
252 r= sys_irqsetpolicy(pp->p_irq, 0, &pp->p_hook);
253 if (r != OK)
254 panic("ti1225","sys_irqsetpolicy failed", r);
255 #endif
257 /* Clear CBB_BC_INTEXCA */
258 v16= pci_attr_r16(devind, CBB_BRIDGECTRL);
259 if (debug)
260 printf("ti1225: Bridge control 0x%04x\n", v16);
261 v16 &= ~CBB_BC_INTEXCA;
262 pci_attr_w16(devind, CBB_BRIDGECTRL, v16);
264 if (debug)
266 v32= pci_attr_r32(devind, TI_SYSCTRL);
267 printf("ti1225: System Control Register 0x%08x\n", v32);
269 v8= pci_attr_r8(devind, TI_CARD_CTRL);
270 printf("ti1225: Card Control 0x%02x\n", v8);
272 v8= pci_attr_r8(devind, TI_DEV_CTRL);
273 printf("ti1225: Device Control 0x%02x\n", v8);
276 /* Enable socket interrupts */
277 pp->csr_ptr->csr_mask |= CM_PWRMASK | CM_CDMASK | CM_CSTSMASK;
279 do_int(pp);
281 #if USE_INTS
282 r= sys_irqenable(&pp->p_hook);
283 if (r != OK)
284 panic("ti1225","unable enable interrupts", r);
285 #endif
288 PRIVATE void map_regs(pp, base)
289 struct port *pp;
290 u32_t base;
292 int r;
293 vir_bytes buf_base;
295 buf_base= (vir_bytes)pp->buffer;
296 if (buf_base % I386_PAGE_SIZE)
297 buf_base += I386_PAGE_SIZE-(buf_base % I386_PAGE_SIZE);
298 pp->base_ptr= (char *)buf_base;
299 if (debug)
301 printf("ti1225: map_regs: using %p for %p\n",
302 pp->base_ptr, pp->buffer);
305 /* Clear low order bits in base */
306 base &= ~(u32_t)0xF;
308 #if 0
309 r= sys_vm_map(SELF, 1 /* map */, (vir_bytes)pp->base_ptr,
310 I386_PAGE_SIZE, (phys_bytes)base);
311 #else
312 r = ENOSYS;
313 #endif
314 if (r != OK)
315 panic("ti1225", "map_regs: sys_vm_map failed", r);
318 PRIVATE void do_int(pp)
319 struct port *pp;
321 int i, r, devind, vcc_5v, vcc_3v, vcc_Xv, vcc_Yv,
322 socket_5v, socket_3v, socket_Xv, socket_Yv;
323 clock_t t0, t1;
324 u32_t csr_event, csr_present, csr_control;
325 u8_t v8;
326 u16_t v16;
328 devind= pp->p_devind;
329 v8= pci_attr_r8(devind, TI_CARD_CTRL);
330 if (v8 & TI_CCR_IFG)
332 printf("ti1225: got functional interrupt\n");
333 pci_attr_w8(devind, TI_CARD_CTRL, v8);
336 if (debug)
338 printf("Socket event: 0x%x\n", pp->csr_ptr->csr_event);
339 printf("Socket mask: 0x%x\n", pp->csr_ptr->csr_mask);
342 csr_present= pp->csr_ptr->csr_present;
343 csr_control= pp->csr_ptr->csr_control;
345 if ((csr_present & (CP_CDETECT1|CP_CDETECT2)) != 0)
347 if (debug)
348 printf("do_int: no card present\n");
349 return;
351 if (csr_present & CP_BADVCCREQ)
353 printf("do_int: Bad Vcc request\n");
354 /* return; */
356 if (csr_present & CP_DATALOST)
358 /* Do we care? */
359 if (debug)
360 printf("do_int: Data lost\n");
361 /* return; */
363 if (csr_present & CP_NOTACARD)
365 printf("do_int: Not a card\n");
366 return;
368 if (debug)
370 if (csr_present & CP_CBCARD)
371 printf("do_int: Cardbus card detected\n");
372 if (csr_present & CP_16BITCARD)
373 printf("do_int: 16-bit card detected\n");
375 if (csr_present & CP_PWRCYCLE)
377 if (debug)
378 printf("do_int: powered up\n");
379 return;
381 vcc_5v= !!(csr_present & CP_5VCARD);
382 vcc_3v= !!(csr_present & CP_3VCARD);
383 vcc_Xv= !!(csr_present & CP_XVCARD);
384 vcc_Yv= !!(csr_present & CP_YVCARD);
385 if (debug)
387 printf("do_int: card supports:%s%s%s%s\n",
388 vcc_5v ? " 5V" : "", vcc_3v ? " 3V" : "",
389 vcc_Xv ? " X.X V" : "", vcc_Yv ? " Y.Y V" : "");
391 socket_5v= !!(csr_present & CP_5VSOCKET);
392 socket_3v= !!(csr_present & CP_3VSOCKET);
393 socket_Xv= !!(csr_present & CP_XVSOCKET);
394 socket_Yv= !!(csr_present & CP_YVSOCKET);
395 if (debug)
397 printf("do_int: socket supports:%s%s%s%s\n",
398 socket_5v ? " 5V" : "", socket_3v ? " 3V" : "",
399 socket_Xv ? " X.X V" : "", socket_Yv ? " Y.Y V" : "");
401 if (vcc_5v && socket_5v)
403 csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_5V;
404 pp->csr_ptr->csr_control= csr_control;
405 if (debug)
406 printf("do_int: applying 5V\n");
408 else if (vcc_3v && socket_3v)
410 csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_3V;
411 pp->csr_ptr->csr_control= csr_control;
412 if (debug)
413 printf("do_int: applying 3V\n");
415 else if (vcc_Xv && socket_Xv)
417 csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_XV;
418 pp->csr_ptr->csr_control= csr_control;
419 printf("do_int: applying X.X V\n");
421 else if (vcc_Yv && socket_Yv)
423 csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_YV;
424 pp->csr_ptr->csr_control= csr_control;
425 printf("do_int: applying Y.Y V\n");
427 else
429 printf("do_int: socket and card are not compatible\n");
430 return;
433 csr_event= pp->csr_ptr->csr_event;
434 if (csr_event)
436 if (debug)
437 printf("clearing socket event\n");
438 pp->csr_ptr->csr_event= csr_event;
439 if (debug)
441 printf("Socket event (cleared): 0x%x\n",
442 pp->csr_ptr->csr_event);
446 devind= pp->p_devind;
447 v8= pci_attr_r8(devind, TI_CARD_CTRL);
448 if (v8 & TI_CCR_IFG)
450 printf("ti1225: got functional interrupt\n", v8);
451 pci_attr_w8(devind, TI_CARD_CTRL, v8);
454 if (debug)
456 v8= pci_attr_r8(devind, TI_CARD_CTRL);
457 printf("TI_CARD_CTRL: 0x%02x\n", v8);
460 getuptime(&t0);
461 do {
462 csr_present= pp->csr_ptr->csr_present;
463 if (csr_present & CP_PWRCYCLE)
464 break;
465 } while (getuptime(&t1)==OK && (t1-t0) < micros_to_ticks(100000));
467 if (!(csr_present & CP_PWRCYCLE))
469 printf("do_int: not powered up?\n");
470 return;
473 /* Reset device */
474 v16= pci_attr_r16(devind, CBB_BRIDGECTRL);
475 v16 |= CBB_BC_CRST;
476 pci_attr_w16(devind, CBB_BRIDGECTRL, v16);
478 /* Wait one microsecond. Is this correct? What are the specs? */
479 micro_delay(1);
481 /* Clear CBB_BC_CRST */
482 v16= pci_attr_r16(devind, CBB_BRIDGECTRL);
483 v16 &= ~CBB_BC_CRST;
484 pci_attr_w16(devind, CBB_BRIDGECTRL, v16);
486 /* Wait one microsecond after clearing the reset line. Is this
487 * correct? What are the specs?
489 micro_delay(1);
491 pci_rescan_bus(pp->p_cb_busnr);
493 #if USE_INTS
494 r= sys_irqenable(&pp->p_hook);
495 if (r != OK)
496 panic("ti1225","unable enable interrupts", r);
497 #endif
501 PRIVATE u8_t read_exca(pp, socket, reg)
502 struct port *pp;
503 int socket;
504 int reg;
506 u16_t port;
508 port= pp->p_exca_port;
509 if (port == 0)
510 panic("ti1225", "read_exca: bad port", NO_NUM);
511 do_outb(port, socket * 0x40 + reg);
512 return do_inb(port+1);
515 PRIVATE u8_t do_inb(port_t port)
517 int r;
518 u32_t value;
520 r= sys_inb(port, &value);
521 if (r != OK)
522 panic("ti1225","sys_inb failed", r);
523 return value;
526 PRIVATE void do_outb(port_t port, u8_t value)
528 int r;
530 r= sys_outb(port, value);
531 if (r != OK)
532 panic("ti1225","sys_outb failed", r);