implemented hook_interrupt() in PCI code

enabled PCI interrupts
ohci seems to damage something in PCI config -> PCI device enumeration 
does not top with latest device
networking in EmuTOS lost (probably a result of PCI interrupt
implementation)
This commit is contained in:
Markus Fröschle
2014-10-05 17:50:15 +00:00
parent 342c3cd34a
commit 4154149154
21 changed files with 1842 additions and 1577 deletions

View File

@@ -3,7 +3,7 @@ define tr
#!killall m68k-bdm-gdbserver #!killall m68k-bdm-gdbserver
target remote | m68k-bdm-gdbserver pipe /dev/bdmcf3 target remote | m68k-bdm-gdbserver pipe /dev/bdmcf3
#target remote localhost:1234 #target remote localhost:1234
#target remote | m68k-bdm-gdbserver pipe /dev/tblcf3 #target remote | m68k-bdm-gdbserver pipe /dev/tblcf1
#target dbug /dev/ttyS0 #target dbug /dev/ttyS0
#monitor bdm-reset #monitor bdm-reset
end end

View File

@@ -39,7 +39,7 @@
#error "unknown machine!" #error "unknown machine!"
#endif /* MACHINE_FIREBEE */ #endif /* MACHINE_FIREBEE */
//#define DBG_DMA #define DBG_DMA
#ifdef DBG_DMA #ifdef DBG_DMA
#define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0) #define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0)
#else #else

View File

@@ -63,4 +63,4 @@ erase 0xe0000000 37
erase 0xe0000000 38 erase 0xe0000000 38
erase 0xe0000000 39 erase 0xe0000000 39
load ../../emutos/emutos-m548x_bas.elf load ../../emutos/emutos-m548x-bas_gcc.elf

View File

@@ -95,14 +95,41 @@
#define FEC1TX_DMA_PRI 4 #define FEC1TX_DMA_PRI 4
#define FECTX_DMA_PRI(x) ((x == 0) ? FEC0TX_DMA_PRI : FEC1TX_DMA_PRI) #define FECTX_DMA_PRI(x) ((x == 0) ? FEC0TX_DMA_PRI : FEC1TX_DMA_PRI)
extern int register_interrupt_handler(uint8_t source, uint8_t level, uint8_t priority, uint8_t intr, void (*handler)(void));
#define ISR_DBUG_ISR 0x01 #define ISR_DBUG_ISR 0x01
#define ISR_USER_ISR 0x02 #define ISR_USER_ISR 0x02
#if defined(MACHINE_FIREBEE)
/* Firebee FPGA interrupt controller */
#define FPGA_INTR_CONTROL ((volatile uint32_t *) 0xf0010000)
#define FPGA_INTR_ENABLE ((volatile uint32_t *) 0xf0010004)
#define FPGA_INTR_CLEAR ((volatile uint32_t *) 0xf0010008)
#define FPGA_INTR_PENDING ((volatile uint32_t *) 0xff01000c)
/* register bits for Firebee FPGA-based interrupt controller */
#define FPGA_INTR_PIC (1)
#define FPGA_INTR_ETHERNET (1 << 1)
#define FPGA_INTR_DVI (1 << 2)
#define FPGA_INTR_PCI_INTA (1 << 3)
#define FPGA_INTR_PCI_INTB (1 << 4)
#define FPGA_INTR_PCI_INTC (1 << 5)
#define FPGA_INTR_PCI_INTD (1 << 6)
#define FPGA_INTR_INT_DSP (1 << 7)
#define FPGA_INTR_INT_VSYNC (1 << 8)
#define FPGA_INTR_INT_HSYNC (1 << 9)
#define FPGA_INTR_INT_HSYNC_IRQ2 (1 << 26)
#define FPGA_INTR_INT_CTR0_IRQ3 (1 << 27)
#define FPGA_INTR_INT_VSYNC_IRQ4 (1 << 28)
#define FPGA_INTR_INT_FPGA_IRQ5 (1 << 29)
#define FPGA_INTR_INT_MFP_IRQ6 (1 << 30)
#define FPGA_INTR_INT_IRQ7 (1 << 31)
#endif /* MACHINE_FIREBEE */
extern void isr_init(void); extern void isr_init(void);
extern int isr_register_handler(int vector, int (*handler)(void *, void *), void *hdev, void *harg); extern int isr_register_handler(int vector, int (*handler)(void *, void *), void *hdev, void *harg);
extern void isr_remove_handler(int (*handler)(void *, void *)); extern void isr_remove_handler(int (*handler)(void *, void *));
extern bool isr_execute_handler(int vector); extern bool isr_execute_handler(int vector);
extern int pic_interrupt_handler(void *arg1, void *arg2); extern int pic_interrupt_handler(void *arg1, void *arg2);
extern int xlbpci_interrupt_handler(void *arg1, void *arg2);
extern int pciarb_interrupt_handler(void *arg1, void *arg2);
#endif /* _INTERRUPTS_H_ */ #endif /* _INTERRUPTS_H_ */

View File

