Disabling auto-refresh of game list by default, as it is causing bugs sometimes
[open-ps2-loader.git] / modules / iopcore / cdvdman / dev9.c
blob7b8c6aa1399f289774274184fa853b5ec9b235c5
1 /*
2 # _____ ___ ____ ___ ____
3 # ____| | ____| | | |____|
4 # | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5 #-----------------------------------------------------------------------
6 # Copyright (c) 2003 Marcus R. Brown <mrbrown@0xd6.org>
7 # Licenced under Academic Free License version 2.0
8 # Review ps2sdk README & LICENSE files for further details.
10 # $Id: ps2dev9.c 1454 2007-11-04 23:19:57Z roman_ps2dev $
11 # DEV9 Device Driver.
14 #include <types.h>
15 #include <defs.h>
16 #include <loadcore.h>
17 #include <intrman.h>
18 #include <dmacman.h>
19 #include <thbase.h>
20 #include <thsemap.h>
21 #include <dev9regs.h>
22 #include <speedregs.h>
23 #include <smapregs.h>
24 #include <stdio.h>
26 #include "dev9.h"
27 #include "ioman.h"
28 #include "ioman_add.h"
30 #ifdef HDD_DRIVER
31 extern int atad_inited;
32 #endif
34 #ifdef DEV9_DEBUG
35 #define M_PRINTF(format, args...) \
36 printf(MODNAME ": " format, ## args)
37 #else
38 #define M_PRINTF(format, args...) \
39 do {} while (0)
40 #endif
42 #define VERSION "1.0"
43 #define BANNER "\nDEV9 device driver v%s - Copyright (c) 2003 Marcus R. Brown\n\n"
45 #define DEV9_INTR 13
47 /* SSBUS registers. */
48 #define SSBUS_R_1418 0xbf801418
49 #define SSBUS_R_141c 0xbf80141c
50 #define SSBUS_R_1420 0xbf801420
52 static int dev9type = -1; /* 0 for PCMCIA, 1 for expansion bay */
53 #ifdef PCMCIA
54 static int using_aif = 0; /* 1 if using AIF on a T10K */
55 #endif
57 static void (*p_dev9_intr_cb)(int flag) = NULL;
58 static int dma_lock_sem = -1; /* used to arbitrate DMA */
59 static int dma_complete_sem = -1; /* signalled on DMA transfer completion. */
61 #ifdef PCMCIA
62 static int pcic_cardtype; /* Translated value of bits 0-1 of 0xbf801462 */
63 static int pcic_voltage; /* Translated value of bits 2-3 of 0xbf801462 */
64 #endif
66 static s16 eeprom_data[5]; /* 2-byte EEPROM status (0/-1 = invalid, 1 = valid),
67 6-byte MAC address,
68 2-byte MAC address checksum. */
70 /* Each driver can register callbacks that correspond to each bit of the
71 SMAP interrupt status register (0xbx000028). */
72 static dev9_intr_cb_t dev9_intr_cbs[16];
74 static dev9_shutdown_cb_t dev9_shutdown_cbs[16];
76 static dev9_dma_cb_t dev9_predma_cbs[4], dev9_postdma_cbs[4];
78 static int dev9_intr_dispatch(int flag);
79 static int dev9_dma_intr(void *arg);
81 static void smap_set_stat(int stat);
82 static int read_eeprom_data(void);
84 static int smap_device_probe(void);
85 static int smap_device_reset(void);
86 static int smap_subsys_init(void);
87 static int smap_device_init(void);
89 #ifdef PCMCIA
90 static void pcmcia_set_stat(int stat);
91 static int pcic_ssbus_mode(int voltage);
92 static int pcmcia_device_probe(void);
93 static int pcmcia_device_reset(void);
94 static int card_find_manfid(u32 manfid);
95 static int pcmcia_init(void);
96 #else
97 static void expbay_set_stat(int stat);
98 static int expbay_device_probe(void);
99 static int expbay_device_reset(void);
100 static int expbay_init(void);
101 #endif
103 int dev9x_dummy() { return 0; }
104 int dev9x_devctl(iop_file_t *f, const char *name, int cmd, void *args, int arglen, void *buf, int buflen)
106 if (cmd == 0x4401)
107 return dev9type;
109 return 0;
112 /* driver ops func tab */
113 void *dev9x_ops[27] = {
114 (void*)dev9x_dummy,
115 (void*)dev9x_dummy,
116 (void*)dev9x_dummy,
117 (void*)dev9x_dummy,
118 (void*)dev9x_dummy,
119 (void*)dev9x_dummy,
120 (void*)dev9x_dummy,
121 (void*)dev9x_dummy,
122 (void*)dev9x_dummy,
123 (void*)dev9x_dummy,
124 (void*)dev9x_dummy,
125 (void*)dev9x_dummy,
126 (void*)dev9x_dummy,
127 (void*)dev9x_dummy,
128 (void*)dev9x_dummy,
129 (void*)dev9x_dummy,
130 (void*)dev9x_dummy,
131 (void*)dev9x_dummy,
132 (void*)dev9x_dummy,
133 (void*)dev9x_dummy,
134 (void*)dev9x_dummy,
135 (void*)dev9x_dummy,
136 (void*)dev9x_dummy,
137 (void*)dev9x_devctl,
138 (void*)dev9_init,
139 (void*)dev9_init,
140 (void*)dev9_init
143 /* driver descriptor */
144 static iop_ext_device_t dev9x_dev = {
145 "dev9x",
146 IOP_DT_FS | 0x10000000, /* EXT FS */
148 "DEV9",
149 (struct _iop_ext_device_ops *)&dev9x_ops
152 int dev9_init(void)
154 USE_DEV9_REGS;
155 int idx, res = 1;
156 u16 dev9hw;
158 M_PRINTF(BANNER, VERSION);
160 for (idx = 0; idx < 16; idx++)
161 dev9_shutdown_cbs[idx] = NULL;
163 dev9hw = DEV9_REG(DEV9_R_REV) & 0xf0;
164 if (dev9hw == 0x20) { /* CXD9566 (PCMCIA) */
165 dev9type = 0;
166 #ifdef PCMCIA
167 res = pcmcia_init();
168 #else
169 return 1;
170 #endif
171 } else if (dev9hw == 0x30) { /* CXD9611 (Expansion Bay) */
172 dev9type = 1;
173 #ifndef PCMCIA
174 res = expbay_init();
175 #else
176 return 1;
177 #endif
180 if (res)
181 return res;
183 DelDrv("dev9x");
184 AddDrv((iop_device_t *)&dev9x_dev);
186 return 0;
189 /* Export 4 */
190 void dev9RegisterIntrCb(int intr, dev9_intr_cb_t cb)
192 #ifdef HDD_DRIVER
193 if (intr < 2) {
194 if (atad_inited)
195 return;
197 #endif
198 dev9_intr_cbs[intr] = cb;
201 /* Export 12 */
202 void dev9RegisterPreDmaCb(int ctrl, dev9_dma_cb_t cb){
203 dev9_predma_cbs[ctrl] = cb;
206 /* Export 13 */
207 void dev9RegisterPostDmaCb(int ctrl, dev9_dma_cb_t cb){
208 dev9_postdma_cbs[ctrl] = cb;
211 /* flag is 1 if a card (pcmcia) was removed or added */
212 static int dev9_intr_dispatch(int flag)
214 USE_SPD_REGS;
215 int i, bit;
217 if (flag) {
218 for (i = 0; i < 16; i++)
219 if (dev9_intr_cbs[i] != NULL)
220 dev9_intr_cbs[i](flag);
223 while (SPD_REG16(SPD_R_INTR_STAT) & SPD_REG16(SPD_R_INTR_MASK)) {
224 for (i = 0; i < 16; i++) {
225 if (dev9_intr_cbs[i] != NULL) {
226 bit = (SPD_REG16(SPD_R_INTR_STAT) &
227 SPD_REG16(SPD_R_INTR_MASK)) >> i;
228 if (bit & 0x01)
229 dev9_intr_cbs[i](flag);
234 return 0;
237 /* Signal the end of a DMA transfer. */
238 static int dev9_dma_intr(void *arg)
240 int sem = *(int *)arg;
242 iSignalSema(sem);
243 return 1;
246 static void smap_set_stat(int stat)
248 if (dev9type == 0)
249 #ifdef PCMCIA
250 pcmcia_set_stat(stat);
251 #else
252 return;
253 #endif
254 else if (dev9type == 1)
255 #ifndef PCMCIA
256 expbay_set_stat(stat);
257 #else
258 return;
259 #endif
262 static int smap_device_probe()
264 if (dev9type == 0)
265 #ifdef PCMCIA
266 return pcmcia_device_probe();
267 #else
268 return -1;
269 #endif
270 else if (dev9type == 1)
271 #ifndef PCMCIA
272 return expbay_device_probe();
273 #else
274 return -1;
275 #endif
276 return -1;
279 static int smap_device_reset()
281 if (dev9type == 0)
282 #ifdef PCMCIA
283 return pcmcia_device_reset();
284 #else
285 return -1;
286 #endif
287 else if (dev9type == 1)
288 #ifndef PCMCIA
289 return expbay_device_reset();
290 #else
291 return -1;
292 #endif
293 return -1;
296 /* Export 6 */
297 void dev9Shutdown()
299 int idx;
300 USE_DEV9_REGS;
302 for (idx = 0; idx < 16; idx++)
303 if (dev9_shutdown_cbs[idx])
304 dev9_shutdown_cbs[idx]();
306 if (dev9type == 0) { /* PCMCIA */
307 #ifdef PCMCIA
308 DEV9_REG(DEV9_R_POWER) = 0;
309 DEV9_REG(DEV9_R_1474) = 0;
310 #endif
311 } else if (dev9type == 1) {
312 #ifndef PCMCIA
313 DEV9_REG(DEV9_R_1466) = 1;
314 DEV9_REG(DEV9_R_1464) = 0;
315 DEV9_REG(DEV9_R_1460) = DEV9_REG(DEV9_R_1464);
316 DEV9_REG(DEV9_R_POWER) = DEV9_REG(DEV9_R_POWER) & ~4;
317 DEV9_REG(DEV9_R_POWER) = DEV9_REG(DEV9_R_POWER) & ~1;
318 #endif
320 DelayThread(1000000);
323 /* Export 7 */
324 void dev9IntrEnable(int mask)
326 USE_SPD_REGS;
327 int flags;
329 CpuSuspendIntr(&flags);
330 SPD_REG16(SPD_R_INTR_MASK) = SPD_REG16(SPD_R_INTR_MASK) | mask;
331 CpuResumeIntr(flags);
334 /* Export 8 */
335 void dev9IntrDisable(int mask)
337 USE_SPD_REGS;
338 int flags;
340 CpuSuspendIntr(&flags);
341 SPD_REG16(SPD_R_INTR_MASK) = SPD_REG16(SPD_R_INTR_MASK) & ~mask;
342 CpuResumeIntr(flags);
345 /* Export 5 */
346 /* This differs from the "official" dev9 in that it puts the calling thread to
347 sleep when doing the actual DMA transfer. I'm not sure why SCEI didn't do
348 this in dev9.irx, when they do it in PS2Linux's dmarelay.irx. Anyway,
349 since this no longer blocks, it should speed up anything else on the IOP
350 when HDD or SMAP are doing DMA. */
351 int dev9DmaTransfer(int ctrl, void *buf, int bcr, int dir)
353 USE_SPD_REGS;
354 volatile iop_dmac_chan_t *dev9_chan = (iop_dmac_chan_t *)DEV9_DMAC_BASE;
355 int stat, res = 0, dmactrl;
357 switch(ctrl){
358 case 0:
359 case 1: dmactrl = ctrl;
360 break;
362 case 2:
363 case 3:
364 if (dev9_predma_cbs[ctrl] == NULL) return -1;
365 if (dev9_postdma_cbs[ctrl] == NULL) return -1;
366 dmactrl = (4 << ctrl);
367 break;
369 default:
370 return -1;
373 if ((res = WaitSema(dma_lock_sem)) < 0)
374 return res;
376 if (SPD_REG16(SPD_R_REV_1) < 17)
377 dmactrl = (dmactrl & 0x03) | 0x04;
378 else
379 dmactrl = (dmactrl & 0x01) | 0x06;
380 SPD_REG16(SPD_R_DMA_CTRL) = dmactrl;
382 if (dev9_predma_cbs[ctrl])
383 dev9_predma_cbs[ctrl](bcr, dir);
385 EnableIntr(IOP_IRQ_DMA_DEV9);
386 dev9_chan->madr = (u32)buf;
387 dev9_chan->bcr = bcr;
388 dev9_chan->chcr = DMAC_CHCR_30|DMAC_CHCR_TR|DMAC_CHCR_CO|
389 (dir & DMAC_CHCR_DR);
391 /* Wait for DMA to complete. */
392 if ((res = WaitSema(dma_complete_sem)) >= 0)
393 res = 0;
395 DisableIntr(IOP_IRQ_DMA_DEV9, &stat);
397 if (dev9_postdma_cbs[ctrl])
398 dev9_postdma_cbs[ctrl](bcr, dir);
400 SignalSema(dma_lock_sem);
401 return res;
404 static int read_eeprom_data()
406 USE_SPD_REGS;
407 int i, j, res = -2;
408 u8 val;
410 if (eeprom_data[0] < 0)
411 goto out;
413 SPD_REG8(SPD_R_PIO_DIR) = 0xe1;
414 DelayThread(1);
415 SPD_REG8(SPD_R_PIO_DATA) = 0x80;
416 DelayThread(1);
418 for (i = 0; i < 2; i++) {
419 SPD_REG8(SPD_R_PIO_DATA) = 0xa0;
420 DelayThread(1);
421 SPD_REG8(SPD_R_PIO_DATA) = 0xe0;
422 DelayThread(1);
424 for (i = 0; i < 7; i++) {
425 SPD_REG8(SPD_R_PIO_DATA) = 0x80;
426 DelayThread(1);
427 SPD_REG8(SPD_R_PIO_DATA) = 0xc0;
428 DelayThread(1);
430 SPD_REG8(SPD_R_PIO_DATA) = 0xc0;
431 DelayThread(1);
433 val = SPD_REG8(SPD_R_PIO_DATA);
434 DelayThread(1);
435 if (val & 0x10) { /* Error. */
436 SPD_REG8(SPD_R_PIO_DATA) = 0;
437 DelayThread(1);
438 res = -1;
439 eeprom_data[0] = 0;
440 goto out;
443 SPD_REG8(SPD_R_PIO_DATA) = 0x80;
444 DelayThread(1);
446 /* Read the MAC address and checksum from the EEPROM. */
447 for (i = 0; i < 4; i++) {
448 eeprom_data[i+1] = 0;
450 for (j = 15; j >= 0; j--) {
451 SPD_REG8(SPD_R_PIO_DATA) = 0xc0;
452 DelayThread(1);
453 val = SPD_REG8(SPD_R_PIO_DATA);
454 if (val & 0x10)
455 eeprom_data[i+1] |= (1<<j);
456 SPD_REG8(SPD_R_PIO_DATA) = 0x80;
457 DelayThread(1);
461 SPD_REG8(SPD_R_PIO_DATA) = 0;
462 DelayThread(1);
463 eeprom_data[0] = 1; /* The EEPROM data is valid. */
464 res = 0;
466 out:
467 SPD_REG8(SPD_R_PIO_DIR) = 1;
468 return res;
471 /* Export 9 */
472 int dev9GetEEPROM(u16 *buf)
474 int i;
476 if (!eeprom_data[0])
477 return -1;
478 if (eeprom_data[0] < 0)
479 return -2;
481 /* We only return the MAC address and checksum. */
482 for (i = 0; i < 4; i++)
483 buf[i] = eeprom_data[i+1];
485 return 0;
488 /* Export 10 */
489 void dev9LEDCtl(int ctl)
491 USE_SPD_REGS;
492 SPD_REG8(SPD_R_PIO_DATA) = (ctl == 0);
495 /* Export 11 */
496 int dev9RegisterShutdownCb(int idx, dev9_shutdown_cb_t cb){
497 if (idx < 16)
499 dev9_shutdown_cbs[idx] = cb;
500 return 0;
502 return -1;
505 static int smap_subsys_init(void)
507 int i, stat, flags;
509 if ((dma_lock_sem = CreateMutex(IOP_MUTEX_UNLOCKED)) < 0)
510 return -1;
511 if ((dma_complete_sem = CreateMutex(IOP_MUTEX_LOCKED)) < 0)
512 return -1;
514 DisableIntr(IOP_IRQ_DMA_DEV9, &stat);
515 CpuSuspendIntr(&flags);
516 /* Enable the DEV9 DMAC channel. */
517 ReleaseIntrHandler(IOP_IRQ_DMA_DEV9);
518 RegisterIntrHandler(IOP_IRQ_DMA_DEV9, 1, dev9_dma_intr, &dma_complete_sem);
519 dmac_set_dpcr2(dmac_get_dpcr2() | 0x80);
520 CpuResumeIntr(flags);
522 /* Not quite sure what this enables yet. */
523 smap_set_stat(0x103);
525 /* Disable all device interrupts. */
526 dev9IntrDisable(0xffff);
528 p_dev9_intr_cb = (void *)dev9_intr_dispatch;
530 /* Reset the SMAP interrupt callback table. */
531 for (i = 0; i < 16; i++)
532 dev9_intr_cbs[i] = NULL;
534 for (i = 0; i < 4; i++){
535 dev9_predma_cbs[i] = NULL;
536 dev9_postdma_cbs[i] = NULL;
539 /* Read in the MAC address. */
540 read_eeprom_data();
541 /* Turn the LED off. */
542 dev9LEDCtl(0);
543 return 0;
546 static int smap_device_init(void)
548 #ifdef DEV9_DEBUG
549 USE_SPD_REGS;
550 const char *spdnames[] = { "(unknown)", "TS", "ES1", "ES2" };
551 int idx;
552 u16 spdrev;
553 #endif
555 eeprom_data[0] = 0;
557 if (smap_device_probe() < 0) {
558 M_PRINTF("PC card or expansion device isn't connected.\n");
559 return -1;
562 smap_device_reset();
564 #ifdef PCMCIA
565 int res;
567 /* Locate the SPEED Lite chip and get the bus ready for the
568 PCMCIA device. */
569 if (dev9type == 0) {
570 if ((res = card_find_manfid(0xf15300)))
571 M_PRINTF("SPEED Lite not found.\n");
573 if (!res && (res = pcic_ssbus_mode(5)))
574 M_PRINTF("Unable to change SSBUS mode.\n");
576 if (res) {
577 dev9Shutdown();
578 return -1;
581 #endif
583 #ifdef DEV9_DEBUG
584 /* Print out the SPEED chip revision. */
585 spdrev = SPD_REG16(SPD_R_REV_1);
586 idx = (spdrev & 0xffff) - 14;
587 if (spdrev == 9)
588 idx = 1; /* TS */
589 else if (spdrev < 9 || (spdrev < 16 || spdrev > 17))
590 idx = 0; /* Unknown revision */
592 M_PRINTF("SPEED chip '%s', revision 0x%0X\n", spdnames[idx], spdrev);
593 #endif
595 return 0;
598 #ifdef PCMCIA
599 static int pcic_get_cardtype()
601 USE_DEV9_REGS;
602 u16 val = DEV9_REG(DEV9_R_1462) & 0x03;
604 if (val == 0)
605 return 1; /* 16-bit */
606 else
607 if (val < 3)
608 return 2; /* CardBus */
609 return 0;
612 static int pcic_get_voltage()
614 USE_DEV9_REGS;
615 u16 val = DEV9_REG(DEV9_R_1462) & 0x0c;
617 if (val == 0x04)
618 return 3;
619 if (val == 0 || val == 0x08)
620 return 1;
621 if (val == 0x0c)
622 return 2;
623 return 0;
626 static int pcic_power(int voltage, int flag)
628 USE_DEV9_REGS;
629 u16 cstc1, cstc2;
630 u16 val = (voltage == 1) << 2;
632 DEV9_REG(DEV9_R_POWER) = 0;
634 if (voltage == 2)
635 val |= 0x08;
636 if (flag == 1)
637 val |= 0x10;
639 DEV9_REG(DEV9_R_POWER) = val;
640 DelayThread(22000);
642 if (DEV9_REG(DEV9_R_1462) & 0x100)
643 return 0;
645 DEV9_REG(DEV9_R_POWER) = 0;
646 DEV9_REG(DEV9_R_1464) = cstc1 = DEV9_REG(DEV9_R_1464);
647 DEV9_REG(DEV9_R_1466) = cstc2 = DEV9_REG(DEV9_R_1466);
648 return -1;
651 static void pcmcia_set_stat(int stat)
653 USE_DEV9_REGS;
654 u16 val = stat & 0x01;
656 if (stat & 0x10)
657 val = 1;
658 if (stat & 0x02)
659 val |= 0x02;
660 if (stat & 0x20)
661 val |= 0x02;
662 if (stat & 0x04)
663 val |= 0x08;
664 if (stat & 0x08)
665 val |= 0x10;
666 if (stat & 0x200)
667 val |= 0x20;
668 if (stat & 0x100)
669 val |= 0x40;
670 if (stat & 0x400)
671 val |= 0x80;
672 if (stat & 0x800)
673 val |= 0x04;
674 DEV9_REG(DEV9_R_1476) = val & 0xff;
677 static int pcic_ssbus_mode(int voltage)
679 USE_DEV9_REGS;
680 USE_SPD_REGS;
681 u16 stat = DEV9_REG(DEV9_R_1474) & 7;
683 if (voltage != 3 && voltage != 5)
684 return -1;
686 DEV9_REG(DEV9_R_1460) = 2;
687 if (stat)
688 return -1;
690 if (voltage == 3) {
691 DEV9_REG(DEV9_R_1474) = 1;
692 DEV9_REG(DEV9_R_1460) = 1;
693 SPD_REG8(0x20) = 1;
694 DEV9_REG(DEV9_R_1474) = voltage;
695 } else if (voltage == 5) {
696 DEV9_REG(DEV9_R_1474) = voltage;
697 DEV9_REG(DEV9_R_1460) = 1;
698 SPD_REG8(0x20) = 1;
699 DEV9_REG(DEV9_R_1474) = 7;
701 _sw(0xe01a3043, SSBUS_R_1418);
703 DelayThread(5000);
704 DEV9_REG(DEV9_R_POWER) = DEV9_REG(DEV9_R_POWER) & ~1;
705 return 0;
708 static int pcmcia_device_probe()
710 #ifdef DEBUG
711 const char *pcic_ct_names[] = { "No", "16-bit", "CardBus" };
712 #endif
713 int voltage;
715 pcic_voltage = pcic_get_voltage();
716 pcic_cardtype = pcic_get_cardtype();
717 voltage = (pcic_voltage == 2 ? 5 : (pcic_voltage == 1 ? 3 : 0));
719 M_PRINTF("%s PCMCIA card detected. Vcc = %dV\n",
720 pcic_ct_names[pcic_cardtype], voltage);
722 if (pcic_voltage == 3 || pcic_cardtype != 1)
723 return -1;
725 return 0;
728 static int pcmcia_device_reset(void)
730 USE_DEV9_REGS;
731 u16 cstc1, cstc2;
733 /* The card must be 16-bit (type 2?) */
734 if (pcic_cardtype != 1)
735 return -1;
737 DEV9_REG(DEV9_R_147E) = 1;
738 if (pcic_power(pcic_voltage, 1) < 0)
739 return -1;
741 DEV9_REG(DEV9_R_POWER) = DEV9_REG(DEV9_R_POWER) | 0x02;
742 DelayThread(500000);
744 DEV9_REG(DEV9_R_POWER) = DEV9_REG(DEV9_R_POWER) | 0x01;
745 DEV9_REG(DEV9_R_1464) = cstc1 = DEV9_REG(DEV9_R_1464);
746 DEV9_REG(DEV9_R_1466) = cstc2 = DEV9_REG(DEV9_R_1466);
747 return 0;
750 static int card_find_manfid(u32 manfid)
752 USE_DEV9_REGS;
753 USE_SPD_REGS;
754 u32 spdaddr, spdend, next, tuple;
755 u8 hdr, ofs;
757 DEV9_REG(DEV9_R_1460) = 2;
758 _sw(0x1a00bb, SSBUS_R_1418);
760 /* Scan the card for the MANFID tuple. */
761 spdaddr = 0;
762 spdend = 0x1000;
763 /* I hate this code, and it hates me. */
764 while (spdaddr < spdend) {
765 hdr = SPD_REG8(spdaddr) & 0xff;
766 spdaddr += 2;
767 if (!hdr)
768 continue;
769 if (hdr == 0xff)
770 break;
771 if (spdaddr >= spdend)
772 goto error;
774 ofs = SPD_REG8(spdaddr) & 0xff;
775 spdaddr += 2;
776 if (ofs == 0xff)
777 break;
779 next = spdaddr + (ofs * 2);
780 if (next >= spdend)
781 goto error;
783 if (hdr == 0x20) {
784 if ((spdaddr + 8) >= spdend)
785 goto error;
787 tuple = (SPD_REG8(spdaddr + 2) << 24)|
788 (SPD_REG8(spdaddr) << 16)|
789 (SPD_REG8(spdaddr + 6) << 8)|
790 SPD_REG8(spdaddr + 4);
791 if (manfid == tuple)
792 return 0;
793 M_PRINTF("MANFID 0x%08lx doesn't match expected 0x%08lx\n",
794 tuple, manfid);
795 return -1;
797 spdaddr = next;
800 M_PRINTF("MANFID 0x%08lx not found.\n", manfid);
801 return -1;
802 error:
803 M_PRINTF("Invalid tuples at offset 0x%08lx.\n", spdaddr - SPD_REGBASE);
804 return -1;
807 static int pcmcia_intr(void *unused)
809 USE_DEV9_REGS;
810 u16 cstc1, cstc2;
812 cstc1 = DEV9_REG(DEV9_R_1464);
813 cstc2 = DEV9_REG(DEV9_R_1466);
815 if (using_aif) {
816 if (_lh(0xb4000004) & 0x04)
817 _sh(0x04, 0xb4000004);
818 else
819 return 0; /* Unknown interrupt. */
822 /* Acknowledge the interrupt. */
823 DEV9_REG(DEV9_R_1464) = cstc1;
824 DEV9_REG(DEV9_R_1466) = cstc2;
825 if (cstc1 & 0x03 || cstc2 & 0x03) { /* Card removed or added? */
826 if (p_dev9_intr_cb)
827 p_dev9_intr_cb(1);
829 /* Shutdown the card. */
830 DEV9_REG(DEV9_R_POWER) = 0;
831 DEV9_REG(DEV9_R_1474) = 0;
833 pcmcia_device_probe();
835 if (cstc1 & 0x80 || cstc2 & 0x80) {
836 if (p_dev9_intr_cb)
837 p_dev9_intr_cb(0);
840 DEV9_REG(DEV9_R_147E) = 1;
841 DEV9_REG(DEV9_R_147E) = 0;
842 return 1;
845 static int pcmcia_init(void)
847 USE_DEV9_REGS;
848 int *mode;
849 int flags;
850 u16 cstc1, cstc2;
852 _sw(0x51011, SSBUS_R_1420);
853 _sw(0x1a00bb, SSBUS_R_1418);
854 _sw(0xef1a3043, SSBUS_R_141c);
856 /* If we are a T10K, then we go through AIF. */
857 if ((mode = QueryBootMode(6)) != NULL) {
858 if ((*(u16 *)mode & 0xfe) == 0x60) {
859 if (_lh(0xb4000000) == 0xa1) {
860 _sh(4, 0xb4000006);
861 using_aif = 1;
862 } else {
863 M_PRINTF("T10k detected, but AIF not detected.\n");
864 return 1;
869 if (DEV9_REG(DEV9_R_POWER) == 0) {
870 DEV9_REG(DEV9_R_POWER) = 0;
871 DEV9_REG(DEV9_R_147E) = 1;
872 DEV9_REG(DEV9_R_1460) = 0;
873 DEV9_REG(DEV9_R_1474) = 0;
874 DEV9_REG(DEV9_R_1464) = cstc1 = DEV9_REG(DEV9_R_1464);
875 DEV9_REG(DEV9_R_1466) = cstc2 = DEV9_REG(DEV9_R_1466);
876 DEV9_REG(DEV9_R_1468) = 0x10;
877 DEV9_REG(DEV9_R_146A) = 0x90;
878 DEV9_REG(DEV9_R_147C) = 1;
879 DEV9_REG(DEV9_R_147A) = DEV9_REG(DEV9_R_147C);
881 pcic_voltage = pcic_get_voltage();
882 pcic_cardtype = pcic_get_cardtype();
884 if (smap_device_init() != 0)
885 return 1;
886 } else {
887 _sw(0xe01a3043, SSBUS_R_1418);
890 if (smap_subsys_init() != 0)
891 return 1;
893 CpuSuspendIntr(&flags);
894 RegisterIntrHandler(DEV9_INTR, 1, pcmcia_intr, NULL);
895 EnableIntr(DEV9_INTR);
896 CpuResumeIntr(flags);
898 DEV9_REG(DEV9_R_147E) = 0;
899 M_PRINTF("CXD9566 (PCMCIA type) initialized.\n");
900 return 0;
902 #else
904 static void expbay_set_stat(int stat)
906 USE_DEV9_REGS;
907 DEV9_REG(DEV9_R_1464) = stat & 0x3f;
910 static int expbay_device_probe()
912 USE_DEV9_REGS;
913 return (DEV9_REG(DEV9_R_1462) & 0x01) ? -1 : 0;
916 static int expbay_device_reset(void)
918 USE_DEV9_REGS;
920 if (expbay_device_probe() < 0)
921 return -1;
923 DEV9_REG(DEV9_R_POWER) = (DEV9_REG(DEV9_R_POWER) & ~1) | 0x04; /* power on */
924 DelayThread(500000);
926 DEV9_REG(DEV9_R_1460) = DEV9_REG(DEV9_R_1460) | 0x01;
927 DEV9_REG(DEV9_R_POWER) = DEV9_REG(DEV9_R_POWER) | 0x01;
928 DelayThread(500000);
929 return 0;
932 static int expbay_intr(void *unused)
934 USE_DEV9_REGS;
936 if (p_dev9_intr_cb)
937 p_dev9_intr_cb(0);
939 DEV9_REG(DEV9_R_1466) = 1;
940 DEV9_REG(DEV9_R_1466) = 0;
941 return 1;
944 static int expbay_init(void)
946 USE_DEV9_REGS;
947 int flags;
949 _sw(0x51011, SSBUS_R_1420);
950 _sw(0xe01a3043, SSBUS_R_1418);
951 _sw(0xef1a3043, SSBUS_R_141c);
953 if ((DEV9_REG(DEV9_R_POWER) & 0x04) == 0) { /* if not already powered */
954 DEV9_REG(DEV9_R_1466) = 1;
955 DEV9_REG(DEV9_R_1464) = 0;
956 DEV9_REG(DEV9_R_1460) = DEV9_REG(DEV9_R_1464);
958 if (smap_device_init() != 0)
959 return 1;
962 if (smap_subsys_init() != 0)
963 return 1;
965 CpuSuspendIntr(&flags);
966 ReleaseIntrHandler(DEV9_INTR);
967 RegisterIntrHandler(DEV9_INTR, 1, expbay_intr, NULL);
968 EnableIntr(DEV9_INTR);
969 CpuResumeIntr(flags);
971 DEV9_REG(DEV9_R_1466) = 0;
972 M_PRINTF("CXD9611 (Expansion Bay type) initialized.\n");
973 return 0;
975 #endif