PS2SDK
PS2 Homebrew Libraries
ps2dev9.c
Go to the documentation of this file.
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.
9 */
10 
16 #include <types.h>
17 #include <defs.h>
18 #include <loadcore.h>
19 #include <intrman.h>
20 #include <iomanX.h>
21 #include <dmacman.h>
22 #include <thbase.h>
23 #include <thsemap.h>
24 #include <stdio.h>
25 #include <sysclib.h>
26 #include <dev9.h>
27 #ifdef DEV9_ENABLE_AIF
28 #include <aifdev9.h>
29 #endif
30 
31 #include <aifregs.h>
32 #include <dev9regs.h>
33 #include <speedregs.h>
34 #include <smapregs.h>
35 
36 #define MODNAME "dev9"
37 #define DRIVERNAME "dev9"
38 // This is version from last SDK 3.1.0
39 IRX_ID(MODNAME, 2, 8);
40 
41 #define M_PRINTF(format, args...) \
42  printf(MODNAME ": " format, ##args)
43 
44 #define VERSION "1.0"
45 #define BANNER "\nDEV9 device driver v%s - Copyright (c) 2003 Marcus R. Brown\n\n"
46 
47 /* SSBUS registers. */
48 #define SSBUS_R_1418 0xbf801418
49 #define SSBUS_R_141c 0xbf80141c
50 #define SSBUS_R_1420 0xbf801420
51 
52 static int semaAttrGlobal; /* Semaphore attribute value to use. */
53 static const char *mod_name; /* Module name. */
54 static int dev9type = -1; /* 0 for PCMCIA, 1 for expansion bay */
55 static int using_aif = 0; /* 1 if using AIF on a T10K */
56 
57 static int dma_lock_sem; /* used to arbitrate DMA */
58 
59 enum PC_CARD_TYPE {
60  PC_CARD_TYPE_NONE = 0,
61  PC_CARD_TYPE_PCMCIA,
62  PC_CARD_TYPE_CARDBUS,
63 };
64 
65 enum PC_CARD_VOLTAGE {
66  PC_CARD_VOLTAGE_INVALID = 0,
67  PC_CARD_VOLTAGE_3V,
68  PC_CARD_VOLTAGE_5V,
69  PC_CARD_VOLTAGE_04h
70 };
71 
72 static int pcic_cardtype; /* Translated value of bits 0-1 of 0xbf801462 */
73 static int pcic_voltage; /* Translated value of bits 2-3 of 0xbf801462 */
74 
75 static s16 eeprom_data[5]; /* 2-byte EEPROM status (0/-1 = invalid, 1 = valid),
76  6-byte MAC address,
77  2-byte MAC address checksum. */
78 
79 typedef int (*dev9IntrDispatchCb_t)(int flag);
80 static dev9IntrDispatchCb_t p_dev9_intr_cb = NULL;
81 static void dev9RegisterIntrDispatchCb(dev9IntrDispatchCb_t callback);
82 
83 /* Each driver can register callbacks that correspond to each bit of the
84  SMAP interrupt status register (0xbx000028). */
85 static dev9_intr_cb_t dev9_intr_cbs[16];
86 #ifdef DEV9_ENABLE_AIF
87 static aif_intr_cb_t aif_intr_cbs[AIF_INUM_COUNT];
88 #endif
89 
90 static dev9_shutdown_cb_t dev9_shutdown_cbs[16];
91 #ifdef DEV9_ENABLE_AIF
92 static dev9_shutdown_cb_t aif_shutdown_cbs[AIF_INUM_COUNT];
93 #endif
94 
95 static dev9_dma_cb_t dev9_predma_cbs[4], dev9_postdma_cbs[4];
96 
97 static u8 dev9_has_dvr_capability = 0;
98 
99 static int dev9_intr_dispatch(int flag);
100 
101 static void dev9_set_stat(int stat);
102 static int dev9_ssbus_mode(int mode);
103 static int dev9_device_probe(void);
104 static int dev9_device_reset(void);
105 static int dev9_card_find_manfid(u32 manfid);
106 
107 static int read_eeprom_data(void);
108 static int dev9_init(int sema_attr);
109 static int speed_device_init(void);
110 
111 static void pcmcia_set_stat(int stat);
112 static int pcic_ssbus_mode(int mode);
113 static int pcmcia_device_probe(void);
114 static int pcmcia_device_reset(void);
115 static int card_find_manfid(u32 manfid);
116 static int pcmcia_init(int sema_attr);
117 
118 static void expbay_set_stat(int stat);
119 static int expbay_device_probe(void);
120 static int expbay_device_reset(void);
121 static int expbay_init(int sema_attr);
122 
123 extern struct irx_export_table _exp_dev9;
124 
125 static int dev9x_devctl(iop_file_t *f, const char *name, int cmd, void *args, unsigned int arglen, void *buf, unsigned int buflen)
126 {
127  (void)f;
128  (void)name;
129  (void)arglen;
130  (void)buf;
131  (void)buflen;
132  switch (cmd) {
133  case DDIOC_MODEL:
134  return dev9type;
135  case DDIOC_OFF:
136  Dev9CardStop();
137  return 0;
138  case DDIOC_SETPIO3:
139  dev9ControlPIO3(((u32 *)args)[0]);
140  return 0;
141  case DDIOC_LED2CTL:
142  dev9LED2Ctl(((u32 *)args)[0]);
143  return 0;
144  default:
145  return 0;
146  }
147 }
148 
149 IOMANX_RETURN_VALUE_IMPL(0);
150 
151 static iop_device_ops_t dev9x_ops =
152  {
153  IOMANX_RETURN_VALUE(0), // init
154  IOMANX_RETURN_VALUE(0), // deinit
155  IOMANX_RETURN_VALUE(0), // format
156  IOMANX_RETURN_VALUE(0), // open
157  IOMANX_RETURN_VALUE(0), // close
158  IOMANX_RETURN_VALUE(0), // read
159  IOMANX_RETURN_VALUE(0), // write
160  IOMANX_RETURN_VALUE(0), // lseek
161  IOMANX_RETURN_VALUE(0), // ioctl
162  IOMANX_RETURN_VALUE(0), // remove
163  IOMANX_RETURN_VALUE(0), // mkdir
164  IOMANX_RETURN_VALUE(0), // rmdir
165  IOMANX_RETURN_VALUE(0), // dopen
166  IOMANX_RETURN_VALUE(0), // dclose
167  IOMANX_RETURN_VALUE(0), // dread
168  IOMANX_RETURN_VALUE(0), // getstat
169  IOMANX_RETURN_VALUE(0), // chstat
170  IOMANX_RETURN_VALUE(0), // rename
171  IOMANX_RETURN_VALUE(0), // chdir
172  IOMANX_RETURN_VALUE(0), // sync
173  IOMANX_RETURN_VALUE(0), // mount
174  IOMANX_RETURN_VALUE(0), // umount
175  IOMANX_RETURN_VALUE_S64(0), // lseek64
176  &dev9x_devctl, // devctl
177  IOMANX_RETURN_VALUE(0), // symlink
178  IOMANX_RETURN_VALUE(0), // readlink
179  IOMANX_RETURN_VALUE(0), // ioctl2
180 };
181 
182 static iop_device_t dev9x_device =
183  {
184  "dev9x",
185  IOP_DT_FS | IOP_DT_FSEXT,
186  1,
187  "DEV9",
188  &dev9x_ops,
189 };
190 
191 static int print_help(void)
192 { // The original made a printf() call for each line.
193  printf("Usage:\n"
194  " %s [-sa] <attribute>]\n"
195  " -sa You can specify attibute of sempahore for queuing thread.\n"
196  " List of possible <attribute>:\n"
197  " SA_THPRI(default), SA_THFIFO\n",
198  mod_name);
199 
200  return MODULE_NO_RESIDENT_END;
201 }
202 
203 int _start(int argc, char *argv[])
204 {
205  USE_DEV9_REGS;
206  const char *pModName;
207  int idx, res;
208  u16 dev9hw;
209 
210  semaAttrGlobal = SA_THPRI;
211 
212  printf(BANNER, VERSION);
213 
214  mod_name = (pModName = strrchr(argv[0], '/')) != NULL ? pModName + 1 : argv[0];
215 
216  for (--argc, ++argv; argc > 0; argc--, argv++) {
217  if ((*argv)[0] != '-')
218  break;
219 
220  if (strcmp("-sa", *argv) == 0) {
221  --argc;
222  ++argv;
223  if (argc > 0) {
224  if (strcmp("SA_THFIFO", *argv) == 0) {
225  semaAttrGlobal = SA_THFIFO;
226  } else if (strcmp("SA_THPRI", *argv) == 0) {
227  semaAttrGlobal = SA_THPRI;
228  } else {
229  return print_help();
230  }
231  } else {
232  return print_help();
233  }
234  } else {
235  return print_help();
236  }
237  }
238 
239  for (idx = 0; idx < 16; idx++)
240  dev9_shutdown_cbs[idx] = NULL;
241 
242 #ifdef DEV9_ENABLE_AIF
243  for (idx = 0; idx < AIF_INUM_COUNT; idx++)
244  aif_shutdown_cbs[idx] = NULL;
245 #endif
246 
247  dev9hw = DEV9_REG(DEV9_R_REV) & 0xf0;
248  if (dev9hw == 0x20) { /* CXD9566 (PCMCIA) */
249  dev9type = DEV9_TYPE_PCMCIA;
250  M_PRINTF("CXD9566 detected.\n");
251  res = pcmcia_init(semaAttrGlobal);
252  } else if (dev9hw == 0x30) { /* CXD9611 (Expansion Bay) */
253  dev9type = DEV9_TYPE_EXPBAY;
254  M_PRINTF("CXD9611 detected.\n");
255  res = expbay_init(semaAttrGlobal);
256  } else {
257  M_PRINTF("unknown dev9 hardware.\n");
258  res = MODULE_NO_RESIDENT_END;
259  }
260 
261  if (res)
262  return res;
263 
264  DelDrv(dev9x_device.name);
265  if (AddDrv(&dev9x_device) != 0) {
266  return MODULE_NO_RESIDENT_END;
267  }
268 
269  return MODULE_RESIDENT_END;
270 }
271 
272 int _exit(void) { return MODULE_RESIDENT_END; }
273 
274 /* Export 4 */
275 void SpdRegisterIntrHandler(int intr, dev9_intr_cb_t cb)
276 {
277  dev9_intr_cbs[intr] = cb;
278 }
279 
280 /* Export 12 */
281 void dev9RegisterPreDmaCb(int ctrl, dev9_dma_cb_t cb)
282 {
283  dev9_predma_cbs[ctrl] = cb;
284 }
285 
286 /* Export 13 */
287 void dev9RegisterPostDmaCb(int ctrl, dev9_dma_cb_t cb)
288 {
289  dev9_postdma_cbs[ctrl] = cb;
290 }
291 
292 // flag is 1 if a card (pcmcia) was removed or added
293 static int dev9_intr_dispatch(int flag)
294 {
295  USE_SPD_REGS;
296  int i, bit;
297 
298  if (flag) {
299  for (i = 0; i < 16; i++)
300  if (dev9_intr_cbs[i] != NULL)
301  dev9_intr_cbs[i](flag);
302  }
303 
304  while (SPD_REG16(SPD_R_INTR_STAT) & SPD_REG16(SPD_R_INTR_MASK)) {
305  for (i = 0; i < 16; i++) {
306  if (dev9_intr_cbs[i] != NULL) {
307  bit = (SPD_REG16(SPD_R_INTR_STAT) &
308  SPD_REG16(SPD_R_INTR_MASK)) >>
309  i;
310  if (bit & 0x01)
311  dev9_intr_cbs[i](flag);
312  }
313  }
314  }
315 
316  return 0;
317 }
318 
319 static void dev9_set_stat(int stat)
320 {
321  switch (dev9type) {
322  case DEV9_TYPE_PCMCIA:
323  pcmcia_set_stat(stat);
324  break;
325  case DEV9_TYPE_EXPBAY:
326  expbay_set_stat(stat);
327  break;
328  }
329 }
330 
331 static int dev9_ssbus_mode(int mode)
332 {
333  switch (dev9type) {
334  case DEV9_TYPE_PCMCIA:
335  return pcic_ssbus_mode(mode);
336  case DEV9_TYPE_EXPBAY:
337  return 0;
338  }
339 
340  return -1;
341 }
342 
343 static int dev9_device_probe(void)
344 {
345  switch (dev9type) {
346  case DEV9_TYPE_PCMCIA:
347  return pcmcia_device_probe();
348  case DEV9_TYPE_EXPBAY:
349  return expbay_device_probe();
350  }
351 
352  return -1;
353 }
354 
355 static int dev9_device_reset(void)
356 {
357  switch (dev9type) {
358  case DEV9_TYPE_PCMCIA:
359  return pcmcia_device_reset();
360  case DEV9_TYPE_EXPBAY:
361  return expbay_device_reset();
362  }
363 
364  return -1;
365 }
366 
367 /* Export 6 */
368 void Dev9CardStop(void)
369 {
370  int idx;
371  USE_DEV9_REGS;
372 
373  for (idx = 0; idx < 16; idx++)
374  if (dev9_shutdown_cbs[idx])
375  dev9_shutdown_cbs[idx]();
376 
377 #ifdef DEV9_ENABLE_AIF
378  for (idx = 0; idx < AIF_INUM_COUNT; idx++)
379  if (aif_shutdown_cbs[idx])
380  aif_shutdown_cbs[idx]();
381 #endif
382 
383  if (dev9type == DEV9_TYPE_PCMCIA) { /* PCMCIA */
384  DEV9_REG(DEV9_R_POWER) = 0;
385  DEV9_REG(DEV9_R_1474) = 0;
386  } else if (dev9type == DEV9_TYPE_EXPBAY) {
387  DEV9_REG(DEV9_R_1466) = 1;
388  DEV9_REG(DEV9_R_1464) = 0;
389  DEV9_REG(DEV9_R_1460) = DEV9_REG(DEV9_R_1464);
390  DEV9_REG(DEV9_R_POWER) = DEV9_REG(DEV9_R_POWER) & ~4;
391  DEV9_REG(DEV9_R_POWER) = DEV9_REG(DEV9_R_POWER) & ~1;
392  }
393  DelayThread(1000000);
394 }
395 
396 static int dev9_card_find_manfid(u32 manfid)
397 {
398  switch (dev9type) {
399  case DEV9_TYPE_PCMCIA:
400  return card_find_manfid(manfid);
401  case DEV9_TYPE_EXPBAY:
402  return 0;
403  }
404 
405  return -1;
406 }
407 
408 /* Export 7 */
409 void SpdIntrEnable(int mask)
410 {
411  USE_SPD_REGS;
412  int flags;
413 
414  CpuSuspendIntr(&flags);
415  SPD_REG16(SPD_R_INTR_MASK) = SPD_REG16(SPD_R_INTR_MASK) | mask;
416  CpuResumeIntr(flags);
417 }
418 
419 /* Export 8 */
420 void SpdIntrDisable(int mask)
421 {
422  USE_SPD_REGS;
423  int flags;
424 
425  CpuSuspendIntr(&flags);
426  SPD_REG16(SPD_R_INTR_MASK) = SPD_REG16(SPD_R_INTR_MASK) & ~mask;
427  CpuResumeIntr(flags);
428 }
429 
430 /* Export 5 */
431 int SpdDmaTransfer(int device, void *buf, int bcr, int dir)
432 {
433  USE_SPD_REGS;
434  volatile iop_dmac_chan_t *dev9_chan = (iop_dmac_chan_t *)DEV9_DMAC_BASE;
435  int res, dmactrl, OldState;
436 
437  if (device >= 4) {
438  return -1;
439  } else if (device >= 2) {
440  if (dev9_predma_cbs[device] == NULL)
441  return -1;
442  if (dev9_postdma_cbs[device] == NULL)
443  return -1;
444  }
445 
446  if ((res = WaitSema(dma_lock_sem)) < 0)
447  return res;
448 
449  switch (device) {
450  case 0:
451  dmactrl = 0;
452  break;
453  case 1:
454  dmactrl = 1;
455  break;
456 #ifdef DEV9_PSX_SUPPORT
457  // Used for the PSX
458  case 2:
459  dmactrl = 0x10;
460  break;
461  case 3:
462  dmactrl = 0x20;
463  break;
464 #endif
465  default:
466  dmactrl = 0;
467  }
468 
469  SPD_REG16(SPD_R_DMA_CTRL) = (SPD_REG16(SPD_R_REV_1) < 17) ? (dmactrl & 0x03) | 0x04 : dmactrl | 0x06;
470 
471  if (dev9_predma_cbs[device])
472  dev9_predma_cbs[device](bcr, dir);
473 
474  dev9_chan->madr = (u32)buf;
475 
476  /* Older versions of DEV9 do not suspend interrupts. Not sure why this must be done though. */
477  CpuSuspendIntr(&OldState);
478  dev9_chan->bcr = bcr;
479  dev9_chan->chcr = DMAC_CHCR_30 | DMAC_CHCR_TR | DMAC_CHCR_CO | (dir & DMAC_CHCR_DR);
480  CpuResumeIntr(OldState);
481 
482  /* Wait for DMA to complete. Do not use a semaphore as thread switching hurts throughput greatly. */
483  while (dev9_chan->chcr & DMAC_CHCR_TR) {}
484 
485  if (dev9_postdma_cbs[device])
486  dev9_postdma_cbs[device](bcr, dir);
487 
488  SignalSema(dma_lock_sem);
489  return 0;
490 }
491 
492 static int read_eeprom_data(void)
493 {
494  USE_SPD_REGS;
495  int i, j, res = -2;
496  u8 val;
497 
498  if (eeprom_data[0] < 0)
499  goto out;
500 
501  SPD_REG8(SPD_R_PIO_DIR) = 0xe0 | (dev9_has_dvr_capability ? 7 : 1);
502  DelayThread(1);
503  SPD_REG8(SPD_R_PIO_DATA) = 0x80;
504  DelayThread(1);
505 
506  for (i = 0; i < 2; i++) {
507  SPD_REG8(SPD_R_PIO_DATA) = 0xa0;
508  DelayThread(1);
509  SPD_REG8(SPD_R_PIO_DATA) = 0xe0;
510  DelayThread(1);
511  }
512  for (i = 0; i < 7; i++) {
513  SPD_REG8(SPD_R_PIO_DATA) = 0x80;
514  DelayThread(1);
515  SPD_REG8(SPD_R_PIO_DATA) = 0xc0;
516  DelayThread(1);
517  }
518  SPD_REG8(SPD_R_PIO_DATA) = 0xc0;
519  DelayThread(1);
520 
521  val = SPD_REG8(SPD_R_PIO_DATA);
522  DelayThread(1);
523  if (val & 0x10) { /* Error. */
524  SPD_REG8(SPD_R_PIO_DATA) = 0;
525  DelayThread(1);
526  res = -1;
527  eeprom_data[0] = 0;
528  goto out;
529  }
530 
531  SPD_REG8(SPD_R_PIO_DATA) = 0x80;
532  DelayThread(1);
533 
534  /* Read the MAC address and checksum from the EEPROM. */
535  for (i = 0; i < 4; i++) {
536  eeprom_data[i + 1] = 0;
537 
538  for (j = 15; j >= 0; j--) {
539  SPD_REG8(SPD_R_PIO_DATA) = 0xc0;
540  DelayThread(1);
541  val = SPD_REG8(SPD_R_PIO_DATA);
542  if (val & 0x10)
543  eeprom_data[i + 1] |= (1 << j);
544  SPD_REG8(SPD_R_PIO_DATA) = 0x80;
545  DelayThread(1);
546  }
547  }
548 
549  SPD_REG8(SPD_R_PIO_DATA) = 0;
550  DelayThread(1);
551  eeprom_data[0] = 1; /* The EEPROM data is valid. */
552  res = 0;
553 
554 out:
555  SPD_REG8(SPD_R_PIO_DIR) = dev9_has_dvr_capability ? 7 : 1;
556  return res;
557 }
558 
559 /* Export 9 */
560 int SpdGetEthernetID(u16 *buf)
561 {
562  int i;
563 
564  if (!eeprom_data[0])
565  return -1;
566  if (eeprom_data[0] < 0)
567  return -2;
568 
569  /* We only return the MAC address and checksum. */
570  for (i = 0; i < 4; i++)
571  buf[i] = eeprom_data[i + 1];
572 
573  return 0;
574 }
575 
576 // Exerpt from Wisi's SPEED.txt:
577 // 1:0 Dev9 LED Control. 0=On/1=Off.
578 // Clearing either to 0 will light the LED.
579 // Each is connected to the cathode of a diode, sharing a common anode.
580 // The anode has a 10kohm pull-up to Vcc, and is connected to the base of an PNP transistor,
581 // with collector grounded and emitter, connecting through a 240ohm resistor to the ACS_LED
582 // pin (90) of the Expansion Bay connector. It connects to the cathode of the HDD Activity LED
583 // in the PS2, the anode of which connects through 180ohm resistor to +5V.
584 
585 // The specific LED part used is the Citizen CITILED CL-200TLY-C, which has a "Lemon Yellow" color.
586 
587 /* Export 10 */
588 void SpdSetLED(int ctl)
589 {
590  USE_SPD_REGS;
591  if (dev9_has_dvr_capability) {
592  SPD_REG8(SPD_R_PIO_DIR) |= 1;
593  SPD_REG8(SPD_R_PIO_DATA) = (SPD_REG8(SPD_R_PIO_DATA) & 0xE) | (ctl ? 0 : 1);
594  } else {
595  SPD_REG8(SPD_R_PIO_DATA) = (ctl == 0);
596  }
597 }
598 
599 /* Export 15 */
600 void dev9LED2Ctl(int ctl)
601 {
602  if (dev9_has_dvr_capability) {
603  USE_SPD_REGS;
604  SPD_REG8(SPD_R_PIO_DIR) |= 2;
605  DelayThread(1);
606  SPD_REG8(SPD_R_PIO_DATA) = (SPD_REG8(SPD_R_PIO_DATA) & 0xD) | (ctl ? 0 : 2);
607  DelayThread(1);
608  }
609 }
610 
611 // Exerpt from Wisi's SPEED.txt:
612 // 3:2 On SCPH-70000, each is connected through 10kohm R to Vcc, so they were inputs once.
613 // On the SCPH-10350 Network Adapter - as well.
614 
615 /* Export 14 */
616 void dev9ControlPIO3(int ctl)
617 {
618  if (dev9_has_dvr_capability) {
619  USE_SPD_REGS;
620  SPD_REG8(SPD_R_PIO_DIR) |= 4;
621  DelayThread(1);
622  SPD_REG8(SPD_R_PIO_DATA) = (SPD_REG8(SPD_R_PIO_DATA) & 0xB) | (ctl ? 0 : 4);
623  DelayThread(1);
624  }
625 }
626 
627 static void dev9RegisterIntrDispatchCb(dev9IntrDispatchCb_t callback)
628 {
629  p_dev9_intr_cb = callback;
630 }
631 
632 /* Export 11 */
633 int Dev9RegisterPowerOffHandler(int idx, dev9_shutdown_cb_t cb)
634 {
635  if (idx < 16) {
636  dev9_shutdown_cbs[idx] = cb;
637  return 0;
638  }
639  return -1;
640 }
641 
642 static int dev9_init(int sema_attr)
643 {
644  iop_sema_t sema;
645  int i, flags;
646 
647  sema.attr = sema_attr;
648  sema.initial = 1;
649  sema.max = 1;
650  if ((dma_lock_sem = CreateSema(&sema)) < 0)
651  return -1;
652 
653  CpuSuspendIntr(&flags);
654  /* Enable the DEV9 DMAC channel. */
655  dmac_set_dpcr2(dmac_get_dpcr2() | 0x80);
656  CpuResumeIntr(flags);
657 
658  /* Not quite sure what this enables yet. */
659  dev9_set_stat(0x103);
660 
661  /* Disable all device interrupts. */
662  SpdIntrDisable(0xffff);
663 
664 #ifdef DEV9_ENABLE_AIF
665  if (using_aif)
666  aifIntrDisable(0xffff);
667 #endif
668 
669  /* Register interrupt dispatch callback handler. */
670  dev9RegisterIntrDispatchCb(&dev9_intr_dispatch);
671 
672  /* Reset the SMAP interrupt callback table. */
673  for (i = 0; i < 16; i++)
674  dev9_intr_cbs[i] = NULL;
675 #ifdef DEV9_ENABLE_AIF
676  for (i = 0; i < AIF_INUM_COUNT; i++)
677  aif_intr_cbs[i] = NULL;
678 #endif
679 
680  for (i = 0; i < 4; i++) {
681  dev9_predma_cbs[i] = NULL;
682  dev9_postdma_cbs[i] = NULL;
683  }
684 
685  /* Read in the MAC address. */
686  read_eeprom_data();
687 
688  dev9LED2Ctl(0);
689  dev9ControlPIO3(0);
690 
691  /* Turn the LED off. */
692  SpdSetLED(0);
693  return 0;
694 }
695 
696 #ifndef DEV9_SKIP_SMAP_INIT
697 static int dev9_smap_read_phy(volatile u8 *emac3_regbase, unsigned int address, unsigned int *data)
698 {
699  unsigned int i, PHYRegisterValue;
700  int result;
701 
702  PHYRegisterValue = (address & SMAP_E3_PHY_REG_ADDR_MSK) | SMAP_E3_PHY_READ | ((SMAP_DsPHYTER_ADDRESS & SMAP_E3_PHY_ADDR_MSK) << SMAP_E3_PHY_ADDR_BITSFT);
703 
704  i = 0;
705  result = 0;
706  SMAP_EMAC3_SET(SMAP_R_EMAC3_STA_CTRL, PHYRegisterValue);
707 
708  do {
709  if (SMAP_EMAC3_GET(SMAP_R_EMAC3_STA_CTRL) & SMAP_E3_PHY_OP_COMP) {
710  if (SMAP_EMAC3_GET(SMAP_R_EMAC3_STA_CTRL) & SMAP_E3_PHY_OP_COMP) {
711  if ((result = SMAP_EMAC3_GET(SMAP_R_EMAC3_STA_CTRL)) & SMAP_E3_PHY_OP_COMP) {
712  result >>= SMAP_E3_PHY_DATA_BITSFT;
713  break;
714  }
715  }
716  }
717 
718  DelayThread(1000);
719  i++;
720  } while (i < 100);
721 
722  if (i >= 100) {
723  return 1;
724  } else {
725  *data = result;
726  return 0;
727  }
728 }
729 
730 static int dev9_smap_write_phy(volatile u8 *emac3_regbase, unsigned char address, unsigned short int value)
731 {
732  unsigned int i, PHYRegisterValue;
733 
734  PHYRegisterValue = (address & SMAP_E3_PHY_REG_ADDR_MSK) | SMAP_E3_PHY_WRITE | ((SMAP_DsPHYTER_ADDRESS & SMAP_E3_PHY_ADDR_MSK) << SMAP_E3_PHY_ADDR_BITSFT);
735  PHYRegisterValue |= ((unsigned int)value) << SMAP_E3_PHY_DATA_BITSFT;
736 
737  i = 0;
738  SMAP_EMAC3_SET(SMAP_R_EMAC3_STA_CTRL, PHYRegisterValue);
739 
740  for (; !(SMAP_EMAC3_GET(SMAP_R_EMAC3_STA_CTRL) & SMAP_E3_PHY_OP_COMP); i++) {
741  DelayThread(1000);
742  if (i >= 100)
743  break;
744  }
745 
746  return ((i >= 100) ? 1 : 0);
747 }
748 
749 static int dev9_smap_init(void)
750 {
751  unsigned int value;
752  USE_SPD_REGS;
753  USE_SMAP_REGS;
754  USE_SMAP_EMAC3_REGS;
755  USE_SMAP_TX_BD;
756  USE_SMAP_RX_BD;
757  int i;
758 
759  // Do not perform SMAP initialization if the SPEED device does not have such an interface
760  if (!(SPD_REG16(SPD_R_REV_3) & SPD_CAPS_SMAP)
761 #ifdef DEV9_GAMESTAR_WORKAROUND
762  /* If this adaptor is a compatible adaptor, do not initialize SMAP.
763  Official adaptors appear to have a 0x0001 set for this register, but not compatibles.
764  While official I/O to this register are 8-bit, some compatibles have a 0x01 for the lower 8-bits,
765  but the upper 8-bits contain some random value. Hence perform a 16-bit read instead. */
766  || (SPD_REG16(0x20) != 1)
767 #endif
768  )
769  return 0;
770 
771  SMAP_REG8(SMAP_R_TXFIFO_CTRL) = SMAP_TXFIFO_RESET;
772  for (i = 9; SMAP_REG8(SMAP_R_TXFIFO_CTRL) & SMAP_TXFIFO_RESET; i--) {
773  if (i <= 0)
774  return 1;
775  DelayThread(1000);
776  }
777 
778  SMAP_REG8(SMAP_R_RXFIFO_CTRL) = SMAP_RXFIFO_RESET;
779  for (i = 9; SMAP_REG8(SMAP_R_RXFIFO_CTRL) & SMAP_RXFIFO_RESET; i--) {
780  if (i <= 0)
781  return 1;
782  DelayThread(1000);
783  }
784 
785  SMAP_EMAC3_SET(SMAP_R_EMAC3_MODE0, SMAP_E3_SOFT_RESET);
786  for (i = 9; SMAP_EMAC3_GET(SMAP_R_EMAC3_MODE0) & SMAP_E3_SOFT_RESET; i--) {
787  if (i <= 0)
788  return 3;
789  DelayThread(1000);
790  }
791 
792  // Unlike the SMAP driver, this reset operation is done in big-endian.
793  if (SPD_REG16(SPD_R_REV_1) >= 0x11)
794  SMAP_REG8(SMAP_R_BD_MODE) = SMAP_BD_SWAP;
795 
796  for (i = 0; i < SMAP_BD_MAX_ENTRY; i++) {
797  tx_bd[i].ctrl_stat = 0;
798  tx_bd[i].reserved = 0;
799  tx_bd[i].length = 0;
800  tx_bd[i].pointer = 0;
801  }
802 
803  for (i = 0; i < SMAP_BD_MAX_ENTRY; i++) {
804  rx_bd[i].ctrl_stat = 0x80; // SMAP_BD_RX_EMPTY
805  rx_bd[i].reserved = 0;
806  rx_bd[i].length = 0;
807  rx_bd[i].pointer = 0;
808  }
809 
810  SMAP_REG16(SMAP_R_INTR_CLR) = SMAP_INTR_BITMSK;
811  if (SPD_REG16(SPD_R_REV_1) < 0x11)
812  SPD_REG8(0x100) = 1;
813 
814  SMAP_EMAC3_SET(SMAP_R_EMAC3_MODE1, SMAP_E3_FDX_ENABLE | SMAP_E3_IGNORE_SQE | SMAP_E3_MEDIA_100M | SMAP_E3_RXFIFO_2K | SMAP_E3_TXFIFO_1K | SMAP_E3_TXREQ0_MULTI | SMAP_E3_TXREQ1_SINGLE);
815  SMAP_EMAC3_SET(SMAP_R_EMAC3_TxMODE1, 7 << SMAP_E3_TX_LOW_REQ_BITSFT | 15 << SMAP_E3_TX_URG_REQ_BITSFT);
816  SMAP_EMAC3_SET(SMAP_R_EMAC3_RxMODE, SMAP_E3_RX_RX_RUNT_FRAME | SMAP_E3_RX_RX_FCS_ERR | SMAP_E3_RX_RX_TOO_LONG_ERR | SMAP_E3_RX_RX_IN_RANGE_ERR | SMAP_E3_RX_PROP_PF | SMAP_E3_RX_PROMISC);
817  SMAP_EMAC3_SET(SMAP_R_EMAC3_INTR_STAT, SMAP_E3_INTR_TX_ERR_0 | SMAP_E3_INTR_SQE_ERR_0 | SMAP_E3_INTR_DEAD_0);
818  SMAP_EMAC3_SET(SMAP_R_EMAC3_INTR_ENABLE, SMAP_E3_INTR_TX_ERR_0 | SMAP_E3_INTR_SQE_ERR_0 | SMAP_E3_INTR_DEAD_0);
819  SMAP_EMAC3_SET(SMAP_R_EMAC3_ADDR_HI, 0);
820  SMAP_EMAC3_SET(SMAP_R_EMAC3_ADDR_LO, 0);
821  SMAP_EMAC3_SET(SMAP_R_EMAC3_PAUSE_TIMER, 0xFFFF);
822  SMAP_EMAC3_SET(SMAP_R_EMAC3_INTER_FRAME_GAP, 4);
823  SMAP_EMAC3_SET(SMAP_R_EMAC3_TX_THRESHOLD, 12 << SMAP_E3_TX_THRESHLD_BITSFT);
824  SMAP_EMAC3_SET(SMAP_R_EMAC3_RX_WATERMARK, 16 << SMAP_E3_RX_LO_WATER_BITSFT | 128 << SMAP_E3_RX_HI_WATER_BITSFT);
825 
826  dev9_smap_write_phy(emac3_regbase, SMAP_DsPHYTER_BMCR, SMAP_PHY_BMCR_RST);
827  for (i = 9;; i--) {
828  if (dev9_smap_read_phy(emac3_regbase, SMAP_DsPHYTER_BMCR, &value))
829  return 4;
830  if (!(value & SMAP_PHY_BMCR_RST))
831  break;
832  if (i <= 0)
833  return 5;
834  }
835 
836  dev9_smap_write_phy(emac3_regbase, SMAP_DsPHYTER_BMCR, SMAP_PHY_BMCR_LPBK | SMAP_PHY_BMCR_100M | SMAP_PHY_BMCR_DUPM);
837  DelayThread(10000);
838  SMAP_EMAC3_SET(SMAP_R_EMAC3_MODE0, SMAP_E3_TXMAC_ENABLE | SMAP_E3_RXMAC_ENABLE);
839  value = SMAP_REG16(SMAP_R_TXFIFO_WR_PTR) + SMAP_TX_BASE;
840 
841  for (i = 0; i < 0x5EA; i += 4)
842  SMAP_REG32(SMAP_R_TXFIFO_DATA) = i;
843 
844  tx_bd[0].length = 0xEA05;
845  tx_bd[0].pointer = (value >> 8) | (value << 8);
846  SMAP_REG8(SMAP_R_TXFIFO_FRAME_INC) = 0;
847  tx_bd[0].ctrl_stat = 0x83; // SMAP_BD_TX_READY|SMAP_BD_TX_GENFCS|SMAP_BD_TX_GENPAD
848 
849  SMAP_EMAC3_SET(SMAP_R_EMAC3_TxMODE0, SMAP_E3_TX_GNP_0);
850  for (i = 9;; i--) {
851  value = SPD_REG16(SPD_R_INTR_STAT);
852 
853  if ((value & (SMAP_INTR_RXEND | SMAP_INTR_TXEND | SMAP_INTR_TXDNV)) == (SMAP_INTR_RXEND | SMAP_INTR_TXEND | SMAP_INTR_TXDNV))
854  break;
855  if (i <= 0)
856  return 6;
857  DelayThread(1000);
858  }
859  SMAP_EMAC3_SET(SMAP_R_EMAC3_MODE0, SMAP_E3_SOFT_RESET);
860 
861  return 0;
862 }
863 #endif
864 
865 static int speed_device_init(void)
866 {
867  USE_SPD_REGS;
868  const char *spdnames[] = {"(unknown)", "TS", "ES1", "ES2"};
869  int idx, res;
870  u16 spdrev;
871 #ifndef DEV9_SKIP_SMAP_INIT
872  int i;
873 #endif
874 
875  eeprom_data[0] = 0;
876 
877 #ifndef DEV9_SKIP_SMAP_INIT
878  for (i = 0; i < 8; i++) {
879 #endif
880  if (dev9_device_probe() < 0) {
881  M_PRINTF("No device.\n");
882 #ifdef DEV9_ENABLE_AIF
883  return (using_aif ? 0 : -1);
884 #else
885  return -1;
886 #endif
887  }
888 
889  dev9_device_reset();
890 
891  /* Locate the SPEED Lite chip and get the bus ready for the
892  PCMCIA device. */
893  if ((res = dev9_card_find_manfid(0xf15300)))
894  M_PRINTF("SPEED Lite not found.\n");
895 
896  if (!res && (res = dev9_ssbus_mode(5)))
897  M_PRINTF("Unable to change SSBUS mode.\n");
898 
899  if (res) {
900  Dev9CardStop();
901  return -1;
902  }
903 
904 #ifndef DEV9_SKIP_SMAP_INIT
905  if ((res = dev9_smap_init()) == 0) {
906  break;
907  }
908 
909  Dev9CardStop();
910  DelayThread(4500000);
911  }
912 
913  if (res) {
914  M_PRINTF("SMAP initialization failed: %d\n", res);
915  eeprom_data[0] = -1;
916  }
917 #endif
918 
919  /* Print out the SPEED chip revision. */
920  spdrev = SPD_REG16(SPD_R_REV_1);
921  idx = (spdrev & 0xffff) - 14;
922  if (spdrev == 9)
923  idx = 1; /* TS */
924  else if (spdrev < 9 || (spdrev < 16 || spdrev > 17))
925  idx = 0; /* Unknown revision */
926 
927  M_PRINTF("SPEED chip '%s', revision %0x\n", spdnames[idx], spdrev);
928  return 0;
929 }
930 
931 static int pcic_get_cardtype(void)
932 {
933  USE_DEV9_REGS;
934  u16 val = DEV9_REG(DEV9_R_1462) & 0x03;
935 
936  if (val == 0)
937  return PC_CARD_TYPE_PCMCIA; /* 16-bit */
938  else if (val < 3) // If the bit pattern is either 10b or 01b
939  return PC_CARD_TYPE_CARDBUS; /* CardBus */
940  return PC_CARD_TYPE_NONE;
941 }
942 
943 static int pcic_get_voltage(void)
944 {
945  USE_DEV9_REGS;
946  u16 val = DEV9_REG(DEV9_R_1462) & 0x0c;
947 
948  if (val == 0x04)
949  return PC_CARD_VOLTAGE_04h;
950  if (val == 0 || val == 0x08)
951  return PC_CARD_VOLTAGE_3V;
952  if (val == 0x0c)
953  return PC_CARD_VOLTAGE_5V;
954  return PC_CARD_VOLTAGE_INVALID;
955 }
956 
957 static int pcic_power(int voltage, int flag)
958 {
959  USE_DEV9_REGS;
960  u16 cstc1, cstc2;
961  u16 val = (voltage == 1) << 2;
962 
963  DEV9_REG(DEV9_R_POWER) = 0;
964 
965  if (voltage == 2)
966  val |= 0x08;
967  if (flag == 1)
968  val |= 0x10;
969 
970  DEV9_REG(DEV9_R_POWER) = val;
971  DelayThread(22000);
972 
973  if (DEV9_REG(DEV9_R_1462) & 0x100)
974  return 0;
975 
976  DEV9_REG(DEV9_R_POWER) = 0;
977  DEV9_REG(DEV9_R_1464) = cstc1 = DEV9_REG(DEV9_R_1464);
978  DEV9_REG(DEV9_R_1466) = cstc2 = DEV9_REG(DEV9_R_1466);
979  return -1;
980 }
981 
982 static void pcmcia_set_stat(int stat)
983 {
984  USE_DEV9_REGS;
985  u16 val = stat & 0x01;
986 
987  if (stat & 0x10)
988  val = 1;
989  if (stat & 0x02)
990  val |= 0x02;
991  if (stat & 0x20)
992  val |= 0x02;
993  if (stat & 0x04)
994  val |= 0x08;
995  if (stat & 0x08)
996  val |= 0x10;
997  if (stat & 0x200)
998  val |= 0x20;
999  if (stat & 0x100)
1000  val |= 0x40;
1001  if (stat & 0x400)
1002  val |= 0x80;
1003  if (stat & 0x800)
1004  val |= 0x04;
1005  DEV9_REG(DEV9_R_1476) = val & 0xff;
1006 }
1007 
1008 static int pcic_ssbus_mode(int mode)
1009 {
1010  USE_DEV9_REGS;
1011  USE_SPD_REGS;
1012  u16 stat = DEV9_REG(DEV9_R_1474) & 7;
1013 
1014  if (mode != 3 && mode != 5)
1015  return -1;
1016 
1017  DEV9_REG(DEV9_R_1460) = 2;
1018  if (stat)
1019  return -1;
1020 
1021  if (mode == 3) {
1022  DEV9_REG(DEV9_R_1474) = 1;
1023  DEV9_REG(DEV9_R_1460) = 1;
1024  SPD_REG8(0x20) = 1;
1025  DEV9_REG(DEV9_R_1474) = mode;
1026  } else if (mode == 5) {
1027  DEV9_REG(DEV9_R_1474) = mode;
1028  DEV9_REG(DEV9_R_1460) = 1;
1029  SPD_REG8(0x20) = 1;
1030  DEV9_REG(DEV9_R_1474) = 7;
1031  }
1032  _sw(0xe01a3043, SSBUS_R_1418);
1033 
1034  DelayThread(5000);
1035  DEV9_REG(DEV9_R_POWER) = DEV9_REG(DEV9_R_POWER) & ~1;
1036  return 0;
1037 }
1038 
1039 static int pcmcia_device_probe(void)
1040 {
1041  const char *pcic_ct_names[] = {"No", "16-bit", "CardBus"};
1042  int voltage;
1043 
1044  pcic_voltage = pcic_get_voltage();
1045  pcic_cardtype = pcic_get_cardtype();
1046  voltage = (pcic_voltage == PC_CARD_VOLTAGE_5V ? 5 : (pcic_voltage == PC_CARD_VOLTAGE_3V ? 3 : 0));
1047 
1048  M_PRINTF("%s PCMCIA card detected. Vcc = %dV\n",
1049  pcic_ct_names[pcic_cardtype], voltage);
1050 
1051  if (pcic_voltage == PC_CARD_VOLTAGE_04h || pcic_cardtype != PC_CARD_TYPE_PCMCIA)
1052  return -1;
1053 
1054  return 0;
1055 }
1056 
1057 static int pcmcia_device_reset(void)
1058 {
1059  USE_DEV9_REGS;
1060  u16 cstc1, cstc2;
1061 
1062  /* The card must be 16-bit (type 2?) */
1063  if ((DEV9_REG(DEV9_R_1462) & 0x03) != 0)
1064  return -1;
1065 
1066  DEV9_REG(DEV9_R_147E) = 1;
1067  if (pcic_power(pcic_voltage, 1) < 0)
1068  return -1;
1069 
1070  DEV9_REG(DEV9_R_POWER) = DEV9_REG(DEV9_R_POWER) | 0x02;
1071  DelayThread(500000);
1072 
1073  DEV9_REG(DEV9_R_POWER) = DEV9_REG(DEV9_R_POWER) | 0x01;
1074  DEV9_REG(DEV9_R_1464) = cstc1 = DEV9_REG(DEV9_R_1464);
1075  DEV9_REG(DEV9_R_1466) = cstc2 = DEV9_REG(DEV9_R_1466);
1076  return 0;
1077 }
1078 
1079 static int card_find_manfid(u32 manfid)
1080 {
1081  USE_DEV9_REGS;
1082  USE_SPD_REGS;
1083  u32 spdaddr, spdend, next, tuple;
1084  u8 hdr, ofs;
1085 
1086  DEV9_REG(DEV9_R_1460) = 2;
1087  _sw(0x1a00bb, SSBUS_R_1418);
1088 
1089  /* Scan the card for the MANFID tuple. */
1090  spdaddr = 0;
1091  spdend = 0x1000;
1092  /* I hate this code, and it hates me. */
1093  while (spdaddr < spdend) {
1094  hdr = SPD_REG8(spdaddr) & 0xff;
1095  spdaddr += 2;
1096  if (!hdr)
1097  continue;
1098  if (hdr == 0xff)
1099  break;
1100  if (spdaddr >= spdend)
1101  goto error;
1102 
1103  ofs = SPD_REG8(spdaddr) & 0xff;
1104  spdaddr += 2;
1105  if (ofs == 0xff)
1106  break;
1107 
1108  next = spdaddr + (ofs * 2);
1109  if (next >= spdend)
1110  goto error;
1111 
1112  if (hdr == 0x20) {
1113  if ((spdaddr + 8) >= spdend)
1114  goto error;
1115 
1116  tuple = (SPD_REG8(spdaddr + 2) << 24) |
1117  (SPD_REG8(spdaddr) << 16) |
1118  (SPD_REG8(spdaddr + 6) << 8) |
1119  SPD_REG8(spdaddr + 4);
1120  if (manfid == tuple)
1121  return 0;
1122  M_PRINTF("MANFID 0x%08lx doesn't match expected 0x%08lx\n",
1123  tuple, manfid);
1124  return -1;
1125  }
1126  spdaddr = next;
1127  }
1128 
1129  M_PRINTF("MANFID 0x%08lx not found.\n", manfid);
1130  return -1;
1131 error:
1132  M_PRINTF("Invalid tuples at offset 0x%08lx.\n", spdaddr - SPD_REGBASE);
1133  return -1;
1134 }
1135 
1136 static int pcmcia_intr(void *unused)
1137 {
1138  USE_AIF_REGS;
1139  USE_DEV9_REGS;
1140  u16 cstc1, cstc2;
1141 
1142  (void)unused;
1143 
1144  cstc1 = DEV9_REG(DEV9_R_1464);
1145  cstc2 = DEV9_REG(DEV9_R_1466);
1146 
1147  if (using_aif) {
1148  if (aif_regs[AIF_INTSR] & AIF_INTR_PCMCIA)
1149  aif_regs[AIF_INTCL] = AIF_INTR_PCMCIA;
1150  else
1151  return 0; /* Unknown interrupt. */
1152  }
1153 
1154  /* Acknowledge the interrupt. */
1155  DEV9_REG(DEV9_R_1464) = cstc1;
1156  DEV9_REG(DEV9_R_1466) = cstc2;
1157  if (cstc1 & 0x03 || cstc2 & 0x03) { /* Card removed or added? */
1158  if (p_dev9_intr_cb)
1159  p_dev9_intr_cb(1);
1160 
1161  /* Shutdown the card. */
1162  DEV9_REG(DEV9_R_POWER) = 0;
1163  DEV9_REG(DEV9_R_1474) = 0;
1164 
1165  pcmcia_device_probe();
1166  }
1167  if (cstc1 & 0x80 || cstc2 & 0x80) {
1168  if (p_dev9_intr_cb)
1169  p_dev9_intr_cb(0);
1170  }
1171 
1172  DEV9_REG(DEV9_R_147E) = 1;
1173  DEV9_REG(DEV9_R_147E) = 0;
1174  return 1;
1175 }
1176 
1177 #ifdef DEV9_ENABLE_AIF
1178 static int aif_pcmcia_intr_handler(void)
1179 {
1180  USE_AIF_REGS;
1181 
1182  aif_regs[AIF_INTCL] = AIF_INTR_PCMCIA;
1183  pcmcia_intr(NULL);
1184 
1185  return 1;
1186 }
1187 
1188 static int aif_intr(void *unused)
1189 {
1190  USE_AIF_REGS;
1191  unsigned int i;
1192 
1193  while ((aif_regs[AIF_INTSR] & aif_regs[AIF_INTEN]) != 0) {
1194  for (i = 0; i < AIF_INUM_COUNT; i++) {
1195  if ((aif_intr_cbs[i] != NULL) && ((aif_regs[AIF_INTSR] & aif_regs[AIF_INTEN]) & (1 << i))) {
1196  aif_intr_cbs[i]();
1197  }
1198  }
1199  }
1200 
1201  return 1;
1202 }
1203 #endif
1204 
1205 
1206 static int pcmcia_init(int sema_attr)
1207 {
1208  USE_DEV9_REGS;
1209  USE_AIF_REGS;
1210  int *mode;
1211  int flags;
1212  u16 cstc1, cstc2;
1213 
1214  _sw(0x51011, SSBUS_R_1420);
1215  _sw(0x1a00bb, SSBUS_R_1418);
1216  _sw(0xef1a3043, SSBUS_R_141c);
1217 
1218  /* If we are a T10K, then we go through AIF. */
1219  if ((mode = QueryBootMode(6)) != NULL) {
1220  if ((*(u16 *)mode & 0xfe) == 0x60) {
1221  M_PRINTF("T10K detected.\n");
1222 
1223  if (aif_regs[AIF_IDENT] == 0xa1) {
1224 #ifdef DEV9_ENABLE_AIF
1225  M_PRINTF("AIF controller revision: %d.\n", aif_regs[AIF_REVISION]);
1226  aif_regs[AIF_INTCL] = 7; // Clear interrupts.
1227 #else
1228  aif_regs[AIF_INTEN] = AIF_INTR_PCMCIA;
1229 #endif
1230  using_aif = 1;
1231  } else {
1232  M_PRINTF("AIF not detected.\n");
1233  return 1;
1234  }
1235  }
1236  }
1237 
1238  if (DEV9_REG(DEV9_R_POWER) == 0) {
1239  DEV9_REG(DEV9_R_POWER) = 0;
1240  DEV9_REG(DEV9_R_147E) = 1;
1241  DEV9_REG(DEV9_R_1460) = 0;
1242  DEV9_REG(DEV9_R_1474) = 0;
1243  DEV9_REG(DEV9_R_1464) = cstc1 = DEV9_REG(DEV9_R_1464);
1244  DEV9_REG(DEV9_R_1466) = cstc2 = DEV9_REG(DEV9_R_1466);
1245  DEV9_REG(DEV9_R_1468) = 0x10;
1246  DEV9_REG(DEV9_R_146A) = 0x90;
1247  DEV9_REG(DEV9_R_147C) = 1;
1248  DEV9_REG(DEV9_R_147A) = DEV9_REG(DEV9_R_147C);
1249 
1250  pcic_voltage = pcic_get_voltage();
1251  pcic_cardtype = pcic_get_cardtype();
1252 
1253  if (speed_device_init() != 0)
1254  return 1;
1255  } else {
1256  _sw(0xe01a3043, SSBUS_R_1418);
1257  }
1258 
1259  if (dev9_init(sema_attr) != 0)
1260  return 1;
1261 
1262  CpuSuspendIntr(&flags);
1263 #ifdef DEV9_ENABLE_AIF
1264  if (using_aif) {
1265  RegisterIntrHandler(IOP_IRQ_DEV9, 1, &aif_intr, NULL);
1266  aifRegisterIntrCb(AIF_INUM_PCMCIA, &aif_pcmcia_intr_handler);
1267  aifIntrEnable(AIF_INTR_PCMCIA);
1268  } else
1269 #endif
1270  {
1271  RegisterIntrHandler(IOP_IRQ_DEV9, 1, &pcmcia_intr, NULL);
1272  }
1273  EnableIntr(IOP_IRQ_DEV9);
1274  CpuResumeIntr(flags);
1275 
1276  DEV9_REG(DEV9_R_147E) = 0;
1277 
1278  if (RegisterLibraryEntries(&_exp_dev9) != 0)
1279  return 1;
1280 
1281  M_PRINTF("CXD9566 (PCMCIA) driver start.\n");
1282  return 0;
1283 }
1284 
1285 static void expbay_set_stat(int stat)
1286 {
1287  USE_DEV9_REGS;
1288  DEV9_REG(DEV9_R_1464) = stat & 0x3f;
1289 }
1290 
1291 static int expbay_device_probe(void)
1292 {
1293  USE_DEV9_REGS;
1294  return (DEV9_REG(DEV9_R_1462) & 0x01) ? -1 : 0;
1295 }
1296 
1297 static int expbay_device_reset(void)
1298 {
1299  USE_DEV9_REGS;
1300 
1301  if (expbay_device_probe() < 0)
1302  return -1;
1303 
1304  DEV9_REG(DEV9_R_POWER) = (DEV9_REG(DEV9_R_POWER) & ~1) | 0x04; // power on
1305  DelayThread(500000);
1306 
1307  DEV9_REG(DEV9_R_1460) = DEV9_REG(DEV9_R_1460) | 0x01;
1308  DEV9_REG(DEV9_R_POWER) = DEV9_REG(DEV9_R_POWER) | 0x01;
1309  DelayThread(500000);
1310  return 0;
1311 }
1312 
1313 static int expbay_intr(void *unused)
1314 {
1315  USE_DEV9_REGS;
1316 
1317  (void)unused;
1318 
1319  if (p_dev9_intr_cb)
1320  p_dev9_intr_cb(0);
1321 
1322  if (!dev9_has_dvr_capability) {
1323  DEV9_REG(DEV9_R_1466) = 1;
1324  }
1325  DEV9_REG(DEV9_R_1466) = 0;
1326  return 1;
1327 }
1328 
1329 static int expbay_init(int sema_attr)
1330 {
1331  USE_DEV9_REGS;
1332  USE_SPD_REGS;
1333  int flags;
1334 
1335  _sw(0x51011, SSBUS_R_1420);
1336  _sw(0xe01a3043, SSBUS_R_1418);
1337  _sw(0xef1a3043, SSBUS_R_141c);
1338 
1339  if ((DEV9_REG(DEV9_R_POWER) & 0x04) == 0) { // if not already powered
1340  DEV9_REG(DEV9_R_1466) = 1;
1341  DEV9_REG(DEV9_R_1464) = 0;
1342  DEV9_REG(DEV9_R_1460) = DEV9_REG(DEV9_R_1464);
1343 
1344  if (speed_device_init() != 0)
1345  return 1;
1346  }
1347 
1348  /* Disable control of LED 2 and PIO 3 if the dev9 device does not have DVR capabilities. */
1349  dev9_has_dvr_capability = (SPD_REG16(SPD_R_REV_3) & SPD_CAPS_DVR) ? 1 : 0;
1350 
1351  if (dev9_init(sema_attr) != 0)
1352  return 1;
1353 
1354  CpuSuspendIntr(&flags);
1355  RegisterIntrHandler(IOP_IRQ_DEV9, 1, &expbay_intr, NULL);
1356  EnableIntr(IOP_IRQ_DEV9);
1357  CpuResumeIntr(flags);
1358 
1359  DEV9_REG(DEV9_R_1466) = 0;
1360 
1361  if (RegisterLibraryEntries(&_exp_dev9) != 0)
1362  return 1;
1363 
1364  M_PRINTF("CXD9611 (SSBUS Buffer) driver start.\n");
1365  return 0;
1366 }
1367 
1368 #ifdef DEV9_ENABLE_AIF
1369 int aifIsDetected(void)
1370 {
1371  return using_aif;
1372 }
1373 
1374 void aifIntrEnable(int mask)
1375 {
1376  USE_AIF_REGS;
1377  int OldState;
1378 
1379  CpuSuspendIntr(&OldState);
1380  aif_regs[AIF_INTEN] |= mask;
1381  CpuResumeIntr(OldState);
1382 }
1383 
1384 void aifIntrDisable(int mask)
1385 {
1386  USE_AIF_REGS;
1387  int OldState;
1388 
1389  CpuSuspendIntr(&OldState);
1390  aif_regs[AIF_INTEN] &= ~mask;
1391  CpuResumeIntr(OldState);
1392 }
1393 
1394 void aifRegisterIntrCb(int intr, aif_intr_cb_t cb)
1395 {
1396  if (intr < AIF_INUM_COUNT) {
1397  aif_intr_cbs[intr] = cb;
1398  }
1399 }
1400 
1401 int aifRegisterShutdownCb(int idx, dev9_shutdown_cb_t cb)
1402 {
1403  if (idx < AIF_INUM_COUNT) {
1404  aif_shutdown_cbs[idx] = cb;
1405  return 0;
1406  }
1407  return -1;
1408 }
1409 
1410 unsigned char aifRTCReadData(unsigned short int address)
1411 {
1412  USE_AIF_REGS;
1413  USE_AIF_RTC_REGS;
1414 
1415  return aif_rtc_regs[address & 0x7F];
1416 }
1417 
1418 void aifRTCWriteData(unsigned char data, unsigned short int address)
1419 {
1420  USE_AIF_REGS;
1421  USE_AIF_RTC_REGS;
1422 
1423  aif_rtc_regs[address & 0x7F] = data;
1424 }
1425 #endif
DMAC_CHCR_DR
#define DMAC_CHCR_DR
Definition: dmacman.h:42
iomanX.h
RegisterIntrHandler
int RegisterIntrHandler(int irq, int mode, int(*handler)(void *arg), void *arg)
Definition: intrman.c:115
dmacman.h
smapregs.h
speedregs.h
aifregs.h
IOP_DT_FSEXT
#define IOP_DT_FSEXT
Definition: iomanX.h:66
thbase.h
iop_sema_t
Definition: thsemap.h:38
sysclib.h
CpuSuspendIntr
int CpuSuspendIntr(int *state)
Definition: intrman.c:195
_iop_dmac_chan
Definition: dmacman.h:26
loadcore.h
SMAP_E3_TX_GNP_0
#define SMAP_E3_TX_GNP_0
Definition: smapregs.h:154
EnableIntr
int EnableIntr(int irq)
Definition: intrman.c:336
thsemap.h
SMAP_E3_TX_LOW_REQ_BITSFT
#define SMAP_E3_TX_LOW_REQ_BITSFT
Definition: smapregs.h:165
irx_export_table
Definition: irx.h:90
DMAC_CHCR_CO
#define DMAC_CHCR_CO
Definition: dmacman.h:39
SMAP_E3_RX_PROP_PF
#define SMAP_E3_RX_PROP_PF
Definition: smapregs.h:179
_iop_file
Definition: ioman.h:53
stdio.h
SMAP_E3_TX_URG_REQ_BITSFT
#define SMAP_E3_TX_URG_REQ_BITSFT
Definition: smapregs.h:169
CpuResumeIntr
int CpuResumeIntr(int state)
Definition: intrman.c:217
_iop_device_ops
Definition: ioman.h:79
SMAP_E3_PHY_OP_COMP
#define SMAP_E3_PHY_OP_COMP
Definition: smapregs.h:256
dev9regs.h
dev9.h
DMAC_CHCR_TR
#define DMAC_CHCR_TR
Definition: dmacman.h:35
defs.h
_iop_device
Definition: ioman.h:64
intrman.h