@@ -58,10 +58,10 @@
enum mmu_page_size enum mmu_page_size
{ {
MMU_PAGE_SIZE_1M = 0, MMU_PAGE_SIZE_1M = 0,
MMU_PAGE_SIZE_4K = 1, MMU_PAGE_SIZE_4K = 1,
MMU_PAGE_SIZE_8K = 2, MMU_PAGE_SIZE_8K = 2,
MMU_PAGE_SIZE_1K = 3 MMU_PAGE_SIZE_1K = 3
}; };
#define SIZE_1M 0x100000 /* 1 Megabyte */ #define SIZE_1M 0x100000 /* 1 Megabyte */
@@ -100,7 +100,7 @@ extern long video_sbt;
struct page_descriptor; struct page_descriptor;
extern void mmu_init(void); extern void mmu_init(void);
extern int mmu_map_page(uint32_t virt, uint32_t phys, enum mmu_page_size sz, uint8_t page_id, const struct page_descriptor *flags); extern int mmu_map_page(int32_t virt, int32_t phys, enum mmu_page_size sz, uint8_t page_id, const struct page_descriptor *flags);
/* /*
* API functions for the BaS driver interface * API functions for the BaS driver interface

View File

@@ -6,62 +6,62 @@
* *
* usb-ohci.h * usb-ohci.h
*/ */
#define USB_OHCI_MAX_ROOT_PORTS 4 #define USB_OHCI_MAX_ROOT_PORTS 4
static int cc_to_error[16] = static int cc_to_error[16] =
{ {
/* mapping of the OHCI CC status to error codes */ /* mapping of the OHCI CC status to error codes */
/* No Error */ 0, /* No Error */ 0,
/* CRC Error */ USB_ST_CRC_ERR, /* CRC Error */ USB_ST_CRC_ERR,
/* Bit Stuff */ USB_ST_BIT_ERR, /* Bit Stuff */ USB_ST_BIT_ERR,
/* Data Togg */ USB_ST_CRC_ERR, /* Data Togg */ USB_ST_CRC_ERR,
/* Stall */ USB_ST_STALLED, /* Stall */ USB_ST_STALLED,
/* DevNotResp */ -1, /* DevNotResp */ -1,
/* PIDCheck */ USB_ST_BIT_ERR, /* PIDCheck */ USB_ST_BIT_ERR,
/* UnExpPID */ USB_ST_BIT_ERR, /* UnExpPID */ USB_ST_BIT_ERR,
/* DataOver */ USB_ST_BUF_ERR, /* DataOver */ USB_ST_BUF_ERR,
/* DataUnder */ USB_ST_BUF_ERR, /* DataUnder */ USB_ST_BUF_ERR,
/* reservd */ -1, /* reservd */ -1,
/* reservd */ -1, /* reservd */ -1,
/* BufferOver */ USB_ST_BUF_ERR, /* BufferOver */ USB_ST_BUF_ERR,
/* BuffUnder */ USB_ST_BUF_ERR, /* BuffUnder */ USB_ST_BUF_ERR,
/* Not Access */ -1, /* Not Access */ -1,
/* Not Access */ -1 /* Not Access */ -1
}; };
static const char *cc_to_string[16] = static const char *cc_to_string[16] =
{ {
"No Error", "No Error",
"CRC: Last data packet from endpoint contained a CRC error.", "CRC: Last data packet from endpoint contained a CRC error.",
"BITSTUFFING:\r\nLast data packet from endpoint contained a bit stuffing violation", "BITSTUFFING:\r\nLast data packet from endpoint contained a bit stuffing violation",
"DATATOGGLEMISMATCH:\r\n Last packet from endpoint had data toggle PID\r\n" \ "DATATOGGLEMISMATCH:\r\n Last packet from endpoint had data toggle PID\r\n" \
"that did not match the expected value.", "that did not match the expected value.",
"STALL: TD was moved to the Done Queue because the endpoint returned a STALL PID", "STALL: TD was moved to the Done Queue because the endpoint returned a STALL PID",
"DEVICENOTRESPONDING:\r\nDevice did not respond to token (IN) or did\r\n" \ "DEVICENOTRESPONDING:\r\nDevice did not respond to token (IN) or did\r\n" \
"not provide a handshake (OUT)", "not provide a handshake (OUT)",
"PIDCHECKFAILURE:\r\nCheck bits on PID from endpoint failed on data PID\r\n"\ "PIDCHECKFAILURE:\r\nCheck bits on PID from endpoint failed on data PID\r\n"\
"(IN) or handshake (OUT)", "(IN) or handshake (OUT)",
"UNEXPECTEDPID:\r\nReceive PID was not valid when encountered or PID\r\n" \ "UNEXPECTEDPID:\r\nReceive PID was not valid when encountered or PID\r\n" \
"value is not defined.", "value is not defined.",
"DATAOVERRUN:\r\nThe amount of data returned by the endpoint exceeded\r\n" \ "DATAOVERRUN:\r\nThe amount of data returned by the endpoint exceeded\r\n" \
"either the size of the maximum data packet allowed\r\n" \ "either the size of the maximum data packet allowed\r\n" \
"from the endpoint (found in MaximumPacketSize field\r\n" \ "from the endpoint (found in MaximumPacketSize field\r\n" \
"of ED) or the remaining buffer size.", "of ED) or the remaining buffer size.",
"DATAUNDERRUN:\r\nThe endpoint returned less than MaximumPacketSize\r\n" \ "DATAUNDERRUN:\r\nThe endpoint returned less than MaximumPacketSize\r\n" \
"and that amount was not sufficient to fill the\r\n" \ "and that amount was not sufficient to fill the\r\n" \
"specified buffer", "specified buffer",
"reserved1", "reserved1",
"reserved2", "reserved2",
"BUFFEROVERRUN:\r\nDuring an IN, HC received data from endpoint faster\r\n" \ "BUFFEROVERRUN:\r\nDuring an IN, HC received data from endpoint faster\r\n" \
"than it could be written to system memory", "than it could be written to system memory",
"BUFFERUNDERRUN:\r\nDuring an OUT, HC could not retrieve data from\r\n" \ "BUFFERUNDERRUN:\r\nDuring an OUT, HC could not retrieve data from\r\n" \
"system memory fast enough to keep up with data USB data rate.", "system memory fast enough to keep up with data USB data rate.",
"NOT ACCESSED:\r\nThis code is set by software before the TD is placed\r\n" \ "NOT ACCESSED:\r\nThis code is set by software before the TD is placed\r\n" \
"on a list to be processed by the HC.(1)", "on a list to be processed by the HC.(1)",
"NOT ACCESSED:\r\nThis code is set by software before the TD is placed\r\n" \ "NOT ACCESSED:\r\nThis code is set by software before the TD is placed\r\n" \
"on a list to be processed by the HC.(2)", "on a list to be processed by the HC.(2)",
}; };
/* ED States */ /* ED States */
@@ -75,24 +75,24 @@ static const char *cc_to_string[16] =
/* usb_ohci_ed */ /* usb_ohci_ed */
struct ed struct ed
{ {
uint32_t hwINFO; uint32_t hwINFO;
uint32_t hwTailP; uint32_t hwTailP;
uint32_t hwHeadP; uint32_t hwHeadP;
uint32_t hwNextED; uint32_t hwNextED;
struct ed *ed_prev; struct ed *ed_prev;
uint8_t int_period; uint8_t int_period;
uint8_t int_branch; uint8_t int_branch;
uint8_t int_load; uint8_t int_load;
uint8_t int_interval; uint8_t int_interval;
uint8_t state; uint8_t state;
uint8_t type; uint8_t type;
uint16_t last_iso; uint16_t last_iso;
struct ed *ed_rm_list; struct ed *ed_rm_list;
struct usb_device *usb_dev; struct usb_device *usb_dev;
void *purb; void *purb;
uint32_t unused[2]; uint32_t unused[2];
} __attribute__((aligned(16))); } __attribute__((aligned(16)));
typedef struct ed ed_t; typedef struct ed ed_t;
@@ -137,21 +137,21 @@ typedef struct ed ed_t;
struct td struct td
{ {
uint32_t hwINFO; uint32_t hwINFO;
uint32_t hwCBP; /* Current Buffer Pointer */ uint32_t hwCBP; /* Current Buffer Pointer */
uint32_t hwNextTD; /* Next TD Pointer */ uint32_t hwNextTD; /* Next TD Pointer */
uint32_t hwBE; /* Memory Buffer End Pointer */ uint32_t hwBE; /* Memory Buffer End Pointer */
uint16_t hwPSW[MAXPSW]; uint16_t hwPSW[MAXPSW];
uint8_t unused; uint8_t unused;
uint8_t index; uint8_t index;
struct ed *ed; struct ed *ed;
struct td *next_dl_td; struct td *next_dl_td;
struct usb_device *usb_dev; struct usb_device *usb_dev;
int transfer_len; int transfer_len;
uint32_t data; uint32_t data;
uint32_t unused2[2]; uint32_t unused2[2];
} __attribute__((aligned(32))); } __attribute__((aligned(32)));
typedef struct td td_t; typedef struct td td_t;
@@ -166,16 +166,16 @@ typedef struct td td_t;
#define NUM_INTS 32 /* part of the OHCI standard */ #define NUM_INTS 32 /* part of the OHCI standard */
struct ohci_hcca struct ohci_hcca
{ {
uint32_t int_table[NUM_INTS]; /* Interrupt ED table */ uint32_t int_table[NUM_INTS]; /* Interrupt ED table */
#if defined(CONFIG_MPC5200) #if defined(CONFIG_MPC5200)
uint16_t pad1; /* set to 0 on each frame_no change */ uint16_t pad1; /* set to 0 on each frame_no change */
uint16_t frame_no; /* current frame number */ uint16_t frame_no; /* current frame number */
#else #else
uint16_t frame_no; /* current frame number */ uint16_t frame_no; /* current frame number */
uint16_t pad1; /* set to 0 on each frame_no change */ uint16_t pad1; /* set to 0 on each frame_no change */
#endif #endif
uint32_t done_head; /* info returned for an interrupt */ uint32_t done_head; /* info returned for an interrupt */
uint8_t reserved_for_hc[116]; uint8_t reserved_for_hc[116];
} __attribute__((aligned(256))); } __attribute__((aligned(256)));
/* /*
@@ -185,35 +185,35 @@ struct ohci_hcca
*/ */
struct ohci_regs struct ohci_regs
{ {
/* control and status registers */ /* control and status registers */
uint32_t revision; uint32_t revision;
uint32_t control; uint32_t control;
uint32_t cmdstatus; uint32_t cmdstatus;
uint32_t intrstatus; uint32_t intrstatus;
uint32_t intrenable; uint32_t intrenable;
uint32_t intrdisable; uint32_t intrdisable;
/* memory pointers */ /* memory pointers */
uint32_t hcca; uint32_t hcca;
uint32_t ed_periodcurrent; uint32_t ed_periodcurrent;
uint32_t ed_controlhead; uint32_t ed_controlhead;
uint32_t ed_controlcurrent; uint32_t ed_controlcurrent;
uint32_t ed_bulkhead; uint32_t ed_bulkhead;
uint32_t ed_bulkcurrent; uint32_t ed_bulkcurrent;
uint32_t donehead; uint32_t donehead;
/* frame counters */ /* frame counters */
uint32_t fminterval; uint32_t fminterval;
uint32_t fmremaining; uint32_t fmremaining;
uint32_t fmnumber; uint32_t fmnumber;
uint32_t periodicstart; uint32_t periodicstart;
uint32_t lsthresh; uint32_t lsthresh;
/* Root hub ports */ /* Root hub ports */
struct ohci_roothub_regs struct ohci_roothub_regs
{ {
uint32_t a; uint32_t a;
uint32_t b; uint32_t b;
uint32_t status; uint32_t status;
uint32_t portstatus[USB_OHCI_MAX_ROOT_PORTS]; uint32_t portstatus[USB_OHCI_MAX_ROOT_PORTS];
} roothub; } roothub;
} __attribute__((aligned(32))); } __attribute__((aligned(32)));
/* Some EHCI controls */ /* Some EHCI controls */
@@ -270,11 +270,11 @@ struct ohci_regs
/* Virtual Root HUB */ /* Virtual Root HUB */
struct virt_root_hub struct virt_root_hub
{ {
int devnum; /* Address of Root Hub endpoint */ int devnum; /* Address of Root Hub endpoint */
void *dev; /* was urb */ void *dev; /* was urb */
void *int_addr; void *int_addr;
int send; int send;
int interval; int interval;
}; };
/* USB HUB CONSTANTS (not OHCI-specific; see hub.h) */ /* USB HUB CONSTANTS (not OHCI-specific; see hub.h) */
@@ -372,18 +372,18 @@ struct virt_root_hub
#define N_URB_TD 48 #define N_URB_TD 48
typedef struct typedef struct
{ {
ed_t *ed; ed_t *ed;
uint16_t length; /* number of tds associated with this request */ uint16_t length; /* number of tds associated with this request */
uint16_t td_cnt; /* number of tds already serviced */ uint16_t td_cnt; /* number of tds already serviced */
struct usb_device *dev; struct usb_device *dev;
int state; int state;
uint32_t pipe; uint32_t pipe;
void *transfer_buffer; void *transfer_buffer;
int transfer_buffer_length; int transfer_buffer_length;
int interval; int interval;
int actual_length; int actual_length;
int finished; int finished;
td_t *td[N_URB_TD]; /* list pointer to all corresponding TDs associated with this request */ td_t *td[N_URB_TD]; /* list pointer to all corresponding TDs associated with this request */
} urb_priv_t; } urb_priv_t;
#define URB_DEL 1 #define URB_DEL 1
@@ -391,8 +391,8 @@ typedef struct
struct ohci_device struct ohci_device
{ {
ed_t ed[NUM_EDS]; ed_t ed[NUM_EDS];
int ed_cnt; int ed_cnt;
}; };
/* /*
@@ -404,45 +404,45 @@ struct ohci_device
typedef struct ohci typedef struct ohci
{ {
/* ------- common part -------- */ /* ------- common part -------- */
long handle; /* PCI BIOS */ long handle; /* PCI BIOS */
const struct pci_device_id *ent; const struct pci_device_id *ent;
int usbnum; int usbnum;
/* ---- end of common part ---- */ /* ---- end of common part ---- */
int big_endian; /* PCI BIOS */ int big_endian; /* PCI BIOS */
int controller; int controller;
struct ohci_hcca *hcca_unaligned; struct ohci_hcca *hcca_unaligned;
struct ohci_hcca *hcca; /* hcca */ struct ohci_hcca *hcca; /* hcca */
td_t *td_unaligned; td_t *td_unaligned;
struct ohci_device *ohci_dev_unaligned; struct ohci_device *ohci_dev_unaligned;
/* this allocates EDs for all possible endpoints */ /* this allocates EDs for all possible endpoints */
struct ohci_device *ohci_dev; struct ohci_device *ohci_dev;
int irq_enabled; int irq_enabled;
int stat_irq; int stat_irq;
int irq; int irq;
int disabled; /* e.g. got a UE, we're hung */ int disabled; /* e.g. got a UE, we're hung */
int sleeping; int sleeping;
#define OHCI_FLAGS_NEC 0x80000000 #define OHCI_FLAGS_NEC 0x80000000
uint32_t flags; /* for HC bugs */ uint32_t flags; /* for HC bugs */
uint32_t offset; uint32_t offset;
uint32_t dma_offset; uint32_t dma_offset;
struct ohci_regs *regs; /* OHCI controller's memory */ struct ohci_regs *regs; /* OHCI controller's memory */
int ohci_int_load[32]; /* load of the 32 Interrupt Chains (for load balancing)*/ int ohci_int_load[32]; /* load of the 32 Interrupt Chains (for load balancing)*/
ed_t *ed_rm_list[2]; /* lists of all endpoints to be removed */ ed_t *ed_rm_list[2]; /* lists of all endpoints to be removed */
ed_t *ed_bulktail; /* last endpoint of bulk list */ ed_t *ed_bulktail; /* last endpoint of bulk list */
ed_t *ed_controltail; /* last endpoint of control list */ ed_t *ed_controltail; /* last endpoint of control list */
int intrstatus; int intrstatus;
uint32_t hc_control; /* copy of the hc control reg */ uint32_t hc_control; /* copy of the hc control reg */
uint32_t ndp; /* copy NDP from roothub_a */ uint32_t ndp; /* copy NDP from roothub_a */
struct virt_root_hub rh; struct virt_root_hub rh;
const char *slot_name; const char *slot_name;
/* device which was disconnected */ /* device which was disconnected */
struct usb_device *devgone; struct usb_device *devgone;
} ohci_t; } ohci_t;
/* hcd */ /* hcd */
@@ -458,7 +458,7 @@ static ed_t * ep_add_ed(ohci_t * ohci, struct usb_device * usb_dev, uint32_t pip
static inline void ed_free(struct ed *ed) static inline void ed_free(struct ed *ed)
{ {
ed->usb_dev = NULL; ed->usb_dev = NULL;
} }

View File

@@ -44,13 +44,13 @@
#define PCIHTR 0x0E /* PCI Header Type Register */ #define PCIHTR 0x0E /* PCI Header Type Register */
#define PCIBISTR 0x0F /* PCI Build-In Self Test Register */ #define PCIBISTR 0x0F /* PCI Build-In Self Test Register */
#define PCIBAR0 0x10 /* PCI Base Address Register for Memory #define PCIBAR0 0x10 /* PCI Base Address Register for Memory
Accesses to Local, Runtime, and DMA */ Accesses to Local, Runtime, and DMA */
#define PCIBAR1 0x14 /* PCI Base Address Register for I/O #define PCIBAR1 0x14 /* PCI Base Address Register for I/O
Accesses to Local, Runtime, and DMA */ Accesses to Local, Runtime, and DMA */
#define PCIBAR2 0x18 /* PCI Base Address Register for Memory #define PCIBAR2 0x18 /* PCI Base Address Register for Memory
Accesses to Local Address Space 0 */ Accesses to Local Address Space 0 */
#define PCIBAR3 0x1C /* PCI Base Address Register for Memory #define PCIBAR3 0x1C /* PCI Base Address Register for Memory
Accesses to Local Address Space 1 */ Accesses to Local Address Space 1 */
#define PCIBAR4 0x20 /* PCI Base Address Register, reserved */ #define PCIBAR4 0x20 /* PCI Base Address Register, reserved */
#define PCIBAR5 0x24 /* PCI Base Address Register, reserved */ #define PCIBAR5 0x24 /* PCI Base Address Register, reserved */
#define PCICIS 0x28 /* PCI Cardbus CIS Pointer, not support*/ #define PCICIS 0x28 /* PCI Cardbus CIS Pointer, not support*/
@@ -64,7 +64,7 @@
#define PCIMLR 0x3F /* PCI Max_Lat Register */ #define PCIMLR 0x3F /* PCI Max_Lat Register */
#define PMCAPID 0x40 /* Power Management Capability ID */ #define PMCAPID 0x40 /* Power Management Capability ID */
#define PMNEXT 0x41 /* Power Management Next Capability #define PMNEXT 0x41 /* Power Management Next Capability
Pointer */ Pointer */
#define PMC 0x42 /* Power Management Capabilities */ #define PMC 0x42 /* Power Management Capabilities */
#define PMCSR 0x44 /* Power Management Control/Status */ #define PMCSR 0x44 /* Power Management Control/Status */
#define PMCSR_BSE 0x46 /* PMCSR Bridge Support Extensions */ #define PMCSR_BSE 0x46 /* PMCSR Bridge Support Extensions */
@@ -74,7 +74,7 @@
#define HS_CSR 0x4A /* Hot Swap Control/Status */ #define HS_CSR 0x4A /* Hot Swap Control/Status */
#define PVPDCNTL 0x4C /* PCI Vital Product Data Control */ #define PVPDCNTL 0x4C /* PCI Vital Product Data Control */
#define PVPD_NEXT 0x4D /* PCI Vital Product Data Next #define PVPD_NEXT 0x4D /* PCI Vital Product Data Next
Capability Pointer */ Capability Pointer */
#define PVPDAD 0x4E /* PCI Vital Product Data Address */ #define PVPDAD 0x4E /* PCI Vital Product Data Address */
#define PVPDATA 0x50 /* PCI VPD Data */ #define PVPDATA 0x50 /* PCI VPD Data */
@@ -128,18 +128,18 @@
struct pci_rd /* structure of resource descriptor */ struct pci_rd /* structure of resource descriptor */
{ {
unsigned short next; /* length of the following structure */ unsigned short next; /* length of the following structure */
unsigned short flags; /* type of resource and misc. flags */ unsigned short flags; /* type of resource and misc. flags */
unsigned long start; /* start-address of resource */ unsigned long start; /* start-address of resource */
unsigned long length; /* length of resource */ unsigned long length; /* length of resource */
unsigned long offset; /* offset PCI to phys. CPU Address */ unsigned long offset; /* offset PCI to phys. CPU Address */
unsigned long dmaoffset; /* offset for DMA-transfers */ unsigned long dmaoffset; /* offset for DMA-transfers */
} __attribute__ ((packed)); } __attribute__ ((packed));
typedef struct /* structure of address conversion */ typedef struct /* structure of address conversion */
{ {
unsigned long adr; /* calculated address (CPU<->PCI) */ unsigned long adr; /* calculated address (CPU<->PCI) */
unsigned long len; /* length of memory range */ unsigned long len; /* length of memory range */
} PCI_CONV_ADR; } PCI_CONV_ADR;
/******************************************************************************/ /******************************************************************************/
@@ -227,10 +227,14 @@ typedef struct /* structure of address conversion */
extern void init_eport(void); extern void init_eport(void);
extern void init_xlbus_arbiter(void); extern void init_xlbus_arbiter(void);
extern void init_pci(void); extern void init_pci(void);
extern int pci_handle2index(int32_t handle);
extern int32_t pci_find_device(uint16_t device_id, uint16_t vendor_id, int index); extern int32_t pci_find_device(uint16_t device_id, uint16_t vendor_id, int index);
extern int32_t pci_find_classcode(uint32_t classcode, int index); extern int32_t pci_find_classcode(uint32_t classcode, int index);
extern int32_t pci_get_interrupt_cause(void);
extern int32_t pci_call_interrupt_chain(int32_t handle, int32_t data);
/* /*
* match bits for pci_find_classcode() * match bits for pci_find_classcode()
*/ */
@@ -337,9 +341,9 @@ extern int32_t wrapper_virt_to_phys(uint32_t address, PCI_CONV_ADR *pointer);
extern int32_t wrapper_phys_to_virt(uint32_t address, PCI_CONV_ADR *pointer); extern int32_t wrapper_phys_to_virt(uint32_t address, PCI_CONV_ADR *pointer);
#define PCI_MK_CONF_ADDR(bus, device, function) (MCF_PCI_PCICAR_E | \ #define PCI_MK_CONF_ADDR(bus, device, function) (MCF_PCI_PCICAR_E | \
((bus) << 16) | \ ((bus) << 16) | \
((device << 8) | \ ((device << 8) | \
(function)) (function))
#define PCI_HANDLE(bus, slot, function) (0 | ((bus & 0xff) << 10 | (slot & 0x1f) << 3 | (function & 7))) #define PCI_HANDLE(bus, slot, function) (0 | ((bus & 0xff) << 10 | (slot & 0x1f) << 3 | (function & 7)))
#define PCI_BUS_FROM_HANDLE(h) (((h) & 0xff00) >> 10) #define PCI_BUS_FROM_HANDLE(h) (((h) & 0xff00) >> 10)

View File

@@ -598,8 +598,10 @@
#define PCI_DEVICE_ID_NEC_VL 0x0016 /* PCI-VL Bridge */ #define PCI_DEVICE_ID_NEC_VL 0x0016 /* PCI-VL Bridge */
#define PCI_DEVICE_ID_NEC_STARALPHA2 0x002c /* STAR ALPHA2 */ #define PCI_DEVICE_ID_NEC_STARALPHA2 0x002c /* STAR ALPHA2 */
#define PCI_DEVICE_ID_NEC_CBUS_2 0x002d /* PCI-Cbus Bridge */ #define PCI_DEVICE_ID_NEC_CBUS_2 0x002d /* PCI-Cbus Bridge */
#define PCI_DEVICE_ID_NEC_USB_A 0x0031
#define PCI_DEVICE_ID_NEC_USB 0x0035 /* PCI-USB Host */ #define PCI_DEVICE_ID_NEC_USB 0x0035 /* PCI-USB Host */
#define PCI_DEVICE_ID_NEC_USB_2 0x00e0 /* PCI-USB 2 Host */ #define PCI_DEVICE_ID_NEC_USB_2 0x00e0 /* PCI-USB 2 Host */
#define PCI_DEVICE_ID_NEC_USB_3 0x00f0
#define PCI_DEVICE_ID_NEC_CBUS_3 0x003b #define PCI_DEVICE_ID_NEC_CBUS_3 0x003b
#define PCI_DEVICE_ID_NEC_NAPCCARD 0x003e #define PCI_DEVICE_ID_NEC_NAPCCARD 0x003e
#define PCI_DEVICE_ID_NEC_PCX2 0x0046 /* PowerVR */ #define PCI_DEVICE_ID_NEC_PCX2 0x0046 /* PowerVR */
@@ -798,7 +800,7 @@
#define PCI_VENDOR_ID_ANIGMA 0x1051 #define PCI_VENDOR_ID_ANIGMA 0x1051
#define PCI_DEVICE_ID_ANIGMA_MC145575 0x0100 #define PCI_DEVICE_ID_ANIGMA_MC145575 0x0100
#define PCI_VENDOR_ID_EFAR 0x1055 #define PCI_VENDOR_ID_EFAR 0x1055
#define PCI_DEVICE_ID_EFAR_SLC90E66_1 0x9130 #define PCI_DEVICE_ID_EFAR_SLC90E66_1 0x9130
#define PCI_DEVICE_ID_EFAR_SLC90E66_0 0x9460 #define PCI_DEVICE_ID_EFAR_SLC90E66_0 0x9460
@@ -1507,7 +1509,7 @@
#define PCI_VENDOR_ID_ZIATECH 0x1138 #define PCI_VENDOR_ID_ZIATECH 0x1138
#define PCI_DEVICE_ID_ZIATECH_5550_HC 0x5550 #define PCI_DEVICE_ID_ZIATECH_5550_HC 0x5550
#define PCI_VENDOR_ID_CYCLONE 0x113c #define PCI_VENDOR_ID_CYCLONE 0x113c
#define PCI_DEVICE_ID_CYCLONE_SDK 0x0001 #define PCI_DEVICE_ID_CYCLONE_SDK 0x0001
@@ -1707,8 +1709,8 @@
#define PCI_DEVICE_ID_RP8OCTA 0x0005 #define PCI_DEVICE_ID_RP8OCTA 0x0005
#define PCI_DEVICE_ID_RP8J 0x0006 #define PCI_DEVICE_ID_RP8J 0x0006
#define PCI_DEVICE_ID_RP4J 0x0007 #define PCI_DEVICE_ID_RP4J 0x0007
#define PCI_DEVICE_ID_RP8SNI 0x0008 #define PCI_DEVICE_ID_RP8SNI 0x0008
#define PCI_DEVICE_ID_RP16SNI 0x0009 #define PCI_DEVICE_ID_RP16SNI 0x0009
#define PCI_DEVICE_ID_RPP4 0x000A #define PCI_DEVICE_ID_RPP4 0x000A
#define PCI_DEVICE_ID_RPP8 0x000B #define PCI_DEVICE_ID_RPP8 0x000B
#define PCI_DEVICE_ID_RP8M 0x000C #define PCI_DEVICE_ID_RP8M 0x000C
@@ -1719,9 +1721,9 @@
#define PCI_DEVICE_ID_URP8INTF 0x0802 #define PCI_DEVICE_ID_URP8INTF 0x0802
#define PCI_DEVICE_ID_URP16INTF 0x0803 #define PCI_DEVICE_ID_URP16INTF 0x0803
#define PCI_DEVICE_ID_URP8OCTA 0x0805 #define PCI_DEVICE_ID_URP8OCTA 0x0805
#define PCI_DEVICE_ID_UPCI_RM3_8PORT 0x080C #define PCI_DEVICE_ID_UPCI_RM3_8PORT 0x080C
#define PCI_DEVICE_ID_UPCI_RM3_4PORT 0x080D #define PCI_DEVICE_ID_UPCI_RM3_4PORT 0x080D
#define PCI_DEVICE_ID_CRP16INTF 0x0903 #define PCI_DEVICE_ID_CRP16INTF 0x0903
#define PCI_VENDOR_ID_CYCLADES 0x120e #define PCI_VENDOR_ID_CYCLADES 0x120e
#define PCI_DEVICE_ID_CYCLOM_Y_Lo 0x0100 #define PCI_DEVICE_ID_CYCLOM_Y_Lo 0x0100
@@ -2143,7 +2145,7 @@
#define PCI_DEVICE_ID_RASTEL_2PORT 0x2000 #define PCI_DEVICE_ID_RASTEL_2PORT 0x2000
#define PCI_VENDOR_ID_ZOLTRIX 0x15b0 #define PCI_VENDOR_ID_ZOLTRIX 0x15b0
#define PCI_DEVICE_ID_ZOLTRIX_2BD0 0x2bd0 #define PCI_DEVICE_ID_ZOLTRIX_2BD0 0x2bd0
#define PCI_VENDOR_ID_MELLANOX 0x15b3 #define PCI_VENDOR_ID_MELLANOX 0x15b3
#define PCI_DEVICE_ID_MELLANOX_TAVOR 0x5a44 #define PCI_DEVICE_ID_MELLANOX_TAVOR 0x5a44
@@ -2288,8 +2290,8 @@
#define PCI_DEVICE_ID_INTEL_82092AA_0 0x1221 #define PCI_DEVICE_ID_INTEL_82092AA_0 0x1221
#define PCI_DEVICE_ID_INTEL_82092AA_1 0x1222 #define PCI_DEVICE_ID_INTEL_82092AA_1 0x1222
#define PCI_DEVICE_ID_INTEL_7116 0x1223 #define PCI_DEVICE_ID_INTEL_7116 0x1223
#define PCI_DEVICE_ID_INTEL_7505_0 0x2550 #define PCI_DEVICE_ID_INTEL_7505_0 0x2550
#define PCI_DEVICE_ID_INTEL_7505_1 0x2552 #define PCI_DEVICE_ID_INTEL_7505_1 0x2552
#define PCI_DEVICE_ID_INTEL_7205_0 0x255d #define PCI_DEVICE_ID_INTEL_7205_0 0x255d
#define PCI_DEVICE_ID_INTEL_82596 0x1226 #define PCI_DEVICE_ID_INTEL_82596 0x1226
#define PCI_DEVICE_ID_INTEL_82865 0x1227 #define PCI_DEVICE_ID_INTEL_82865 0x1227

View File

@@ -44,6 +44,8 @@
typedef bool (*checker_func)(void); typedef bool (*checker_func)(void);
extern void wait(uint32_t); extern void wait(uint32_t);
extern void wait_us(uint32_t); /* this is just an alias to the above */
inline static void udelay(long us) inline static void udelay(long us)
{ {
wait((uint32_t) us); wait((uint32_t) us);

File diff suppressed because it is too large Load Diff

View File

@@ -28,6 +28,7 @@
#include "cache.h" #include "cache.h"
#include "usb.h" #include "usb.h"
#include "ehci.h" #include "ehci.h"
#include "pci.h"
#define DBG_EHCI #define DBG_EHCI
#ifdef DBG_EHCI #ifdef DBG_EHCI
@@ -124,6 +125,15 @@ struct pci_device_id ehci_usb_pci_table[] =
0, 0,
0 0
}, /* NEC PCI OHCI module ids */ }, /* NEC PCI OHCI module ids */
{
PCI_VENDOR_ID_NEC,
PCI_DEVICE_ID_NEC_USB_3,
PCI_ANY_ID,
PCI_ANY_ID,
PCI_CLASS_SERIAL_USB_EHCI,
0,
0
},
{ {
PCI_VENDOR_ID_PHILIPS, PCI_VENDOR_ID_PHILIPS,
PCI_DEVICE_ID_PHILIPS_ISP1561_2, PCI_DEVICE_ID_PHILIPS_ISP1561_2,

View File

@@ -43,17 +43,18 @@
*/ */
#include "wait.h" /* for wait routines */ #include "wait.h" /* for wait_ms routines */
#include "bas_printf.h" #include "bas_printf.h"
#include "bas_string.h" /* for memset() */ #include "bas_string.h" /* for memset() */
#include "pci.h" #include "pci.h"
#include "interrupts.h"
#undef OHCI_USE_NPS /* force NoPowerSwitching mode */ #undef OHCI_USE_NPS /* force NoPowerSwitching mode */
#undef OHCI_VERBOSE_DEBUG /* not always helpful */ #undef OHCI_VERBOSE_DEBUG /* not always helpful */
#undef OHCI_FILL_TRACE #undef OHCI_FILL_TRACE
//#define DEBUG_OHCI #define DEBUG_OHCI
#ifdef DEBUG_OHCI #ifdef DEBUG_OHCI
#define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0) #define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0)
#else #else
@@ -126,6 +127,15 @@ struct pci_device_id ohci_usb_pci_table[] =
0, 0,
0 0
}, /* NEC PCI OHCI module ids */ }, /* NEC PCI OHCI module ids */
{
PCI_VENDOR_ID_NEC,
PCI_DEVICE_ID_NEC_USB_A,
PCI_ANY_ID,
PCI_ANY_ID,
PCI_CLASS_SERIAL_USB_OHCI,
0,
0
}, /* NEC PCI OHCI module ids */
{ {
PCI_VENDOR_ID_PHILIPS, PCI_VENDOR_ID_PHILIPS,
PCI_DEVICE_ID_PHILIPS_ISP1561, PCI_DEVICE_ID_PHILIPS_ISP1561,
@@ -148,7 +158,7 @@ struct pci_device_id ohci_usb_pci_table[] =
}; };
/* global ohci_t */ /* global ohci_t */
static ohci_t gohci[2]; static ohci_t gohci[10];
int ohci_inited; int ohci_inited;
static inline uint32_t roothub_a(ohci_t *ohci) { return readl(&ohci->regs->roothub.a); } static inline uint32_t roothub_a(ohci_t *ohci) { return readl(&ohci->regs->roothub.a); }
@@ -157,7 +167,6 @@ static inline uint32_t roothub_status(ohci_t *ohci) { return readl(&ohci->regs->
static inline uint32_t roothub_portstatus(ohci_t *ohci, int i) { return readl(&ohci->regs->roothub.portstatus[i]); } static inline uint32_t roothub_portstatus(ohci_t *ohci, int i) { return readl(&ohci->regs->roothub.portstatus[i]); }
/* forward declaration */ /* forward declaration */
static void flush_data_cache(ohci_t *ohci);
static int hc_interrupt(ohci_t *ohci); static int hc_interrupt(ohci_t *ohci);
static void td_submit_job(ohci_t *ohci, struct usb_device *dev, uint32_t pipe, static void td_submit_job(ohci_t *ohci, struct usb_device *dev, uint32_t pipe,
void *buffer, int transfer_len, struct devrequest *setup, void *buffer, int transfer_len, struct devrequest *setup,
@@ -550,10 +559,13 @@ static int sohci_submit_job(ohci_t *ohci, urb_priv_t *urb, struct devrequest *se
/* link the ed into a chain if is not already */ /* link the ed into a chain if is not already */
if (ed->state != ED_OPER) if (ed->state != ED_OPER)
{
ep_link(ohci, ed); ep_link(ohci, ed);
}
/* fill the TDs and link it to the ed */ /* fill the TDs and link it to the ed */
td_submit_job(ohci, dev, pipe, buffer, transfer_len, setup, purb_priv, interval); td_submit_job(ohci, dev, pipe, buffer, transfer_len, setup, purb_priv, interval);
return 0; return 0;
} }
@@ -571,7 +583,7 @@ static inline int sohci_return_job(ohci_t *ohci, urb_priv_t *urb)
readl(&regs->intrenable); /* PCI posting flush */ readl(&regs->intrenable); /* PCI posting flush */
/* call interrupt device routine */ /* call interrupt device routine */
// dbg("irq_handle device %d", urb->dev->devnum); dbg("irq_handle device %d", urb->dev->devnum);
urb->dev->irq_handle(urb->dev); urb->dev->irq_handle(urb->dev);
writel(OHCI_INTR_WDH, &regs->intrdisable); writel(OHCI_INTR_WDH, &regs->intrdisable);
@@ -1374,7 +1386,7 @@ static int ohci_submit_rh_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pip
#else #else
if (ohci->irq) if (ohci->irq)
{ {
wait(10); wait_ms(10);
} }
#endif #endif
@@ -1462,7 +1474,7 @@ static int ohci_submit_rh_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pip
OK(0); OK(0);
case (RH_PORT_POWER): case (RH_PORT_POWER):
WR_RH_PORTSTAT(RH_PS_PPS); WR_RH_PORTSTAT(RH_PS_PPS);
wait(100); wait_ms(100);
OK(0); OK(0);
case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/ case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/
if (RD_RH_PORTSTAT & RH_PS_CCS) if (RD_RH_PORTSTAT & RH_PS_CCS)
@@ -1562,7 +1574,7 @@ static int ohci_submit_rh_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pip
#else #else
if (ohci->irq) if (ohci->irq)
{ {
wait(10); wait_ms(10);
} }
#endif #endif
@@ -1582,7 +1594,7 @@ static int ohci_submit_rh_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pip
if (ohci->irq) if (ohci->irq)
{ {
wait(10); wait_ms(10);
} }
#endif #endif
@@ -1629,7 +1641,7 @@ static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pipe
#else #else
if (ohci->irq) if (ohci->irq)
{ {
wait(10); wait_ms(10);
} }
#endif #endif
@@ -1646,7 +1658,7 @@ static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pipe
} }
#if 0 #if 0
wait(10); wait_ms(10);
/* ohci_dump_status(ohci); */ /* ohci_dump_status(ohci); */
#endif #endif
@@ -1663,7 +1675,7 @@ static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pipe
timeout = 1000; timeout = 1000;
} }
/* wait for it to complete */ /* wait_ms for it to complete */
while (ohci->irq) while (ohci->irq)
{ {
/* check whether the controller is done */ /* check whether the controller is done */
@@ -1702,13 +1714,13 @@ static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pipe
if (--timeout) if (--timeout)
{ {
wait(10); wait_ms(10);
if (!urb->finished) if (!urb->finished)
xprintf("*"); xprintf("*\r\n");
} }
else else
{ {
err("OHCI usb-%s-%c CTL:TIMEOUT", ohci->slot_name, (char)ohci->controller + '0'); err("OHCI usb-%s-%c CTL:TIMEOUT", ohci->slot_name, (char) ohci->controller + '0');
dbg("submit_common_msg: TO status %x\r\n", stat); dbg("submit_common_msg: TO status %x\r\n", stat);
urb->finished = 1; urb->finished = 1;
stat = USB_ST_CRC_ERR; stat = USB_ST_CRC_ERR;
@@ -1722,7 +1734,7 @@ static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pipe
pkt_print(ohci, urb, dev, pipe, buffer, transfer_len, setup, "RET(ctlr)", usb_pipein(pipe)); pkt_print(ohci, urb, dev, pipe, buffer, transfer_len, setup, "RET(ctlr)", usb_pipein(pipe));
#else #else
if (ohci->irq) if (ohci->irq)
wait(10); wait_ms(10);
#endif #endif
/* free TDs in urb_priv */ /* free TDs in urb_priv */
if (!usb_pipeint(pipe)) if (!usb_pipeint(pipe))
@@ -1749,7 +1761,7 @@ int ohci_submit_control_msg(struct usb_device *dev, uint32_t pipe, void *buffer,
#else #else
if (ohci->irq) if (ohci->irq)
{ {
wait(10); wait_ms(10);
} }
#endif #endif
@@ -1796,7 +1808,7 @@ static int hc_reset(ohci_t *ohci)
* Some multi-function controllers (e.g. ISP1562) allow root hub * Some multi-function controllers (e.g. ISP1562) allow root hub
* resetting via EHCI registers only. * resetting via EHCI registers only.
*/ */
short index = 0; int index = 0;
long handle; long handle;
do do
@@ -1831,7 +1843,7 @@ static int hc_reset(ohci_t *ohci)
err("USB RootHub reset timed out!\r\n"); err("USB RootHub reset timed out!\r\n");
break; break;
} }
wait(1); wait_ms(1);
} }
} }
} }
@@ -1845,6 +1857,7 @@ static int hc_reset(ohci_t *ohci)
} }
while (handle >= 0); while (handle >= 0);
} }
if ((ohci->controller == 0) && (ohci->ent->vendor == PCI_VENDOR_ID_NEC) if ((ohci->controller == 0) && (ohci->ent->vendor == PCI_VENDOR_ID_NEC)
&& (ohci->ent->device == PCI_DEVICE_ID_NEC_USB)) && (ohci->ent->device == PCI_DEVICE_ID_NEC_USB))
{ {
@@ -1853,26 +1866,28 @@ static int hc_reset(ohci_t *ohci)
{ {
dbg("USB OHCI set 48MHz clock\r\n"); dbg("USB OHCI set 48MHz clock\r\n");
pci_write_config_longword(ohci->handle, 0xE4, 0x21); // oscillator & disable ehci pci_write_config_longword(ohci->handle, 0xE4, 0x21); // oscillator & disable ehci
wait(10); wait_us(1);
} }
//else //else
#else #else
{ {
pci_write_config_longword(ohci->handle, 0xE4, pci_read_config_longword(ohci->handle, 0xE4) | 0x01); // disable ehci pci_write_config_longword(ohci->handle, 0xE4, pci_read_config_longword(ohci->handle, 0xE4) | 0x01); // disable ehci
wait(10); wait_us(1);
} }
#endif #endif
} }
dbg("control: %x\r\n", readl(&ohci->regs->control)); dbg("control: %x\r\n", readl(&ohci->regs->control));
if (readl(&ohci->regs->control) & OHCI_CTRL_IR) if (readl(&ohci->regs->control) & OHCI_CTRL_IR)
{ {
/* SMM owns the HC */ /* SMM owns the HC */
writel(OHCI_OCR, &ohci->regs->cmdstatus);/* request ownership */ writel(OHCI_OCR, &ohci->regs->cmdstatus); /* request ownership */
err("USB HC TakeOver from SMM"); err("USB HC TakeOver from SMM");
while (readl(&ohci->regs->control) & OHCI_CTRL_IR) while (readl(&ohci->regs->control) & OHCI_CTRL_IR)
{ {
wait(10); wait_us(10);
if (--smm_timeout == 0) if (--smm_timeout == 0)
{ {
err("USB HC TakeOver failed!"); err("USB HC TakeOver failed!");
@@ -1884,17 +1899,12 @@ static int hc_reset(ohci_t *ohci)
/* Disable HC interrupts */ /* Disable HC interrupts */
writel(OHCI_INTR_MIE, &ohci->regs->intrdisable); writel(OHCI_INTR_MIE, &ohci->regs->intrdisable);
#ifdef DEBUG_OHCI
ohci_dump_status(ohci);
#endif /* DEBUG_OHCI */
dbg("USB OHCI HC reset_hc usb-%s-%c: ctrl = 0x%X\r\n", ohci->slot_name, dbg("USB OHCI HC reset_hc usb-%s-%c: ctrl = 0x%X\r\n", ohci->slot_name,
(char) ohci->controller + '0', readl(&ohci->regs->control)); (char) ohci->controller + '0', readl(&ohci->regs->control));
/* Reset USB (needed by some controllers) */ /* Reset USB (needed by some controllers) */
ohci->hc_control = 0; ohci->hc_control = 0;
writel(ohci->hc_control, &ohci->regs->control); writel(ohci->hc_control, &ohci->regs->control);
wait(50);
/* HC Reset requires max 10 us delay */ /* HC Reset requires max 10 us delay */
writel(OHCI_HCR, &ohci->regs->cmdstatus); writel(OHCI_HCR, &ohci->regs->cmdstatus);
@@ -1908,12 +1918,11 @@ static int hc_reset(ohci_t *ohci)
#endif /* DEBUG_OHCI */ #endif /* DEBUG_OHCI */
return -1; return -1;
} }
wait(10); wait_us(1);
} }
return 0; return 0;
} }
/*-------------------------------------------------------------------------*/
/* /*
* Start an OHCI controller, set the BUS operational * Start an OHCI controller, set the BUS operational
@@ -1935,7 +1944,7 @@ static int hc_start(ohci_t *ohci)
writel(0, &ohci->regs->ed_controlhead); writel(0, &ohci->regs->ed_controlhead);
writel(0, &ohci->regs->ed_bulkhead); writel(0, &ohci->regs->ed_bulkhead);
writel((uint32_t) ohci->hcca - ohci->dma_offset, &ohci->regs->hcca); /* a reset clears this */ writel((uint32_t) ohci->hcca, &ohci->regs->hcca); /* a reset clears this */
fminterval = 0x2edf; fminterval = 0x2edf;
writel((fminterval * 9) / 10, &ohci->regs->periodicstart); writel((fminterval * 9) / 10, &ohci->regs->periodicstart);
@@ -1951,7 +1960,8 @@ static int hc_start(ohci_t *ohci)
/* disable all interrupts */ /* disable all interrupts */
mask = (OHCI_INTR_SO | OHCI_INTR_WDH | OHCI_INTR_SF | OHCI_INTR_RD | mask = (OHCI_INTR_SO | OHCI_INTR_WDH | OHCI_INTR_SF | OHCI_INTR_RD |
OHCI_INTR_UE | OHCI_INTR_FNO | OHCI_INTR_RHSC | OHCI_INTR_OC | OHCI_INTR_MIE); OHCI_INTR_UE | OHCI_INTR_FNO | OHCI_INTR_RHSC |
OHCI_INTR_OC | OHCI_INTR_MIE);
writel(mask, &ohci->regs->intrdisable); writel(mask, &ohci->regs->intrdisable);
/* clear all interrupts */ /* clear all interrupts */
@@ -1970,9 +1980,12 @@ static int hc_start(ohci_t *ohci)
#endif /* OHCI_USE_NPS */ #endif /* OHCI_USE_NPS */
/* POTPGT delay is bits 24-31, in 2 ms units. */ /* POTPGT delay is bits 24-31, in 2 ms units. */
#define mdelay(n) ({unsigned long msec = (n); while (msec--) wait(1); }) #define mdelay(n) ({unsigned long msec = (n); while (msec--) wait_ms(1); })
dbg("wait_ms(0x%x)\r\n", (ohci->ndp >> 23) & 0x1fe);
mdelay((ohci->ndp >> 23) & 0x1fe); mdelay((ohci->ndp >> 23) & 0x1fe);
ohci->ndp &= RH_A_NDP;
// ohci->ndp &= RH_A_NDP;
/* connect the virtual root hub */ /* connect the virtual root hub */
ohci->rh.devnum = 0; ohci->rh.devnum = 0;
@@ -1981,33 +1994,7 @@ static int hc_start(ohci_t *ohci)
} }
#ifdef CONFIG_USB_INTERRUPT_POLLING
/* Poll USB interrupt. */
void ohci_usb_event_poll(int interrupt)
{
if (ohci_inited)
{
int i;
for (i = 0; i < (sizeof(gohci) / sizeof(ohci_t)); i++)
{
ohci_t *ohci = &gohci[i];
if (!ohci->handle || ohci->disabled)
continue;
else
{
flush_data_cache(ohci);
if (interrupt)
ohci->irq = 0;
hc_interrupt(ohci);
if (interrupt)
ohci->irq = -1;
}
}
}
}
#endif /* CONFIG_USB_INTERRUPT_POLLING */
/* /*
* an interrupt happens * an interrupt happens
@@ -2018,6 +2005,7 @@ static int hc_interrupt(ohci_t *ohci)
int ints; int ints;
int stat = -1; int stat = -1;
dbg("\r\n");
if ((ohci->hcca->done_head != 0) && !(swpl(ohci->hcca->done_head) & 0x01)) if ((ohci->hcca->done_head != 0) && !(swpl(ohci->hcca->done_head) & 0x01))
{ {
ints = OHCI_INTR_WDH; ints = OHCI_INTR_WDH;
@@ -2050,18 +2038,6 @@ static int hc_interrupt(ohci_t *ohci)
if (ints & OHCI_INTR_RHSC) /* root hub status change */ if (ints & OHCI_INTR_RHSC) /* root hub status change */
{ {
#ifdef USB_POLL_HUB
if ((queue_poll_hub != NULL) && (rh_check_port_status(ohci) >= 0))
{
if (ohci->irq)
xQueueAltSend(queue_poll_hub, (void *)&ohci->usbnum, 0);
else
{
portBASE_TYPE xNeedSwitch = pdFALSE;
xNeedSwitch = xQueueSendFromISR(queue_poll_hub, &ohci->usbnum, xNeedSwitch);
} /* to fix xNeedSwitch usage */
}
#endif /* USB_POLL_HUB */
stat = 0xff; stat = 0xff;
} }
@@ -2085,7 +2061,7 @@ static int hc_interrupt(ohci_t *ohci)
#else #else
if (ohci->irq) if (ohci->irq)
{ {
wait(1); wait_ms(1);
} }
#endif #endif
/* HC Reset */ /* HC Reset */
@@ -2099,7 +2075,7 @@ static int hc_interrupt(ohci_t *ohci)
{ {
if (ohci->irq) if (ohci->irq)
{ {
wait(1); wait_ms(1);
} }
writel(OHCI_INTR_WDH, &regs->intrdisable); writel(OHCI_INTR_WDH, &regs->intrdisable);
@@ -2122,29 +2098,26 @@ static int hc_interrupt(ohci_t *ohci)
{ {
unsigned int frame = swpw(ohci->hcca->frame_no) & 1; unsigned int frame = swpw(ohci->hcca->frame_no) & 1;
if (ohci->irq) wait_ms(1);
wait(1);
writel(OHCI_INTR_SF, &regs->intrdisable); writel(OHCI_INTR_SF, &regs->intrdisable);
if (ohci->ed_rm_list[frame] != NULL) if (ohci->ed_rm_list[frame] != NULL)
{
writel(OHCI_INTR_SF, &regs->intrenable); writel(OHCI_INTR_SF, &regs->intrenable);
}
stat = 0xff; stat = 0xff;
} }
writel(ints, &regs->intrstatus); writel(ints, &regs->intrstatus);
return stat; return stat;
} }
#ifndef CONFIG_USB_INTERRUPT_POLLING
static int handle_usb_interrupt(ohci_t *ohci) static int handle_usb_interrupt(ohci_t *ohci)
{ {
if (!ohci->irq_enabled) if(!ohci->irq_enabled)
{ {
dbg("no interrupts enabled\r\n");
return 0; return 0;
} }
// flush_data_cache(ohci); no need for that
ohci->irq = 0; ohci->irq = 0;
ohci->stat_irq = hc_interrupt(ohci); ohci->stat_irq = hc_interrupt(ohci);
ohci->irq = -1; ohci->irq = -1;
@@ -2157,11 +2130,14 @@ void ohci_usb_enable_interrupt(int enable)
int i; int i;
dbg("usb_enable_interrupt(%d)", enable); dbg("usb_enable_interrupt(%d)", enable);
for (i = 0; i < (sizeof(gohci) / sizeof(ohci_t)); i++)
for(i = 0; i < (sizeof(gohci) / sizeof(ohci_t)); i++)
{ {
ohci_t *ohci = &gohci[i]; ohci_t *ohci = &gohci[i];
if (!ohci->handle) if(!ohci->handle)
{
continue; continue;
}
ohci->irq_enabled = enable; ohci->irq_enabled = enable;
if (enable) if (enable)
writel(OHCI_INTR_MIE, &ohci->regs->intrenable); writel(OHCI_INTR_MIE, &ohci->regs->intrenable);
@@ -2170,15 +2146,15 @@ void ohci_usb_enable_interrupt(int enable)
} }
} }
#endif /* !CONFIG_USB_INTERRUPT_POLLING */
/* De-allocate all resources.. */ /* De-allocate all resources.. */
static void hc_release_ohci(ohci_t *ohci) static void hc_release_ohci(ohci_t *ohci)
{ {
dbg("USB HC release OHCI usb-%s-%c", ohci->slot_name, (char)ohci->controller + '0'); dbg("USB HC release OHCI usb-%s-%c", ohci->slot_name, (char) ohci->controller + '0');
if (!ohci->disabled) if (!ohci->disabled)
{
hc_reset(ohci); hc_reset(ohci);
}
} }
static void hc_free_buffers(ohci_t *ohci) static void hc_free_buffers(ohci_t *ohci)
@@ -2206,7 +2182,7 @@ static void hc_free_buffers(ohci_t *ohci)
int ohci_usb_lowlevel_init(int32_t handle, const struct pci_device_id *ent, void **priv) int ohci_usb_lowlevel_init(int32_t handle, const struct pci_device_id *ent, void **priv)
{ {
uint32_t usb_base_addr = 0xFFFFFFFF; uint32_t usb_base_addr = 0xFFFFFFFF;
ohci_t *ohci = &gohci[PCI_FUNCTION_FROM_HANDLE(handle) & 1]; ohci_t *ohci = &gohci[pci_handle2index(handle)];
struct pci_rd *pci_rsc_desc = pci_get_resource(handle); /* USB OHCI */ struct pci_rd *pci_rsc_desc = pci_get_resource(handle); /* USB OHCI */
if (handle && (ent != NULL)) if (handle && (ent != NULL))
@@ -2372,9 +2348,11 @@ int ohci_usb_lowlevel_init(int32_t handle, const struct pci_device_id *ent, void
#ifdef DEBUG_OHCI #ifdef DEBUG_OHCI
ohci_dump(ohci, 1); ohci_dump(ohci, 1);
#endif #endif
pci_hook_interrupt(handle, handle_usb_interrupt, ohci); pci_hook_interrupt(handle, (pci_interrupt_handler) handle_usb_interrupt, ohci);
if (priv != NULL) if (priv != NULL)
{
*priv = (void *) ohci; *priv = (void *) ohci;
}
ohci_inited = 1; ohci_inited = 1;

View File

@@ -33,12 +33,13 @@
#include "interrupts.h" #include "interrupts.h"
#include "wait.h" #include "wait.h"
#define DEBUG_PCI //#define DEBUG_PCI
#ifdef DEBUG_PCI #ifdef DEBUG_PCI
#define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0) #define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0)
#else #else
#define dbg(format, arg...) do { ; } while (0) #define dbg(format, arg...) do { ; } while (0)
#endif /* DEBUG_PCI */ #endif /* DEBUG_PCI */
#define err(format, arg...) do { xprintf("ERROR: %s(): " format, __FUNCTION__, ##arg); } while (0)
#define pci_config_wait() do { __asm__ __volatile("tpf" ::: "memory"); } while (0) #define pci_config_wait() do { __asm__ __volatile("tpf" ::: "memory"); } while (0)
@@ -122,36 +123,41 @@ static inline __attribute__((aligned(16))) void chip_errata_135(void)
*/ */
__asm__ __volatile( __asm__ __volatile(
" .extern __MBAR\n\t" " .extern __MBAR \n\t"
" clr.l d0\n\t" " clr.l d0 \n\t"
" move.l d0,__MBAR+0xF0C\n\t" /* Must use direct addressing. write to EPORT module */ " move.l d0,__MBAR+0xF0C \n\t" /* Must use direct addressing. write to EPORT module */
/* xlbus -> slavebus -> eport, writing '0' to register */ /* xlbus -> slavebus -> eport, writing '0' to register */
/* has no effect */ /* has no effect */
" rts\n\t" " rts \n\t"
" tpf.l #0x0\n\t" " tpf.l #0x0 \n\t"
" tpf.l #0x0\n\t" " tpf.l #0x0 \n\t"
" tpf.l #0x0\n\t" " tpf.l #0x0 \n\t"
" tpf.l #0x0\n\t" " tpf.l #0x0 \n\t"
" tpf.l #0x0\n\t" " tpf.l #0x0 \n\t"
::: "memory"); ::: "memory");
} }
static inline void chip_errata_055(int32_t handle)
__attribute__((interrupt)) void pci_arb_interrupt(void)
{ {
dbg("XLBARB slave error interrupt\r\n"); uint32_t dummy;
MCF_XLB_XARB_SR |= ~MCF_XLB_XARB_SR_SEA;
}
__attribute__((interrupt)) void xlb_pci_interrupt(void) return; /* test */
{
dbg("XLBPCI interrupt\r\n");
}
__attribute__((interrupt)) void pci_interrupt(void) /* initiate PCI configuration access to device */
{ MCF_PCI_PCICAR = MCF_PCI_PCICAR_E | /* enable configuration access special cycle */
dbg("PCI interrupt\r\n"); MCF_PCI_PCICAR_BUSNUM(3) | /* note: invalid bus number */
MCF_PCI_PCICAR_DEVNUM(PCI_DEVICE_FROM_HANDLE(handle)) | /* device number, devices 0 - 9 are reserved */
MCF_PCI_PCICAR_FUNCNUM(PCI_FUNCTION_FROM_HANDLE(handle)) | /* function number */
MCF_PCI_PCICAR_DWORD(0);
/* issue a dummy read to an unsupported bus number (will fail) */
dummy = * (volatile uint32_t *) PCI_IO_OFFSET; /* access device */
/* silently clear the PCI errors we produced just now */
MCF_PCI_PCIISR = 0xffffffff; /* clear all errors */
MCF_PCI_PCIGSCR = MCF_PCI_PCIGSCR_PE | MCF_PCI_PCIGSCR_SE;
(void) dummy;
} }
/* /*
@@ -162,14 +168,14 @@ __attribute__((interrupt)) void pci_interrupt(void)
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function" #pragma GCC diagnostic ignored "-Wunused-function"
static int32_t pci_get_interrupt_cause(int32_t *handles) int32_t pci_get_interrupt_cause(void)
{ {
int32_t handle; int32_t handle;
int32_t *hdl = &handles[0];
/* /*
* loop through all PCI devices... * loop through all PCI devices...
*/ */
while ((handle = *handles++) != -1) while ((handle = *hdl++) != -1)
{ {
uint16_t command_register = swpw(pci_read_config_word(handle, PCICR)); uint16_t command_register = swpw(pci_read_config_word(handle, PCICR));
uint16_t status_register = swpw(pci_read_config_word(handle, PCISR)); uint16_t status_register = swpw(pci_read_config_word(handle, PCISR));
@@ -188,7 +194,7 @@ static int32_t pci_get_interrupt_cause(int32_t *handles)
return -1; return -1;
} }
static int32_t pci_call_interrupt_chain(int32_t handle, int32_t data) int32_t pci_call_interrupt_chain(int32_t handle, int32_t data)
{ {
int i; int i;
@@ -205,58 +211,12 @@ static int32_t pci_call_interrupt_chain(int32_t handle, int32_t data)
} }
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
/*
* This gets called from irq5 in exceptions.S
* Once we arrive here, the SR has been set to disable interrupts and the gcc scratch registers have been saved
*/
void irq5_handler(void)
{
int32_t handle;
int32_t value = 0;
int32_t newvalue;
MCF_EPORT_EPFR |= (1 << 5); /* clear interrupt from edge port */
xprintf("IRQ5!\r\n");
if ((handle = pci_get_interrupt_cause(handles)) > 0)
{
newvalue = pci_call_interrupt_chain(handle, value);
if (newvalue == value)
{
dbg("interrupt not handled!\r\n");
}
}
}
#ifdef MACHINE_M5484LITE
/*
* This gets called from irq7 in exceptions.S
* Once we arrive here, the SR has been set to disable interrupts and the gcc scratch registers have been saved
*/
void irq7_handler(void)
{
int32_t handle;
int32_t value = 0;
int32_t newvalue;
MCF_EPORT_EPFR |= (1 << 7);
dbg("IRQ7!\r\n");
if ((handle = pci_get_interrupt_cause(handles)) > 0)
{
newvalue = pci_call_interrupt_chain(handle, value);
if (newvalue == value)
{
dbg("interrupt not handled!\r\n");
}
}
}
#endif /* MACHINE_M548X */
/* /*
* retrieve handle for i'th device * retrieve handle for i'th device
*/ */
static int handle2index(int32_t handle) int pci_handle2index(int32_t handle)
{ {
int i; int i;
@@ -287,6 +247,67 @@ static char *device_class(int classcode)
return "not found"; return "not found";
} }
/*
* do error checking after a PCI transaction
*/
static int pci_check_status(void)
{
uint32_t pcisr;
uint32_t pcigscr;
int ret = 0;
pcisr = MCF_PCI_PCIISR; /* retrieve initiator status register */
if (pcisr & MCF_PCI_PCIISR_RE)
{
dbg("PCI initiator retry error. Cleared.\r\n");
MCF_PCI_PCIISR |= MCF_PCI_PCIISR_RE;
ret = 1;
}
if (pcisr & MCF_PCI_PCIISR_IA)
{
dbg("PCI initiator abort. Error cleared\r\n");
MCF_PCI_PCIISR |= MCF_PCI_PCIISR_IA;
ret = 1;
}
if (pcisr & MCF_PCI_PCIISR_TA)
{
dbg("PCI initiator target abort error. Error cleared\r\n");
MCF_PCI_PCIISR |= MCF_PCI_PCIISR_TA;
ret = 1;
}
pcigscr = MCF_PCI_PCIGSCR;
if (pcigscr & MCF_PCI_PCIGSCR_PE)
{
dbg("PCI parity error. Error cleared\r\n");
MCF_PCI_PCIGSCR |= MCF_PCI_PCIGSCR_PE;
ret = 1;
}
if (pcigscr & MCF_PCI_PCIGSCR_SE)
{
dbg("PCI system error. Error cleared\r\n");
MCF_PCI_PCIGSCR |= MCF_PCI_PCIGSCR_SE;
ret = 1;
}
if (!ret)
{
dbg("no error\r\n");
}
return ret;
}
/* /*
* read an uint32_t from configuration space of card with handle and offset * read an uint32_t from configuration space of card with handle and offset
* *
@@ -297,22 +318,23 @@ uint32_t pci_read_config_longword(int32_t handle, int offset)
uint32_t value; uint32_t value;
/* initiate PCI configuration access to device */ /* initiate PCI configuration access to device */
MCF_PCI_PCICAR = MCF_PCI_PCICAR_E | /* enable configuration access special cycle */ MCF_PCI_PCICAR = MCF_PCI_PCICAR_E | /* enable configuration access special cycle */
MCF_PCI_PCICAR_BUSNUM(PCI_BUS_FROM_HANDLE(handle)) | MCF_PCI_PCICAR_BUSNUM(PCI_BUS_FROM_HANDLE(handle)) |
MCF_PCI_PCICAR_DEVNUM(PCI_DEVICE_FROM_HANDLE(handle)) | /* device number, devices 0 - 9 are reserved */ MCF_PCI_PCICAR_DEVNUM(PCI_DEVICE_FROM_HANDLE(handle)) | /* device number, devices 0 - 9 are reserved */
MCF_PCI_PCICAR_FUNCNUM(PCI_FUNCTION_FROM_HANDLE(handle)) | /* function number */ MCF_PCI_PCICAR_FUNCNUM(PCI_FUNCTION_FROM_HANDLE(handle)) | /* function number */
MCF_PCI_PCICAR_DWORD(offset / 4); MCF_PCI_PCICAR_DWORD(offset / 4);
__asm__ __volatile__("nop" ::: "memory"); /* this is what the Linux BSP does */ NOP();
pci_config_wait();
value = * (volatile uint32_t *) PCI_IO_OFFSET; /* access device */ value = * (volatile uint32_t *) PCI_IO_OFFSET; /* access device */
__asm__ __volatile__("tpf" ::: "memory"); /* this is what the Linux BSP does */ NOP();
/* finish PCI configuration access special cycle (allow regular PCI accesses) */ /* finish PCI configuration access special cycle (allow regular PCI accesses) */
MCF_PCI_PCICAR &= ~MCF_PCI_PCICAR_E; MCF_PCI_PCICAR &= ~MCF_PCI_PCICAR_E;
pci_check_status();
return value; return value;
} }
@@ -329,15 +351,17 @@ uint16_t pci_read_config_word(int32_t handle, int offset)
MCF_PCI_PCICAR_FUNCNUM(PCI_FUNCTION_FROM_HANDLE(handle)) | MCF_PCI_PCICAR_FUNCNUM(PCI_FUNCTION_FROM_HANDLE(handle)) |
MCF_PCI_PCICAR_DWORD(offset / 4); MCF_PCI_PCICAR_DWORD(offset / 4);
__asm__ __volatile("nop" ::: "memory"); /* this is what Linux BSP does */ NOP();
value = * (volatile uint16_t *) PCI_IO_OFFSET + (offset & 2); value = * (volatile uint16_t *) PCI_IO_OFFSET + (offset & 2);
__asm__ __volatile("tpf" ::: "memory"); NOP();
/* finish PCI configuration access special cycle */ /* finish PCI configuration access special cycle */
MCF_PCI_PCICAR &= ~MCF_PCI_PCICAR_E; MCF_PCI_PCICAR &= ~MCF_PCI_PCICAR_E;
pci_check_status();
return value; return value;
} }
@@ -352,14 +376,16 @@ uint8_t pci_read_config_byte(int32_t handle, int offset)
MCF_PCI_PCICAR_FUNCNUM(PCI_FUNCTION_FROM_HANDLE(handle)) | /* function number */ MCF_PCI_PCICAR_FUNCNUM(PCI_FUNCTION_FROM_HANDLE(handle)) | /* function number */
MCF_PCI_PCICAR_DWORD(offset / 4); MCF_PCI_PCICAR_DWORD(offset / 4);
__asm__ __volatile__("nop" ::: "memory"); NOP();
value = * (volatile uint8_t *) (PCI_IO_OFFSET + (offset & 3)); value = * (volatile uint8_t *) (PCI_IO_OFFSET + (offset & 3));
__asm__ __volatile__("tpf" ::: "memory"); NOP();
MCF_PCI_PCICAR &= ~MCF_PCI_PCICAR_E; MCF_PCI_PCICAR &= ~MCF_PCI_PCICAR_E;
pci_check_status();
return value; return value;
} }
@@ -376,18 +402,18 @@ int32_t pci_write_config_longword(int32_t handle, int offset, uint32_t value)
MCF_PCI_PCICAR_DEVNUM(PCI_DEVICE_FROM_HANDLE(handle)) | /* device number, devices 0 - 9 are reserved */ MCF_PCI_PCICAR_DEVNUM(PCI_DEVICE_FROM_HANDLE(handle)) | /* device number, devices 0 - 9 are reserved */
MCF_PCI_PCICAR_FUNCNUM(PCI_FUNCTION_FROM_HANDLE(handle)) | /* function number */ MCF_PCI_PCICAR_FUNCNUM(PCI_FUNCTION_FROM_HANDLE(handle)) | /* function number */
MCF_PCI_PCICAR_DWORD(offset / 4); MCF_PCI_PCICAR_DWORD(offset / 4);
chip_errata_135();
__asm__ __volatile__("nop" ::: "memory"); NOP();
* (volatile uint32_t *) PCI_IO_OFFSET = value; /* access device */ * (volatile uint32_t *) PCI_IO_OFFSET = value; /* access device */
chip_errata_135(); chip_errata_135();
__asm__ __volatile__("tpf" ::: "memory"); NOP();
/* finish configuration space access cycle */ /* finish configuration space access cycle */
MCF_PCI_PCICAR &= ~MCF_PCI_PCICAR_E; MCF_PCI_PCICAR &= ~MCF_PCI_PCICAR_E;
chip_errata_135();
pci_check_status();
return PCI_SUCCESSFUL; return PCI_SUCCESSFUL;
} }
@@ -405,16 +431,15 @@ int32_t pci_write_config_word(int32_t handle, int offset, uint16_t value)
MCF_PCI_PCICAR_DWORD(offset / 4); MCF_PCI_PCICAR_DWORD(offset / 4);
chip_errata_135(); chip_errata_135();
__asm__ __volatile__("tpf" ::: "memory"); NOP();
* (volatile uint16_t *) (PCI_IO_OFFSET + (offset & 2)) = value; * (volatile uint16_t *) (PCI_IO_OFFSET + (offset & 2)) = value;
chip_errata_135(); chip_errata_135();
__asm__ __volatile__("tpf" ::: "memory");
/* finish configuration space access cycle */ /* finish configuration space access cycle */
MCF_PCI_PCICAR &= ~MCF_PCI_PCICAR_E; MCF_PCI_PCICAR &= ~MCF_PCI_PCICAR_E;
chip_errata_135();
pci_check_status();
return PCI_SUCCESSFUL; return PCI_SUCCESSFUL;
} }
@@ -431,7 +456,7 @@ int32_t pci_write_config_byte(int32_t handle, int offset, uint8_t value)
MCF_PCI_PCICAR_DWORD(offset / 4); MCF_PCI_PCICAR_DWORD(offset / 4);
chip_errata_135(); chip_errata_135();
__asm__ __volatile__("tpf" ::: "memory"); NOP();
* (volatile uint8_t *) (PCI_IO_OFFSET + (offset & 3)) = value; * (volatile uint8_t *) (PCI_IO_OFFSET + (offset & 3)) = value;
chip_errata_135(); chip_errata_135();
@@ -441,7 +466,7 @@ int32_t pci_write_config_byte(int32_t handle, int offset, uint8_t value)
/* finish configuration space access cycle */ /* finish configuration space access cycle */
MCF_PCI_PCICAR &= ~MCF_PCI_PCICAR_E; MCF_PCI_PCICAR &= ~MCF_PCI_PCICAR_E;
chip_errata_135(); pci_check_status();
return PCI_SUCCESSFUL; return PCI_SUCCESSFUL;
} }
@@ -455,11 +480,15 @@ struct pci_rd *pci_get_resource(int32_t handle)
int index = -1; int index = -1;
struct pci_rd *ret; struct pci_rd *ret;
index = handle2index(handle); index = pci_handle2index(handle);
if (index == -1) if (index == -1)
{
ret = NULL; ret = NULL;
}
else else
{
ret = &resource_descriptors[index][0]; ret = &resource_descriptors[index][0];
}
dbg("pci_get_resource: resource struct for handle %lx (index %d) is at %p\r\n", handle, index, ret); dbg("pci_get_resource: resource struct for handle %lx (index %d) is at %p\r\n", handle, index, ret);
@@ -840,7 +869,7 @@ static void pci_device_config(uint16_t bus, uint16_t device, uint16_t function)
handle = PCI_HANDLE(bus, device, function); handle = PCI_HANDLE(bus, device, function);
/* find index into resource descriptor table for handle */ /* find index into resource descriptor table for handle */
index = handle2index(handle); index = pci_handle2index(handle);
if (index == -1) if (index == -1)
{ {
@@ -992,9 +1021,11 @@ static void pci_device_config(uint16_t bus, uint16_t device, uint16_t function)
il = pci_read_config_byte(handle, PCIIPR); il = pci_read_config_byte(handle, PCIIPR);
dbg("device requests interrupts on interrupt pin %d\r\n", il); dbg("device requests interrupts on interrupt pin %d\r\n", il);
/* if so, register interrupts */ /* enable interrupt on PCI device */
/* TODO: register interrupts here */ il = pci_read_config_byte(handle, PCICR);
il &= ~PCICSR_INT_DISABLE;
pci_write_config_byte(handle, PCICR, il);
/* /*
* enable device memory or I/O access * enable device memory or I/O access
@@ -1133,18 +1164,13 @@ void init_pci(void)
xprintf("initializing PCI bridge:\r\n"); xprintf("initializing PCI bridge:\r\n");
(void) res; /* for now */ (void) res; /* for now */
res = register_interrupt_handler(0, INT_SOURCE_PCIARB, 5, 5, pci_arb_interrupt);
dbg("registered interrupt handler for PCI arbiter: %s\r\n",
(res < 0 ? "failed" : "succeeded"));
register_interrupt_handler(0, INT_SOURCE_XLBPCI, 5, 5, xlb_pci_interrupt);
dbg("registered interrupt handler for XLB PCI: %s\r\n",
(res < 0 ? "failed" : "succeeded"));
init_eport(); init_eport();
init_xlbus_arbiter(); init_xlbus_arbiter();
MCF_PCI_PCIGSCR = 1; /* reset PCI */ MCF_PCI_PCIGSCR = 1; /* reset PCI */
#ifdef _NOT_USED_
/* /*
* setup the PCI arbiter * setup the PCI arbiter
*/ */
@@ -1152,6 +1178,7 @@ void init_pci(void)
| MCF_PCIARB_PACR_EXTMPRI(0xf) /* external master priority: high */ | MCF_PCIARB_PACR_EXTMPRI(0xf) /* external master priority: high */
| MCF_PCIARB_PACR_INTMINTEN /* enable "internal master broken" interrupt */ | MCF_PCIARB_PACR_INTMINTEN /* enable "internal master broken" interrupt */
| MCF_PCIARB_PACR_EXTMINTEN(0x0f); /* enable "external master broken" interrupt */ | MCF_PCIARB_PACR_EXTMINTEN(0x0f); /* enable "external master broken" interrupt */
#endif
#ifdef _NOT_USED_ /* since this is already done in sysinit.c */ #ifdef _NOT_USED_ /* since this is already done in sysinit.c */
#if MACHINE_FIREBEE #if MACHINE_FIREBEE
@@ -1173,18 +1200,18 @@ void init_pci(void)
/* Setup burst parameters */ /* Setup burst parameters */
MCF_PCI_PCICR1 = MCF_PCI_PCICR1_CACHELINESIZE(8) | MCF_PCI_PCICR1 = MCF_PCI_PCICR1_CACHELINESIZE(8) |
MCF_PCI_PCICR1_LATTIMER(0xff); /* TODO: test increased latency timer */ MCF_PCI_PCICR1_LATTIMER(0xff); /* TODO: test increased latency timer */
#ifdef _NOT_USED_
MCF_PCI_PCICR2 = MCF_PCI_PCICR2_MINGNT(1) | MCF_PCI_PCICR2 = MCF_PCI_PCICR2_MINGNT(1) |
MCF_PCI_PCICR2_MAXLAT(32); MCF_PCI_PCICR2_MAXLAT(32);
#endif /* _NOT_USED_ */
MCF_PCI_PCICR2 = 0; /* this is what Linux does */ // MCF_PCI_PCICR2 = 0; /* this is what Linux does */
/* error signaling */ /* error signaling */
#ifdef NOT_USED
MCF_PCI_PCIICR = MCF_PCI_PCIICR_TAE | /* target abort enable */ MCF_PCI_PCIICR = MCF_PCI_PCIICR_TAE | /* target abort enable */
MCF_PCI_PCIICR_IAE; /* initiator abort enable */ MCF_PCI_PCIICR_IAE; /* initiator abort enable */
#endif /* NOT_USED */
MCF_PCI_PCIICR = 0; /* this is what Linux does */ // MCF_PCI_PCIICR = 0; /* this is what Linux does */
MCF_PCI_PCIGSCR |= MCF_PCI_PCIGSCR_SEE; /* system error interrupt enable */ MCF_PCI_PCIGSCR |= MCF_PCI_PCIGSCR_SEE; /* system error interrupt enable */
@@ -1194,20 +1221,21 @@ void init_pci(void)
MCF_PCI_PCIIW0BTAR = (PCI_MEMORY_OFFSET | (((PCI_MEMORY_SIZE - 1) >> 8) & 0xffff0000)) MCF_PCI_PCIIW0BTAR = (PCI_MEMORY_OFFSET | (((PCI_MEMORY_SIZE - 1) >> 8) & 0xffff0000))
| ((PCI_MEMORY_OFFSET >> 16) & 0xff00); | ((PCI_MEMORY_OFFSET >> 16) & 0xff00);
NOP();
dbg("PCIIW0BTAR=0x%08x\r\n", MCF_PCI_PCIIW0BTAR); dbg("PCIIW0BTAR=0x%08x\r\n", MCF_PCI_PCIIW0BTAR);
/* initiator window 1 base / translation adress register */ /* initiator window 1 base / translation adress register */
MCF_PCI_PCIIW1BTAR = (PCI_IO_OFFSET | ((PCI_IO_SIZE - 1) >> 8)) & 0xffff0000; MCF_PCI_PCIIW1BTAR = (PCI_IO_OFFSET | ((PCI_IO_SIZE - 1) >> 8)) & 0xffff0000;
NOP();
/* initiator window 2 base / translation address register */ /* initiator window 2 base / translation address register */
MCF_PCI_PCIIW2BTAR = 0L; /* not used */ MCF_PCI_PCIIW2BTAR = 0L; /* not used */
NOP();
/* initiator window configuration register */ /* initiator window configuration register */
MCF_PCI_PCIIWCR = MCF_PCI_PCIIWCR_WINCTRL0_MEMRDLINE | MCF_PCI_PCIIWCR = MCF_PCI_PCIIWCR_WINCTRL0_MEMRDLINE |
MCF_PCI_PCIIWCR_WINCTRL1_IO | MCF_PCI_PCIIWCR_WINCTRL1_IO |
MCF_PCI_PCIIWCR_WINCTRL0_E | MCF_PCI_PCIIWCR_WINCTRL0_E |
MCF_PCI_PCIIWCR_WINCTRL1_E; MCF_PCI_PCIIWCR_WINCTRL1_E;
NOP();
/* /*
* Initialize target control register. * Initialize target control register.
* Used when an external bus master accesses the Coldfire PCI as target * Used when an external bus master accesses the Coldfire PCI as target
@@ -1219,7 +1247,7 @@ void init_pci(void)
/* reset PCI devices */ /* reset PCI devices */
MCF_PCI_PCIGSCR &= ~MCF_PCI_PCIGSCR_PR; MCF_PCI_PCIGSCR &= ~MCF_PCI_PCIGSCR_PR;
do {;} while (MCF_PCI_PCIGSCR & MCF_PCI_PCIGSCR_PR); /* wait until reset finished */ do { NOP(); } while (MCF_PCI_PCIGSCR & MCF_PCI_PCIGSCR_PR); /* wait until reset finished */
xprintf("finished\r\n"); xprintf("finished\r\n");
/* initialize/clear resource descriptor table */ /* initialize/clear resource descriptor table */
@@ -1235,7 +1263,7 @@ void init_pci(void)
* give devices a chance to come up befor attempting to configure them, * give devices a chance to come up befor attempting to configure them,
* necessary to properly detect the FireBee USB chip * necessary to properly detect the FireBee USB chip
*/ */
wait(600000); wait_ms(400);
/* /*
* do normal initialization * do normal initialization

View File

@@ -48,6 +48,8 @@
#include "interrupts.h" #include "interrupts.h"
#include "exceptions.h" #include "exceptions.h"
#include "net_timer.h" #include "net_timer.h"
#include "pci.h"
#include "video.h"
//#define BAS_DEBUG //#define BAS_DEBUG
#if defined(BAS_DEBUG) #if defined(BAS_DEBUG)
@@ -76,10 +78,10 @@ extern uint8_t _EMUTOS_SIZE[];
*/ */
static inline bool pic_txready(void) static inline bool pic_txready(void)
{ {
if (MCF_PSC3_PSCSR & MCF_PSC_PSCSR_TXRDY) if (MCF_PSC3_PSCSR & MCF_PSC_PSCSR_TXRDY)
return true; return true;
return false; return false;
} }
/* /*
@@ -87,84 +89,84 @@ static inline bool pic_txready(void)
*/ */
static inline bool pic_rxready(void) static inline bool pic_rxready(void)
{ {
if (MCF_PSC3_PSCSR & MCF_PSC_PSCSR_RXRDY) if (MCF_PSC3_PSCSR & MCF_PSC_PSCSR_RXRDY)
return true; return true;
return false; return false;
} }
void write_pic_byte(uint8_t value) void write_pic_byte(uint8_t value)
{ {
/* Wait until the transmitter is ready or 1000us are passed */ /* Wait until the transmitter is ready or 1000us are passed */
waitfor(1000, pic_txready); waitfor(1000, pic_txready);
/* Transmit the byte */ /* Transmit the byte */
*(volatile uint8_t*)(&MCF_PSC3_PSCTB_8BIT) = value; // Really 8-bit *(volatile uint8_t*)(&MCF_PSC3_PSCTB_8BIT) = value; // Really 8-bit
} }
uint8_t read_pic_byte(void) uint8_t read_pic_byte(void)
{ {
/* Wait until a byte has been received or 1000us are passed */ /* Wait until a byte has been received or 1000us are passed */
waitfor(1000, pic_rxready); waitfor(1000, pic_rxready);
/* Return the received byte */ /* Return the received byte */
return * (volatile uint8_t *) (&MCF_PSC3_PSCTB_8BIT); // Really 8-bit return * (volatile uint8_t *) (&MCF_PSC3_PSCTB_8BIT); // Really 8-bit
} }
void pic_init(void) void pic_init(void)
{ {
char answer[4] = "OLD"; char answer[4] = "OLD";
xprintf("initialize the PIC: "); xprintf("initialize the PIC: ");
/* Send the PIC initialization string */ /* Send the PIC initialization string */
write_pic_byte('A'); write_pic_byte('A');
write_pic_byte('C'); write_pic_byte('C');
write_pic_byte('P'); write_pic_byte('P');
write_pic_byte('F'); write_pic_byte('F');
/* Read the 3-char answer string. Should be "OK!". */ /* Read the 3-char answer string. Should be "OK!". */
answer[0] = read_pic_byte(); answer[0] = read_pic_byte();
answer[1] = read_pic_byte(); answer[1] = read_pic_byte();
answer[2] = read_pic_byte(); answer[2] = read_pic_byte();
answer[3] = '\0'; answer[3] = '\0';
if (answer[0] != 'O' || answer[1] != 'K' || answer[2] != '!') if (answer[0] != 'O' || answer[1] != 'K' || answer[2] != '!')
{ {
dbg("PIC initialization failed. Already initialized?\r\n"); dbg("PIC initialization failed. Already initialized?\r\n");
} }
else else
{ {
xprintf("%s\r\n", answer); xprintf("%s\r\n", answer);
} }
} }
void nvram_init(void) void nvram_init(void)
{ {
int i; int i;
xprintf("Restore the NVRAM data: "); xprintf("Restore the NVRAM data: ");
/* Request for NVRAM backup data */ /* Request for NVRAM backup data */
write_pic_byte(0x01); write_pic_byte(0x01);
/* Check answer type */ /* Check answer type */
if (read_pic_byte() != 0x81) if (read_pic_byte() != 0x81)
{ {
// FIXME: PIC protocol error // FIXME: PIC protocol error
xprintf("FAILED\r\n"); xprintf("FAILED\r\n");
return; return;
} }
/* Restore the NVRAM backup to the FPGA */ /* Restore the NVRAM backup to the FPGA */
for (i = 0; i < 64; i++) for (i = 0; i < 64; i++)
{ {
uint8_t data = read_pic_byte(); uint8_t data = read_pic_byte();
*(volatile uint8_t*)0xffff8961 = i; *(volatile uint8_t*)0xffff8961 = i;
*(volatile uint8_t*)0xffff8963 = data; *(volatile uint8_t*)0xffff8963 = data;
} }
xprintf("finished\r\n"); xprintf("finished\r\n");
} }
#define KBD_ACIA_CONTROL ((uint8_t *) 0xfffffc00) #define KBD_ACIA_CONTROL ((uint8_t *) 0xfffffc00)
@@ -174,70 +176,77 @@ void nvram_init(void)
void acia_init() void acia_init()
{ {
xprintf("init ACIA: "); xprintf("init ACIA: ");
/* init ACIA */ /* init ACIA */
* KBD_ACIA_CONTROL = 3; /* master reset */ * KBD_ACIA_CONTROL = 3; /* master reset */
NOP(); NOP();
* MIDI_ACIA_CONTROL = 3; /* master reset */ * MIDI_ACIA_CONTROL = 3; /* master reset */
NOP(); NOP();
* KBD_ACIA_CONTROL = 0x96; /* clock div = 64, 8N1, RTS low, TX int disable, RX int enable */ * KBD_ACIA_CONTROL = 0x96; /* clock div = 64, 8N1, RTS low, TX int disable, RX int enable */
NOP(); NOP();
* MFP_INTR_IN_SERVICE_A = -1; * MFP_INTR_IN_SERVICE_A = -1;
NOP(); NOP();
* MFP_INTR_IN_SERVICE_B = -1; * MFP_INTR_IN_SERVICE_B = -1;
NOP(); NOP();
xprintf("finished\r\n"); xprintf("finished\r\n");
} }
/* ACP interrupt controller */
#define FPGA_INTR_CONTRL (volatile uint32_t *) 0xf0010000
#define FPGA_INTR_ENABLE (volatile uint8_t *) 0xf0010004
#define FPGA_INTR_PENDIN (volatile uint32_t *) 0xf0010008
void enable_coldfire_interrupts() void enable_coldfire_interrupts()
{ {
xprintf("enable interrupts: "); xprintf("enable interrupts: ");
#if defined(MACHINE_FIREBEE) #if defined(MACHINE_FIREBEE)
*FPGA_INTR_CONTRL = 0L; /* disable all interrupts */ *FPGA_INTR_CONTROL = 0L; /* disable all interrupts */
#endif /* MACHINE_FIREBEE */ #endif /* MACHINE_FIREBEE */
MCF_EPORT_EPPAR = 0xaaa8; /* all interrupts on falling edge */
MCF_EPORT_EPPAR = 0xaaa8; /* all interrupts on falling edge */
#if defined(MACHINE_FIREBEE) #if defined(MACHINE_FIREBEE)
/* /*
* TIN0 on the Coldfire is connected to the FPGA. TIN0 triggers every write * TIN0 on the Coldfire is connected to the FPGA. TIN0 triggers every write
* access to 0xff8201 (vbasehi), i.e. everytime the video base address is written * access to 0xff8201 (vbasehi), i.e. everytime the video base address is written
*/ */
MCF_GPT0_GMS = MCF_GPT_GMS_ICT(1) | /* timer 0 on, video change capture on rising edge */ MCF_GPT0_GMS = MCF_GPT_GMS_ICT(1) | /* timer 0 on, video change capture on rising edge */
MCF_GPT_GMS_IEN | MCF_GPT_GMS_IEN |
MCF_GPT_GMS_TMS(1); MCF_GPT_GMS_TMS(1);
/* route GPT0 interrupt on interrupt controller */ /* route GPT0 interrupt on interrupt controller */
MCF_INTC_ICR62 = 0x3f; /* interrupt level 7, interrupt priority 7 */ MCF_INTC_ICR62 = 0x3f; /* interrupt level 7, interrupt priority 7 */
*FPGA_INTR_ENABLE = 0xfe; /* enable int 1-7 */
MCF_EPORT_EPIER = 0xfe; /* int 1-7 on */ MCF_EPORT_EPIER = 0xfe; /* int 1-7 on */
MCF_EPORT_EPFR = 0xff; /* clear all pending interrupts */ MCF_EPORT_EPFR = 0xff; /* clear all pending interrupts */
MCF_INTC_IMRL = 0xffffff00; /* int 1-7 on */ MCF_INTC_IMRL = 0xffffff00; /* int 1-7 on */
MCF_INTC_IMRH = 0xbffffffe; /* psc3 and timer 0 int on */ MCF_INTC_IMRH = 0xbffffffe; /* psc3 and timer 0 int on */
*FPGA_INTR_ENABLE = FPGA_INTR_INT_IRQ7 |
FPGA_INTR_INT_MFP_IRQ6 |
FPGA_INTR_INT_FPGA_IRQ5 |
FPGA_INTR_INT_VSYNC_IRQ4 |
FPGA_INTR_INT_CTR0_IRQ3 |
FPGA_INTR_INT_HSYNC_IRQ2 |
FPGA_INTR_PCI_INTA |
FPGA_INTR_PCI_INTB |
FPGA_INTR_PCI_INTC |
FPGA_INTR_PCI_INTD |
FPGA_INTR_ETHERNET;
#endif #endif
xprintf("finished\r\n"); xprintf("finished\r\n");
} }
void disable_coldfire_interrupts() void disable_coldfire_interrupts()
{ {
#if defined(MACHINE_FIREBEE) #if defined(MACHINE_FIREBEE)
*FPGA_INTR_ENABLE = 0; /* disable all interrupts */ *FPGA_INTR_ENABLE = 0; /* disable all interrupts */
#endif /* MACHINE_FIREBEE */ #endif /* MACHINE_FIREBEE */
MCF_EPORT_EPIER = 0x0; MCF_EPORT_EPIER = 0x0;
MCF_EPORT_EPFR = 0x0; MCF_EPORT_EPFR = 0x0;
MCF_INTC_IMRL = 0xfffffffe; MCF_INTC_IMRL = 0xfffffffe;
MCF_INTC_IMRH = 0xffffffff; MCF_INTC_IMRH = 0xffffffff;
} }
@@ -252,178 +261,175 @@ NIF nif2;
*/ */
void init_isr(void) void init_isr(void)
{ {
isr_init(); /* need to call that explicitely, otherwise isr table might be full */ isr_init(); /* need to call that explicitely, otherwise isr table might be full */
/* /*
* register the FEC interrupt handler * register the FEC interrupt handler
*/ */
if (!isr_register_handler(64 + INT_SOURCE_FEC0, fec0_interrupt_handler, NULL, (void *) &nif1)) if (!isr_register_handler(64 + INT_SOURCE_FEC0, fec0_interrupt_handler, NULL, (void *) &nif1))
{ {
dbg("unable to register isr for FEC0\r\n"); dbg("unable to register isr for FEC0\r\n");
return; return;
} }
/* /*
* Register the DMA interrupt handler * Register the DMA interrupt handler
*/ */
if (!isr_register_handler(64 + INT_SOURCE_DMA, dma_interrupt_handler, NULL,NULL)) if (!isr_register_handler(64 + INT_SOURCE_DMA, dma_interrupt_handler, NULL,NULL))
{ {
dbg("Error: Unable to register isr for DMA\r\n"); dbg("Error: Unable to register isr for DMA\r\n");
return; return;
} }
dma_irq_enable(5, 3); /* TODO: need to match the FEC driver's specs in MiNT? */ dma_irq_enable(5, 3); /* TODO: need to match the FEC driver's specs in MiNT? */
/* /*
* register the PIC interrupt handler * register the PIC interrupt handler
*/ */
if (isr_register_handler(64 + INT_SOURCE_PSC3, pic_interrupt_handler, NULL, NULL)) if (isr_register_handler(64 + INT_SOURCE_PSC3, pic_interrupt_handler, NULL, NULL))
{ {
dbg("Error: unable to register ISR for PSC3\r\n"); dbg("Error: unable to register ISR for PSC3\r\n");
return; return;
} }
/*
* register the XLB PCI interrupt handler
*/
if (!isr_register_handler(64 + INT_SOURCE_XLBPCI, xlbpci_interrupt_handler, NULL, NULL))
{
dbg("Error: unable to register isr for XLB PIC interrupts\r\n");
return;
}
MCF_XLB_XARB_IMR = MCF_XLB_XARB_IMR_SEAE | /* slave error acknowledge interrupt */
MCF_XLB_XARB_IMR_MME | /* multiple master at prio 0 interrupt */
MCF_XLB_XARB_IMR_TTAE | /* TT address only interrupt */
MCF_XLB_XARB_IMR_TTRE | /* TT reserved interrupt enable */
MCF_XLB_XARB_IMR_ECWE | /* external control word interrupt */
MCF_XLB_XARB_IMR_TTME | /* TBST/TSIZ mismatch interrupt */
MCF_XLB_XARB_IMR_BAE; /* bus activity tenure timeout interrupt */
if (!isr_register_handler(64 + INT_SOURCE_PCIARB, pciarb_interrupt_handler, NULL, NULL))
{
dbg("Error: unable to register isr for PCIARB interrupts\r\n");
return;
}
MCF_PCIARB_PACR = MCF_PCIARB_PACR_EXTMINTEN(0x1f) | /* external master broken interrupt */
MCF_PCIARB_PACR_INTMINTEN; /* internal master broken interrupt */
} }
void BaS(void) void BaS(void)
{ {
uint8_t *src; uint8_t *src;
uint8_t *dst = (uint8_t *) TOS; uint8_t *dst = (uint8_t *) TOS;
#if defined(MACHINE_FIREBEE) /* LITE board has no pic and (currently) no nvram */ #if defined(MACHINE_FIREBEE) /* LITE board has no pic and (currently) no nvram */
pic_init(); pic_init();
nvram_init(); nvram_init();
#endif /* MACHINE_FIREBEE */ #endif /* MACHINE_FIREBEE */
xprintf("copy EmuTOS: "); xprintf("copy EmuTOS: ");
/* copy EMUTOS */ /* copy EMUTOS */
src = (uint8_t *) EMUTOS; src = (uint8_t *) EMUTOS;
dma_memcpy(dst, src, EMUTOS_SIZE); dma_memcpy(dst, src, EMUTOS_SIZE);
xprintf("finished\r\n"); xprintf("finished\r\n");
xprintf("initialize MMU: "); xprintf("initialize MMU: ");
mmu_init(); mmu_init();
xprintf("finished\r\n"); xprintf("finished\r\n");
xprintf("initialize exception vector table: "); xprintf("initialize exception vector table: ");
vec_init(); vec_init();
xprintf("finished\r\n"); xprintf("finished\r\n");
xprintf("flush caches: "); xprintf("flush caches: ");
flush_and_invalidate_caches(); flush_and_invalidate_caches();
xprintf("finished\r\n"); xprintf("finished\r\n");
xprintf("enable MMU: "); xprintf("enable MMU: ");
MCF_MMU_MMUCR = MCF_MMU_MMUCR_EN; /* MMU on */ MCF_MMU_MMUCR = MCF_MMU_MMUCR_EN; /* MMU on */
NOP(); /* force pipeline sync */ NOP(); /* force pipeline sync */
xprintf("finished\r\n"); xprintf("finished\r\n");
#ifdef MACHINE_FIREBEE #ifdef MACHINE_FIREBEE
xprintf("IDE reset: "); xprintf("IDE reset: ");
/* IDE reset */ /* IDE reset */
* (volatile uint8_t *) (0xffff8802 - 2) = 14; * (volatile uint8_t *) (0xffff8802 - 2) = 14;
* (volatile uint8_t *) (0xffff8802 - 0) = 0x80; * (volatile uint8_t *) (0xffff8802 - 0) = 0x80;
wait(1); wait(1);
* (volatile uint8_t *) (0xffff8802 - 0) = 0; * (volatile uint8_t *) (0xffff8802 - 0) = 0;
xprintf("finished\r\n"); xprintf("finished\r\n");
xprintf("enable video: "); xprintf("enable video: ");
/* /*
* video setup (25MHz) * video setup (25MHz)
*/ */
* (volatile uint32_t *) (0xf0000410 + 0) = 0x032002ba; /* horizontal 640x480 */ * (volatile uint32_t *) (0xf0000410 + 0) = 0x032002ba; /* horizontal 640x480 */
* (volatile uint32_t *) (0xf0000410 + 4) = 0x020c020a; /* vertical 640x480 */ * (volatile uint32_t *) (0xf0000410 + 4) = 0x020c020a; /* vertical 640x480 */
* (volatile uint32_t *) (0xf0000410 + 8) = 0x0190015d; /* horizontal 320x240 */ * (volatile uint32_t *) (0xf0000410 + 8) = 0x0190015d; /* horizontal 320x240 */
* (volatile uint32_t *) (0xf0000410 + 12) = 0x020C020A; /* vertical 320x230 */ * (volatile uint32_t *) (0xf0000410 + 12) = 0x020C020A; /* vertical 320x230 */
#ifdef _NOT_USED_ /* fifo on, refresh on, ddrcs and cke on, video dac on */
// 32MHz * (volatile uint32_t *) (0xf0000410 - 0x20) = 0x01070002;
* (volatile uint32_t *) (0xf0000410 + 0) = 0x037002ba; /* horizontal 640x480 */
* (volatile uint32_t *) (0xf0000410 + 4) = 0x020d020a; /* vertical 640x480 */
* (volatile uint32_t *) (0xf0000410 + 8) = 0x02a001e0; /* horizontal 320x240 */
* (volatile uint32_t *) (0xf0000410 + 12) = 0x05a00160; /* vertical 320x230 */
#endif /* _NOT_USED_ */
/* fifo on, refresh on, ddrcs and cke on, video dac on */
* (volatile uint32_t *) (0xf0000410 - 0x20) = 0x01070002;
xprintf("finished\r\n");
enable_coldfire_interrupts();
#ifdef _NOT_USED_
screen_init();
/* experimental */
{
int i;
uint32_t *scradr = 0xd00000;
for (i = 0; i < 100; i++)
{
uint32_t *p = scradr;
for (p = scradr; p < scradr + 1024 * 150L; p++)
{
*p = 0xffffffff;
}
for (p = scradr; p < scradr + 1024 * 150L; p++)
{
*p = 0x0;
}
}
}
#endif /* _NOT_USED_ */
xprintf("finished\r\n");
#endif /* MACHINE_FIREBEE */ #endif /* MACHINE_FIREBEE */
sd_card_init(); sd_card_init();
/* /*
* memory setup * memory setup
*/ */
memset((void *) 0x400, 0, 0x400); memset((void *) 0x400, 0, 0x400);
#if defined(MACHINE_FIREBEE) #if defined(MACHINE_FIREBEE)
/* set Falcon bus control register */ /* set Falcon bus control register */
/* sets bit 3 and 6. Both are undefined on an original Falcon? */ /* sets bit 3 and 6. Both are undefined on an original Falcon? */
* (volatile uint8_t *) 0xffff8007 = 0x48; * (volatile uint8_t *) 0xffff8007 = 0x48;
#endif /* MACHINE_FIREBEE */ #endif /* MACHINE_FIREBEE */
/* ST RAM */ /* ST RAM */
* (uint32_t *) 0x42e = STRAM_END; /* phystop TOS system variable */ * (uint32_t *) 0x42e = STRAM_END; /* phystop TOS system variable */
* (uint32_t *) 0x420 = 0x752019f3; /* memvalid TOS system variable */ * (uint32_t *) 0x420 = 0x752019f3; /* memvalid TOS system variable */
* (uint32_t *) 0x43a = 0x237698aa; /* memval2 TOS system variable */ * (uint32_t *) 0x43a = 0x237698aa; /* memval2 TOS system variable */
* (uint32_t *) 0x51a = 0x5555aaaa; /* memval3 TOS system variable */ * (uint32_t *) 0x51a = 0x5555aaaa; /* memval3 TOS system variable */
/* TT-RAM */ /* TT-RAM */
* (uint32_t *) 0x5a4 = FASTRAM_END; /* ramtop TOS system variable */ * (uint32_t *) 0x5a4 = FASTRAM_END; /* ramtop TOS system variable */
* (uint32_t *) 0x5a8 = 0x1357bd13; /* ramvalid TOS system variable */ * (uint32_t *) 0x5a8 = 0x1357bd13; /* ramvalid TOS system variable */
#if defined(MACHINE_FIREBEE) /* m5484lite has no ACIA and no dip switch... */ #if defined(MACHINE_FIREBEE) /* m5484lite has no ACIA and no dip switch... */
acia_init(); acia_init();
#endif /* MACHINE_FIREBEE */ #endif /* MACHINE_FIREBEE */
srec_execute("BASFLASH.S19"); srec_execute("BASFLASH.S19");
/* Jump into the OS */ /* Jump into the OS */
typedef void void_func(void); typedef void void_func(void);
struct rom_header struct rom_header
{ {
void *initial_sp; void *initial_sp;
void_func *initial_pc; void_func *initial_pc;
}; };
xprintf("BaS initialization finished, enable interrupts\r\n"); xprintf("BaS initialization finished, enable interrupts\r\n");
enable_coldfire_interrupts(); init_isr();
init_isr(); enable_coldfire_interrupts();
init_pci();
video_init();
set_ipl(0); /* enable interrupts */
xprintf("call EmuTOS\r\n"); /* initialize USB devices */
struct rom_header *os_header = (struct rom_header *) TOS; init_usb();
os_header->initial_pc();
//set_ipl(7); /* disable interrupts */
xprintf("call EmuTOS\r\n");
struct rom_header *os_header = (struct rom_header *) TOS;
os_header->initial_pc();
} }

View File

@@ -216,6 +216,9 @@ init_vec_loop:
// install lowlevel_isr_handler for the PSC3 interrupt // install lowlevel_isr_handler for the PSC3 interrupt
move.l a1,(INT_SOURCE_PSC3 + 64) * 4(a0) move.l a1,(INT_SOURCE_PSC3 + 64) * 4(a0)
// install lowlevel_isr_handler for the XLBPCI interrupt
move.l a1,(INT_SOURCE_XLBPCI + 64) * 4(a0)
#ifndef MACHINE_FIREBEE #ifndef MACHINE_FIREBEE
// FEC1 not wired on the FireBee, but used on other machines // FEC1 not wired on the FireBee, but used on other machines
move.l a1,(INT_SOURCE_FEC1 + 64) * 4(a0) move.l a1,(INT_SOURCE_FEC1 + 64) * 4(a0)
@@ -429,10 +432,65 @@ irq7text:
.text .text
#elif MACHINE_FIREBEE /* these handlers are only meaningful for the Firebee */ #elif MACHINE_FIREBEE /* these handlers are only meaningful for the Firebee */
irq5:
irq 0x74,5,0x20
irq6: // MFP interrupt from FPGA irq5: move.w #0x2700,sr // disable interrupts
subq.l #4,sp // extra space
link a6,#-4 * 4 // save gcc scratch registers
movem.l d0-d1/a0-a1,(sp)
jsr _irq5_handler // call C handler routine
tst.l d0 // handled?
bne irq5_forward
movem.l (sp),d0-d1/a0-a1 // restore registers
unlk a6
addq.l #4,sp
rte // return from exception
irq5_forward: move.l 0x74,a0 // fetch OS irq5 vector
add.l _rt_vbr,a0 // add runtime vbr
move.l a0,4(a6) // put on stack
movem.l (sp),d0-d1/a0-a1 // restore registers
unlk a6 //
move.w #0x2500,sr // set interrupt level
rts // jump through vector
irq6: move.w #0x2700,sr // disable interrupt
subq.l #4,sp // extra space
link a6,#-4 * 4 // save gcc scratch registers
movem.l d0-d1/a0-a1,(sp)
move.l 4(a6),-(sp) // format status word
move.l 8(a6),-(sp) // pc at exception
jsr _irq6_interrupt_handler // call C handler
lea 8(sp),sp // fix stack
tst.l d0 // interrupt handled?
bne irq6_forward // no, forward to TOS
movem.l (sp),d0-d1/a0-a1 // restore registers
unlk a6
addq.l #4,sp // extra word not needed in this case
rte
irq6_forward:
move.l 0xf0020000,a0 // fetch "autovector"
add.l _rt_vbr,a0 // add runtime VBR
move.l (a0),4(a6) // fetch handler address and put it on stack
movem.l (sp),d0-d1/a0-a1
unlk a6
move.w #0x2600,sr // set interrupt level
rts // jump through vector
#ifdef _NOT_USED_
// MFP interrupt from FPGA
move.w #0x2700,sr // disable interrupt move.w #0x2700,sr // disable interrupt
subq.l #8,sp subq.l #8,sp
movem.l d0/a5,(sp) // save registers movem.l d0/a5,(sp) // save registers
@@ -555,6 +613,9 @@ acsi_dma_end:
move.l (sp)+,d1 move.l (sp)+,d1
move.l (sp)+,a1 move.l (sp)+,a1
rts rts
#endif /* _NOT_USED_ */
/* /*
* irq 7 = pseudo bus error * irq 7 = pseudo bus error
*/ */

View File

@@ -35,63 +35,19 @@
#include "cache.h" #include "cache.h"
#include "util.h" #include "util.h"
#include "dma.h" #include "dma.h"
#include "pci.h"
extern void (*rt_vbr[])(void); extern void (*rt_vbr[])(void);
#define VBR rt_vbr #define VBR rt_vbr
//#define IRQ_DEBUG #define IRQ_DEBUG
#if defined(IRQ_DEBUG) #if defined(IRQ_DEBUG)
#define dbg(format, arg...) do { xprintf("DEBUG %s(): " format, __FUNCTION__, ##arg); } while (0) #define dbg(format, arg...) do { xprintf("DEBUG %s(): " format, __FUNCTION__, ##arg); } while (0)
#else #else
#define dbg(format, arg...) do { ; } while (0) #define dbg(format, arg...) do { ; } while (0)
#endif #endif
#define err(format, arg...) do { xprintf("DEBUG %s(): " format, __FUNCTION__, ##arg); } while (0)
/*
* register an interrupt handler at the Coldfire interrupt controller and add the handler to
* the interrupt vector table
*/
int register_interrupt_handler(uint8_t source, uint8_t level, uint8_t priority, uint8_t intr, void (*handler)(void))
{
int ipl;
int i;
volatile uint8_t *ICR = &MCF_INTC_ICR01 - 1;
uint8_t lp;
source &= 63;
priority &= 7;
if (source < 1 || source > 63)
{
dbg("interrupt source %d not defined\r\n", source);
return -1;
}
lp = MCF_INTC_ICR_IL(level) | MCF_INTC_ICR_IP(priority);
/* check if this combination is already set somewhere */
for (i = 1; i < 64; i++)
{
if (ICR[i] == lp)
{
dbg("level %d and priority %d already used for interrupt source %d!\r\n",
level, priority, i);
return -1;
}
}
/* disable interrupts */
ipl = set_ipl(7);
VBR[64 + source] = handler; /* first 64 vectors are system exceptions */
/* set level and priority in interrupt controller */
ICR[source] = lp;
/* set interrupt mask to where it was before */
set_ipl(ipl);
return 0;
}
#ifndef MAX_ISR_ENTRY #ifndef MAX_ISR_ENTRY
#define MAX_ISR_ENTRY (20) #define MAX_ISR_ENTRY (20)
@@ -236,12 +192,19 @@ int pic_interrupt_handler(void *arg1, void *arg2)
return 1; return 1;
} }
int xlbpci_interrupt_handler(void *arg1, void *arg2)
void video_addr_timeout(void)
{ {
dbg("video address timeout\r\n"); dbg("XLB PCI interrupt\r\n");
return 1;
} }
int pciarb_interrupt_handler(void *arg1, void *arg2)
{
dbg("PCI ARB interrupt\r\n");
return 1;
}
/* /*
* blink the Firebee's LED to show we are still alive * blink the Firebee's LED to show we are still alive
@@ -288,6 +251,7 @@ bool irq6_interrupt_handler(uint32_t sf1, uint32_t sf2)
{ {
bool handled = false; bool handled = false;
//err("IRQ6!\r\n");
MCF_EPORT_EPFR |= (1 << 6); /* clear int6 from edge port */ MCF_EPORT_EPFR |= (1 << 6); /* clear int6 from edge port */
if (FALCON_MFP_IPRA || FALCON_MFP_IPRB) if (FALCON_MFP_IPRA || FALCON_MFP_IPRB)
@@ -298,6 +262,65 @@ bool irq6_interrupt_handler(uint32_t sf1, uint32_t sf2)
return handled; return handled;
} }
#if defined(MACHINE_FIREBEE)
/*
* This gets called from irq5 in exceptions.S
* Once we arrive here, the SR has been set to disable interrupts and the gcc scratch registers have been saved
*/
int irq5_handler(void)
{
int32_t handle;
int32_t value = 0;
int32_t newvalue;
err("FPGA_INTR_CONTROL = 0x%08x\r\n", * FPGA_INTR_CONTROL);
err("FPGA_INTR_ENABLE = 0x%08x\r\n", * FPGA_INTR_ENABLE);
err("FPGA_INTR_CLEAR = 0x%08x\r\n", * FPGA_INTR_CLEAR);
err("FPGA_INTR_PENDING = 0x%08x\r\n", * FPGA_INTR_PENDING);
* FPGA_INTR_CLEAR &= ~0x20000000UL; /* clear interrupt from FPGA */
err("\r\nFPGA_INTR_CLEAR = 0x%08x\r\n", * FPGA_INTR_CLEAR);
//MCF_EPORT_EPFR |= (1 << 5); /* clear interrupt from edge port */
//xprintf("IRQ5!\r\n");
if ((handle = pci_get_interrupt_cause()) > 0)
{
newvalue = pci_call_interrupt_chain(handle, value);
if (newvalue == value)
{
dbg("interrupt not handled!\r\n");
return 1;
}
}
return 0;
}
#endif /* MACHINE_FIREBEE */
#ifdef MACHINE_M5484LITE
/*
* This gets called from irq7 in exceptions.S
* Once we arrive here, the SR has been set to disable interrupts and the gcc scratch registers have been saved
*/
void irq7_handler(void)
{
int32_t handle;
int32_t value = 0;
int32_t newvalue;
MCF_EPORT_EPFR |= (1 << 7);
dbg("IRQ7!\r\n");
if ((handle = pci_get_interrupt_cause()) > 0)
{
newvalue = pci_call_interrupt_chain(handle, value);
if (newvalue == value)
{
dbg("interrupt not handled!\r\n");
}
}
}
#endif /* MACHINE_M548X */
#if defined(MACHINE_FIREBEE) #if defined(MACHINE_FIREBEE)
#define vbasehi (* (volatile uint8_t *) 0xffff8201) #define vbasehi (* (volatile uint8_t *) 0xffff8201)
#define vbasemid (* (volatile uint8_t *) 0xffff8203) #define vbasemid (* (volatile uint8_t *) 0xffff8203)

View File

@@ -213,6 +213,7 @@ struct virt_to_phys
uint32_t physical_offset; uint32_t physical_offset;
}; };
#if defined(MACHINE_FIREBEE)
static struct virt_to_phys translation[] = static struct virt_to_phys translation[] =
{ {
/* virtual , length , offset */ /* virtual , length , offset */
@@ -221,9 +222,33 @@ static struct virt_to_phys translation[] =
{ 0x00f00000, 0x00100000, 0xff000000 }, /* map Falcon I/O area to FPGA */ { 0x00f00000, 0x00100000, 0xff000000 }, /* map Falcon I/O area to FPGA */
{ 0x01000000, 0x1f000000, 0x00000000 }, /* map rest of ram virt = phys */ { 0x01000000, 0x1f000000, 0x00000000 }, /* map rest of ram virt = phys */
}; };
#elif defined(MACHINE_M5484LITE)
static struct virt_to_phys translation[] =
{
/* virtual , length , offset */
{ 0x00000000, 0x00e00000, 0x00000000 }, /* map first 14 MByte to first 14 Mb of SD ram */
{ 0x00e00000, 0x00100000, 0x00000000 }, /* map TOS to SDRAM */
{ 0x01000000, 0x04000000, 0x00000000 }, /* map rest of ram virt = phys */
{ 0x60000000, 0x10000000, 0x00000000 }, /* map CPLD CF card I/O area */
};
#elif defined(MACHINE_M54455)
/* FIXME: this is not determined yet! */
static struct virt_to_phys translation[] =
{
/* virtual , length , offset */
{ 0x00000000, 0x00e00000, 0x60000000 }, /* map first 14 MByte to first 14 Mb of video ram */
{ 0x00e00000, 0x00100000, 0x00000000 }, /* map TOS to SDRAM */
{ 0x00f00000, 0x00100000, 0xff000000 }, /* map Falcon I/O area to FPGA */
{ 0x01000000, 0x1f000000, 0x00000000 }, /* map rest of ram virt = phys */
};
#else
#error unknown machine!
#endif
static int num_translations = sizeof(translation) / sizeof(struct virt_to_phys); static int num_translations = sizeof(translation) / sizeof(struct virt_to_phys);
static inline uint32_t lookup_phys(uint32_t virt) static inline int32_t lookup_phys(int32_t virt)
{ {
int i; int i;
@@ -235,6 +260,7 @@ static inline uint32_t lookup_phys(uint32_t virt)
} }
} }
err("virtual address 0x%lx not found in translation table!\r\n", virt); err("virtual address 0x%lx not found in translation table!\r\n", virt);
return -1; return -1;
} }
@@ -253,19 +279,23 @@ struct page_descriptor
* page descriptors. Size depending on DEFAULT_PAGE_SIZE, either 1M (resulting in 512 * page descriptors. Size depending on DEFAULT_PAGE_SIZE, either 1M (resulting in 512
* bytes size) or 8k pages (64k descriptor array size) * bytes size) or 8k pages (64k descriptor array size)
*/ */
static struct page_descriptor pages[512UL * 1024 * 1024 / DEFAULT_PAGE_SIZE]; static struct page_descriptor pages[SDRAM_SIZE / DEFAULT_PAGE_SIZE];
int mmu_map_instruction_page(uint32_t virt, uint8_t asid) int mmu_map_instruction_page(int32_t virt, uint8_t asid)
{ {
const uint32_t size_mask = ~ (DEFAULT_PAGE_SIZE - 1); /* pagesize */ const uint32_t size_mask = ~ (DEFAULT_PAGE_SIZE - 1); /* pagesize */
int page_index = (virt & size_mask) / DEFAULT_PAGE_SIZE; /* index into page_descriptor array */ int page_index = (virt & size_mask) / DEFAULT_PAGE_SIZE; /* index into page_descriptor array */
struct page_descriptor *page = &pages[page_index]; /* attributes of page to map */ struct page_descriptor *page = &pages[page_index]; /* attributes of page to map */
int ipl; int ipl;
uint32_t phys = lookup_phys(virt); /* virtual to physical translation of page */ int32_t phys = lookup_phys(virt); /* virtual to physical translation of page */
if (phys == -1) if (phys == -1)
{
/* no valid mapping found, caller will issue a bus error in return */
return 0; return 0;
}
#ifdef DBG_MMU #ifdef DBG_MMU
register int sp asm("sp"); register int sp asm("sp");
@@ -307,17 +337,21 @@ int mmu_map_instruction_page(uint32_t virt, uint8_t asid)
return 1; return 1;
} }
int mmu_map_data_page(uint32_t virt, uint8_t asid) int mmu_map_data_page(int32_t virt, uint8_t asid)
{ {
uint16_t ipl; uint16_t ipl;
const uint32_t size_mask = ~ (DEFAULT_PAGE_SIZE - 1); /* pagesize */ const uint32_t size_mask = ~ (DEFAULT_PAGE_SIZE - 1); /* pagesize */
int page_index = (virt & size_mask) / DEFAULT_PAGE_SIZE; /* index into page_descriptor array */ int page_index = (virt & size_mask) / DEFAULT_PAGE_SIZE; /* index into page_descriptor array */
struct page_descriptor *page = &pages[page_index]; /* attributes of page to map */ struct page_descriptor *page = &pages[page_index]; /* attributes of page to map */
uint32_t phys = lookup_phys(virt); /* virtual to physical translation of page */ int32_t phys = lookup_phys(virt); /* virtual to physical translation of page */
if (phys == -1) if (phys == -1)
{
/* no valid mapping found, caller will issue a bus error in return */
return 0; return 0;
}
#ifdef DBG_MMU #ifdef DBG_MMU
register int sp asm("sp"); register int sp asm("sp");
@@ -365,7 +399,7 @@ int mmu_map_data_page(uint32_t virt, uint8_t asid)
* per instruction as a minimum, more for performance. Thus locked pages (that can't be touched by the * per instruction as a minimum, more for performance. Thus locked pages (that can't be touched by the
* LRU algorithm) should be used sparsingly. * LRU algorithm) should be used sparsingly.
*/ */
int mmu_map_page(uint32_t virt, uint32_t phys, enum mmu_page_size sz, uint8_t page_id, const struct page_descriptor *flags) int mmu_map_page(int32_t virt, int32_t phys, enum mmu_page_size sz, uint8_t page_id, const struct page_descriptor *flags)
{ {
int size_mask; int size_mask;
int ipl; int ipl;
@@ -447,7 +481,8 @@ void mmu_init(void)
{ {
uint32_t addr = i * DEFAULT_PAGE_SIZE; uint32_t addr = i * DEFAULT_PAGE_SIZE;
if (addr >= 0x00f00000 && addr < 0x00ffffff) #if defined(MACHINE_FIREBEE)
if (addr >= 0x00f00000UL && addr < 0x00ffffffUL) /* Falcon I/O area on the Firebee */
{ {
pages[i].cache_mode = CACHE_NOCACHE_PRECISE; pages[i].cache_mode = CACHE_NOCACHE_PRECISE;
pages[i].execute = 0; pages[i].execute = 0;
@@ -457,7 +492,7 @@ void mmu_init(void)
pages[i].global = 1; pages[i].global = 1;
pages[i].supervisor_protect = 1; pages[i].supervisor_protect = 1;
} }
else if (addr >= 0x0 && addr < 0x00e00000) /* ST-RAM, potential video memory */ else if (addr >= 0x0UL && addr < 0x00e00000UL) /* ST-RAM, potential video memory */
{ {
pages[i].cache_mode = CACHE_WRITETHROUGH; pages[i].cache_mode = CACHE_WRITETHROUGH;
pages[i].execute = 1; pages[i].execute = 1;
@@ -467,7 +502,7 @@ void mmu_init(void)
pages[i].execute = 1; pages[i].execute = 1;
pages[i].global = 1; pages[i].global = 1;
} }
else if (addr >= 0x00e00000 && addr < 0x00f00000) /* EmuTOS */ else if (addr >= 0x00e00000UL && addr < 0x00f00000UL) /* EmuTOS */
{ {
pages[i].cache_mode = CACHE_COPYBACK; pages[i].cache_mode = CACHE_COPYBACK;
pages[i].execute = 1; pages[i].execute = 1;
@@ -488,16 +523,107 @@ void mmu_init(void)
} }
pages[i].locked = 0; /* not locked */ pages[i].locked = 0; /* not locked */
pages[0].supervisor_protect = 0; /* protect system vectors */ pages[0].supervisor_protect = 0; /* protect system vectors */
#elif defined(MACHINE_M5484LITE)
if (addr >= 0x60000000UL && addr < 0x70000000UL) /* Compact Flash on the m5484lite */
{
pages[i].cache_mode = CACHE_NOCACHE_PRECISE;
pages[i].execute = 0;
pages[i].read = 1;
pages[i].write = 1;
pages[i].execute = 0;
pages[i].global = 1;
pages[i].supervisor_protect = 1;
}
else if (addr >= 0x0UL && addr < 0x00e00000UL) /* ST-RAM, potential video memory */
{
pages[i].cache_mode = CACHE_WRITETHROUGH;
pages[i].execute = 1;
pages[i].supervisor_protect = 0;
pages[i].read = 1;
pages[i].write = 1;
pages[i].execute = 1;
pages[i].global = 1;
}
else if (addr >= 0x00e00000UL && addr < 0x00f00000UL) /* EmuTOS */
{
pages[i].cache_mode = CACHE_COPYBACK;
pages[i].execute = 1;
pages[i].supervisor_protect = 1;
pages[i].read = 1;
pages[i].write = 0;
pages[i].execute = 1;
pages[i].global = 1;
}
else
{
pages[i].cache_mode = CACHE_COPYBACK; /* rest of RAM */
pages[i].execute = 1;
pages[i].read = 1;
pages[i].write = 1;
pages[i].supervisor_protect = 0;
pages[i].global = 1;
}
pages[i].locked = 0; /* not locked */
pages[0].supervisor_protect = 0; /* protect system vectors */
#elif defined(MACHINE_M54455)
if (addr >= 0x60000000UL && addr < 0x70000000UL) /* Compact Flash on the m5484lite */
{
pages[i].cache_mode = CACHE_NOCACHE_PRECISE;
pages[i].execute = 0;
pages[i].read = 1;
pages[i].write = 1;
pages[i].execute = 0;
pages[i].global = 1;
pages[i].supervisor_protect = 1;
}
else if (addr >= 0x0UL && addr < 0x00e00000UL) /* ST-RAM, potential video memory */
{
pages[i].cache_mode = CACHE_WRITETHROUGH;
pages[i].execute = 1;
pages[i].supervisor_protect = 0;
pages[i].read = 1;
pages[i].write = 1;
pages[i].execute = 1;
pages[i].global = 1;
}
else if (addr >= 0x00e00000UL && addr < 0x00f00000UL) /* EmuTOS */
{
pages[i].cache_mode = CACHE_COPYBACK;
pages[i].execute = 1;
pages[i].supervisor_protect = 1;
pages[i].read = 1;
pages[i].write = 0;
pages[i].execute = 1;
pages[i].global = 1;
}
else
{
pages[i].cache_mode = CACHE_COPYBACK; /* rest of RAM */
pages[i].execute = 1;
pages[i].read = 1;
pages[i].write = 1;
pages[i].supervisor_protect = 0;
pages[i].global = 1;
}
pages[i].locked = 0; /* not locked */
pages[0].supervisor_protect = 0; /* protect system vectors */
#else
#error Unknown machine!
#endif /* MACHINE_FIREBEE */
} }
set_asid(0); /* do not use address extension (ASID provides virtual 48 bit addresses */ set_asid(0); /* do not use address extension (ASID provides virtual 48 bit addresses */
/* set data access attributes in ACR0 and ACR1 */ /* set data access attributes in ACR0 and ACR1 */
/* map PCI address space */
set_acr0(ACR_W(0) | /* read and write accesses permitted */ set_acr0(ACR_W(0) | /* read and write accesses permitted */
ACR_SP(0) | /* supervisor and user mode access permitted */ ACR_SP(1) | /* supervisor and user mode access permitted */
ACR_CM(ACR_CM_CACHE_INH_PRECISE) | /* cache inhibit, precise */ ACR_CM(ACR_CM_CACHE_INH_PRECISE) | /* cache inhibit, precise */
ACR_AMM(0) | /* control region > 16 MB */ ACR_AMM(0) | /* control region > 16 MB */
ACR_S(ACR_S_ALL) | /* match addresses in user and supervisor mode */ ACR_S(ACR_S_SUPERVISOR_MODE) | /* match addresses in supervisor mode only */
ACR_E(1) | /* enable ACR */ ACR_E(1) | /* enable ACR */
#if defined(MACHINE_FIREBEE) #if defined(MACHINE_FIREBEE)
ACR_ADMSK(0x7f) | /* cover 2GB area from 0x80000000 to 0xffffffff */ ACR_ADMSK(0x7f) | /* cover 2GB area from 0x80000000 to 0xffffffff */
@@ -520,11 +646,11 @@ void mmu_init(void)
ACR_SP(0) | ACR_SP(0) |
ACR_CM(0) | ACR_CM(0) |
#if defined(MACHINE_FIREBEE) #if defined(MACHINE_FIREBEE)
ACR_CM(ACR_CM_CACHEABLE_WT) | /* flash on the Firebee */ ACR_CM(ACR_CM_CACHEABLE_WT) |
#elif defined(MACHINE_M5484LITE) #elif defined(MACHINE_M5484LITE)
ACR_CM(ACR_CM_CACHE_INH_PRECISE) | /* Compact Flash on the M548xLITE */ ACR_CM(ACR_CM_CACHEABLE_WT) |
#elif defined(MACHINE_M54455) #elif defined(MACHINE_M54455)
ACR_CM(ACR_CM_CACHE_INH_PRECISE) | /* FIXME: not determined yet */ ACR_CM(ACR_CM_CACHEABLE_WT) |
#else #else
#error unknown machine! #error unknown machine!
#endif /* MACHINE_FIREBEE */ #endif /* MACHINE_FIREBEE */
@@ -568,6 +694,7 @@ void mmu_init(void)
/* 0x00000000 - 0x00100000 (first MB of physical memory) locked virt = phys */ /* 0x00000000 - 0x00100000 (first MB of physical memory) locked virt = phys */
mmu_map_page(0x0, 0x0, MMU_PAGE_SIZE_1M, 0, &flags); mmu_map_page(0x0, 0x0, MMU_PAGE_SIZE_1M, 0, &flags);
#ifdef _NOT_USED_
#if defined(MACHINE_FIREBEE) #if defined(MACHINE_FIREBEE)
/* /*
* 0x00d00000 - 0x00e00000 (last megabyte of ST RAM = Falcon video memory) locked ID = 6 * 0x00d00000 - 0x00e00000 (last megabyte of ST RAM = Falcon video memory) locked ID = 6
@@ -581,8 +708,8 @@ void mmu_init(void)
flags.execute = 1; flags.execute = 1;
flags.locked = true; flags.locked = true;
mmu_map_page(0x00d00000, 0x60d00000, MMU_PAGE_SIZE_1M, SCA_PAGE_ID, &flags); mmu_map_page(0x00d00000, 0x60d00000, MMU_PAGE_SIZE_1M, SCA_PAGE_ID, &flags);
#endif /* MACHINE_FIREBEE */ #endif /* MACHINE_FIREBEE */
#endif
/* /*
* Make the TOS (in SDRAM) read-only * Make the TOS (in SDRAM) read-only

View File

@@ -30,7 +30,6 @@
#include "startcf.h" #include "startcf.h"
#include "cache.h" #include "cache.h"
#include "sysinit.h" #include "sysinit.h"
#include "pci.h"
#include "bas_printf.h" #include "bas_printf.h"
#include "bas_string.h" #include "bas_string.h"
#include "bas_types.h" #include "bas_types.h"
@@ -52,7 +51,6 @@
#include "pci_ids.h" #include "pci_ids.h"
#include "driver_mem.h" #include "driver_mem.h"
#include "usb.h" #include "usb.h"
#include "video.h"
#define DEBUG_SYSINIT #define DEBUG_SYSINIT
#ifdef DEBUG_SYSINIT #ifdef DEBUG_SYSINIT
@@ -708,9 +706,11 @@ void init_usb(void)
uint32_t id = 0; uint32_t id = 0;
uint32_t pci_class = 0; uint32_t pci_class = 0;
dbg("PCI device handle = %x\r\n", handle);
id = pci_read_config_longword(handle, PCIIDR); id = pci_read_config_longword(handle, PCIIDR);
pci_class = pci_read_config_longword(handle, PCIREV); pci_class = pci_read_config_longword(handle, PCIREV);
dbg("compare class code 0x%x to 0x%x\r\n", PCI_CLASS_CODE(pci_class), PCI_CLASS_SERIAL_USB);
if (PCI_CLASS_CODE(pci_class) == PCI_CLASS_SERIAL_USB) if (PCI_CLASS_CODE(pci_class) == PCI_CLASS_SERIAL_USB)
{ {
xprintf("serial USB found at bus=0x%x, dev=0x%x, fnc=0x%x (0x%x)\r\n", xprintf("serial USB found at bus=0x%x, dev=0x%x, fnc=0x%x (0x%x)\r\n",
@@ -718,14 +718,12 @@ void init_usb(void)
PCI_DEVICE_FROM_HANDLE(handle), PCI_DEVICE_FROM_HANDLE(handle),
PCI_FUNCTION_FROM_HANDLE(handle), PCI_FUNCTION_FROM_HANDLE(handle),
handle); handle);
dbg("compare subclass code 0x%x against 0x%x\r\n", PCI_SUBCLASS(pci_class), PCI_CLASS_SERIAL_USB_EHCI);
if (PCI_SUBCLASS(pci_class) == PCI_CLASS_SERIAL_USB_EHCI) if (PCI_SUBCLASS(pci_class) == PCI_CLASS_SERIAL_USB_EHCI)
{ {
board = ehci_usb_pci_table; board = ehci_usb_pci_table;
while (board->vendor) while (board->vendor)
{ {
dbg("compare vendor id 0x%x against 0x%x\r\n", board->vendor, PCI_VENDOR_ID(id));
dbg("compare device id 0x%x against 0x%x\r\n", board->device, PCI_DEVICE_ID(id));
if ((board->vendor == PCI_VENDOR_ID(id)) && board->device == PCI_DEVICE_ID(id)) if ((board->vendor == PCI_VENDOR_ID(id)) && board->device == PCI_DEVICE_ID(id))
{ {
dbg("match. trying to init board\r\n"); dbg("match. trying to init board\r\n");
@@ -738,15 +736,12 @@ void init_usb(void)
} }
} }
dbg("compare subclass code 0x%x against 0x%x\r\n", PCI_SUBCLASS(pci_class), PCI_CLASS_SERIAL_USB_OHCI);
if (PCI_SUBCLASS(pci_class) == PCI_CLASS_SERIAL_USB_OHCI) if (PCI_SUBCLASS(pci_class) == PCI_CLASS_SERIAL_USB_OHCI)
{ {
board = ohci_usb_pci_table; board = ohci_usb_pci_table;
while (board->vendor) while (board->vendor)
{ {
dbg("matched. compare vendor id 0x%x against 0x%x\r\n", board->vendor, PCI_VENDOR_ID(id));
dbg("compare device id 0x%x against 0x%x\r\n", board->device, PCI_DEVICE_ID(id));
if ((board->vendor == PCI_VENDOR_ID(id)) && board->device == PCI_DEVICE_ID(id)) if ((board->vendor == PCI_VENDOR_ID(id)) && board->device == PCI_DEVICE_ID(id))
{ {
if (usb_init(handle, board) >= 0) if (usb_init(handle, board) >= 0)
@@ -759,7 +754,6 @@ void init_usb(void)
} }
} }
} }
dbg("PCI device handle = %x\r\n", handle);
} while (handle >= 0); } while (handle >= 0);
xprintf("finished (found %d USB host controller(s))\r\n", usb_found); xprintf("finished (found %d USB host controller(s))\r\n", usb_found);
@@ -1228,11 +1222,6 @@ void initialize_hardware(void)
#endif /* MACHINE_FIREBEE */ #endif /* MACHINE_FIREBEE */
driver_mem_init(); driver_mem_init();
init_pci();
video_init();
/* initialize USB devices */
init_usb();
#if MACHINE_FIREBEE #if MACHINE_FIREBEE
init_ac97(); init_ac97();

View File

@@ -529,7 +529,7 @@ int usb_parse_config(struct usb_device *dev, unsigned char *buffer, int cfgno)
if (head->bDescriptorType != USB_DT_CONFIG) if (head->bDescriptorType != USB_DT_CONFIG)
{ {
dbg(" ERROR: NOT USB_CONFIG_DESC %x\r\n", head->bDescriptorType); dbg(" ERROR: NOT USB_CONFIG_DESC (0x%x instead of 0x%x)\r\n", head->bDescriptorType, USB_DT_CONFIG);
return -1; return -1;
} }
memcpy(&dev->config, buffer, buffer[0]); memcpy(&dev->config, buffer, buffer[0]);
@@ -1089,6 +1089,7 @@ int usb_new_device(struct usb_device *dev)
unsigned char *tmpbuf; unsigned char *tmpbuf;
dbg("\r\n"); dbg("\r\n");
#ifndef CONFIG_LEGACY_USB_INIT_SEQ #ifndef CONFIG_LEGACY_USB_INIT_SEQ
struct usb_device_descriptor *desc; struct usb_device_descriptor *desc;
int port = -1; int port = -1;
@@ -1113,6 +1114,7 @@ int usb_new_device(struct usb_device *dev)
return 1; return 1;
} }
//#define CONFIG_LEGACY_USB_INIT_SEQ
#ifdef CONFIG_LEGACY_USB_INIT_SEQ #ifdef CONFIG_LEGACY_USB_INIT_SEQ
/* /*
* this is the old and known way of initializing devices, it is * this is the old and known way of initializing devices, it is
@@ -1244,6 +1246,9 @@ int usb_new_device(struct usb_device *dev)
dev->descriptor.idProduct = swpw(dev->descriptor.idProduct); dev->descriptor.idProduct = swpw(dev->descriptor.idProduct);
dev->descriptor.bcdDevice = swpw(dev->descriptor.bcdDevice); dev->descriptor.bcdDevice = swpw(dev->descriptor.bcdDevice);
dbg("vendor: 0x%x, prod: 0x%x, dev: 0x%x\r\n",
dev->descriptor.idVendor, dev->descriptor.idProduct, dev->descriptor.bcdDevice);
/* only support for one config for now */ /* only support for one config for now */
usb_get_configuration_no(dev, &tmpbuf[0], 0); usb_get_configuration_no(dev, &tmpbuf[0], 0);
usb_parse_config(dev, &tmpbuf[0], 0); usb_parse_config(dev, &tmpbuf[0], 0);

View File

@@ -216,12 +216,14 @@ static int usb_mouse_probe(struct usb_device *dev, unsigned int ifnum)
int pipe; int pipe;
int maxp; int maxp;
#ifdef _NOT_USED_
if (dev->descriptor.bNumConfigurations != 1) if (dev->descriptor.bNumConfigurations != 1)
{ {
dbg("dev->descriptor.bNumConfigurations != 1\r\n"); dbg("dev->descriptor.bNumConfigurations != 1\r\n");
return 0; return 0;
} }
#endif
iface = &dev->config.if_desc[ifnum]; iface = &dev->config.if_desc[ifnum];

View File

@@ -31,7 +31,7 @@
uint32_t get_timer(void) uint32_t get_timer(void)
{ {
return MCF_SLT_SCNT(0); return MCF_SLT_SCNT(0);
} }
/* /*
* wait for the specified number of us on slice timer 0. Replaces the original routines that had * wait for the specified number of us on slice timer 0. Replaces the original routines that had
@@ -39,17 +39,18 @@ uint32_t get_timer(void)
*/ */
void wait(uint32_t us) void wait(uint32_t us)
{ {
int32_t target = MCF_SLT_SCNT(0) - (us * (SYSCLK / 1000)); int32_t target = MCF_SLT_SCNT(0) - (us * (SYSCLK / 1000));
while (MCF_SLT_SCNT(0) - target > 0); while (MCF_SLT_SCNT(0) - target > 0);
} }
void wait_us() __attribute__ ((weak, alias("wait")));
/* /*
* same as above, but with milliseconds wait time * same as above, but with milliseconds wait time
*/ */
void wait_ms(uint32_t ms) void wait_ms(uint32_t ms)
{ {
wait(ms * 1000); wait(ms * 1000);
} }
/* /*
* the same as above, with a checker function which gets called while * the same as above, with a checker function which gets called while
@@ -57,13 +58,13 @@ void wait_ms(uint32_t ms)
*/ */
bool waitfor(uint32_t us, checker_func condition) bool waitfor(uint32_t us, checker_func condition)
{ {
int32_t target = MCF_SLT_SCNT(0) - (us * (SYSCLK / 1000)); int32_t target = MCF_SLT_SCNT(0) - (us * (SYSCLK / 1000));
bool res; bool res;
do do
{ {
if ((res = (*condition)())) if ((res = (*condition)()))
return res; return res;
} while (MCF_SLT_SCNT(0) - target > 0); } while (MCF_SLT_SCNT(0) - target > 0);
return false; return false;
} }