Commit 327f7a020a3037ae8ef6c94488d5e9a3aa772943
1 parent
12e4407c6a
Exists in
master
and in
54 other branches
Initial revision
Showing 27 changed files with 4866 additions and 0 deletions Side-by-side Diff
- board/mousse/u-boot.lds.ram
- board/sandpoint/early_init.S
- board/sandpoint/u-boot.lds.mw.debug
- cpu/mpc824x/drivers/dma/Makefile
- cpu/mpc824x/drivers/dma/Makefile_pc
- cpu/mpc824x/drivers/dma/README
- cpu/mpc824x/drivers/dma/dma.h
- cpu/mpc824x/drivers/dma/dma1.c
- cpu/mpc824x/drivers/dma/dma2.S
- cpu/mpc824x/drivers/dma/dma_export.h
- cpu/mpc824x/drivers/dma_export.h
- cpu/mpc824x/drivers/epic.h
- cpu/mpc824x/drivers/epic/README
- cpu/mpc824x/drivers/epic/epic2.S
- cpu/mpc824x/drivers/epic/epicutil.S
- cpu/mpc824x/drivers/errors.h
- cpu/mpc824x/drivers/i2c/Makefile
- cpu/mpc824x/drivers/i2c/Makefile_pc
- cpu/mpc824x/drivers/i2c/README
- cpu/mpc824x/drivers/i2c/i2c_export.h
- cpu/mpc824x/drivers/i2c_export.h
- cpu/mpc824x/drivers/i2o.h
- cpu/mpc824x/drivers/i2o/Makefile
- cpu/mpc824x/drivers/i2o/Makefile_pc
- cpu/mpc824x/drivers/i2o/i2o.h
- cpu/mpc824x/drivers/i2o/i2o1.c
- cpu/mpc824x/drivers/i2o/i2o2.S
board/mousse/u-boot.lds.ram
1 | +/* | |
2 | + * (C) Copyright 2000 | |
3 | + * Rob Taylor, Flying Pig Systems Ltd. robt@flyingpig.com | |
4 | + * | |
5 | + * See file CREDITS for list of people who contributed to this | |
6 | + * project. | |
7 | + * | |
8 | + * This program is free software; you can redistribute it and/or | |
9 | + * modify it under the terms of the GNU General Public License as | |
10 | + * published by the Free Software Foundation; either version 2 of | |
11 | + * the License, or (at your option) any later version. | |
12 | + * | |
13 | + * This program is distributed in the hope that it will be useful, | |
14 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | + * GNU General Public License for more details. | |
17 | + * | |
18 | + * You should have received a copy of the GNU General Public License | |
19 | + * along with this program; if not, write to the Free Software | |
20 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
21 | + * MA 02111-1307 USA | |
22 | + */ | |
23 | + | |
24 | +OUTPUT_ARCH(powerpc) | |
25 | +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); | |
26 | + | |
27 | +MEMORY { | |
28 | + ram (!rx) : org = 0x00000000 , LENGTH = 8M | |
29 | + code (!rx) : org = 0x00002000 , LENGTH = (4M - 0x2000) | |
30 | + rom (rx) : org = 0xfff00000 , LENGTH = 512K | |
31 | +} | |
32 | + | |
33 | +SECTIONS | |
34 | +{ | |
35 | + _f_init = .; | |
36 | + PROVIDE(_f_init = .); | |
37 | + _f_init_rom = .; | |
38 | + PROVIDE(_f_init_rom = .); | |
39 | + | |
40 | + .init : { | |
41 | + cpu/mpc824x/start.o (.text) | |
42 | + *(.init) | |
43 | + } > ram | |
44 | + _init_size = SIZEOF(.init); | |
45 | + PROVIDE(_init_size = SIZEOF(.init)); | |
46 | + | |
47 | + ENTRY(_start) | |
48 | + | |
49 | +/* _ftext = .; | |
50 | + _ftext_rom = .; | |
51 | + _text_size = SIZEOF(.text); | |
52 | + */ | |
53 | + .text : { | |
54 | + *(.text) | |
55 | + *(.got1) | |
56 | + } > ram | |
57 | + .rodata : { *(.rodata) } > ram | |
58 | + .dtors : { *(.dtors) } > ram | |
59 | + .data : { *(.data) } > ram | |
60 | + .sdata : { *(.sdata) } > ram | |
61 | + .sdata2 : { *(.sdata2) | |
62 | + *(.got) | |
63 | + _GOT2_TABLE_ = .; | |
64 | + *(.got2) | |
65 | + _FIXUP_TABLE_ = .; | |
66 | + *(.fixup) | |
67 | + } > ram | |
68 | + __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2; | |
69 | + __fixup_entries = (. - _FIXUP_TABLE_)>>2; | |
70 | + | |
71 | + .sbss : { *(.sbss) } > ram | |
72 | + .sbss2 : { *(.sbss2) } > ram | |
73 | + .bss : { *(.bss) } > ram | |
74 | + .debug : { *(.debug) } > ram | |
75 | + .line : { *(.line) } > ram | |
76 | + .symtab : { *(.symtab) } > ram | |
77 | + .shrstrtab : { *(.shstrtab) } > ram | |
78 | + .strtab : { *(.strtab) } > ram | |
79 | + /* .reloc : | |
80 | + { | |
81 | + *(.got) | |
82 | + _GOT2_TABLE_ = .; | |
83 | + *(.got2) | |
84 | + _FIXUP_TABLE_ = .; | |
85 | + *(.fixup) | |
86 | + } > ram | |
87 | + */ | |
88 | + __start___ex_table = .; | |
89 | + __ex_table : { *(__ex_table) } > ram | |
90 | + __stop___ex_table = .; | |
91 | + | |
92 | + | |
93 | + .ppcenv : | |
94 | + { | |
95 | + common/environment.o (.ppcenv) | |
96 | + } > ram | |
97 | + | |
98 | + _end = . ; | |
99 | + PROVIDE (end = .); | |
100 | +} |
board/sandpoint/early_init.S
1 | +/* | |
2 | + * (C) Copyright 2001 | |
3 | + * Thomas Koeller, tkoeller@gmx.net | |
4 | + * | |
5 | + * See file CREDITS for list of people who contributed to this | |
6 | + * project. | |
7 | + * | |
8 | + * This program is free software; you can redistribute it and/or | |
9 | + * modify it under the terms of the GNU General Public License as | |
10 | + * published by the Free Software Foundation; either version 2 of | |
11 | + * the License, or (at your option) any later version. | |
12 | + * | |
13 | + * This program is distributed in the hope that it will be useful, | |
14 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | + * GNU General Public License for more details. | |
17 | + * | |
18 | + * You should have received a copy of the GNU General Public License | |
19 | + * along with this program; if not, write to the Free Software | |
20 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
21 | + * MA 02111-1307 USA | |
22 | + */ | |
23 | + | |
24 | +#ifndef __ASSEMBLY__ | |
25 | +#define __ASSEMBLY__ 1 | |
26 | +#endif | |
27 | + | |
28 | +#include <config.h> | |
29 | +#include <asm/processor.h> | |
30 | +#include <mpc824x.h> | |
31 | +#include <ppc_asm.tmpl> | |
32 | + | |
33 | +#if defined(USE_DINK32) | |
34 | + /* We are running from RAM, so do not clear the MCCR1_MEMGO bit! */ | |
35 | + #define MCCR1VAL ((CFG_ROMNAL << MCCR1_ROMNAL_SHIFT) | (CFG_ROMFAL << MCCR1_ROMFAL_SHIFT) | MCCR1_MEMGO) | |
36 | +#else | |
37 | + #define MCCR1VAL (CFG_ROMNAL << MCCR1_ROMNAL_SHIFT) | (CFG_ROMFAL << MCCR1_ROMFAL_SHIFT) | |
38 | +#endif | |
39 | + | |
40 | + .text | |
41 | + | |
42 | + /* Values to program into memory controller registers */ | |
43 | +tbl: .long MCCR1, MCCR1VAL | |
44 | + .long MCCR2, CFG_REFINT << MCCR2_REFINT_SHIFT | |
45 | + .long MCCR3 | |
46 | + .long (((CFG_BSTOPRE & 0x000000f0) >> 4) << MCCR3_BSTOPRE2TO5_SHIFT) | \ | |
47 | + (CFG_REFREC << MCCR3_REFREC_SHIFT) | \ | |
48 | + (CFG_RDLAT << MCCR3_RDLAT_SHIFT) | |
49 | + .long MCCR4 | |
50 | + .long (CFG_PRETOACT << MCCR4_PRETOACT_SHIFT) | (CFG_ACTTOPRE << MCCR4_ACTTOPRE_SHIFT) | \ | |
51 | + (CFG_REGISTERD_TYPE_BUFFER << 20) | \ | |
52 | + (((CFG_BSTOPRE & 0x00000300) >> 8) << MCCR4_BSTOPRE0TO1_SHIFT ) | \ | |
53 | + ((CFG_SDMODE_CAS_LAT << 4) | (CFG_SDMODE_WRAP << 3) | \ | |
54 | + (CFG_SDMODE_BURSTLEN) << MCCR4_SDMODE_SHIFT) | \ | |
55 | + (CFG_ACTTORW << MCCR4_ACTTORW_SHIFT) | \ | |
56 | + ((CFG_BSTOPRE & 0x0000000f) << MCCR4_BSTOPRE6TO9_SHIFT ) | |
57 | + .long MSAR1 | |
58 | + .long (((CFG_BANK0_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 0) | \ | |
59 | + (((CFG_BANK1_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 8) | \ | |
60 | + (((CFG_BANK2_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 16) | \ | |
61 | + (((CFG_BANK3_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 24) | |
62 | + .long EMSAR1 | |
63 | + .long (((CFG_BANK0_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 0) | \ | |
64 | + (((CFG_BANK1_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 8) | \ | |
65 | + (((CFG_BANK2_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 16) | \ | |
66 | + (((CFG_BANK3_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 24) | |
67 | + .long MSAR2 | |
68 | + .long (((CFG_BANK4_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 0) | \ | |
69 | + (((CFG_BANK5_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 8) | \ | |
70 | + (((CFG_BANK6_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 16) | \ | |
71 | + (((CFG_BANK7_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 24) | |
72 | + .long EMSAR2 | |
73 | + .long (((CFG_BANK4_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 0) | \ | |
74 | + (((CFG_BANK5_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 8) | \ | |
75 | + (((CFG_BANK6_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 16) | \ | |
76 | + (((CFG_BANK7_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 24) | |
77 | + .long MEAR1 | |
78 | + .long (((CFG_BANK0_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 0) | \ | |
79 | + (((CFG_BANK1_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 8) | \ | |
80 | + (((CFG_BANK2_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 16) | \ | |
81 | + (((CFG_BANK3_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 24) | |
82 | + .long EMEAR1 | |
83 | + .long (((CFG_BANK0_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 0) | \ | |
84 | + (((CFG_BANK1_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 8) | \ | |
85 | + (((CFG_BANK2_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 16) | \ | |
86 | + (((CFG_BANK3_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 24) | |
87 | + .long MEAR2 | |
88 | + .long (((CFG_BANK4_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 0) | \ | |
89 | + (((CFG_BANK5_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 8) | \ | |
90 | + (((CFG_BANK6_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 16) | \ | |
91 | + (((CFG_BANK7_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 24) | |
92 | + .long EMEAR2 | |
93 | + .long (((CFG_BANK4_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 0) | \ | |
94 | + (((CFG_BANK5_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 8) | \ | |
95 | + (((CFG_BANK6_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 16) | \ | |
96 | + (((CFG_BANK7_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 24) | |
97 | + .long 0 | |
98 | + | |
99 | + | |
100 | + | |
101 | + /* | |
102 | + * Early CPU initialization. Set up memory controller, so we can access any RAM at all. This | |
103 | + * must be done in assembly, since we have no stack at this point. | |
104 | + */ | |
105 | + .global early_init_f | |
106 | +early_init_f: | |
107 | + mflr r10 | |
108 | + | |
109 | + /* basic memory controller configuration */ | |
110 | + lis r3, CONFIG_ADDR_HIGH | |
111 | + lis r4, CONFIG_DATA_HIGH | |
112 | + bl lab | |
113 | +lab: mflr r5 | |
114 | + lwzu r0, tbl - lab(r5) | |
115 | +loop: lwz r1, 4(r5) | |
116 | + stwbrx r0, 0, r3 | |
117 | + eieio | |
118 | + stwbrx r1, 0, r4 | |
119 | + eieio | |
120 | + lwzu r0, 8(r5) | |
121 | + cmpli cr0, 0, r0, 0 | |
122 | + bne cr0, loop | |
123 | + | |
124 | + /* set bank enable bits */ | |
125 | + lis r0, MBER@h | |
126 | + ori r0, 0, MBER@l | |
127 | + li r1, CFG_BANK_ENABLE | |
128 | + stwbrx r0, 0, r3 | |
129 | + eieio | |
130 | + stb r1, 0(r4) | |
131 | + eieio | |
132 | + | |
133 | + /* delay loop */ | |
134 | + lis r0, 0x0003 | |
135 | + mtctr r0 | |
136 | +delay: bdnz delay | |
137 | + | |
138 | + /* enable memory controller */ | |
139 | + lis r0, MCCR1@h | |
140 | + ori r0, 0, MCCR1@l | |
141 | + stwbrx r0, 0, r3 | |
142 | + eieio | |
143 | + lwbrx r0, 0, r4 | |
144 | + oris r0, 0, MCCR1_MEMGO@h | |
145 | + stwbrx r0, 0, r4 | |
146 | + eieio | |
147 | + | |
148 | + /* set up stack pointer */ | |
149 | + lis r1, CFG_INIT_SP_OFFSET@h | |
150 | + ori r1, r1, CFG_INIT_SP_OFFSET@l | |
151 | + | |
152 | + mtlr r10 | |
153 | + blr |
board/sandpoint/u-boot.lds.mw.debug
1 | +/* | |
2 | + * (C) Copyright 2000 | |
3 | + * Rob Taylor, Flying Pig Systems Ltd. robt@flyingpig.com | |
4 | + * | |
5 | + * See file CREDITS for list of people who contributed to this | |
6 | + * project. | |
7 | + * | |
8 | + * This program is free software; you can redistribute it and/or | |
9 | + * modify it under the terms of the GNU General Public License as | |
10 | + * published by the Free Software Foundation; either version 2 of | |
11 | + * the License, or (at your option) any later version. | |
12 | + * | |
13 | + * This program is distributed in the hope that it will be useful, | |
14 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | + * GNU General Public License for more details. | |
17 | + * | |
18 | + * You should have received a copy of the GNU General Public License | |
19 | + * along with this program; if not, write to the Free Software | |
20 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
21 | + * MA 02111-1307 USA | |
22 | + */ | |
23 | + | |
24 | +OUTPUT_ARCH(powerpc) | |
25 | +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); | |
26 | + | |
27 | +MEMORY { | |
28 | + ram (!rx) : org = 0x00000000 , LENGTH = 8M | |
29 | + code (!rx) : org = 0x00002000 , LENGTH = (4M - 0x2000) | |
30 | + rom (rx) : org = 0xfe000000 , LENGTH = (0x100000000 - 0xfe000000) | |
31 | +} | |
32 | + | |
33 | +SECTIONS | |
34 | +{ | |
35 | + _f_init = .; | |
36 | + PROVIDE(_f_init = .); | |
37 | + _f_init_rom = .; | |
38 | + PROVIDE(_f_init_rom = .); | |
39 | + | |
40 | + .init : { | |
41 | + cpu/mpc824x/start.o (.text) | |
42 | + *(.init) | |
43 | + } > ram | |
44 | + _init_size = SIZEOF(.init); | |
45 | + PROVIDE(_init_size = SIZEOF(.init)); | |
46 | + | |
47 | + ENTRY(_start) | |
48 | + | |
49 | +/* _ftext = .; | |
50 | + _ftext_rom = .; | |
51 | + _text_size = SIZEOF(.text); | |
52 | + */ | |
53 | + .text : { | |
54 | + *(.text) | |
55 | + *(.got1) | |
56 | + } > ram | |
57 | + .rodata : { *(.rodata) } > ram | |
58 | + .dtors : { *(.dtors) } > ram | |
59 | + .data : { *(.data) } > ram | |
60 | + .sdata : { *(.sdata) } > ram | |
61 | + .sdata2 : { *(.sdata2) | |
62 | + *(.got) | |
63 | + _GOT2_TABLE_ = .; | |
64 | + *(.got2) | |
65 | + _FIXUP_TABLE_ = .; | |
66 | + *(.fixup) | |
67 | + } > ram | |
68 | + __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2; | |
69 | + __fixup_entries = (. - _FIXUP_TABLE_)>>2; | |
70 | + | |
71 | + .sbss : { *(.sbss) } > ram | |
72 | + .sbss2 : { *(.sbss2) } > ram | |
73 | + .bss : { *(.bss) } > ram | |
74 | + .debug : { *(.debug) } > ram | |
75 | + .line : { *(.line) } > ram | |
76 | + .symtab : { *(.symtab) } > ram | |
77 | + .shrstrtab : { *(.shstrtab) } > ram | |
78 | + .strtab : { *(.strtab) } > ram | |
79 | + /* .reloc : | |
80 | + { | |
81 | + *(.got) | |
82 | + _GOT2_TABLE_ = .; | |
83 | + *(.got2) | |
84 | + _FIXUP_TABLE_ = .; | |
85 | + *(.fixup) | |
86 | + } > ram | |
87 | + */ | |
88 | + __start___ex_table = .; | |
89 | + __ex_table : { *(__ex_table) } > ram | |
90 | + __stop___ex_table = .; | |
91 | + | |
92 | + | |
93 | + .ppcenv : | |
94 | + { | |
95 | + common/environment.o (.ppcenv) | |
96 | + } > ram | |
97 | + | |
98 | + _end = . ; | |
99 | + PROVIDE (end = .); | |
100 | +} |
cpu/mpc824x/drivers/dma/Makefile
1 | +########################################################################## | |
2 | +# | |
3 | +# Copyright Motorola, Inc. 1997 | |
4 | +# ALL RIGHTS RESERVED | |
5 | +# | |
6 | +# You are hereby granted a copyright license to use, modify, and | |
7 | +# distribute the SOFTWARE so long as this entire notice is retained | |
8 | +# without alteration in any modified and/or redistributed versions, | |
9 | +# and that such modified versions are clearly identified as such. | |
10 | +# No licenses are granted by implication, estoppel or otherwise under | |
11 | +# any patents or trademarks of Motorola, Inc. | |
12 | +# | |
13 | +# The SOFTWARE is provided on an "AS IS" basis and without warranty. | |
14 | +# To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS | |
15 | +# ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED | |
16 | +# WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR | |
17 | +# PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH | |
18 | +# REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS | |
19 | +# THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS. | |
20 | +# | |
21 | +# To the maximum extent permitted by applicable law, IN NO EVENT SHALL | |
22 | +# MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER | |
23 | +# (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF | |
24 | +# BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS | |
25 | +# INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR | |
26 | +# INABILITY TO USE THE SOFTWARE. | |
27 | +# | |
28 | +############################################################################ | |
29 | +TARGET = libdma.a | |
30 | + | |
31 | +DEBUG = -DDMADBG | |
32 | +LST = -Hanno -S | |
33 | +OPTIM = | |
34 | +CC = /risc/tools/pkgs/metaware/bin/hcppc | |
35 | +CFLAGS = -Hnocopyr -c -Hsds -Hon=Char_default_unsigned -Hon=Char_is_rep -I../inc -I/risc/tools/pkgs/metaware/inc | |
36 | +CCobj = $(CC) $(CFLAGS) $(DEBUG) $(OPTIM) | |
37 | +PREP = $(CC) $(CFLAGS) -P | |
38 | + | |
39 | +# Assembler used to build the .s files (for the board version) | |
40 | + | |
41 | +ASOPT = -big_si -c | |
42 | +ASDEBUG = -l -fm | |
43 | +AS = /risc/tools/pkgs/metaware/bin/asppc | |
44 | + | |
45 | +# Linker to bring .o files together into an executable. | |
46 | + | |
47 | +LKOPT = -Bbase=0 -q -r -Qn | |
48 | +LKCMD = | |
49 | +LINK = /risc/tools/pkgs/metaware/bin/ldppc $(LKCMD) $(LKOPT) | |
50 | + | |
51 | +# DOS Utilities | |
52 | + | |
53 | +DEL = rm | |
54 | +COPY = cp | |
55 | +LIST = ls | |
56 | + | |
57 | +OBJECTS = dma1.o dma2.o | |
58 | + | |
59 | +all: $(TARGET) | |
60 | + | |
61 | +$(TARGET): $(OBJECTS) | |
62 | + $(LINK) $(OBJECTS) -o $@ | |
63 | + | |
64 | +objects: dma1.o | |
65 | + | |
66 | +clean: | |
67 | + $(DEL) -f *.o *.i *.map *.lst $(TARGET) $(OBJECTS) | |
68 | + | |
69 | +.s.o: | |
70 | + $(DEL) -f $*.i | |
71 | + $(PREP) -Hasmcpp $< | |
72 | + $(AS) $(ASOPT) $*.i | |
73 | +# $(AS) $(ASOPT) $(ASDEBUG) $*.i > $*.lst | |
74 | + | |
75 | +.c.o: | |
76 | + $(CCobj) $< | |
77 | + | |
78 | +.c.s: | |
79 | + $(CCobj) $(LST) $< | |
80 | + | |
81 | +dma1.o: dma_export.h dma.h dma1.c | |
82 | + | |
83 | +dma2.o: dma.h dma2.s |
cpu/mpc824x/drivers/dma/Makefile_pc
1 | +########################################################################## | |
2 | +# | |
3 | +# makefile_pc for use with mksnt tools drivers/dma | |
4 | +# | |
5 | +# Copyright Motorola, Inc. 1997 | |
6 | +# ALL RIGHTS RESERVED | |
7 | +# | |
8 | +# You are hereby granted a copyright license to use, modify, and | |
9 | +# distribute the SOFTWARE so long as this entire notice is retained | |
10 | +# without alteration in any modified and/or redistributed versions, | |
11 | +# and that such modified versions are clearly identified as such. | |
12 | +# No licenses are granted by implication, estoppel or otherwise under | |
13 | +# any patents or trademarks of Motorola, Inc. | |
14 | +# | |
15 | +# The SOFTWARE is provided on an "AS IS" basis and without warranty. | |
16 | +# To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS | |
17 | +# ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED | |
18 | +# WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR | |
19 | +# PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH | |
20 | +# REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS | |
21 | +# THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS. | |
22 | +# | |
23 | +# To the maximum extent permitted by applicable law, IN NO EVENT SHALL | |
24 | +# MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER | |
25 | +# (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF | |
26 | +# BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS | |
27 | +# INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR | |
28 | +# INABILITY TO USE THE SOFTWARE. | |
29 | +# | |
30 | +############################################################################ | |
31 | +TARGET = libdma.a | |
32 | + | |
33 | +DEBUG = -DDMADBG | |
34 | +LST = -Hanno -S | |
35 | +OPTIM = | |
36 | +CC = m:/old_tools/tools/hcppc/bin/hcppc | |
37 | +CFLAGS = -Hnocopyr -c -Hsds -Hon=Char_default_unsigned -Hon=Char_is_rep -I../inc -I/risc/tools/pkgs/metaware/inc | |
38 | +CCobj = $(CC) $(CFLAGS) $(DEBUG) $(OPTIM) | |
39 | +PREP = $(CC) $(CFLAGS) -P | |
40 | + | |
41 | +# Assembler used to build the .s files (for the board version) | |
42 | + | |
43 | +ASOPT = -big_si -c | |
44 | +ASDEBUG = -l -fm | |
45 | +AS = m:/old_tools/tools/hcppc/bin/asppc | |
46 | + | |
47 | +# Linker to bring .o files together into an executable. | |
48 | + | |
49 | +LKOPT = -Bbase=0 -q -r -Qn | |
50 | +LKCMD = | |
51 | +LINK = m:/old_tools/tools/hcppc/bin/ldppc $(LKCMD) $(LKOPT) | |
52 | + | |
53 | +# DOS Utilities | |
54 | + | |
55 | +DEL = rm | |
56 | +COPY = cp | |
57 | +LIST = ls | |
58 | + | |
59 | +OBJECTS = dma1.o dma2.o | |
60 | + | |
61 | +all: $(TARGET) | |
62 | + | |
63 | +$(TARGET): $(OBJECTS) | |
64 | + $(LINK) $(OBJECTS) -o $@ | |
65 | + | |
66 | +objects: dma1.o | |
67 | + | |
68 | +clean: | |
69 | + $(DEL) -f *.o *.i *.map *.lst $(TARGET) $(OBJECTS) | |
70 | + | |
71 | +.s.o: | |
72 | + $(DEL) -f $*.i | |
73 | + $(PREP) -Hasmcpp $< | |
74 | + $(AS) $(ASOPT) $*.i | |
75 | +# $(AS) $(ASOPT) $(ASDEBUG) $*.i > $*.lst | |
76 | + | |
77 | +.c.o: | |
78 | + $(CCobj) $< | |
79 | + | |
80 | +.c.s: | |
81 | + $(CCobj) $(LST) $< | |
82 | + | |
83 | +dma1.o: dma_export.h dma.h dma1.c | |
84 | + $(CCobj) $< | |
85 | + | |
86 | +dma2.o: dma.h dma2.s | |
87 | + $(DEL) -f $*.i | |
88 | + $(PREP) -Hasmcpp $< | |
89 | + $(AS) $(ASOPT) $*.i |
cpu/mpc824x/drivers/dma/README
1 | +CONTENT: | |
2 | + | |
3 | + dma.h | |
4 | + dma1.c | |
5 | + dma2.s | |
6 | + | |
7 | +WHAT ARE THESE FILES: | |
8 | + | |
9 | +These files contain MPC8240 (Kahlua) DMA controller | |
10 | +driver routines. The driver routines are not | |
11 | +written for any specific operating system. | |
12 | +They serves the purpose of code sample, and | |
13 | +jump-start for using the MPC8240 DMA controller. | |
14 | + | |
15 | +For the reason of correctness of C language | |
16 | +syntax, these files are compiled by Metaware | |
17 | +C compiler and assembler. | |
18 | + | |
19 | +ENDIAN NOTATION: | |
20 | + | |
21 | +The algorithm is designed for big-endian mode, | |
22 | +software is responsible for byte swapping. | |
23 | + | |
24 | +USAGE: | |
25 | + | |
26 | +1. The host system that is running on MPC8240 | |
27 | + or using MPC8240 as I/O device shall link | |
28 | + the files listed here. The memory location | |
29 | + of driver routines shall take into account of | |
30 | + that driver routines need to run in supervisor | |
31 | + mode and they process DMA controller interrupt. | |
32 | + | |
33 | +2. The host system is responsible for configuring | |
34 | + the MPC8240 including Embedded Utilities Memory | |
35 | + Block. Since the DMA controller on MPC8240 can | |
36 | + be accessed by either local 603e core or the host | |
37 | + that MPC8240 serves as I/O processor through host | |
38 | + PCI configuration, it is important that the local | |
39 | + processor uses EUMBBAR to access its local DMA | |
40 | + controller while the PCI master uses I/O | |
41 | + processor's PCSRBAR to access the DMA controller | |
42 | + on I/O device. | |
43 | + | |
44 | + To qualify whether is EUMBBAR or PCSRBAR, one | |
45 | + additional parameter is requied from the host | |
46 | + system, LOCAL or REMOTE so that the base value | |
47 | + can be correctly interpreted. | |
48 | + | |
49 | +3. If the host system is also using the EPIC unit | |
50 | + on MPC8240, the system can register the | |
51 | + DMA_ISR with the EPIC including other | |
52 | + desired resources. | |
53 | + | |
54 | + If the host system does not using the EPIC unit | |
55 | + on MPC8240, DMA_ISR function can be called for | |
56 | + each desired time interval. | |
57 | + | |
58 | + In both cases, the host system is free to | |
59 | + provide its own interrupt service routine. | |
60 | + | |
61 | +4. To start a direct mode DMA transaction, | |
62 | + use DMA_Bld_Curr with the start parameter | |
63 | + set to 1. | |
64 | + | |
65 | + To start a chaining mode DMA transaction, | |
66 | + the application shall build descriptors | |
67 | + in memory first, next, use DMA_Bld_Desp | |
68 | + with the start parameter set to 1. | |
69 | + | |
70 | +5. DMA_Start function clears, then sets the CS | |
71 | + bit of DMA mode register. | |
72 | + | |
73 | + DMA_Halt function clears the CS bit of DMA | |
74 | + mode register. | |
75 | + | |
76 | + These functions can be used to start and | |
77 | + halt the DMA transaction. | |
78 | + | |
79 | + If the chaining descriptors has been | |
80 | + modified since the last time a DMA | |
81 | + transaction started, use DMA_Chn_Cnt | |
82 | + function to let DMA controller process | |
83 | + the modified descriptor chain without | |
84 | + stopping or disturbing the current DMA | |
85 | + transaction. | |
86 | + | |
87 | + It is the host system's responsibility of | |
88 | + setting up the correct DMA transfer mode | |
89 | + and pass the correct memory address parameters. | |
90 | + | |
91 | +6. It is the host system's responsibility of | |
92 | + queueing the DMA I/O request. The host | |
93 | + system can call the DMA_ISR with its own | |
94 | + desired interrupt service subroutines to | |
95 | + handle each individual interrupt and queued | |
96 | + DMA I/O requests. | |
97 | + | |
98 | +7. The DMA driver routines contains a set | |
99 | + of utilities, Set and Get, for host system | |
100 | + to query and modify the desired DMA registers. |
cpu/mpc824x/drivers/dma/dma.h
1 | +#ifndef DMA_H | |
2 | +#define DMA_H | |
3 | +/******************************************************* | |
4 | + * | |
5 | + * copyright @ Motorola 1999 | |
6 | + * | |
7 | + *******************************************************/ | |
8 | +#define NUM_DMA_REG 7 | |
9 | +#define DMA_MR_REG 0 | |
10 | +#define DMA_SR_REG 1 | |
11 | +#define DMA_CDAR_REG 2 | |
12 | +#define DMA_SAR_REG 3 | |
13 | +#define DMA_DAR_REG 4 | |
14 | +#define DMA_BCR_REG 5 | |
15 | +#define DMA_NDAR_REG 6 | |
16 | + | |
17 | +typedef enum _dmastatus | |
18 | +{ | |
19 | + DMASUCCESS = 0x1000, | |
20 | + DMALMERROR, | |
21 | + DMAPERROR, | |
22 | + DMACHNBUSY, | |
23 | + DMAEOSINT, | |
24 | + DMAEOCAINT, | |
25 | + DMAINVALID, | |
26 | + DMANOEVENT, | |
27 | +} DMAStatus; | |
28 | + | |
29 | +typedef enum _location | |
30 | +{ | |
31 | + LOCAL = 0, /* local processor accesses on board DMA, | |
32 | + local processor's eumbbar is required */ | |
33 | + REMOTE = 1, /* PCI master accesses DMA on I/O board, | |
34 | + I/O processor's pcsrbar is required */ | |
35 | +} LOCATION; | |
36 | + | |
37 | +typedef enum dma_mr_bit | |
38 | +{ | |
39 | + IRQS = 0x00080000, | |
40 | + PDE = 0x00040000, | |
41 | + DAHTS = 0x00030000, | |
42 | + SAHTS = 0x0000c000, | |
43 | + DAHE = 0x00002000, | |
44 | + SAHE = 0x00001000, | |
45 | + PRC = 0x00000c00, | |
46 | + EIE = 0x00000080, | |
47 | + EOTIE = 0x00000040, | |
48 | + DL = 0x00000008, | |
49 | + CTM = 0x00000004, | |
50 | + CC = 0x00000002, | |
51 | + CS = 0x00000001, | |
52 | +} DMA_MR_BIT; | |
53 | + | |
54 | +typedef enum dma_sr_bit | |
55 | +{ | |
56 | + LME = 0x00000080, | |
57 | + PE = 0x00000010, | |
58 | + CB = 0x00000004, | |
59 | + EOSI = 0x00000002, | |
60 | + EOCAI = 0x00000001, | |
61 | +} DMA_SR_BIT; | |
62 | + | |
63 | +/* structure for DMA Mode Register */ | |
64 | +typedef struct _dma_mr | |
65 | +{ | |
66 | + unsigned int reserved0 : 12; | |
67 | + unsigned int irqs : 1; | |
68 | + unsigned int pde : 1; | |
69 | + unsigned int dahts : 2; | |
70 | + unsigned int sahts : 2; | |
71 | + unsigned int dahe : 1; | |
72 | + unsigned int sahe : 1; | |
73 | + unsigned int prc : 2; | |
74 | + unsigned int reserved1 : 1; | |
75 | + unsigned int eie : 1; | |
76 | + unsigned int eotie : 1; | |
77 | + unsigned int reserved2 : 3; | |
78 | + unsigned int dl : 1; | |
79 | + unsigned int ctm : 1; | |
80 | + /* if chaining mode is enabled, any time, user can modify the | |
81 | + * descriptor and does not need to halt the current DMA transaction. | |
82 | + * Set CC bit, enable DMA to process the modified descriptors | |
83 | + * Hardware will clear this bit each time, DMA starts. | |
84 | + */ | |
85 | + unsigned int cc : 1; | |
86 | + /* cs bit has dua role, halt the current DMA transaction and | |
87 | + * (re)start DMA transaction. In chaining mode, if the descriptor | |
88 | + * needs modification, cs bit shall be used not the cc bit. | |
89 | + * Hardware will not set/clear this bit each time DMA transaction | |
90 | + * stops or starts. Software shall do it. | |
91 | + * | |
92 | + * cs bit shall not be used to halt chaining DMA transaction for | |
93 | + * modifying the descriptor. That is the role of CC bit. | |
94 | + */ | |
95 | + unsigned int cs : 1; | |
96 | +} DMA_MR; | |
97 | + | |
98 | +/* structure for DMA Status register */ | |
99 | +typedef struct _dma_sr | |
100 | +{ | |
101 | + unsigned int reserved0 : 24; | |
102 | + unsigned int lme : 1; | |
103 | + unsigned int reserved1 : 2; | |
104 | + unsigned int pe : 1; | |
105 | + unsigned int reserved2 : 1; | |
106 | + unsigned int cb : 1; | |
107 | + unsigned int eosi : 1; | |
108 | + unsigned int eocai : 1; | |
109 | +} DMA_SR; | |
110 | + | |
111 | +/* structure for DMA current descriptor address register */ | |
112 | +typedef struct _dma_cdar | |
113 | +{ | |
114 | + unsigned int cda : 27; | |
115 | + unsigned int snen : 1; | |
116 | + unsigned int eosie : 1; | |
117 | + unsigned int ctt : 2; | |
118 | + unsigned int eotd : 1; | |
119 | +} DMA_CDAR; | |
120 | + | |
121 | +/* structure for DMA byte count register */ | |
122 | +typedef struct _dma_bcr | |
123 | +{ | |
124 | + unsigned int reserved : 6; | |
125 | + unsigned int bcr : 26; | |
126 | +} DMA_BCR; | |
127 | + | |
128 | +/* structure for DMA Next Descriptor Address register */ | |
129 | +typedef struct _dma_ndar | |
130 | +{ | |
131 | + unsigned int nda : 27; | |
132 | + unsigned int ndsnen : 1; | |
133 | + unsigned int ndeosie: 1; | |
134 | + unsigned int ndctt : 2; | |
135 | + unsigned int eotd : 1; | |
136 | +} DMA_NDAR; | |
137 | + | |
138 | +/* structure for DMA current transaction info */ | |
139 | +typedef struct _dma_curr | |
140 | +{ | |
141 | + unsigned int src_addr; | |
142 | + unsigned int dest_addr; | |
143 | + unsigned int byte_cnt; | |
144 | +} DMA_CURR; | |
145 | + | |
146 | +/************************* Kernel API******************** | |
147 | + * Kernel APIs are used to interface with O.S. kernel. | |
148 | + * They are the functions required by O.S. kernel to | |
149 | + * provide I/O service. | |
150 | + ********************************************************/ | |
151 | + | |
152 | +/**************DMA Device Control Functions ********/ | |
153 | + | |
154 | +/** | |
155 | + * Note: | |
156 | + * | |
157 | + * In all following functions, the host (KAHLUA) processor has a | |
158 | + * choice of accessing on board local DMA (LOCAL), | |
159 | + * or DMA on a distributed KAHLUA (REMOTE). In either case, | |
160 | + * the caller shall pass the configured embedded utility memory | |
161 | + * block base address relative to the DMA. If LOCAL DMA is used, | |
162 | + * this parameter shall be EUMBBAR, if REMOTE is used, the | |
163 | + * parameter shall be the corresponding PCSRBAR. | |
164 | + **/ | |
165 | + | |
166 | +/************************************************************** | |
167 | + * function: DMA_Get_Stat | |
168 | + * | |
169 | + * description: return the content of status register of | |
170 | + * the given DMA channel | |
171 | + * if error, return DMAINVALID. Otherwise return | |
172 | + * DMASUCCESS. | |
173 | + * | |
174 | + **************************************************************/ | |
175 | +static DMAStatus DMA_Get_Stat( LOCATION, unsigned int eumbbar, unsigned int channel, DMA_SR * ); | |
176 | + | |
177 | +/************************************************************** | |
178 | + * function: DMA_Get_Mode | |
179 | + * | |
180 | + * description: return the content of mode register of the | |
181 | + * given DMA channel | |
182 | + * if error, return DMAINVALID. Otherwise return DMASUCCESS. | |
183 | + * | |
184 | + **************************************************************/ | |
185 | +static DMAStatus DMA_Get_Mode( LOCATION, unsigned int eumbbar, unsigned int channel, DMA_MR * ); | |
186 | + | |
187 | +/************************************************************** | |
188 | + * function: DMA_Set_Mode | |
189 | + * | |
190 | + * description: Set a new mode to a given DMA channel | |
191 | + * return DMASUCCESS if success, otherwise return DMACHNINVALID | |
192 | + * | |
193 | + * note: It is not a good idea of changing the DMA mode during | |
194 | + * the middle of a transaction. | |
195 | + **************************************************************/ | |
196 | +static DMAStatus DMA_Set_Mode( LOCATION, unsigned int eumbbar, unsigned int channel, DMA_MR mode ); | |
197 | + | |
198 | +/************************************************************* | |
199 | + * function: DMA_ISR | |
200 | + * | |
201 | + * description: DMA interrupt service routine | |
202 | + * return DMAStatus based on the status | |
203 | + * | |
204 | + *************************************************************/ | |
205 | +static DMAStatus DMA_ISR( unsigned int eumbbar, | |
206 | + unsigned int channel, | |
207 | + DMAStatus (*lme_func)( unsigned int, unsigned int, DMAStatus ), | |
208 | + DMAStatus (*pe_func) ( unsigned int, unsigned int, DMAStatus ), | |
209 | + DMAStatus (*eosi_func)( unsigned int, unsigned int, DMAStatus ), | |
210 | + DMAStatus (*eocai_func)(unsigned int, unsigned int, DMAStatus )); | |
211 | + | |
212 | +static DMAStatus dma_error_func( unsigned int, unsigned int, DMAStatus ); | |
213 | + | |
214 | +/********************* DMA I/O function ********************/ | |
215 | + | |
216 | +/************************************************************ | |
217 | + * function: DMA_Start | |
218 | + * | |
219 | + * description: start a given DMA channel transaction | |
220 | + * return DMASUCCESS if success, otherwise return DMACHNINVALID | |
221 | + * | |
222 | + * note: this function will clear DMA_MR(CC) first, then | |
223 | + * set DMA_MR(CC). | |
224 | + ***********************************************************/ | |
225 | +static DMAStatus DMA_Start( LOCATION, unsigned int eumbbar,unsigned int channel ); | |
226 | + | |
227 | +/*********************************************************** | |
228 | + * function: DMA_Halt | |
229 | + * | |
230 | + * description: halt the current dma transaction on the specified | |
231 | + * channel. | |
232 | + * return DMASUCCESS if success, otherwise return DMACHNINVALID | |
233 | + * | |
234 | + * note: if the specified DMA channel is idle, nothing happens | |
235 | + *************************************************************/ | |
236 | +static DMAStatus DMA_Halt( LOCATION, unsigned int eumbbar,unsigned int channel ); | |
237 | + | |
238 | +/************************************************************* | |
239 | + * function: DMA_Chn_Cnt | |
240 | + * | |
241 | + * description: set the DMA_MR(CC) bit for a given channel | |
242 | + * that is in chaining mode. | |
243 | + * return DMASUCCESS if successfule, otherwise return DMACHNINVALID | |
244 | + * | |
245 | + * note: if the given channel is not in chaining mode, nothing | |
246 | + * happen. | |
247 | + * | |
248 | + *************************************************************/ | |
249 | +static DMAStatus DMA_Chn_Cnt( LOCATION, unsigned int eumbbar,unsigned int channel ); | |
250 | + | |
251 | +/*********************** App. API *************************** | |
252 | + * App. API are the APIs Kernel provides for the application | |
253 | + * level program | |
254 | + ************************************************************/ | |
255 | +/************************************************************** | |
256 | + * function: DMA_Bld_Curr | |
257 | + * | |
258 | + * description: set current src, dest, byte count registers | |
259 | + * according to the desp for a given channel | |
260 | + * | |
261 | + * if the given channel is busy, no change made, | |
262 | + * return DMACHNBUSY. | |
263 | + * | |
264 | + * otherwise return DMASUCCESS. | |
265 | + * | |
266 | + * note: | |
267 | + **************************************************************/ | |
268 | +static DMAStatus DMA_Bld_Curr( LOCATION, | |
269 | + unsigned int eumbbar, | |
270 | + unsigned int channel, | |
271 | + DMA_CURR desp ); | |
272 | + | |
273 | +/************************************************************** | |
274 | + * function: DMA_Poke_Curr | |
275 | + * | |
276 | + * description: poke the current src, dest, byte count registers | |
277 | + * for a given channel. | |
278 | + * | |
279 | + * return DMASUCCESS if no error otherwise return DMACHNERROR | |
280 | + * | |
281 | + * note: Due to the undeterministic parallelism, in chaining | |
282 | + * mode, the value returned by this function shall | |
283 | + * be taken as reference when the query is made rather | |
284 | + * than the absolute snapshot when the value is returned. | |
285 | + **************************************************************/ | |
286 | +static DMAStatus DMA_Poke_Curr( LOCATION, | |
287 | + unsigned int eumbbar, | |
288 | + unsigned int channel, | |
289 | + DMA_CURR* desp ); | |
290 | + | |
291 | +/************************************************************** | |
292 | + * function: DMA_Bld_Desp | |
293 | + * | |
294 | + * description: set current descriptor address register | |
295 | + * according to the desp for a given channel | |
296 | + * | |
297 | + * if the given channel is busy return DMACHNBUSY | |
298 | + * and no change made, otherwise return DMASUCCESS. | |
299 | + * | |
300 | + * note: | |
301 | + **************************************************************/ | |
302 | +static DMAStatus DMA_Bld_Desp( LOCATION host, | |
303 | + unsigned int eumbbar, | |
304 | + unsigned int channel, | |
305 | + DMA_CDAR desp ); | |
306 | + | |
307 | +/************************************************************** | |
308 | + * function: DMA_Poke_Desp | |
309 | + * | |
310 | + * description: poke the current descriptor address register | |
311 | + * for a given channel | |
312 | + * | |
313 | + * return DMASUCCESS if no error otherwise return | |
314 | + * DMAINVALID | |
315 | + * | |
316 | + * note: Due to the undeterministic parallellism of DMA operation, | |
317 | + * the value returned by this function shall be taken as | |
318 | + * the most recently used descriptor when the last time | |
319 | + * DMA starts a chaining mode operation. | |
320 | + **************************************************************/ | |
321 | +static DMAStatus DMA_Poke_Desp( LOCATION, | |
322 | + unsigned int eumbbar, | |
323 | + unsigned int channel, | |
324 | + DMA_CDAR *desp ); | |
325 | + | |
326 | +#endif |
cpu/mpc824x/drivers/dma/dma1.c
1 | +/************************************************************ | |
2 | + * | |
3 | + * copyright @ Motorola, 1999 | |
4 | + * | |
5 | + * App. API | |
6 | + * | |
7 | + * App. API are the APIs Kernel provides for the application | |
8 | + * level program | |
9 | + * | |
10 | + ************************************************************/ | |
11 | +#include "dma_export.h" | |
12 | +#include "dma.h" | |
13 | + | |
14 | +/* Define a macro to use an optional application-layer print function, if | |
15 | + * one was passed to the library during initialization. If there was no | |
16 | + * function pointer passed, this protects against referencing a NULL pointer. | |
17 | + * Also define The global variable that holds the passed pointer. | |
18 | + */ | |
19 | +#define PRINT if ( app_print ) app_print | |
20 | +static int (*app_print)(char *,...); | |
21 | + | |
22 | +/* Set by call to get_eumbbar during DMA_Initialize. | |
23 | + * This could be globally available to the library, but there is | |
24 | + * an advantage to passing it as a parameter: it is already in a register | |
25 | + * and doesn't have to be loaded from memory. Also, that is the way the | |
26 | + * library was already implemented and I don't want to change it without | |
27 | + * a more detailed analysis. | |
28 | + * It is being set as a global variable during initialization to hide it from | |
29 | + * the DINK application layer, because it is Kahlua-specific. I think that | |
30 | + * get_eumbbar, load_runtime_reg, and store_runtime_reg should be defined in | |
31 | + * a Kahlua-specific library dealing with the embedded utilities memory block. | |
32 | + * Right now, get_eumbbar is defined in dink32/kahlua.s. The other two are | |
33 | + * defined in dink32/drivers/i2c/i2c2.s, drivers/dma/dma2.s, etc. | |
34 | + */ | |
35 | +static unsigned int Global_eumbbar = 0; | |
36 | +extern unsigned int get_eumbbar(); | |
37 | + | |
38 | + | |
39 | +extern unsigned int load_runtime_reg( unsigned int eumbbar, unsigned int reg ); | |
40 | +#pragma Alias( load_runtime_reg, "load_runtime_reg" ); | |
41 | + | |
42 | +extern void store_runtime_reg( unsigned int eumbbar, unsigned int reg, unsigned int val ); | |
43 | +#pragma Alias( store_runtime_reg, "store_runtime_reg" ); | |
44 | + | |
45 | +unsigned int dma_reg_tb[][14] = { | |
46 | + /* local DMA registers */ | |
47 | + { | |
48 | + /* DMA_0_MR */ 0x00001100, | |
49 | + /* DMA_0_SR */ 0x00001104, | |
50 | + /* DMA_0_CDAR */ 0x00001108, | |
51 | + /* DMA_0_SAR */ 0x00001110, | |
52 | + /* DMA_0_DAR */ 0x00001118, | |
53 | + /* DMA_0_BCR */ 0x00001120, | |
54 | + /* DMA_0_NDAR */ 0x00001124, | |
55 | + /* DMA_1_MR */ 0x00001200, | |
56 | + /* DMA_1_SR */ 0x00001204, | |
57 | + /* DMA_1_CDAR */ 0x00001208, | |
58 | + /* DMA_1_SAR */ 0x00001210, | |
59 | + /* DMA_1_DAR */ 0x00001218, | |
60 | + /* DMA_1_BCR */ 0x00001220, | |
61 | + /* DMA_1_NDAR */ 0x00001224, | |
62 | + }, | |
63 | + /* remote DMA registers */ | |
64 | + { | |
65 | + /* DMA_0_MR */ 0x00000100, | |
66 | + /* DMA_0_SR */ 0x00000104, | |
67 | + /* DMA_0_CDAR */ 0x00000108, | |
68 | + /* DMA_0_SAR */ 0x00000110, | |
69 | + /* DMA_0_DAR */ 0x00000118, | |
70 | + /* DMA_0_BCR */ 0x00000120, | |
71 | + /* DMA_0_NDAR */ 0x00000124, | |
72 | + /* DMA_1_MR */ 0x00000200, | |
73 | + /* DMA_1_SR */ 0x00000204, | |
74 | + /* DMA_1_CDAR */ 0x00000208, | |
75 | + /* DMA_1_SAR */ 0x00000210, | |
76 | + /* DMA_1_DAR */ 0x00000218, | |
77 | + /* DMA_1_BCR */ 0x00000220, | |
78 | + /* DMA_1_NDAR */ 0x00000224, | |
79 | + }, | |
80 | +}; | |
81 | + | |
82 | +/* API functions */ | |
83 | + | |
84 | +/* Initialize DMA unit with the following: | |
85 | + * optional pointer to application layer print function | |
86 | + * | |
87 | + * These parameters may be added: | |
88 | + * ??? | |
89 | + * Interrupt enables, modes, etc. are set for each transfer. | |
90 | + * | |
91 | + * This function must be called before DMA unit can be used. | |
92 | + */ | |
93 | +extern | |
94 | +DMA_Status DMA_Initialize( int (*p)(char *,...)) | |
95 | +{ | |
96 | + DMAStatus status; | |
97 | + /* establish the pointer, if there is one, to the application's "printf" */ | |
98 | + app_print = p; | |
99 | + | |
100 | + /* If this is the first call, get the embedded utilities memory block | |
101 | + * base address. I'm not sure what to do about error handling here: | |
102 | + * if a non-zero value is returned, accept it. | |
103 | + */ | |
104 | + if ( Global_eumbbar == 0) | |
105 | + Global_eumbbar = get_eumbbar(); | |
106 | + if ( Global_eumbbar == 0) | |
107 | + { | |
108 | + PRINT( "DMA_Initialize: can't find EUMBBAR\n" ); | |
109 | + return DMA_ERROR; | |
110 | + } | |
111 | + | |
112 | + return DMA_SUCCESS; | |
113 | +} | |
114 | + | |
115 | + | |
116 | +/* Perform the DMA transfer, only direct mode is currently implemented. | |
117 | + * At this point, I think it would be better to define a different | |
118 | + * function for chaining mode. | |
119 | + * Also, I'm not sure if it is appropriate to have the "generic" API | |
120 | + * accept snoop and int_steer parameters. The DINK user interface allows | |
121 | + * them, so for now I'll leave them. | |
122 | + * | |
123 | + * int_steer controls DMA interrupt steering to PCI or local processor | |
124 | + * type is the type of transfer: M2M, M2P, P2M, P2P | |
125 | + * source is the source address of the data | |
126 | + * dest is the destination address of the data | |
127 | + * len is the length of data to transfer | |
128 | + * channel is the DMA channel to use for the transfer | |
129 | + * snoop is the snoop enable control | |
130 | + */ | |
131 | +extern DMA_Status DMA_direct_transfer( DMA_INTERRUPT_STEER int_steer, | |
132 | + DMA_TRANSFER_TYPE type, | |
133 | + unsigned int source, | |
134 | + unsigned int dest, | |
135 | + unsigned int len, | |
136 | + DMA_CHANNEL channel, | |
137 | + DMA_SNOOP_MODE snoop) | |
138 | +{ | |
139 | + DMA_MR md; | |
140 | + DMA_CDAR cdar; | |
141 | + /* it's inappropriate for curr to be a struct, but I'll leave it */ | |
142 | + DMA_CURR curr; | |
143 | + | |
144 | + DMAStatus stat; | |
145 | + | |
146 | + /* The rest of this code was moved from device.c test_dma to here. | |
147 | + * It needs to be cleaned up and validated, but at least it is removed | |
148 | + * from the application and API. Most of the mode is left hard coded. | |
149 | + * This should be changed after the final API is defined and the user | |
150 | + * application has a way to control the transfer. | |
151 | + * | |
152 | + */ | |
153 | + | |
154 | + if ( DMA_Get_Mode( LOCAL, Global_eumbbar, channel, &md ) != DMASUCCESS ) | |
155 | + { | |
156 | + return DMA_ERROR; | |
157 | + } | |
158 | + | |
159 | + md.irqs = int_steer; | |
160 | + md.pde = 0; | |
161 | + md.dahts = 3; /* 8 - byte */ | |
162 | + md.sahts = 3; /* 8 - byte */ | |
163 | + md.dahe = 0; | |
164 | + md.sahe = 0; | |
165 | + md.prc = 0; | |
166 | + /* if steering interrupts to local processor, use polling mode */ | |
167 | + if ( int_steer == DMA_INT_STEER_PCI ) | |
168 | + { | |
169 | + md.eie = 1; | |
170 | + md.eotie = 1; | |
171 | + } else { | |
172 | + md.eie = 0; | |
173 | + md.eotie = 0; | |
174 | + } | |
175 | + md.dl = 0; | |
176 | + md.ctm = 1; /* direct mode */ | |
177 | + md.cc = 0; | |
178 | + | |
179 | + /* validate the length range */ | |
180 | + if (len > 0x3ffffff ) | |
181 | + { | |
182 | + PRINT( "dev DMA: length of transfer too large: %d\n", len ); | |
183 | + return DMA_ERROR; | |
184 | + } | |
185 | + | |
186 | + /* inappropriate to use a struct, but leave as is for now */ | |
187 | + curr.src_addr = source; | |
188 | + curr.dest_addr = dest; | |
189 | + curr.byte_cnt = len; | |
190 | + | |
191 | + (void)DMA_Poke_Desp( LOCAL, Global_eumbbar, channel, &cdar ); | |
192 | + cdar.snen = snoop; | |
193 | + cdar.ctt = type; | |
194 | + | |
195 | + if ( ( stat = DMA_Bld_Desp( LOCAL, Global_eumbbar, channel, cdar )) | |
196 | + != DMASUCCESS || | |
197 | + ( stat = DMA_Bld_Curr( LOCAL, Global_eumbbar, channel, curr )) | |
198 | + != DMASUCCESS || | |
199 | + ( stat = DMA_Set_Mode( LOCAL, Global_eumbbar, channel, md )) | |
200 | + != DMASUCCESS || | |
201 | + ( stat = DMA_Start( LOCAL, Global_eumbbar, channel )) | |
202 | + != DMASUCCESS ) | |
203 | + { | |
204 | + if ( stat == DMACHNBUSY ) | |
205 | + { | |
206 | + PRINT( "dev DMA: channel %d busy.\n", channel ); | |
207 | + } | |
208 | + else | |
209 | + { | |
210 | + PRINT( "dev DMA: invalid channel request.\n", channel ); | |
211 | + } | |
212 | + | |
213 | + return DMA_ERROR; | |
214 | + } | |
215 | + | |
216 | +/* Since we are interested at the DMA performace right now, | |
217 | + we are going to do as less as possible to burden the | |
218 | + 603e core. | |
219 | + | |
220 | + if you have epic enabled or don't care the return from | |
221 | + DMA operation, you can just return SUCCESS. | |
222 | + | |
223 | + if you don't have epic enabled and care the DMA result, | |
224 | + you can use the polling method below. | |
225 | + | |
226 | + Note: I'll attempt to activate the code for handling polling. | |
227 | + */ | |
228 | + | |
229 | +#if 0 | |
230 | + /* if steering interrupt to local processor, let it handle results */ | |
231 | + if ( int_steer == DMA_INT_STEER_LOCAL ) | |
232 | + { | |
233 | + return DMA_SUCCESS; | |
234 | + } | |
235 | + | |
236 | + /* polling since interrupt goes to PCI */ | |
237 | + do | |
238 | + { | |
239 | + stat = DMA_ISR( Global_eumbbar, channel, dma_error_func, | |
240 | + dma_error_func, dma_error_func, dma_error_func ); | |
241 | + } | |
242 | + while ( stat == DMANOEVENT ); | |
243 | +#endif | |
244 | + | |
245 | + return DMA_SUCCESS; | |
246 | +} | |
247 | + | |
248 | +/* DMA library internal functions */ | |
249 | + | |
250 | +/** | |
251 | + * Note: | |
252 | + * | |
253 | + * In all following functions, the host (KAHLUA) processor has a | |
254 | + * choice of accessing on board local DMA (LOCAL), | |
255 | + * or DMA on a distributed KAHLUA (REMOTE). In either case, | |
256 | + * the caller shall pass the configured embedded utility memory | |
257 | + * block base address relative to the DMA. If LOCAL DMA is used, | |
258 | + * this parameter shall be EUMBBAR, if REMOTE is used, the | |
259 | + * parameter shall be the corresponding PCSRBAR. | |
260 | + **/ | |
261 | + | |
262 | +/************************************************************** | |
263 | + * function: DMA_Get_Stat | |
264 | + * | |
265 | + * description: return the content of status register of | |
266 | + * the given DMA channel | |
267 | + * | |
268 | + * if error, reserved0 field all 1s. | |
269 | + **************************************************************/ | |
270 | +static | |
271 | +DMAStatus DMA_Get_Stat( LOCATION host, unsigned int eumbbar, unsigned int channel, DMA_SR *stat ) | |
272 | +{ | |
273 | + unsigned int tmp; | |
274 | + | |
275 | + if ( channel != 0 && channel != 1 || stat == 0 ) | |
276 | + { | |
277 | + return DMAINVALID; | |
278 | + } | |
279 | + | |
280 | + tmp = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SR_REG] ); | |
281 | +#ifdef DMADBG0 | |
282 | + PRINT( "%s(%d): %s DMA %d (0x%08x) stat = 0x%08x\n", __FILE__, __LINE__, | |
283 | + ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SR_REG], tmp ); | |
284 | +#endif | |
285 | + | |
286 | + stat->reserved0 = ( tmp & 0xffffff00 ) >> 8; | |
287 | + stat->lme = ( tmp & 0x00000080 ) >> 7; | |
288 | + stat->reserved1 = ( tmp & 0x00000060 ) >> 5; | |
289 | + stat->pe = ( tmp & 0x00000010 ) >> 4; | |
290 | + stat->reserved2 = ( tmp & 0x00000008 ) >> 3; | |
291 | + stat->cb = ( tmp & 0x00000004 ) >> 2; | |
292 | + stat->eosi = ( tmp & 0x00000002 ) >> 1; | |
293 | + stat->eocai = ( tmp & 0x00000001 ); | |
294 | + | |
295 | + return DMASUCCESS; | |
296 | +} | |
297 | + | |
298 | +/************************************************************** | |
299 | + * function: DMA_Get_Mode | |
300 | + * | |
301 | + * description: return the content of mode register of the | |
302 | + * given DMA channel | |
303 | + * | |
304 | + * if error, return DMAINVALID, otherwise return | |
305 | + * DMASUCCESS | |
306 | + **************************************************************/ | |
307 | +static | |
308 | +DMAStatus DMA_Get_Mode( LOCATION host, unsigned eumbbar, unsigned int channel, DMA_MR *mode ) | |
309 | +{ | |
310 | + unsigned int tmp; | |
311 | + if ( channel != 0 && channel != 1 || mode == 0 ) | |
312 | + { | |
313 | + return DMAINVALID; | |
314 | + } | |
315 | + | |
316 | + tmp = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_MR_REG] ); | |
317 | + | |
318 | +#ifdef DMADBG0 | |
319 | + PRINT( "%s(%d): %s DMA %d (0x%08x) mode = 0x%08x\n", __FILE__, __LINE__, | |
320 | + ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_MR_REG], tmp ); | |
321 | +#endif | |
322 | + | |
323 | + mode->reserved0 = (tmp & 0xfff00000) >> 20; | |
324 | + mode->irqs = (tmp & 0x00080000) >> 19; | |
325 | + mode->pde = (tmp & 0x00040000) >> 18; | |
326 | + mode->dahts = (tmp & 0x00030000) >> 16; | |
327 | + mode->sahts = (tmp & 0x0000c000) >> 14; | |
328 | + mode->dahe = (tmp & 0x00002000) >> 13; | |
329 | + mode->sahe = (tmp & 0x00001000) >> 12; | |
330 | + mode->prc = (tmp & 0x00000c00) >> 10; | |
331 | + mode->reserved1 = (tmp & 0x00000200) >> 9; | |
332 | + mode->eie = (tmp & 0x00000100) >> 8; | |
333 | + mode->eotie = (tmp & 0x00000080) >> 7; | |
334 | + mode->reserved2 = (tmp & 0x00000070) >> 4; | |
335 | + mode->dl = (tmp & 0x00000008) >> 3; | |
336 | + mode->ctm = (tmp & 0x00000004) >> 2; | |
337 | + mode->cc = (tmp & 0x00000002) >> 1; | |
338 | + mode->cs = (tmp & 0x00000001); | |
339 | + | |
340 | + return DMASUCCESS; | |
341 | +} | |
342 | + | |
343 | +/************************************************************** | |
344 | + * function: DMA_Set_Mode | |
345 | + * | |
346 | + * description: Set a new mode to a given DMA channel | |
347 | + * | |
348 | + * note: It is not a good idea of changing the DMA mode during | |
349 | + * the middle of a transaction. | |
350 | + **************************************************************/ | |
351 | +static | |
352 | +DMAStatus DMA_Set_Mode( LOCATION host, unsigned eumbbar, unsigned int channel, DMA_MR mode ) | |
353 | +{ | |
354 | + unsigned int tmp; | |
355 | + if ( channel != 0 && channel != 1 ) | |
356 | + { | |
357 | + return DMAINVALID; | |
358 | + } | |
359 | + | |
360 | + tmp = ( mode.reserved0 & 0xfff ) << 20; | |
361 | + tmp |= ( ( mode.irqs & 0x1 ) << 19); | |
362 | + tmp |= ( ( mode.pde & 0x1 ) << 18 ); | |
363 | + tmp |= ( ( mode.dahts & 0x3 ) << 16 ); | |
364 | + tmp |= ( ( mode.sahts & 0x3 ) << 14 ); | |
365 | + tmp |= ( ( mode.dahe & 0x1 ) << 13 ); | |
366 | + tmp |= ( ( mode.sahe & 0x1 ) << 12 ); | |
367 | + tmp |= ( ( mode.prc & 0x3 ) << 10 ); | |
368 | + tmp |= ( ( mode.reserved1 & 0x1 ) << 9 ); | |
369 | + tmp |= ( ( mode.eie & 0x1 ) << 8 ); | |
370 | + tmp |= ( ( mode.eotie & 0x1 ) << 7 ); | |
371 | + tmp |= ( ( mode.reserved2 & 0x7 ) << 4 ); | |
372 | + tmp |= ( ( mode.dl & 0x1 ) << 3 ); | |
373 | + tmp |= ( ( mode.ctm & 0x1 ) << 2 ); | |
374 | + tmp |= ( ( mode.cc & 0x1 ) << 1 ) ; | |
375 | + tmp |= ( mode.cs & 0x1 ); | |
376 | + | |
377 | + store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], tmp ); | |
378 | + return DMASUCCESS; | |
379 | +} | |
380 | + | |
381 | +/************************************************************ | |
382 | + * function: DMA_Start | |
383 | + * | |
384 | + * description: start a given DMA channel transaction | |
385 | + * return DMASUCCESS if success otherwise return | |
386 | + * DMAStatus value | |
387 | + * | |
388 | + * note: this function will clear DMA_MR(CC) first, then | |
389 | + * set DMA_MR(CC). | |
390 | + ***********************************************************/ | |
391 | +static | |
392 | +DMAStatus DMA_Start( LOCATION host, unsigned int eumbbar, unsigned int channel ) | |
393 | +{ | |
394 | + DMA_SR stat; | |
395 | + unsigned int mode; | |
396 | + | |
397 | + if ( channel != 0 && channel != 1 ) | |
398 | + { | |
399 | + return DMAINVALID; | |
400 | + } | |
401 | + | |
402 | + if ( DMA_Get_Stat( host, eumbbar, channel, &stat ) != DMASUCCESS ) | |
403 | + { | |
404 | + return DMAINVALID; | |
405 | + } | |
406 | + | |
407 | + if ( stat.cb == 1 ) | |
408 | + { | |
409 | + /* DMA is not free */ | |
410 | + return DMACHNBUSY; | |
411 | + } | |
412 | + | |
413 | + mode = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG] ); | |
414 | + /* clear DMA_MR(CS) */ | |
415 | + mode &= 0xfffffffe; | |
416 | + store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], mode ); | |
417 | + | |
418 | + /* set DMA_MR(CS) */ | |
419 | + mode |= CS; | |
420 | + store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], mode ); | |
421 | + return DMASUCCESS; | |
422 | +} | |
423 | + | |
424 | +/*********************************************************** | |
425 | + * function: DMA_Halt | |
426 | + * | |
427 | + * description: halt the current dma transaction on the specified | |
428 | + * channel. | |
429 | + * return DMASUCCESS if success otherwise return DMAINVALID | |
430 | + * | |
431 | + * note: if the specified DMA channel is idle, nothing happens | |
432 | + *************************************************************/ | |
433 | +static | |
434 | +DMAStatus DMA_Halt( LOCATION host, unsigned int eumbbar, unsigned int channel ) | |
435 | +{ | |
436 | + unsigned int mode; | |
437 | + if ( channel != 0 && channel != 1 ) | |
438 | + { | |
439 | + return DMAINVALID; | |
440 | + } | |
441 | + | |
442 | + mode = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG]); | |
443 | + | |
444 | + /* clear DMA_MR(CS) */ | |
445 | + mode &= 0xfffffffe; | |
446 | + store_runtime_reg(eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], mode ); | |
447 | + return DMASUCCESS; | |
448 | +} | |
449 | + | |
450 | +/************************************************************* | |
451 | + * function: DMA_Chn_Cnt | |
452 | + * | |
453 | + * description: set the DMA_MR(CC) bit for a given channel | |
454 | + * that is in chaining mode. | |
455 | + * return DMASUCCESS if successfule, otherwise return | |
456 | + * DMAINVALID. | |
457 | + * | |
458 | + * note: if the given channel is not in chaining mode, nothing | |
459 | + * happen. | |
460 | + * | |
461 | + *************************************************************/ | |
462 | +static | |
463 | +DMAStatus DMA_Chn_Cnt( LOCATION host, unsigned int eumbbar, unsigned int channel ) | |
464 | +{ | |
465 | + DMA_MR mode; | |
466 | + if ( channel != 0 && channel != 1 ) | |
467 | + { | |
468 | + return DMAINVALID; | |
469 | + } | |
470 | + | |
471 | + if ( DMA_Get_Mode( host, eumbbar, channel, &mode ) != DMASUCCESS ) | |
472 | + { | |
473 | + return DMAINVALID; | |
474 | + } | |
475 | + | |
476 | + if ( mode.ctm == 0 ) | |
477 | + { | |
478 | + /* either illegal mode or not chaining mode */ | |
479 | + return DMAINVALID; | |
480 | + } | |
481 | + | |
482 | + mode.cc = 1; | |
483 | + return DMA_Set_Mode( host, eumbbar, channel, mode ); | |
484 | +} | |
485 | + | |
486 | +/************************************************************** | |
487 | + * function: DMA_Bld_Desp | |
488 | + * | |
489 | + * description: set current descriptor address register | |
490 | + * according to the desp for a given channel | |
491 | + * | |
492 | + * if the given channel is busy return DMACHNBUSY | |
493 | + * and no change made, otherwise return DMASUCCESS. | |
494 | + * | |
495 | + * note: | |
496 | + **************************************************************/ | |
497 | +static | |
498 | +DMAStatus DMA_Bld_Desp( LOCATION host, | |
499 | + unsigned int eumbbar, | |
500 | + unsigned int channel, | |
501 | + DMA_CDAR desp ) | |
502 | +{ | |
503 | + DMA_SR status; | |
504 | + unsigned int temp; | |
505 | + | |
506 | + if ( channel != 0 && channel != 1 ) | |
507 | + { | |
508 | + /* channel number out of range */ | |
509 | + return DMAINVALID; | |
510 | + } | |
511 | + | |
512 | + if ( DMA_Get_Stat( host, eumbbar, channel, &status ) != DMASUCCESS ) | |
513 | + { | |
514 | + return DMAINVALID; | |
515 | + } | |
516 | + | |
517 | + if ( status.cb == 1 ) | |
518 | + { | |
519 | + /* channel busy */ | |
520 | + return DMACHNBUSY; | |
521 | + } | |
522 | + | |
523 | + temp = ( desp.cda & 0x7ffffff ) << 5; | |
524 | + temp |= (( desp.snen & 0x1 ) << 4 ); | |
525 | + temp |= (( desp.eosie & 0x1 ) << 3 ); | |
526 | + temp |= (( desp.ctt & 0x3 ) << 1 ); | |
527 | + temp |= ( desp.eotd & 0x1 ); | |
528 | + | |
529 | + store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], temp ); | |
530 | + | |
531 | +#ifdef DMADBG0 | |
532 | + PRINT( "%s(%d): %s DMA %d (0x%08x) cdar := 0x%08x\n", __FILE__, __LINE__, | |
533 | + ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], temp ); | |
534 | +#endif | |
535 | + | |
536 | + return DMASUCCESS; | |
537 | +} | |
538 | + | |
539 | +/************************************************************** | |
540 | + * function: DMA_Poke_Desp | |
541 | + * | |
542 | + * description: poke the current descriptor address register | |
543 | + * for a given channel | |
544 | + * | |
545 | + * return DMASUCCESS if no error | |
546 | + * | |
547 | + * note: Due to the undeterministic parallellism of DMA operation, | |
548 | + * the value returned by this function shall be taken as | |
549 | + * the most recently used descriptor when the last time | |
550 | + * DMA starts a chaining mode operation. | |
551 | + **************************************************************/ | |
552 | +static | |
553 | +DMAStatus DMA_Poke_Desp( LOCATION host, | |
554 | + unsigned int eumbbar, | |
555 | + unsigned int channel, | |
556 | + DMA_CDAR *desp ) | |
557 | +{ | |
558 | + unsigned int cdar; | |
559 | + if ( channel != 0 && channel != 1 || desp == 0 ) | |
560 | + { | |
561 | + return DMAINVALID; | |
562 | + } | |
563 | + | |
564 | + cdar = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG] ); | |
565 | + | |
566 | +#ifdef DMADBG0 | |
567 | + PRINT( "%s(%d): %s DMA %d (0x%08x) cdar : 0x%08x\n", __FILE__, __LINE__, | |
568 | + ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], cdar ); | |
569 | +#endif | |
570 | + | |
571 | + | |
572 | + desp->cda = ( cdar & 0xffffffe0 ) >> 5; | |
573 | + desp->snen = ( cdar & 0x00000010 ) >> 4; | |
574 | + desp->eosie = ( cdar & 0x00000008 ) >> 3; | |
575 | + desp->ctt = ( cdar & 0x00000006 ) >> 1; | |
576 | + desp->eotd = ( cdar & 0x00000001 ); | |
577 | + | |
578 | + return DMASUCCESS; | |
579 | +} | |
580 | + | |
581 | +/************************************************************** | |
582 | + * function: DMA_Bld_Curr | |
583 | + * | |
584 | + * description: set current src, dest, byte count registers | |
585 | + * according to the desp for a given channel | |
586 | + * return DMASUCCESS if no error. | |
587 | + * | |
588 | + * note: | |
589 | + **************************************************************/ | |
590 | +static | |
591 | +DMAStatus DMA_Bld_Curr( LOCATION host, | |
592 | + unsigned int eumbbar, | |
593 | + unsigned int channel, | |
594 | + DMA_CURR desp ) | |
595 | +{ | |
596 | + DMA_SR status; | |
597 | + if ( channel != 0 && channel != 1 ) | |
598 | + { | |
599 | + /* channel number out of range */ | |
600 | + return DMAINVALID; | |
601 | + } | |
602 | + | |
603 | + if ( DMA_Get_Stat( host, eumbbar, channel, &status ) != DMASUCCESS ) | |
604 | + { | |
605 | + return DMAINVALID; | |
606 | + } | |
607 | + | |
608 | + if ( status.cb == 1 ) | |
609 | + { | |
610 | + /* channel busy */ | |
611 | + return DMACHNBUSY; | |
612 | + } | |
613 | + | |
614 | + desp.byte_cnt &= 0x03ffffff; /* upper 6-bits are 0s */ | |
615 | + | |
616 | + store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SAR_REG], desp.src_addr ); | |
617 | +#ifdef DMADBG0 | |
618 | + PRINT( "%s(%d): %s DMA %d (0x%08x) src := 0x%08x\n", __FILE__, __LINE__, | |
619 | + ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp.src_addr ); | |
620 | +#endif | |
621 | + | |
622 | + store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_DAR_REG], desp.dest_addr ); | |
623 | +#ifdef DMADBG0 | |
624 | + PRINT( "%s(%d): %s DMA %d (0x%08x) dest := 0x%08x\n", __FILE__, __LINE__, | |
625 | + ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp.dest_addr ); | |
626 | +#endif | |
627 | + | |
628 | + store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_BCR_REG], desp.byte_cnt ); | |
629 | +#ifdef DMADBG0 | |
630 | + PRINT( "%s(%d): %s DMA %d (0x%08x) count := 0x%08x\n", __FILE__, __LINE__, | |
631 | + ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp.byte_cnt ); | |
632 | +#endif | |
633 | + | |
634 | + | |
635 | + return DMASUCCESS; | |
636 | + | |
637 | +} | |
638 | + | |
639 | +/************************************************************** | |
640 | + * function: DMA_Poke_Curr | |
641 | + * | |
642 | + * description: poke the current src, dest, byte count registers | |
643 | + * for a given channel. | |
644 | + * | |
645 | + * return DMASUCCESS if no error | |
646 | + * | |
647 | + * note: Due to the undeterministic parallelism, in chaining | |
648 | + * mode, the value returned by this function shall | |
649 | + * be taken as reference when the query is made rather | |
650 | + * than the absolute snapshot when the value is returned. | |
651 | + **************************************************************/ | |
652 | +static | |
653 | +DMAStatus DMA_Poke_Curr( LOCATION host, | |
654 | + unsigned int eumbbar, | |
655 | + unsigned int channel, | |
656 | + DMA_CURR* desp ) | |
657 | +{ | |
658 | + if ( channel != 0 && channel != 1 || desp == 0 ) | |
659 | + { | |
660 | + return DMAINVALID; | |
661 | + } | |
662 | + | |
663 | + desp->src_addr = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SAR_REG] ); | |
664 | +#ifdef DMADBG0 | |
665 | + PRINT( "%s(%d): %s DMA %d (0x%08x) src : 0x%08x\n", __FILE__, __LINE__, | |
666 | + ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp->src_addr ); | |
667 | +#endif | |
668 | + | |
669 | + desp->dest_addr = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_DAR_REG] ); | |
670 | +#ifdef DMADBG0 | |
671 | + PRINT( "%s(%d): %s DMA %d (0x%08x) dest : 0x%08x\n", __FILE__, __LINE__, | |
672 | + ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp->dest_addr ); | |
673 | +#endif | |
674 | + | |
675 | + desp->byte_cnt = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_BCR_REG] ); | |
676 | +#ifdef DMADBG0 | |
677 | + PRINT( "%s(%d): %s DMA %d (0x%08x) count : 0x%08x\n", __FILE__, __LINE__, | |
678 | + ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp->byte_cnt ); | |
679 | +#endif | |
680 | + | |
681 | + | |
682 | + return DMASUCCESS; | |
683 | +} | |
684 | + | |
685 | +/***************************************************************** | |
686 | + * function: dma_error_func | |
687 | + * | |
688 | + * description: display the error information | |
689 | + * | |
690 | + * note: This seems like a highly convoluted way to handle messages, | |
691 | + * but I'll leave it as it was in device.c when I moved it into the | |
692 | + * DMA library source. | |
693 | + ****************************************************************/ | |
694 | +static | |
695 | +DMAStatus dma_error_func( unsigned int eumbbar, unsigned int chn, DMAStatus err) | |
696 | +{ | |
697 | + unsigned char *msg[] = | |
698 | + { | |
699 | + "Local Memory Error", | |
700 | + "PCI Error", | |
701 | + "Channel Busy", | |
702 | + "End-of-Segment Interrupt", | |
703 | + "End-of-Chain/Direct Interrupt", | |
704 | + }; | |
705 | + | |
706 | + if ( err >= DMALMERROR && err <= DMAEOCAINT ) | |
707 | + { | |
708 | + PRINT( "DMA Status: channel %d %s\n", chn, msg[err-DMASUCCESS-1] ); | |
709 | + } | |
710 | + | |
711 | + return err; | |
712 | + | |
713 | +} | |
714 | + | |
715 | +/************************************************************* | |
716 | + * function: DMA_ISR | |
717 | + * | |
718 | + * description: DMA interrupt service routine | |
719 | + * return DMAStatus value based on | |
720 | + * the status | |
721 | + * | |
722 | + *************************************************************/ | |
723 | +static | |
724 | +DMAStatus DMA_ISR( unsigned int eumbbar, | |
725 | + unsigned int channel, | |
726 | + DMAStatus (*lme_func)( unsigned int, unsigned int, DMAStatus ), | |
727 | + DMAStatus (*pe_func) ( unsigned int, unsigned int, DMAStatus ), | |
728 | + DMAStatus (*eosi_func)( unsigned int, unsigned int, DMAStatus ), | |
729 | + DMAStatus (*eocai_func)(unsigned int, unsigned int, DMAStatus )) | |
730 | +{ | |
731 | + | |
732 | + DMA_SR stat; | |
733 | + DMAStatus rval = DMANOEVENT; | |
734 | + unsigned int temp; | |
735 | + | |
736 | + if ( channel != 0 && channel != 1 ) | |
737 | + { | |
738 | + return DMAINVALID; | |
739 | + } | |
740 | + | |
741 | + if ( DMA_Get_Stat( LOCAL, eumbbar, channel, &stat ) != DMASUCCESS ) | |
742 | + { | |
743 | + return DMAINVALID; | |
744 | + } | |
745 | + | |
746 | + if ( stat.lme == 1 ) | |
747 | + { | |
748 | + /* local memory error */ | |
749 | + rval = DMALMERROR; | |
750 | + if ( lme_func != 0 ) | |
751 | + { | |
752 | + rval = (*lme_func)(eumbbar, channel, DMALMERROR ); | |
753 | + } | |
754 | + | |
755 | + } | |
756 | + else if ( stat.pe == 1 ) | |
757 | + { | |
758 | + /* PCI error */ | |
759 | + rval = DMAPERROR; | |
760 | + if ( pe_func != 0 ) | |
761 | + { | |
762 | + rval = (*pe_func)(eumbbar, channel, DMAPERROR ); | |
763 | + } | |
764 | + | |
765 | + } | |
766 | + else if ( stat.eosi == 1 ) | |
767 | + { | |
768 | + /* end-of-segment interrupt */ | |
769 | + rval = DMAEOSINT; | |
770 | + if ( eosi_func != 0 ) | |
771 | + { | |
772 | + rval = (*eosi_func)(eumbbar, channel, DMAEOSINT ); | |
773 | + } | |
774 | + } | |
775 | + else | |
776 | + { | |
777 | + /* End-of-chain/direct interrupt */ | |
778 | + rval = DMAEOCAINT; | |
779 | + if ( eocai_func != 0 ) | |
780 | + { | |
781 | + rval = (*eocai_func)(eumbbar, channel, DMAEOCAINT ); | |
782 | + } | |
783 | + } | |
784 | + | |
785 | + temp = ( stat.reserved0 & 0xffffff ) << 8; | |
786 | + temp |= ( ( stat.lme & 0x1 ) << 7 ); /* write one to clear */ | |
787 | + temp |= ( ( stat.reserved1 & 0x3 ) << 5 ); | |
788 | + temp |= ( ( stat.pe & 0x1 ) << 4 ); /* write one to clear */ | |
789 | + temp |= ( ( stat.reserved2 & 0x1 ) << 3 ); | |
790 | + temp |= ( ( stat.cb & 0x1 ) << 2 ); /* write one to clear */ | |
791 | + temp |= ( ( stat.eosi & 0x1 ) << 1 ); /* write one to clear */ | |
792 | + temp |= ( stat.eocai & 0x1 ); /* write one to clear */ | |
793 | + | |
794 | + store_runtime_reg( eumbbar, dma_reg_tb[LOCAL][channel*NUM_DMA_REG + DMA_SR_REG], temp ); | |
795 | + | |
796 | +#ifdef DMADBG0 | |
797 | + PRINT( "%s(%d): DMA channel %d SR := 0x%08x\n", __FILE__, __LINE__, channel, temp ); | |
798 | +#endif | |
799 | + | |
800 | + return rval; | |
801 | +} |
cpu/mpc824x/drivers/dma/dma2.S
1 | +/************************************** | |
2 | + * | |
3 | + * copyright @ Motorola, 1999 | |
4 | + * | |
5 | + **************************************/ | |
6 | + | |
7 | +/********************************************************** | |
8 | + * function: load_runtime_reg | |
9 | + * | |
10 | + * input: r3 - value of eumbbar | |
11 | + * r4 - register offset in embedded utility space | |
12 | + * | |
13 | + * output: r3 - register content | |
14 | + **********************************************************/ | |
15 | + .text | |
16 | + .align 2 | |
17 | + .global load_runtime_reg | |
18 | + | |
19 | +load_runtime_reg: | |
20 | + | |
21 | + lwbrx r3,r4,r3 | |
22 | + sync | |
23 | + | |
24 | + bclr 20, 0 | |
25 | + | |
26 | +/**************************************************************** | |
27 | + * function: store_runtime_reg | |
28 | + * | |
29 | + * input: r3 - value of eumbbar | |
30 | + * r4 - register offset in embedded utility space | |
31 | + * r5 - new value to be stored | |
32 | + * | |
33 | + ****************************************************************/ | |
34 | + .text | |
35 | + .align 2 | |
36 | + .global store_runtime_reg | |
37 | +store_runtime_reg: | |
38 | + | |
39 | + stwbrx r5, r4, r3 | |
40 | + sync | |
41 | + | |
42 | + bclr 20,0 |
cpu/mpc824x/drivers/dma/dma_export.h
1 | +#ifndef DMA_EXPORT_H | |
2 | +#define DMA_EXPORT_H | |
3 | + | |
4 | +/**************************************************** | |
5 | + * $Id: | |
6 | + * | |
7 | + * Copyright Motorola 1999 | |
8 | + * | |
9 | + * $Log: | |
10 | + * | |
11 | + ****************************************************/ | |
12 | + | |
13 | +/* These are the defined return values for the DMA_* functions. | |
14 | + * Any non-zero value indicates failure. Failure modes can be added for | |
15 | + * more detailed error reporting. | |
16 | + */ | |
17 | +typedef enum _dma_status | |
18 | +{ | |
19 | + DMA_SUCCESS = 0, | |
20 | + DMA_ERROR, | |
21 | +} DMA_Status; | |
22 | + | |
23 | +/* These are the defined channel transfer types. */ | |
24 | +typedef enum _dma_transfer_types | |
25 | +{ | |
26 | + DMA_M2M = 0, /* local memory to local memory */ | |
27 | + DMA_M2P = 1, /* local memory to PCI */ | |
28 | + DMA_P2M = 2, /* PCI to local memory */ | |
29 | + DMA_P2P = 3, /* PCI to PCI */ | |
30 | +} DMA_TRANSFER_TYPE; | |
31 | + | |
32 | +typedef enum _dma_interrupt_steer | |
33 | +{ | |
34 | + DMA_INT_STEER_LOCAL = 0, /* steer DMA int to local processor */ | |
35 | + DMA_INT_STEER_PCI = 1, /* steer DMA int to PCI bus through INTA_ */ | |
36 | +} DMA_INTERRUPT_STEER; | |
37 | + | |
38 | +typedef enum _dma_channel | |
39 | +{ | |
40 | + DMA_CHN_0 = 0, /* kahlua has two dma channels: 0 and 1 */ | |
41 | + DMA_CHN_1 = 1, | |
42 | +} DMA_CHANNEL; | |
43 | + | |
44 | +typedef enum _dma_snoop_mode | |
45 | +{ | |
46 | + DMA_SNOOP_DISABLE = 0, | |
47 | + DMA_SNOOP_ENABLE = 1, | |
48 | +} DMA_SNOOP_MODE; | |
49 | + | |
50 | +/******************** App. API ******************** | |
51 | + * The application API is for user level application | |
52 | + * to use the functionality provided by DMA driver. | |
53 | + * This is a "generic" DMA interface, it should contain | |
54 | + * nothing specific to the Kahlua implementation. | |
55 | + * Only the generic functions are exported by the library. | |
56 | + * | |
57 | + * Note: Its App.s responsibility to swap the data | |
58 | + * byte. In our API, we currently transfer whatever | |
59 | + * we are given - Big/Little Endian. This could | |
60 | + * become part of the DMA config, though. | |
61 | + **************************************************/ | |
62 | + | |
63 | + | |
64 | +/* Initialize DMA unit with the following: | |
65 | + * optional pointer to application layer print function | |
66 | + * | |
67 | + * These parameters may be added: | |
68 | + * ??? | |
69 | + * Interrupt enables, modes, etc. are set for each transfer. | |
70 | + * | |
71 | + * This function must be called before DMA unit can be used. | |
72 | + */ | |
73 | +extern DMA_Status DMA_Initialize( | |
74 | + int (*app_print_function)(char *,...)); /* pointer to optional "printf" | |
75 | + * provided by application | |
76 | + */ | |
77 | + | |
78 | +/* Perform the DMA transfer, only direct mode is currently implemented. | |
79 | + * At this point, I think it would be better to define a different | |
80 | + * function for chaining mode. | |
81 | + * Also, I'm not sure if it is appropriate to have the "generic" API | |
82 | + * accept snoop and int_steer parameters. The DINK user interface allows | |
83 | + * them, so for now I'll leave them. | |
84 | + * | |
85 | + * int_steer controls DMA interrupt steering to PCI or local processor | |
86 | + * type is the type of transfer: M2M, M2P, P2M, P2P | |
87 | + * source is the source address of the data | |
88 | + * dest is the destination address of the data | |
89 | + * len is the length of data to transfer | |
90 | + * channel is the DMA channel to use for the transfer | |
91 | + * snoop is the snoop enable control | |
92 | + */ | |
93 | +extern DMA_Status DMA_direct_transfer( DMA_INTERRUPT_STEER int_steer, | |
94 | + DMA_TRANSFER_TYPE type, | |
95 | + unsigned int source, | |
96 | + unsigned int dest, | |
97 | + unsigned int len, | |
98 | + DMA_CHANNEL channel, | |
99 | + DMA_SNOOP_MODE snoop); | |
100 | +#endif |
cpu/mpc824x/drivers/dma_export.h
1 | +#ifndef DMA_EXPORT_H | |
2 | +#define DMA_EXPORT_H | |
3 | + | |
4 | +/**************************************************** | |
5 | + * $Id: | |
6 | + * | |
7 | + * Copyright Motorola 1999 | |
8 | + * | |
9 | + * $Log: | |
10 | + * | |
11 | + ****************************************************/ | |
12 | + | |
13 | +/* These are the defined return values for the DMA_* functions. | |
14 | + * Any non-zero value indicates failure. Failure modes can be added for | |
15 | + * more detailed error reporting. | |
16 | + */ | |
17 | +typedef enum _dma_status | |
18 | +{ | |
19 | + DMA_SUCCESS = 0, | |
20 | + DMA_ERROR, | |
21 | +} DMA_Status; | |
22 | + | |
23 | +/* These are the defined channel transfer types. */ | |
24 | +typedef enum _dma_transfer_types | |
25 | +{ | |
26 | + DMA_M2M = 0, /* local memory to local memory */ | |
27 | + DMA_M2P = 1, /* local memory to PCI */ | |
28 | + DMA_P2M = 2, /* PCI to local memory */ | |
29 | + DMA_P2P = 3, /* PCI to PCI */ | |
30 | +} DMA_TRANSFER_TYPE; | |
31 | + | |
32 | +typedef enum _dma_interrupt_steer | |
33 | +{ | |
34 | + DMA_INT_STEER_LOCAL = 0, /* steer DMA int to local processor */ | |
35 | + DMA_INT_STEER_PCI = 1, /* steer DMA int to PCI bus through INTA_ */ | |
36 | +} DMA_INTERRUPT_STEER; | |
37 | + | |
38 | +typedef enum _dma_channel | |
39 | +{ | |
40 | + DMA_CHN_0 = 0, /* kahlua has two dma channels: 0 and 1 */ | |
41 | + DMA_CHN_1 = 1, | |
42 | +} DMA_CHANNEL; | |
43 | + | |
44 | +typedef enum _dma_snoop_mode | |
45 | +{ | |
46 | + DMA_SNOOP_DISABLE = 0, | |
47 | + DMA_SNOOP_ENABLE = 1, | |
48 | +} DMA_SNOOP_MODE; | |
49 | + | |
50 | +/******************** App. API ******************** | |
51 | + * The application API is for user level application | |
52 | + * to use the functionality provided by DMA driver. | |
53 | + * This is a "generic" DMA interface, it should contain | |
54 | + * nothing specific to the Kahlua implementation. | |
55 | + * Only the generic functions are exported by the library. | |
56 | + * | |
57 | + * Note: Its App.s responsibility to swap the data | |
58 | + * byte. In our API, we currently transfer whatever | |
59 | + * we are given - Big/Little Endian. This could | |
60 | + * become part of the DMA config, though. | |
61 | + **************************************************/ | |
62 | + | |
63 | + | |
64 | +/* Initialize DMA unit with the following: | |
65 | + * optional pointer to application layer print function | |
66 | + * | |
67 | + * These parameters may be added: | |
68 | + * ??? | |
69 | + * Interrupt enables, modes, etc. are set for each transfer. | |
70 | + * | |
71 | + * This function must be called before DMA unit can be used. | |
72 | + */ | |
73 | +extern DMA_Status DMA_Initialize( | |
74 | + int (*app_print_function)(char *,...)); /* pointer to optional "printf" | |
75 | + * provided by application | |
76 | + */ | |
77 | + | |
78 | +/* Perform the DMA transfer, only direct mode is currently implemented. | |
79 | + * At this point, I think it would be better to define a different | |
80 | + * function for chaining mode. | |
81 | + * Also, I'm not sure if it is appropriate to have the "generic" API | |
82 | + * accept snoop and int_steer parameters. The DINK user interface allows | |
83 | + * them, so for now I'll leave them. | |
84 | + * | |
85 | + * int_steer controls DMA interrupt steering to PCI or local processor | |
86 | + * type is the type of transfer: M2M, M2P, P2M, P2P | |
87 | + * source is the source address of the data | |
88 | + * dest is the destination address of the data | |
89 | + * len is the length of data to transfer | |
90 | + * channel is the DMA channel to use for the transfer | |
91 | + * snoop is the snoop enable control | |
92 | + */ | |
93 | +extern DMA_Status DMA_direct_transfer( DMA_INTERRUPT_STEER int_steer, | |
94 | + DMA_TRANSFER_TYPE type, | |
95 | + unsigned int source, | |
96 | + unsigned int dest, | |
97 | + unsigned int len, | |
98 | + DMA_CHANNEL channel, | |
99 | + DMA_SNOOP_MODE snoop); | |
100 | +#endif |
cpu/mpc824x/drivers/epic.h
1 | +#include "epic/epic.h" |
cpu/mpc824x/drivers/epic/README
1 | +CONTENT: | |
2 | + | |
3 | + epic.h | |
4 | + epic1.c | |
5 | + epic2.s | |
6 | + | |
7 | +WHAT ARE THESE FILES: | |
8 | + | |
9 | +These files contain MPC8240 (Kahlua) EPIC | |
10 | +driver routines. The driver routines are not | |
11 | +written for any specific operating system. | |
12 | +They serves the purpose of code sample, and | |
13 | +jump-start for using the MPC8240 EPIC unit. | |
14 | + | |
15 | +For the reason of correctness of C language | |
16 | +syntax, these files are compiled by Metaware | |
17 | +C compiler and assembler. | |
18 | + | |
19 | +ENDIAN NOTATION: | |
20 | + | |
21 | +The algorithm is designed for big-endian mode, | |
22 | +software is responsible for byte swapping. | |
23 | + | |
24 | +USAGE: | |
25 | + | |
26 | +1. The host system that is running on MPC8240 | |
27 | + shall link the files listed here. The memory | |
28 | + location of driver routines shall take into | |
29 | + account of that driver routines need to run | |
30 | + in supervisor mode and they process external | |
31 | + interrupts. | |
32 | + | |
33 | + The routine epic_exception shall be called by | |
34 | + exception vector at location 0x500, i.e., | |
35 | + 603e core external exception vector. | |
36 | + | |
37 | +2. The host system is responsible for configuring | |
38 | + the MPC8240 including Embedded Utilities Memory | |
39 | + Block. All EPIC driver functions require the | |
40 | + content of Embedded Utilities Memory Block | |
41 | + Base Address Register, EUMBBAR, as the first | |
42 | + parameter. | |
43 | + | |
44 | +3. Before EPIC unit of MPC8240 can be used, | |
45 | + initialize EPIC unit by calling epicInit | |
46 | + with the corresponding parameters. | |
47 | + | |
48 | + The initialization shall disable the 603e | |
49 | + core External Exception by calling CoreExtIntDisable( ). | |
50 | + Next, call epicInit( ). Last, enable the 603e core | |
51 | + External Exception by calling CoreExtIntEnable( ). | |
52 | + | |
53 | +4. After EPIC unit has been successfully initialized, | |
54 | + epicIntSourceSet( ) shall be used to register each | |
55 | + external interrupt source. Anytime, an external | |
56 | + interrupt source can be disabled or enabled by | |
57 | + calling corresponding function, epicIntDisable( ), | |
58 | + or epicIntEnable( ). | |
59 | + | |
60 | + Global Timers' resource, base count and frequency, | |
61 | + can be changed by calling epicTmFrequencySet( ) | |
62 | + and epicTmBaseSet( ). | |
63 | + | |
64 | + To stop counting a specific global timer, use | |
65 | + the function, epicTmInhibit while epicTmEnable | |
66 | + can be used to start counting a timer. | |
67 | + | |
68 | +5. To mask a set of external interrupts that are | |
69 | + are certain level below, epicIntPrioritySet( ) | |
70 | + can be used. For example, if the processor's | |
71 | + current task priority register is set to 0x7, | |
72 | + only interrupts of priority 0x8 or higher will | |
73 | + be passed to the processor. | |
74 | + | |
75 | + Be careful when using this function. It may | |
76 | + corrupt the current interrupt pending, selector, | |
77 | + and request registers, resulting an invalid vetor. | |
78 | + | |
79 | + After enabling an interrupt, disable it may also | |
80 | + cause an invalid vector. User may consider using | |
81 | + the spurious vector interrupt service routine to | |
82 | + handle this case. | |
83 | + | |
84 | +6. The EPIC driver routines contains a set | |
85 | + of utilities, Set and Get, for host system | |
86 | + to query and modify the desired EPIC source | |
87 | + registers. | |
88 | + | |
89 | +7. Each external interrupt source shall register | |
90 | + its interrupt service routine. The routine | |
91 | + shall contain all interrupt source specific | |
92 | + processes and keep as short as possible. | |
93 | + | |
94 | + Special customized end of interrupt routine | |
95 | + is optional. If it is needed, it shall contain | |
96 | + the external interrupt source specific end of | |
97 | + interrupt process. | |
98 | + | |
99 | + External interrupt exception vector at 0x500 | |
100 | + shall always call the epicEOI just before | |
101 | + rfi instruction. Refer to the routine, | |
102 | + epic_exception, for a code sample. |
cpu/mpc824x/drivers/epic/epic2.S
1 | +/************************************** | |
2 | + * | |
3 | + * copyright @ Motorola, 1999 | |
4 | + * | |
5 | + **************************************/ | |
6 | + | |
7 | +#include <ppc_asm.tmpl> | |
8 | +#include <ppc_defs.h> | |
9 | +#include <asm/processor.h> | |
10 | + | |
11 | +/********************************************* | |
12 | + * function: CoreExtIntEnable | |
13 | + * | |
14 | + * description: Enable 603e core external interrupt | |
15 | + * | |
16 | + * note: mtmsr is context-synchronization | |
17 | + **********************************************/ | |
18 | + .text | |
19 | + .align 2 | |
20 | + .global CoreExtIntEnable | |
21 | +CoreExtIntEnable: | |
22 | + mfmsr r3 | |
23 | + | |
24 | + ori r3,r3,0x8000 /* enable external interrupt */ | |
25 | + mtmsr r3 | |
26 | + | |
27 | + bclr 20, 0 | |
28 | + | |
29 | +/******************************************* | |
30 | + * function: CoreExtIntDisable | |
31 | + * | |
32 | + * description: Disable 603e core external interrupt | |
33 | + * | |
34 | + * note: | |
35 | + *******************************************/ | |
36 | + .text | |
37 | + .align 2 | |
38 | + .global CoreExtIntDisable | |
39 | +CoreExtIntDisable: | |
40 | + mfmsr r4 | |
41 | + | |
42 | + xor r3,r3,r3 | |
43 | + or r3,r3,r4 | |
44 | + | |
45 | + andis. r4,r4,0xffff | |
46 | + andi. r3,r3,0x7fff /* disable external interrupt */ | |
47 | + | |
48 | + or r3,r3,r4 | |
49 | + mtmsr r3 | |
50 | + | |
51 | + bclr 20, 0 | |
52 | + | |
53 | +/********************************************************* | |
54 | + * function: epicEOI | |
55 | + * | |
56 | + * description: signal the EOI and restore machine status | |
57 | + * Input: r3 - value of eumbbar | |
58 | + * Output: r3 - value of eumbbar | |
59 | + * r4 - ISR vector value | |
60 | + * note: | |
61 | + ********************************************************/ | |
62 | + .text | |
63 | + .align 2 | |
64 | + .global epicEOI | |
65 | +epicEOI: | |
66 | + lis r5,0x0006 /* Build End Of Interrupt Register offset */ | |
67 | + ori r5,r5,0x00b0 | |
68 | + xor r7,r7,r7 /* Clear r7 */ | |
69 | + stwbrx r7,r5,r3 /* Save r7, writing to this register will | |
70 | + * intidate the end of processing the | |
71 | + * highest interrupt. | |
72 | + */ | |
73 | + sync | |
74 | + | |
75 | + /* ---RESTORE MACHINE STATE */ | |
76 | + mfmsr r13 /* Clear Recoverable Interrupt bit in MSR */ | |
77 | + or r7,r7,r13 | |
78 | + | |
79 | + andis. r7,r7,0xffff | |
80 | + andi. r13,r13,0x7ffd /* (and disable interrupts) */ | |
81 | + or r13,r13,r7 | |
82 | + mtmsr r13 | |
83 | + | |
84 | + lwz r13,0x1c(r1) /* pull ctr */ | |
85 | + mtctr r13 | |
86 | + | |
87 | + lwz r13,0x18(r1) /* pull xer */ | |
88 | + mtctr r13 | |
89 | + | |
90 | + lwz r13,0x14(r1) /* pull lr */ | |
91 | + mtctr r13 | |
92 | + | |
93 | + lwz r13,0x10(r1) /* Pull SRR1 from stack */ | |
94 | + mtspr SRR1,r13 /* Restore SRR1 */ | |
95 | + | |
96 | + lwz r13,0xc(r1) /* Pull SRR0 from stack */ | |
97 | + mtspr SRR0,r13 /* Restore SRR0 */ | |
98 | + | |
99 | + lwz r13,0x8(r1) /* Pull User stack pointer from stack */ | |
100 | + mtspr SPRG1,r13 /* Restore SPRG1 */ | |
101 | + | |
102 | + lwz r4,0x4(r1) /* vector value */ | |
103 | + lwz r3,0x0(r1) /* eumbbar */ | |
104 | + sync | |
105 | + | |
106 | + addi r1,r1,0x20 /* Deallocate stack */ | |
107 | + mtspr SPRG0,r1 /* Save updated Supervisor stack pointer */ | |
108 | + mfspr r1,SPRG1 /* Restore User stack pointer */ | |
109 | + | |
110 | + bclr 20,0 | |
111 | + | |
112 | +/*********************************************************** | |
113 | + * function: exception routine called by exception vector | |
114 | + * at 0x500, external interrupt | |
115 | + * | |
116 | + * description: Kahlua EPIC controller | |
117 | + * | |
118 | + * input: r3 - content of eumbbar | |
119 | + * output: r3 - ISR return value | |
120 | + * r4 - Interrupt vector number | |
121 | + * note: | |
122 | + ***********************************************************/ | |
123 | + | |
124 | + .text | |
125 | + .align 2 | |
126 | + .global epic_exception | |
127 | + | |
128 | +epic_exception: | |
129 | + | |
130 | + /*---SAVE MACHINE STATE TO A STACK */ | |
131 | + mtspr SPRG1,r1 /* Save User stack pointer to SPRG1 */ | |
132 | + mfspr r1,SPRG0 /* Load Supervisor stack pointer into r1 */ | |
133 | + | |
134 | + stwu r3,-0x20(r1) /* Push the value of eumbbar onto stack */ | |
135 | + | |
136 | + mfspr r3,SPRG1 /* Push User stack pointer onto stack */ | |
137 | + stw r3,0x8(r1) | |
138 | + mfspr r3,SRR0 /* Push SRR0 onto stack */ | |
139 | + stw r1,0xc(r1) | |
140 | + mfspr r3,SRR1 /* Push SRR1 onto stack */ | |
141 | + stw r3,0x10(r1) | |
142 | + mflr r3 | |
143 | + stw r3,0x14(r1) /* Push LR */ | |
144 | + mfxer r3 | |
145 | + stw r3,0x18(r1) /* Push Xer */ | |
146 | + mfctr r3 | |
147 | + stw r3,0x1c(r1) /* Push CTR */ | |
148 | + | |
149 | + mtspr SPRG0,r1 /* Save updated Supervisor stack pointer | |
150 | + * value to SPRG0 | |
151 | + */ | |
152 | + mfmsr r3 | |
153 | + ori r3,r3,0x0002 /* Set Recoverable Interrupt bit in MSR */ | |
154 | + mtmsr r3 | |
155 | + | |
156 | + /* ---READ IN THE EUMBAR REGISTER */ | |
157 | + lwz r6,0(r1) /* this is eumbbar */ | |
158 | + sync | |
159 | + | |
160 | + /* ---READ EPIC REGISTER: PROCESSOR INTERRUPT ACKNOWLEDGE REGISTER */ | |
161 | + lis r5,0x0006 /* Build Interrupt Acknowledge Register | |
162 | + * offset | |
163 | + */ | |
164 | + ori r5,r5,0x00a0 | |
165 | + lwbrx r7,r5,r6 /* Load interrupt vector into r7 */ | |
166 | + sync | |
167 | + | |
168 | + /* --MASK OFF ALL BITS EXCEPT THE VECTOR */ | |
169 | + xor r3,r3,r3 | |
170 | + xor r4,r4,r4 | |
171 | + or r3, r3, r6 /* eumbbar in r3 */ | |
172 | + andi. r4,r7,0x00ff /* Mask off bits, vector in r4 */ | |
173 | + | |
174 | + stw r4,0x04(r1) /* save the vector value */ | |
175 | + | |
176 | + lis r5,epicISR@ha | |
177 | + ori r5,r5,epicISR@l | |
178 | + mtlr r5 | |
179 | + blrl | |
180 | + | |
181 | + xor r30,r30,r30 | |
182 | + or r30,r30,r3 /* save the r3 which containts the return value from epicISR */ | |
183 | + | |
184 | + /* ---READ IN THE EUMBAR REGISTER */ | |
185 | + lwz r3,0(r1) | |
186 | + sync | |
187 | + | |
188 | + lis r5,epicEOI@ha | |
189 | + ori r5,r5,epicEOI@l | |
190 | + mtlr r5 | |
191 | + blrl | |
192 | + | |
193 | + xor r3,r3,r3 | |
194 | + or r3,r3,r30 /* restore the ISR return value */ | |
195 | + | |
196 | + bclr 20,0 |
cpu/mpc824x/drivers/epic/epicutil.S
1 | +/************************************** | |
2 | + * | |
3 | + * copyright @ Motorola, 1999 | |
4 | + * | |
5 | + * | |
6 | + * This file contains two commonly used | |
7 | + * lower level utility routines. | |
8 | + * | |
9 | + * The utility routines are also in other | |
10 | + * Kahlua device driver libraries. The | |
11 | + * need to be linked in only once. | |
12 | + **************************************/ | |
13 | + | |
14 | +#include <ppc_asm.tmpl> | |
15 | +#include <ppc_defs.h> | |
16 | + | |
17 | +/********************************************************** | |
18 | + * function: load_runtime_reg | |
19 | + * | |
20 | + * input: r3 - value of eumbbar | |
21 | + * r4 - register offset in embedded utility space | |
22 | + * | |
23 | + * output: r3 - register content | |
24 | + **********************************************************/ | |
25 | + .text | |
26 | + .align 2 | |
27 | + .global load_runtime_reg | |
28 | + | |
29 | +load_runtime_reg: | |
30 | + | |
31 | + xor r5,r5,r5 | |
32 | + or r5,r5,r3 /* save eumbbar */ | |
33 | + | |
34 | + lwbrx r3,r4,r5 | |
35 | + sync | |
36 | + | |
37 | + bclr 20, 0 | |
38 | + | |
39 | +/**************************************************************** | |
40 | + * function: store_runtime_reg | |
41 | + * | |
42 | + * input: r3 - value of eumbbar | |
43 | + * r4 - register offset in embedded utility space | |
44 | + * r5 - new value to be stored | |
45 | + * | |
46 | + ****************************************************************/ | |
47 | + .text | |
48 | + .align 2 | |
49 | + .global store_runtime_reg | |
50 | +store_runtime_reg: | |
51 | + | |
52 | + xor r0,r0,r0 | |
53 | + | |
54 | + stwbrx r5, r4, r3 | |
55 | + sync | |
56 | + | |
57 | + bclr 20,0 |
cpu/mpc824x/drivers/errors.h
1 | +/* Copyright Motorola, Inc. 1993, 1994 | |
2 | + ALL RIGHTS RESERVED | |
3 | + | |
4 | + You are hereby granted a copyright license to use, modify, and | |
5 | + distribute the SOFTWARE so long as this entire notice is retained | |
6 | + without alteration in any modified and/or redistributed versions, | |
7 | + and that such modified versions are clearly identified as such. | |
8 | + No licenses are granted by implication, estoppel or otherwise under | |
9 | + any patents or trademarks of Motorola, Inc. | |
10 | + | |
11 | + The SOFTWARE is provided on an "AS IS" basis and without warranty. | |
12 | + To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS | |
13 | + ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED | |
14 | + WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR | |
15 | + PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH | |
16 | + REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS | |
17 | + THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS. | |
18 | + | |
19 | + To the maximum extent permitted by applicable law, IN NO EVENT SHALL | |
20 | + MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER | |
21 | + (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF | |
22 | + BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS | |
23 | + INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR | |
24 | + INABILITY TO USE THE SOFTWARE. Motorola assumes no responsibility | |
25 | + for the maintenance and support of the SOFTWARE. | |
26 | + | |
27 | +*/ | |
28 | + | |
29 | + | |
30 | +#include "config.h" | |
31 | + | |
32 | +/* | |
33 | + 1 2 3 4 5 6 7 8 | |
34 | +01234567890123456789012345678901234567890123456789012345678901234567890123456789 | |
35 | +*/ | |
36 | +/* List define statements here */ | |
37 | + | |
38 | +/* These are for all the toolboxes and functions to use. These will help | |
39 | +to standardize the error handling in the current project */ | |
40 | + | |
41 | + /* this is the "data type" for the error | |
42 | + messages in the system */ | |
43 | +#define STATUS unsigned int | |
44 | + | |
45 | + /* this is a success status code */ | |
46 | +#define SUCCESS 1 | |
47 | + | |
48 | + /* likewise this is failure */ | |
49 | +#define FAILURE 0 | |
50 | + | |
51 | +#define NUM_ERRORS 47 | |
52 | + | |
53 | +/* This first section of "defines" are for error codes ONLY. The called | |
54 | + routine will return one of these error codes to the caller. If the final | |
55 | + returned code is "VALID", then everything is a-okay. However, if one | |
56 | + of the functions returns a non-valid status, that error code should be | |
57 | + propogated back to all the callers. At the end, the last caller will | |
58 | + call an error_processing function, and send in the status which was | |
59 | + returned. It's up to the error_processing function to determine which | |
60 | + error occured (as indicated by the status), and print an appropriate | |
61 | + message back to the user. | |
62 | +*/ | |
63 | +/*----------------------------------------------------------------------*/ | |
64 | +/* these are specifically for the parser routines */ | |
65 | + | |
66 | +#define UNKNOWN_COMMAND 0xfb00 /* "unrecognized command " */ | |
67 | +#define UNKNOWN_REGISTER 0xfb01 /* "unknown register "*/ | |
68 | +#define ILLEGAL_RD_STAGE 0xfb02 /* cannot specify reg. family in range*/ | |
69 | +#define ILLEGAL_REG_FAMILY 0xfb03 /* "cannot specify a range of special | |
70 | + or miscellaneous registers"*/ | |
71 | +#define RANGE_CROSS_FAMILY 0xfb04 /* "cannot specify a range across | |
72 | + register families" */ | |
73 | +#define UNIMPLEMENTED_STAGE 0xfb05 /* invalid rd or rmm parameter format */ | |
74 | +#define REG_NOT_WRITEABLE 0xfb06 /* "unknown operator in arguements"*/ | |
75 | +#define INVALID_FILENAME 0xfb07 /* "invalid download filename" */ | |
76 | +#define INVALID_BAUD_RATE 0xfb08 /* invalid baud rate from sb command */ | |
77 | +#define UNSUPPORTED_REGISTER 0xfb09 /* Special register is not supported */ | |
78 | +#define FOR_BOARD_ONLY 0xfb0a /* "Not available for Unix." */ | |
79 | + | |
80 | + | |
81 | + | |
82 | +/*----------------------------------------------------------------------*/ | |
83 | +/* these are for the error checking toolbox */ | |
84 | + | |
85 | +#define INVALID 0xfd00 /* NOT valid */ | |
86 | +#define VALID 0xfd01 /* valid */ | |
87 | + | |
88 | + /* This error is found in the fcn: | |
89 | + is_right_size_input() to indicate | |
90 | + that the input was not 8 characters | |
91 | + long. */ | |
92 | +#define INVALID_SIZE 0xfd02 | |
93 | + | |
94 | + /* This error is found in the fcn: | |
95 | + is_valid_address_range() to indicate | |
96 | + that the address given falls outside | |
97 | + of valid memory defined by MEM_START | |
98 | + to MEM_END. | |
99 | + */ | |
100 | +#define OUT_OF_BOUNDS_ADDRESS 0xfd03 | |
101 | + | |
102 | + /* This error is found in the fcn: | |
103 | + is_valid_hex_input() to indicate that | |
104 | + one of more of the characters entered | |
105 | + are not valid hex characters. Valid | |
106 | + hex characters are 0-9, A-F, a-f. | |
107 | + */ | |
108 | +#define INVALID_HEX_INPUT 0xfd04 | |
109 | + | |
110 | + /* This error is found in the fcn: | |
111 | + is_valid_register_number() to indicate | |
112 | + that a given register does not exist. | |
113 | + */ | |
114 | +#define REG_NOT_READABLE 0xfd05 | |
115 | + | |
116 | + /* This error is found in the fcn: | |
117 | + is_word_aligned_address() to indicate | |
118 | + that the given address is not word- | |
119 | + aligned. A word-aligned address ends | |
120 | + in 0x0,0x4,0x8,0xc. | |
121 | + */ | |
122 | +#define NOT_WORD_ALIGNED 0xfd07 | |
123 | + | |
124 | + /* This error is found in the fcn: | |
125 | + is_valid_address_range() to indicate | |
126 | + that the starting address is greater | |
127 | + than the ending address. | |
128 | + */ | |
129 | +#define REVERSED_ADDRESS 0xfd08 | |
130 | + | |
131 | + /* this error tells us that the address | |
132 | + specified as the destination is within | |
133 | + the source addresses */ | |
134 | +#define RANGE_OVERLAP 0xfd09 | |
135 | + | |
136 | + | |
137 | +#define ERROR 0xfd0a /* An error occured */ | |
138 | +#define INVALID_PARAM 0xfd0b /* "invalid input parameter " */ | |
139 | + | |
140 | + | |
141 | +#define INVALID_FLAG 0xfd0c /* invalid flag */ | |
142 | + | |
143 | +/*----------------------------------------------------------------------*/ | |
144 | +/* these are for the getarg toolbox */ | |
145 | + | |
146 | +#define INVALID_NUMBER_ARGS 0xFE00 /* invalid number of commd arguements */ | |
147 | +#define UNKNOWN_PARAMETER 0xFE01 /* "unknown type of parameter "*/ | |
148 | + | |
149 | + | |
150 | + | |
151 | + | |
152 | + | |
153 | +/*----------------------------------------------------------------------*/ | |
154 | +/* these are for the tokenizer toolbox */ | |
155 | + | |
156 | +#define ILLEGAL_CHARACTER 0xFF00 /* unrecognized char. in input stream*/ | |
157 | +#define TTL_NOT_SORTED 0xFF01 /* token translation list not sorted */ | |
158 | +#define TTL_NOT_DEFINED 0xFF02 /* token translation list not assigned*/ | |
159 | +#define INVALID_STRING 0xFF03 /* unable to extract string from input */ | |
160 | +#define BUFFER_EMPTY 0xFF04 /* "input buffer is empty" */ | |
161 | +#define INVALID_MODE 0xFF05 /* input buf is in an unrecognized mode*/ | |
162 | +#define TOK_INTERNAL_ERROR 0xFF06 /* "internal tokenizer error" */ | |
163 | +#define TOO_MANY_IBS 0xFF07 /* "too many open input buffers" */ | |
164 | +#define NO_OPEN_IBS 0xFF08 /* "no open input buffers" */ | |
165 | + | |
166 | + | |
167 | + | |
168 | +/* these are for the read from screen toolbox */ | |
169 | + | |
170 | +#define RESERVED_WORD 0xFC00 /* used a reserved word as an arguement*/ | |
171 | + | |
172 | + | |
173 | +/* these are for the breakpoint routines */ | |
174 | + | |
175 | +#define FULL_BPDS 0xFA00 /* breakpoint data structure is full */ | |
176 | + | |
177 | + | |
178 | + | |
179 | +/* THESE are for the downloader */ | |
180 | + | |
181 | +#define NOT_IN_S_RECORD_FORMAT 0xf900 /* "not in S-Record Format" */ | |
182 | +#define UNREC_RECORD_TYPE 0xf901 /* "unrecognized record type" */ | |
183 | +#define CONVERSION_ERROR 0xf902 /* "ascii to int conversion error" */ | |
184 | +#define INVALID_MEMORY 0xf903 /* "bad s-record memory address " */ | |
185 | + | |
186 | + | |
187 | +/* these are for the compression and decompression stuff */ | |
188 | + | |
189 | +#define COMP_UNK_CHARACTER 0xf800 /* "unknown compressed character " */ | |
190 | + | |
191 | +#define COMP_UNKNOWN_STATE 0xf801 /* "unknown binary state" */ | |
192 | + | |
193 | +#define NOT_IN_COMPRESSED_FORMAT 0xf802 /* not in compressed S-Record format */ | |
194 | + | |
195 | + | |
196 | +/* these are for the DUART handling things */ | |
197 | + | |
198 | + /* "unrecognized serial port configuration" */ | |
199 | +#define UNKNOWN_PORT_STATE 0xf700 | |
200 | + | |
201 | + | |
202 | +/* these are for the register toolbox */ | |
203 | + | |
204 | + /* "cannot find register in special | |
205 | + purpose register file " */ | |
206 | +#define SPR_NOT_FOUND 0xf600 | |
207 | + | |
208 | + | |
209 | +/* these are for the duart specific stuff */ | |
210 | + | |
211 | + /* "transparent mode needs access to | |
212 | + two serial ports" */ | |
213 | +#define TM_NEEDS_BOTH_PORTS 0xf500 | |
214 | + | |
215 | + | |
216 | +/*----------------------------------------------------------------------*/ | |
217 | +/* these are specifically for the flash routines */ | |
218 | +#define FLASH_ERROR 0xf100 /* general flash error */ |
cpu/mpc824x/drivers/i2c/Makefile
1 | +########################################################################## | |
2 | +# | |
3 | +# Copyright Motorola, Inc. 1997 | |
4 | +# ALL RIGHTS RESERVED | |
5 | +# | |
6 | +# You are hereby granted a copyright license to use, modify, and | |
7 | +# distribute the SOFTWARE so long as this entire notice is retained | |
8 | +# without alteration in any modified and/or redistributed versions, | |
9 | +# and that such modified versions are clearly identified as such. | |
10 | +# No licenses are granted by implication, estoppel or otherwise under | |
11 | +# any patents or trademarks of Motorola, Inc. | |
12 | +# | |
13 | +# The SOFTWARE is provided on an "AS IS" basis and without warranty. | |
14 | +# To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS | |
15 | +# ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED | |
16 | +# WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR | |
17 | +# PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH | |
18 | +# REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS | |
19 | +# THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS. | |
20 | +# | |
21 | +# To the maximum extent permitted by applicable law, IN NO EVENT SHALL | |
22 | +# MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER | |
23 | +# (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF | |
24 | +# BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS | |
25 | +# INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR | |
26 | +# INABILITY TO USE THE SOFTWARE. | |
27 | +# | |
28 | +############################################################################ | |
29 | +TARGET = libi2c.a | |
30 | + | |
31 | +#DEBUG = -g | |
32 | +DEBUG = -DI2CDBG | |
33 | +LST = -Hanno -S | |
34 | +OPTIM = | |
35 | +CC = /risc/tools/pkgs/metaware/bin/hcppc | |
36 | +CFLAGS = -Hnocopyr -c -Hsds -Hon=Char_default_unsigned -Hon=Char_is_rep -I../inc -I/risc/tools/pkgs/metaware/inc | |
37 | +CCobj = $(CC) $(CFLAGS) $(DEBUG) $(OPTIM) | |
38 | +PREP = $(CC) $(CFLAGS) -P | |
39 | + | |
40 | +# Assembler used to build the .s files (for the board version) | |
41 | + | |
42 | +ASOPT = -big_si -c | |
43 | +ASDEBUG = -l -fm | |
44 | +AS = /risc/tools/pkgs/metaware/bin/asppc | |
45 | + | |
46 | +# Linker to bring .o files together into an executable. | |
47 | + | |
48 | +LKOPT = -Bbase=0 -q -Qn -r | |
49 | +LKCMD = | |
50 | +LINK = /risc/tools/pkgs/metaware/bin/ldppc $(LKCMD) $(LKOPT) | |
51 | + | |
52 | +# DOS Utilities | |
53 | + | |
54 | +DEL = rm | |
55 | +COPY = cp | |
56 | +LIST = ls | |
57 | + | |
58 | +OBJECTS = i2c1.o i2c2.o | |
59 | + | |
60 | +all: $(TARGET) | |
61 | + | |
62 | +objects: $(OBJECTS) | |
63 | + | |
64 | +$(TARGET): $(OBJECTS) | |
65 | + $(LINK) $(OBJECTS) -o $@ | |
66 | + | |
67 | +clean: | |
68 | + $(DEL) -f *.o *.i *.map *.lst $(TARGET) $(OBJECTS) | |
69 | + | |
70 | +.s.o: | |
71 | + $(DEL) -f $*.i | |
72 | + $(PREP) -Hasmcpp $< | |
73 | + $(AS) $(ASOPT) $*.i | |
74 | +# $(AS) $(ASOPT) $(ASDEBUG) $*.i > $*.lst | |
75 | + | |
76 | +.c.o: | |
77 | + $(CCobj) $< | |
78 | + | |
79 | +.c.s: | |
80 | + $(CCobj) $(LST) $< | |
81 | + | |
82 | +i2c1.o: i2c_export.h i2c.h i2c1.c | |
83 | + | |
84 | +i2c2.o: i2c.h i2c2.s |
cpu/mpc824x/drivers/i2c/Makefile_pc
1 | +########################################################################## | |
2 | +# | |
3 | +# makefile_pc for use with PC mksnt tools dink32/drivers/i2c | |
4 | +# | |
5 | +# Copyright Motorola, Inc. 1997 | |
6 | +# ALL RIGHTS RESERVED | |
7 | +# | |
8 | +# You are hereby granted a copyright license to use, modify, and | |
9 | +# distribute the SOFTWARE so long as this entire notice is retained | |
10 | +# without alteration in any modified and/or redistributed versions, | |
11 | +# and that such modified versions are clearly identified as such. | |
12 | +# No licenses are granted by implication, estoppel or otherwise under | |
13 | +# any patents or trademarks of Motorola, Inc. | |
14 | +# | |
15 | +# The SOFTWARE is provided on an "AS IS" basis and without warranty. | |
16 | +# To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS | |
17 | +# ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED | |
18 | +# WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR | |
19 | +# PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH | |
20 | +# REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS | |
21 | +# THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS. | |
22 | +# | |
23 | +# To the maximum extent permitted by applicable law, IN NO EVENT SHALL | |
24 | +# MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER | |
25 | +# (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF | |
26 | +# BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS | |
27 | +# INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR | |
28 | +# INABILITY TO USE THE SOFTWARE. | |
29 | +# | |
30 | +############################################################################ | |
31 | +TARGET = libi2c.a | |
32 | + | |
33 | +#DEBUG = -g | |
34 | +DEBUG = -DI2CDBG | |
35 | +LST = -Hanno -S | |
36 | +OPTIM = | |
37 | +CC = m:/old_tools/tools/hcppc/bin/hcppc | |
38 | +CFLAGS = -Hnocopyr -c -Hsds -Hon=Char_default_unsigned -Hon=Char_is_rep -I../inc -I/risc/tools/pkgs/metaware/inc | |
39 | +CCobj = $(CC) $(CFLAGS) $(DEBUG) $(OPTIM) | |
40 | +PREP = $(CC) $(CFLAGS) -P | |
41 | + | |
42 | +# Assembler used to build the .s files (for the board version) | |
43 | + | |
44 | +ASOPT = -big_si -c | |
45 | +ASDEBUG = -l -fm | |
46 | +AS = m:/old_tools/tools/hcppc/bin/asppc | |
47 | + | |
48 | +# Linker to bring .o files together into an executable. | |
49 | + | |
50 | +LKOPT = -Bbase=0 -q -Qn -r | |
51 | +LKCMD = | |
52 | +LINK = m:/old_tools/tools/hcppc/bin/ldppc $(LKCMD) $(LKOPT) | |
53 | + | |
54 | +# DOS Utilities | |
55 | + | |
56 | +DEL = rm | |
57 | +COPY = cp | |
58 | +LIST = ls | |
59 | + | |
60 | +OBJECTS = i2c1.o i2c2.o | |
61 | + | |
62 | +all: $(TARGET) | |
63 | + | |
64 | +objects: $(OBJECTS) | |
65 | + | |
66 | +$(TARGET): $(OBJECTS) | |
67 | + $(LINK) $(OBJECTS) -o $@ | |
68 | + | |
69 | +clean: | |
70 | + $(DEL) -f *.o *.i *.map *.lst $(TARGET) $(OBJECTS) | |
71 | + | |
72 | +.s.o: | |
73 | + $(DEL) -f $*.i | |
74 | + $(PREP) -Hasmcpp $< | |
75 | + $(AS) $(ASOPT) $*.i | |
76 | +# $(AS) $(ASOPT) $(ASDEBUG) $*.i > $*.lst | |
77 | + | |
78 | +.c.o: | |
79 | + $(CCobj) $< | |
80 | + | |
81 | +.c.s: | |
82 | + $(CCobj) $(LST) $< | |
83 | + | |
84 | +i2c1.o: i2c_export.h i2c.h i2c1.c | |
85 | + $(CCobj) $< | |
86 | + | |
87 | + | |
88 | +i2c2.o: i2c.h i2c2.s | |
89 | + $(DEL) -f $*.i | |
90 | + $(PREP) -Hasmcpp $< | |
91 | + $(AS) $(ASOPT) $*.i |
cpu/mpc824x/drivers/i2c/README
1 | +CONTENT: | |
2 | + | |
3 | + i2c.h | |
4 | + i2c1.c | |
5 | + i2c2.s | |
6 | + | |
7 | +WHAT ARE THESE FILES: | |
8 | + | |
9 | +These files contain MPC8240 (Kahlua) I2C | |
10 | +driver routines. The driver routines are not | |
11 | +written for any specific operating system. | |
12 | +They serves the purpose of code sample, and | |
13 | +jump-start for using the MPC8240 I2C unit. | |
14 | + | |
15 | +For the reason of correctness of C language | |
16 | +syntax, these files are compiled by Metaware | |
17 | +C compiler and assembler. | |
18 | + | |
19 | +ENDIAN NOTATION: | |
20 | + | |
21 | +The algorithm is designed for big-endian mode, | |
22 | +software is responsible for byte swapping. | |
23 | + | |
24 | +USAGE: | |
25 | + | |
26 | +1. The host system that is running on MPC8240 | |
27 | + shall link the files listed here. The memory | |
28 | + location of driver routines shall take into | |
29 | + account of that driver routines need to run | |
30 | + in supervisor mode and they process I2C | |
31 | + interrupt. | |
32 | + | |
33 | +2. The host system is responsible for configuring | |
34 | + the MPC8240 including Embedded Utilities Memory | |
35 | + Block. All I2C driver functions require the | |
36 | + content of Embedded Utilities Memory Block | |
37 | + Base Address Register, EUMBBAR, as the first | |
38 | + parameter. | |
39 | + | |
40 | +3. Before I2C unit of MPC8240 can be used, | |
41 | + initialize I2C unit by calling I2C_Init | |
42 | + with the corresponding parameters. | |
43 | + | |
44 | + Note that the I2CFDR register shall be written | |
45 | + once during the initialization. If it is written | |
46 | + in the midst of transers, or after I2C STOPs or | |
47 | + REPEAT STATRs, depending on the data written, | |
48 | + a long reset time may be encountered. | |
49 | + | |
50 | +4. After I2C unit has been successfully initialized, | |
51 | + use the Application level API to send data or | |
52 | + receive data upon the desired mode, Master or | |
53 | + Slave. | |
54 | + | |
55 | +5. If the host system is also using the EPIC unit | |
56 | + on MPC8240, the system can register the | |
57 | + I2C_ISR with the EPIC including other | |
58 | + desired resources. | |
59 | + | |
60 | + If the host system does not using the EPIC unit | |
61 | + on MPC8240, I2C_Timer_Event function can | |
62 | + be called for each desired time interval. | |
63 | + | |
64 | + In both cases, the host system is free to provide | |
65 | + its own timer event handler and interrupt service | |
66 | + routine. | |
67 | + | |
68 | +6. The I2C driver routines contains a set | |
69 | + of utilities, Set and Get, for host system | |
70 | + to query and modify the desired I2C registers. | |
71 | + | |
72 | +7. It is the host system's responsibility of | |
73 | + queueing the I2C I/O request. The host | |
74 | + system shall check the I2C_ISR return code | |
75 | + for I2C I/O status. If I2C_ISR returns | |
76 | + I2CBUFFEMPTY or I2CBUFFFULL, it means | |
77 | + I2C unit has completed a I/O request | |
78 | + stated by the Application API. | |
79 | + | |
80 | +8. If the host system has more than one master | |
81 | + mode I2C unit I/O requests but doesn't want | |
82 | + to be intervented by being addressed as slave, | |
83 | + the host system can use the master mode | |
84 | + Application API with stop_flag set to 0 in | |
85 | + conjunction with is_cnt flag set to 1. | |
86 | + The first API call sets both stop_flag and | |
87 | + is_cnt to 0, indicating a START condition | |
88 | + shall be generated but when the end of | |
89 | + transaction is reached, do not generate a | |
90 | + STOP condition. Once the host system is | |
91 | + informed that the transaction has been | |
92 | + completed, the next Application API call | |
93 | + shall set is_cnt flag to 1, indicating a | |
94 | + repeated START condition shall be generated. | |
95 | + The last Application API call shall set | |
96 | + stop_flag | |
97 | + to 1. | |
98 | + | |
99 | +9. The I2C_Timer_Event function containes | |
100 | + a user defined function pointer. It | |
101 | + serves the purpose of providing the | |
102 | + host system a way to use its own event | |
103 | + handler instead of the I2C_ISR provided | |
104 | + here. |
cpu/mpc824x/drivers/i2c/i2c_export.h
1 | +#ifndef I2C_EXPORT_H | |
2 | +#define I2C_EXPORT_H | |
3 | + | |
4 | +/**************************************************** | |
5 | + * | |
6 | + * Copyright Motrola 1999 | |
7 | + * | |
8 | + ****************************************************/ | |
9 | + | |
10 | +/* These are the defined return values for the I2C_do_transaction function. | |
11 | + * Any non-zero value indicates failure. Failure modes can be added for | |
12 | + * more detailed error reporting. | |
13 | + */ | |
14 | +typedef enum _i2c_status | |
15 | +{ | |
16 | + I2C_SUCCESS = 0, | |
17 | + I2C_ERROR, | |
18 | +} I2C_Status; | |
19 | + | |
20 | +/* These are the defined tasks for I2C_do_transaction. | |
21 | + * Modes for SLAVE_RCV and SLAVE_XMIT will be added. | |
22 | + */ | |
23 | +typedef enum _i2c_transaction_mode | |
24 | +{ | |
25 | + I2C_MASTER_RCV = 0, | |
26 | + I2C_MASTER_XMIT = 1, | |
27 | +} I2C_TRANSACTION_MODE; | |
28 | + | |
29 | +typedef enum _i2c_interrupt_mode | |
30 | +{ | |
31 | + I2C_INT_DISABLE = 0, | |
32 | + I2C_INT_ENABLE = 1, | |
33 | +} I2C_INTERRUPT_MODE; | |
34 | + | |
35 | +typedef enum _i2c_stop | |
36 | +{ | |
37 | + I2C_NO_STOP = 0, | |
38 | + I2C_STOP = 1, | |
39 | +} I2C_STOP_MODE; | |
40 | + | |
41 | +typedef enum _i2c_restart | |
42 | +{ | |
43 | + I2C_NO_RESTART = 0, | |
44 | + I2C_RESTART = 1, | |
45 | +} I2C_RESTART_MODE; | |
46 | + | |
47 | +/******************** App. API ******************** | |
48 | + * The application API is for user level application | |
49 | + * to use the functionality provided by I2C driver. | |
50 | + * This is a "generic" I2C interface, it should contain | |
51 | + * nothing specific to the Kahlua implementation. | |
52 | + * Only the generic functions are exported by the library. | |
53 | + * | |
54 | + * Note: Its App.s responsibility to swap the data | |
55 | + * byte. In our API, we just transfer whatever | |
56 | + * we are given | |
57 | + **************************************************/ | |
58 | + | |
59 | + | |
60 | +/* Initialize I2C unit with the following: | |
61 | + * driver's slave address | |
62 | + * interrupt enabled | |
63 | + * optional pointer to application layer print function | |
64 | + * | |
65 | + * These parameters may be added: | |
66 | + * desired clock rate | |
67 | + * digital filter frequency sampling rate | |
68 | + * | |
69 | + * This function must be called before I2C unit can be used. | |
70 | + */ | |
71 | +extern I2C_Status I2C_Initialize( | |
72 | + unsigned char addr, /* driver's I2C slave address */ | |
73 | + I2C_INTERRUPT_MODE en_int, /* 1 - enable I2C interrupt | |
74 | + * 0 - disable I2C interrupt | |
75 | + */ | |
76 | + int (*app_print_function)(char *,...)); /* pointer to optional "printf" | |
77 | + * provided by application | |
78 | + */ | |
79 | + | |
80 | +/* Perform the given I2C transaction, only MASTER_XMIT and MASTER_RCV | |
81 | + * are implemented. Both are only in polling mode. | |
82 | + * | |
83 | + * en_int controls interrupt/polling mode | |
84 | + * act is the type of transaction | |
85 | + * addr is the I2C address of the slave device | |
86 | + * len is the length of data to send or receive | |
87 | + * buffer is the address of the data buffer | |
88 | + * stop = I2C_NO_STOP, don't signal STOP at end of transaction | |
89 | + * I2C_STOP, signal STOP at end of transaction | |
90 | + * retry is the timeout retry value, currently ignored | |
91 | + * rsta = I2C_NO_RESTART, this is not continuation of existing transaction | |
92 | + * I2C_RESTART, this is a continuation of existing transaction | |
93 | + */ | |
94 | +extern I2C_Status I2C_do_transaction( I2C_INTERRUPT_MODE en_int, | |
95 | + I2C_TRANSACTION_MODE act, | |
96 | + unsigned char i2c_addr, | |
97 | + unsigned char data_addr, | |
98 | + int len, | |
99 | + char *buffer, | |
100 | + I2C_STOP_MODE stop, | |
101 | + int retry, | |
102 | + I2C_RESTART_MODE rsta); | |
103 | +#endif |
cpu/mpc824x/drivers/i2c_export.h
1 | +#ifndef I2C_EXPORT_H | |
2 | +#define I2C_EXPORT_H | |
3 | + | |
4 | +/**************************************************** | |
5 | + * | |
6 | + * Copyright Motrola 1999 | |
7 | + * | |
8 | + ****************************************************/ | |
9 | + | |
10 | +/* These are the defined return values for the I2C_do_transaction function. | |
11 | + * Any non-zero value indicates failure. Failure modes can be added for | |
12 | + * more detailed error reporting. | |
13 | + */ | |
14 | +typedef enum _i2c_status | |
15 | +{ | |
16 | + I2C_SUCCESS = 0, | |
17 | + I2C_ERROR, | |
18 | +} I2C_Status; | |
19 | + | |
20 | +/* These are the defined tasks for I2C_do_transaction. | |
21 | + * Modes for SLAVE_RCV and SLAVE_XMIT will be added. | |
22 | + */ | |
23 | +typedef enum _i2c_transaction_mode | |
24 | +{ | |
25 | + I2C_MASTER_RCV = 0, | |
26 | + I2C_MASTER_XMIT = 1, | |
27 | +} I2C_TRANSACTION_MODE; | |
28 | + | |
29 | +typedef enum _i2c_interrupt_mode | |
30 | +{ | |
31 | + I2C_INT_DISABLE = 0, | |
32 | + I2C_INT_ENABLE = 1, | |
33 | +} I2C_INTERRUPT_MODE; | |
34 | + | |
35 | +typedef enum _i2c_stop | |
36 | +{ | |
37 | + I2C_NO_STOP = 0, | |
38 | + I2C_STOP = 1, | |
39 | +} I2C_STOP_MODE; | |
40 | + | |
41 | +typedef enum _i2c_restart | |
42 | +{ | |
43 | + I2C_NO_RESTART = 0, | |
44 | + I2C_RESTART = 1, | |
45 | +} I2C_RESTART_MODE; | |
46 | + | |
47 | +/******************** App. API ******************** | |
48 | + * The application API is for user level application | |
49 | + * to use the functionality provided by I2C driver. | |
50 | + * This is a "generic" I2C interface, it should contain | |
51 | + * nothing specific to the Kahlua implementation. | |
52 | + * Only the generic functions are exported by the library. | |
53 | + * | |
54 | + * Note: Its App.s responsibility to swap the data | |
55 | + * byte. In our API, we just transfer whatever | |
56 | + * we are given | |
57 | + **************************************************/ | |
58 | + | |
59 | + | |
60 | +/* Initialize I2C unit with the following: | |
61 | + * driver's slave address | |
62 | + * interrupt enabled | |
63 | + * optional pointer to application layer print function | |
64 | + * | |
65 | + * These parameters may be added: | |
66 | + * desired clock rate | |
67 | + * digital filter frequency sampling rate | |
68 | + * | |
69 | + * This function must be called before I2C unit can be used. | |
70 | + */ | |
71 | +extern I2C_Status I2C_Initialize( | |
72 | + unsigned char addr, /* driver's I2C slave address */ | |
73 | + I2C_INTERRUPT_MODE en_int, /* 1 - enable I2C interrupt | |
74 | + * 0 - disable I2C interrupt | |
75 | + */ | |
76 | + int (*app_print_function)(char *,...)); /* pointer to optional "printf" | |
77 | + * provided by application | |
78 | + */ | |
79 | + | |
80 | +/* Perform the given I2C transaction, only MASTER_XMIT and MASTER_RCV | |
81 | + * are implemented. Both are only in polling mode. | |
82 | + * | |
83 | + * en_int controls interrupt/polling mode | |
84 | + * act is the type of transaction | |
85 | + * addr is the I2C address of the slave device | |
86 | + * len is the length of data to send or receive | |
87 | + * buffer is the address of the data buffer | |
88 | + * stop = I2C_NO_STOP, don't signal STOP at end of transaction | |
89 | + * I2C_STOP, signal STOP at end of transaction | |
90 | + * retry is the timeout retry value, currently ignored | |
91 | + * rsta = I2C_NO_RESTART, this is not continuation of existing transaction | |
92 | + * I2C_RESTART, this is a continuation of existing transaction | |
93 | + */ | |
94 | +extern I2C_Status I2C_do_transaction( I2C_INTERRUPT_MODE en_int, | |
95 | + I2C_TRANSACTION_MODE act, | |
96 | + unsigned char i2c_addr, | |
97 | + unsigned char data_addr, | |
98 | + int len, | |
99 | + char *buffer, | |
100 | + I2C_STOP_MODE stop, | |
101 | + int retry, | |
102 | + I2C_RESTART_MODE rsta); | |
103 | +#endif |
cpu/mpc824x/drivers/i2o.h
1 | +#ifndef I2O_H | |
2 | +#define I2O_H | |
3 | +/********************************************************* | |
4 | + * | |
5 | + * copyright @ Motorola, 1999 | |
6 | + *********************************************************/ | |
7 | + | |
8 | +#define I2O_REG_OFFSET 0x0004 | |
9 | + | |
10 | +#define PCI_CFG_CLA 0x0B | |
11 | +#define PCI_CFG_SCL 0x0A | |
12 | +#define PCI_CFG_PIC 0x09 | |
13 | + | |
14 | +#define I2O_IMR0 0x0050 | |
15 | +#define I2O_IMR1 0x0054 | |
16 | +#define I2O_OMR0 0x0058 | |
17 | +#define I2O_OMR1 0x005C | |
18 | + | |
19 | +#define I2O_ODBR 0x0060 | |
20 | +#define I2O_IDBR 0x0068 | |
21 | + | |
22 | +#define I2O_OMISR 0x0030 | |
23 | +#define I2O_OMIMR 0x0034 | |
24 | +#define I2O_IMISR 0x0100 | |
25 | +#define I2O_IMIMR 0x0104 | |
26 | + | |
27 | +/* accessable to PCI master but local processor */ | |
28 | +#define I2O_IFQPR 0x0040 | |
29 | +#define I2O_OFQPR 0x0044 | |
30 | + | |
31 | +/* accessable to local processor */ | |
32 | +#define I2O_IFHPR 0x0120 | |
33 | +#define I2O_IFTPR 0x0128 | |
34 | +#define I2O_IPHPR 0x0130 | |
35 | +#define I2O_IPTPR 0x0138 | |
36 | +#define I2O_OFHPR 0x0140 | |
37 | +#define I2O_OFTPR 0x0148 | |
38 | +#define I2O_OPHPR 0x0150 | |
39 | +#define I2O_OPTPR 0x0158 | |
40 | +#define I2O_MUCR 0x0164 | |
41 | +#define I2O_QBAR 0x0170 | |
42 | + | |
43 | +#define I2O_NUM_MSG 2 | |
44 | + | |
45 | +typedef enum _i2o_status | |
46 | +{ | |
47 | + I2OSUCCESS = 0, | |
48 | + I2OINVALID, | |
49 | + I2OMSGINVALID, | |
50 | + I2ODBINVALID, | |
51 | + I2OQUEINVALID, | |
52 | + I2OQUEEMPTY, | |
53 | + I2OQUEFULL, | |
54 | + I2ONOEVENT, | |
55 | +} I2OSTATUS; | |
56 | + | |
57 | +typedef enum _queue_size | |
58 | +{ | |
59 | + QSIZE_4K = 0x02, | |
60 | + QSIZE_8K = 0x04, | |
61 | + QSIZE_16K = 0x08, | |
62 | + QSIZE_32K = 0x10, | |
63 | + QSIZe_64K = 0x20, | |
64 | +} QUEUE_SIZE; | |
65 | + | |
66 | +typedef enum _location | |
67 | +{ | |
68 | + LOCAL = 0, /* used by local processor to access its own on board device, | |
69 | + local processor's eumbbar is required */ | |
70 | + REMOTE, /* used by PCI master to access the devices on its PCI device, | |
71 | + device's pcsrbar is required */ | |
72 | +} LOCATION; | |
73 | + | |
74 | +/* door bell */ | |
75 | +typedef enum _i2o_in_db | |
76 | +{ | |
77 | + IN_DB = 1, | |
78 | + MC, /* machine check */ | |
79 | +} I2O_IN_DB; | |
80 | + | |
81 | +/* I2O PCI configuration identification */ | |
82 | +typedef struct _i2o_iop | |
83 | +{ | |
84 | + unsigned int base_class : 8; | |
85 | + unsigned int sub_class : 8; | |
86 | + unsigned int prg_code : 8; | |
87 | +} I2OIOP; | |
88 | + | |
89 | +/* I2O Outbound Message Interrupt Status Register */ | |
90 | +typedef struct _i2o_om_stat | |
91 | +{ | |
92 | + unsigned int rsvd0 : 26; | |
93 | + unsigned int opqi : 1; | |
94 | + unsigned int rsvd1 : 1; | |
95 | + unsigned int odi : 1; | |
96 | + unsigned int rsvd2 : 1; | |
97 | + unsigned int om1i : 1; | |
98 | + unsigned int om0i : 1; | |
99 | +} I2OOMSTAT; | |
100 | + | |
101 | +/* I2O inbound Message Interrupt Status Register */ | |
102 | +typedef struct _i2o_im_stat | |
103 | +{ | |
104 | + unsigned int rsvd0 : 23; | |
105 | + unsigned int ofoi : 1; | |
106 | + unsigned int ipoi : 1; | |
107 | + unsigned int rsvd1 : 1; | |
108 | + unsigned int ipqi : 1; | |
109 | + unsigned int mci : 1; | |
110 | + unsigned int idi : 1; | |
111 | + unsigned int rsvd2 : 1; | |
112 | + unsigned int im1i : 1; | |
113 | + unsigned int im0i : 1; | |
114 | +} I2OIMSTAT; | |
115 | + | |
116 | +/** | |
117 | + Enable the interrupt associated with in/out bound msg | |
118 | + | |
119 | + Inbound message interrupt generated by PCI master and serviced by local processor | |
120 | + local processor needs to enable its inbound interrupts it wants to handle (LOCAL) | |
121 | + | |
122 | + Outbound message interrupt generated by local processor and serviced by PCI master | |
123 | + PCI master needs to enable the devices' outbound interrupts it wants to handle (REMOTE) | |
124 | + **/ | |
125 | +extern I2OSTATUS I2OMsgEnable( LOCATION, /* REMOTE/LOCAL */ | |
126 | + unsigned int base, /* pcsrbar/eumbbar */ | |
127 | + unsigned char n ); /* b'1' - msg 0 | |
128 | + * b'10'- msg 1 | |
129 | + * b'11'- both | |
130 | + */ | |
131 | + | |
132 | +/** | |
133 | + Disable the interrupt associated with in/out bound msg | |
134 | + | |
135 | + local processor needs to disable its inbound interrupts it is not interested (LOCAL) | |
136 | + | |
137 | + PCI master needs to disable outbound interrupts of devices it is not interested (REMOTE) | |
138 | + **/ | |
139 | +extern I2OSTATUS I2OMsgDisable( LOCATION, /* REMOTE/LOCAL */ | |
140 | + unsigned int base, /* pcsrbar/eumbbar */ | |
141 | + unsigned char n ); /* b'1' - msg 0 | |
142 | + * b'10'- msg 1 | |
143 | + * b'11'- both | |
144 | + */ | |
145 | + | |
146 | +/** | |
147 | + Read the msg register either from local inbound msg 0/1, | |
148 | + or an outbound msg 0/1 of devices. | |
149 | + | |
150 | + If it is not local, pcsrbar must be passed to the function. | |
151 | + Otherwise eumbbar is passed. | |
152 | + | |
153 | + If it is remote, outbound msg of the device is read. | |
154 | + Otherwise local inbound msg is read. | |
155 | + **/ | |
156 | +extern I2OSTATUS I2OMsgGet ( LOCATION, /* REMOTE/LOCAL */ | |
157 | + unsigned int base, /*pcsrbar/eumbbar */ | |
158 | + unsigned int n, /* 0 or 1 */ | |
159 | + unsigned int *msg ); | |
160 | + | |
161 | +/** | |
162 | + Write to nth Msg register either on local outbound msg 0/1, | |
163 | + or aninbound msg 0/1 of devices | |
164 | + | |
165 | + If it is not local, pcsrbar must be passed to the function. | |
166 | + Otherwise eumbbar is passed. | |
167 | + | |
168 | + If it is remote, inbound msg on the device is written. | |
169 | + Otherwise local outbound msg is written. | |
170 | + **/ | |
171 | +extern I2OSTATUS I2OMsgPost( LOCATION, /* REMOTE/LOCAL */ | |
172 | + unsigned int base, /*pcsrbar/eumbbar */ | |
173 | + unsigned int n, /* 0 or 1 */ | |
174 | + unsigned int msg ); | |
175 | + | |
176 | +/** | |
177 | + Enable the In/Out DoorBell Interrupt | |
178 | + | |
179 | + InDoorBell interrupt is generated by PCI master and serviced by local processor | |
180 | + local processor needs to enable its inbound doorbell interrupts it wants to handle | |
181 | + | |
182 | + OutDoorbell interrupt is generated by local processor and serviced by PCI master | |
183 | + PCI master needs to enable outbound doorbell interrupts of the devices it wants to handle | |
184 | + **/ | |
185 | +extern I2OSTATUS I2ODBEnable( LOCATION, /* REMOTE/LOCAL */ | |
186 | + unsigned int base, /* pcsrbar/eumbbar */ | |
187 | + unsigned int in_db );/* when LOCAL, I2O_IN_DB, MC, I2O_IN_DB|MC */ | |
188 | + | |
189 | +/** | |
190 | + Disable the In/Out DoorBell Interrupt | |
191 | + | |
192 | + local processor needs to disable its inbound doorbell interrupts it is not interested | |
193 | + | |
194 | + PCI master needs to disable outbound doorbell interrupts of devices it is not interested | |
195 | + | |
196 | + **/ | |
197 | +extern I2OSTATUS I2ODBDisable( LOCATION, /* REMOTE/LOCAL */ | |
198 | + unsigned int base, /* pcsrbar/eumbbar */ | |
199 | + unsigned int in_db ); /* when LOCAL, I2O_IN_DB, MC, I2O_IN_DB|MC */ | |
200 | + | |
201 | +/** | |
202 | + Read a local indoorbell register, or an outdoorbell of devices. | |
203 | + Reading a doorbell register, the register will be cleared. | |
204 | + | |
205 | + If it is not local, pcsrbar must be passed to the function. | |
206 | + Otherwise eumbbar is passed. | |
207 | + | |
208 | + If it is remote, outdoorbell register on the device is read. | |
209 | + Otherwise local in doorbell is read | |
210 | + **/ | |
211 | +extern unsigned int I2ODBGet( LOCATION, /* REMOTE/LOCAL */ | |
212 | + unsigned int base); /* pcsrbar/eumbbar */ | |
213 | + | |
214 | +/** | |
215 | + Write to a local outdoorbell register, or an indoorbell register of devices. | |
216 | + | |
217 | + If it is not local, pcsrbar must be passed to the function. | |
218 | + Otherwise eumbbar is passed. | |
219 | + | |
220 | + If it is remote, in doorbell register on the device is written. | |
221 | + Otherwise local out doorbell is written | |
222 | + **/ | |
223 | +extern void I2ODBPost( LOCATION, /* REMOTE/LOCAL */ | |
224 | + unsigned int base, /* pcsrbar/eumbbar */ | |
225 | + unsigned int msg ); /* in / out */ | |
226 | + | |
227 | +/** | |
228 | + Read the outbound msg unit interrupt status of devices. Reading an interrupt status register, | |
229 | + the register will be cleared. | |
230 | + | |
231 | + The outbound interrupt status is AND with the outbound | |
232 | + interrupt mask. The result is returned. | |
233 | + | |
234 | + PCI master must pass the pcsrbar to the function. | |
235 | + **/ | |
236 | +extern I2OSTATUS I2OOutMsgStatGet( unsigned int pcsrbar, I2OOMSTAT * ); | |
237 | + | |
238 | +/** | |
239 | + Read the inbound msg unit interrupt status. Reading an interrupt status register, | |
240 | + the register will be cleared. | |
241 | + | |
242 | + The inbound interrupt status is AND with the inbound | |
243 | + interrupt mask. The result is returned. | |
244 | + | |
245 | + Local process must pass its eumbbar to the function. | |
246 | +**/ | |
247 | +extern I2OSTATUS I2OInMsgStatGet( unsigned int eumbbar, I2OIMSTAT * ); | |
248 | + | |
249 | +/** | |
250 | + Configure the I2O FIFO, including QBAR, IFHPR/IFTPR,IPHPR/IPTPR,OFHPR/OFTPR, OPHPR/OPTPR, | |
251 | + MUCR. | |
252 | + **/ | |
253 | +extern I2OSTATUS I2OFIFOInit( unsigned int eumbbar, | |
254 | + QUEUE_SIZE, | |
255 | + unsigned int qba);/* queue base address that must be aligned at 1M */ | |
256 | +/** | |
257 | + Enable the circular queue | |
258 | + **/ | |
259 | +extern I2OSTATUS I2OFIFOEnable( unsigned int eumbbar ); | |
260 | + | |
261 | +/** | |
262 | + Disable the circular queue | |
263 | + **/ | |
264 | +extern void I2OFIFODisable( unsigned int eumbbar ); | |
265 | + | |
266 | +/** | |
267 | + Enable the circular queue interrupt | |
268 | + PCI master enables outbound FIFO interrupt of device | |
269 | + Device enables its inbound FIFO interrupt | |
270 | + **/ | |
271 | +extern void I2OFIFOIntEnable( LOCATION, unsigned int base ); | |
272 | + | |
273 | +/** | |
274 | + Disable the circular queue interrupt | |
275 | + PCI master disables outbound FIFO interrupt of device | |
276 | + Device disables its inbound FIFO interrupt | |
277 | + **/ | |
278 | +extern void I2OFIFOIntDisable( LOCATION, unsigned int base ); | |
279 | + | |
280 | +/** | |
281 | + Enable the circular queue overflow interrupt | |
282 | + **/ | |
283 | +extern void I2OFIFOOverflowIntEnable( unsigned int eumbbar ); | |
284 | + | |
285 | +/** | |
286 | + Disable the circular queue overflow interrupt | |
287 | + **/ | |
288 | +extern void I2OFIFOOverflowIntDisable( unsigned int eumbbar ); | |
289 | + | |
290 | +/** | |
291 | + Allocate a free msg frame from free FIFO. | |
292 | + | |
293 | + PCI Master allocates a free msg frame through inbound queue port of device(IFQPR) | |
294 | + while local processor allocates a free msg frame from outbound free queue(OFTPR) | |
295 | + | |
296 | + Unless both free queues are initialized, allocating a free MF will return 0xffffffff | |
297 | + **/ | |
298 | +extern I2OSTATUS I2OFIFOAlloc( LOCATION, | |
299 | + unsigned int base, | |
300 | + void **pMsg); | |
301 | +/** | |
302 | + Free a used msg frame back to free queue | |
303 | + PCI Master frees a MFA through outbound queue port of device(OFQPR) | |
304 | + while local processor frees a MFA into its inbound free queue(IFHPR) | |
305 | + | |
306 | + Used msg frame does not need to be recycled in the order they | |
307 | + read | |
308 | + | |
309 | + This function has to be called by PCI master to initialize Inbound free queue | |
310 | + and by device to initialize Outbound free queue before I2OFIFOAlloc can be used. | |
311 | + **/ | |
312 | +extern I2OSTATUS I2OFIFOFree( LOCATION, | |
313 | + unsigned int base, | |
314 | + void *pMsg ); | |
315 | + | |
316 | +/** | |
317 | + Post a msg into FIFO | |
318 | + PCI Master posts a msg through inbound queue port of device(IFQPR) | |
319 | + while local processor post a msg into its outbound post queue(OPHPR) | |
320 | + | |
321 | + The total number of msg must be less than the max size of the queue | |
322 | + Otherwise queue overflow interrupt will assert. | |
323 | + **/ | |
324 | +extern I2OSTATUS I2OFIFOPost( LOCATION, | |
325 | + unsigned int base, | |
326 | + void *pMsg ); | |
327 | + | |
328 | +/** | |
329 | + Read a msg from FIFO | |
330 | + PCI Master reads a msg through outbound queue port of device(OFQPR) | |
331 | + while local processor reads a msg from its inbound post queue(IPTPR) | |
332 | + **/ | |
333 | +extern I2OSTATUS I2OFIFOGet( LOCATION, | |
334 | + unsigned int base, | |
335 | + void **pMsg ); | |
336 | + | |
337 | +/** | |
338 | + Get the I2O PCI configuration identification register | |
339 | + **/ | |
340 | +extern I2OSTATUS I2OPCIConfigGet( LOCATION, | |
341 | + unsigned int base, | |
342 | + I2OIOP *); | |
343 | + | |
344 | +#endif |
cpu/mpc824x/drivers/i2o/Makefile
1 | +########################################################################## | |
2 | +# | |
3 | +# Copyright Motorola, Inc. 1997 | |
4 | +# ALL RIGHTS RESERVED | |
5 | +# | |
6 | +# You are hereby granted a copyright license to use, modify, and | |
7 | +# distribute the SOFTWARE so long as this entire notice is retained | |
8 | +# without alteration in any modified and/or redistributed versions, | |
9 | +# and that such modified versions are clearly identified as such. | |
10 | +# No licenses are granted by implication, estoppel or otherwise under | |
11 | +# any patents or trademarks of Motorola, Inc. | |
12 | +# | |
13 | +# The SOFTWARE is provided on an "AS IS" basis and without warranty. | |
14 | +# To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS | |
15 | +# ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED | |
16 | +# WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR | |
17 | +# PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH | |
18 | +# REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS | |
19 | +# THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS. | |
20 | +# | |
21 | +# To the maximum extent permitted by applicable law, IN NO EVENT SHALL | |
22 | +# MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER | |
23 | +# (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF | |
24 | +# BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS | |
25 | +# INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR | |
26 | +# INABILITY TO USE THE SOFTWARE. | |
27 | +# | |
28 | +############################################################################ | |
29 | +TARGET = libi2o.a | |
30 | + | |
31 | +#DEBUG = -g | |
32 | +DEBUG = | |
33 | +LST = -Hanno -S | |
34 | +OPTIM = | |
35 | +CC = /risc/tools/pkgs/metaware/bin/hcppc | |
36 | +CFLAGS = -Hnocopyr -c -Hsds -Hon=Char_default_unsigned -Hon=Char_is_rep -I../inc -I/risc/tools/pkgs/metaware/inc | |
37 | +CCobj = $(CC) $(CFLAGS) $(DEBUG) $(OPTIM) | |
38 | +PREP = $(CC) $(CFLAGS) -P | |
39 | + | |
40 | +# Assembler used to build the .s files (for the board version) | |
41 | + | |
42 | +ASOPT = -big_si -c | |
43 | +ASDEBUG = -l -fm | |
44 | +AS = /risc/tools/pkgs/metaware/bin/asppc | |
45 | + | |
46 | +# Linker to bring .o files together into an executable. | |
47 | + | |
48 | +LKOPT = -Bbase=0 -Qn -q -r | |
49 | +LKCMD = | |
50 | +LINK = /risc/tools/pkgs/metaware/bin/ldppc $(LKCMD) $(LKOPT) | |
51 | + | |
52 | +# DOS Utilities | |
53 | + | |
54 | +DEL = rm | |
55 | +COPY = cp | |
56 | +LIST = ls | |
57 | + | |
58 | +OBJECTS = i2o1.o i2o2.o | |
59 | + | |
60 | +all: $(TARGET) | |
61 | + | |
62 | +$(TARGET): $(OBJECTS) | |
63 | + $(LINK) $(OBJECTS) -o $@ | |
64 | + | |
65 | +objects: i2o1.o | |
66 | + | |
67 | +clean: | |
68 | + $(DEL) -f *.o *.i *.map *.lst $(TARGET) $(OBJECTS) | |
69 | + | |
70 | +.s.o: | |
71 | + $(DEL) -f $*.i | |
72 | + $(PREP) -Hasmcpp $< | |
73 | + $(AS) $(ASOPT) $*.i | |
74 | +# $(AS) $(ASOPT) $(ASDEBUG) $*.i > $*.lst | |
75 | + | |
76 | +.c.o: | |
77 | + $(CCobj) $< | |
78 | + | |
79 | +.c.s: | |
80 | + $(CCobj) $(LST) $< | |
81 | + | |
82 | +i2o1.o: i2o.h i2o1.c | |
83 | + | |
84 | +i2o2.o: i2o.h i2o2.s |
cpu/mpc824x/drivers/i2o/Makefile_pc
1 | +########################################################################## | |
2 | +# | |
3 | +# makefile_pc for use with PC mksnt tools dink32/drivers/i2o | |
4 | +# | |
5 | +# Copyright Motorola, Inc. 1997 | |
6 | +# ALL RIGHTS RESERVED | |
7 | +# | |
8 | +# You are hereby granted a copyright license to use, modify, and | |
9 | +# distribute the SOFTWARE so long as this entire notice is retained | |
10 | +# without alteration in any modified and/or redistributed versions, | |
11 | +# and that such modified versions are clearly identified as such. | |
12 | +# No licenses are granted by implication, estoppel or otherwise under | |
13 | +# any patents or trademarks of Motorola, Inc. | |
14 | +# | |
15 | +# The SOFTWARE is provided on an "AS IS" basis and without warranty. | |
16 | +# To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS | |
17 | +# ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED | |
18 | +# WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR | |
19 | +# PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH | |
20 | +# REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS | |
21 | +# THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS. | |
22 | +# | |
23 | +# To the maximum extent permitted by applicable law, IN NO EVENT SHALL | |
24 | +# MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER | |
25 | +# (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF | |
26 | +# BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS | |
27 | +# INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR | |
28 | +# INABILITY TO USE THE SOFTWARE. | |
29 | +# | |
30 | +############################################################################ | |
31 | +TARGET = libi2o.a | |
32 | + | |
33 | +#DEBUG = -g | |
34 | +DEBUG = | |
35 | +LST = -Hanno -S | |
36 | +OPTIM = | |
37 | +CC = m:/old_tools/tools/hcppc/bin/hcppc | |
38 | +CFLAGS = -Hnocopyr -c -Hsds -Hon=Char_default_unsigned -Hon=Char_is_rep -I../inc -I/risc/tools/pkgs/metaware/inc | |
39 | +CCobj = $(CC) $(CFLAGS) $(DEBUG) $(OPTIM) | |
40 | +PREP = $(CC) $(CFLAGS) -P | |
41 | + | |
42 | +# Assembler used to build the .s files (for the board version) | |
43 | + | |
44 | +ASOPT = -big_si -c | |
45 | +ASDEBUG = -l -fm | |
46 | +AS = m:/old_tools/tools/hcppc/bin/asppc | |
47 | + | |
48 | +# Linker to bring .o files together into an executable. | |
49 | + | |
50 | +LKOPT = -Bbase=0 -Qn -q -r | |
51 | +LKCMD = | |
52 | +LINK = m:/old_tools/tools/hcppc/bin/ldppc $(LKCMD) $(LKOPT) | |
53 | + | |
54 | +# DOS Utilities | |
55 | + | |
56 | +DEL = rm | |
57 | +COPY = cp | |
58 | +LIST = ls | |
59 | + | |
60 | +OBJECTS = i2o1.o i2o2.o | |
61 | + | |
62 | +all: $(TARGET) | |
63 | + | |
64 | +$(TARGET): $(OBJECTS) | |
65 | + $(LINK) $(OBJECTS) -o $@ | |
66 | + | |
67 | +objects: i2o1.o | |
68 | + | |
69 | +clean: | |
70 | + $(DEL) -f *.o *.i *.map *.lst $(TARGET) $(OBJECTS) | |
71 | + | |
72 | +.s.o: | |
73 | + $(DEL) -f $*.i | |
74 | + $(PREP) -Hasmcpp $< | |
75 | + $(AS) $(ASOPT) $*.i | |
76 | +# $(AS) $(ASOPT) $(ASDEBUG) $*.i > $*.lst | |
77 | + | |
78 | +.c.o: | |
79 | + $(CCobj) $< | |
80 | + | |
81 | +.c.s: | |
82 | + $(CCobj) $(LST) $< | |
83 | + | |
84 | +i2o1.o: i2o.h i2o1.c | |
85 | + $(CCobj) $< | |
86 | + | |
87 | +i2o2.o: i2o.h i2o2.s | |
88 | + $(DEL) -f $*.i | |
89 | + $(PREP) -Hasmcpp $< | |
90 | + $(AS) $(ASOPT) $*.i |
cpu/mpc824x/drivers/i2o/i2o.h
1 | +#ifndef I2O_H | |
2 | +#define I2O_H | |
3 | +/********************************************************* | |
4 | + * | |
5 | + * copyright @ Motorola, 1999 | |
6 | + * | |
7 | + *********************************************************/ | |
8 | + | |
9 | +#define I2O_REG_OFFSET 0x0004 | |
10 | + | |
11 | +#define PCI_CFG_CLA 0x0B | |
12 | +#define PCI_CFG_SCL 0x0A | |
13 | +#define PCI_CFG_PIC 0x09 | |
14 | + | |
15 | +#define I2O_IMR0 0x0050 | |
16 | +#define I2O_IMR1 0x0054 | |
17 | +#define I2O_OMR0 0x0058 | |
18 | +#define I2O_OMR1 0x005C | |
19 | + | |
20 | +#define I2O_ODBR 0x0060 | |
21 | +#define I2O_IDBR 0x0068 | |
22 | + | |
23 | +#define I2O_OMISR 0x0030 | |
24 | +#define I2O_OMIMR 0x0034 | |
25 | +#define I2O_IMISR 0x0100 | |
26 | +#define I2O_IMIMR 0x0104 | |
27 | + | |
28 | +/* accessable to PCI master but local processor */ | |
29 | +#define I2O_IFQPR 0x0040 | |
30 | +#define I2O_OFQPR 0x0044 | |
31 | + | |
32 | +/* accessable to local processor */ | |
33 | +#define I2O_IFHPR 0x0120 | |
34 | +#define I2O_IFTPR 0x0128 | |
35 | +#define I2O_IPHPR 0x0130 | |
36 | +#define I2O_IPTPR 0x0138 | |
37 | +#define I2O_OFHPR 0x0140 | |
38 | +#define I2O_OFTPR 0x0148 | |
39 | +#define I2O_OPHPR 0x0150 | |
40 | +#define I2O_OPTPR 0x0158 | |
41 | +#define I2O_MUCR 0x0164 | |
42 | +#define I2O_QBAR 0x0170 | |
43 | + | |
44 | +#define I2O_NUM_MSG 2 | |
45 | + | |
46 | +typedef enum _i2o_status | |
47 | +{ | |
48 | + I2OSUCCESS = 0, | |
49 | + I2OINVALID, | |
50 | + I2OMSGINVALID, | |
51 | + I2ODBINVALID, | |
52 | + I2OQUEINVALID, | |
53 | + I2OQUEEMPTY, | |
54 | + I2OQUEFULL, | |
55 | + I2ONOEVENT, | |
56 | +} I2OSTATUS; | |
57 | + | |
58 | +typedef enum _queue_size | |
59 | +{ | |
60 | + QSIZE_4K = 0x02, | |
61 | + QSIZE_8K = 0x04, | |
62 | + QSIZE_16K = 0x08, | |
63 | + QSIZE_32K = 0x10, | |
64 | + QSIZe_64K = 0x20, | |
65 | +} QUEUE_SIZE; | |
66 | + | |
67 | +typedef enum _location | |
68 | +{ | |
69 | + LOCAL = 0, /* used by local processor to access its own on board device, | |
70 | + local processor's eumbbar is required */ | |
71 | + REMOTE, /* used by PCI master to access the devices on its PCI device, | |
72 | + device's pcsrbar is required */ | |
73 | +} LOCATION; | |
74 | + | |
75 | +/* door bell */ | |
76 | +typedef enum _i2o_in_db | |
77 | +{ | |
78 | + IN_DB = 1, | |
79 | + MC, /* machine check */ | |
80 | +} I2O_IN_DB; | |
81 | + | |
82 | +/* I2O PCI configuration identification */ | |
83 | +typedef struct _i2o_iop | |
84 | +{ | |
85 | + unsigned int base_class : 8; | |
86 | + unsigned int sub_class : 8; | |
87 | + unsigned int prg_code : 8; | |
88 | +} I2OIOP; | |
89 | + | |
90 | +/* I2O Outbound Message Interrupt Status Register */ | |
91 | +typedef struct _i2o_om_stat | |
92 | +{ | |
93 | + unsigned int rsvd0 : 26; | |
94 | + unsigned int opqi : 1; | |
95 | + unsigned int rsvd1 : 1; | |
96 | + unsigned int odi : 1; | |
97 | + unsigned int rsvd2 : 1; | |
98 | + unsigned int om1i : 1; | |
99 | + unsigned int om0i : 1; | |
100 | +} I2OOMSTAT; | |
101 | + | |
102 | +/* I2O inbound Message Interrupt Status Register */ | |
103 | +typedef struct _i2o_im_stat | |
104 | +{ | |
105 | + unsigned int rsvd0 : 23; | |
106 | + unsigned int ofoi : 1; | |
107 | + unsigned int ipoi : 1; | |
108 | + unsigned int rsvd1 : 1; | |
109 | + unsigned int ipqi : 1; | |
110 | + unsigned int mci : 1; | |
111 | + unsigned int idi : 1; | |
112 | + unsigned int rsvd2 : 1; | |
113 | + unsigned int im1i : 1; | |
114 | + unsigned int im0i : 1; | |
115 | +} I2OIMSTAT; | |
116 | + | |
117 | +/** | |
118 | + Enable the interrupt associated with in/out bound msg | |
119 | + | |
120 | + Inbound message interrupt generated by PCI master and serviced by local processor | |
121 | + local processor needs to enable its inbound interrupts it wants to handle (LOCAL) | |
122 | + | |
123 | + Outbound message interrupt generated by local processor and serviced by PCI master | |
124 | + PCI master needs to enable the devices' outbound interrupts it wants to handle (REMOTE) | |
125 | + **/ | |
126 | +extern I2OSTATUS I2OMsgEnable( LOCATION, /* REMOTE/LOCAL */ | |
127 | + unsigned int base, /* pcsrbar/eumbbar */ | |
128 | + unsigned char n ); /* b'1' - msg 0 | |
129 | + * b'10'- msg 1 | |
130 | + * b'11'- both | |
131 | + */ | |
132 | + | |
133 | +/** | |
134 | + Disable the interrupt associated with in/out bound msg | |
135 | + | |
136 | + local processor needs to disable its inbound interrupts it is not interested (LOCAL) | |
137 | + | |
138 | + PCI master needs to disable outbound interrupts of devices it is not interested (REMOTE) | |
139 | + **/ | |
140 | +extern I2OSTATUS I2OMsgDisable( LOCATION, /* REMOTE/LOCAL */ | |
141 | + unsigned int base, /* pcsrbar/eumbbar */ | |
142 | + unsigned char n ); /* b'1' - msg 0 | |
143 | + * b'10'- msg 1 | |
144 | + * b'11'- both | |
145 | + */ | |
146 | + | |
147 | +/** | |
148 | + Read the msg register either from local inbound msg 0/1, | |
149 | + or an outbound msg 0/1 of devices. | |
150 | + | |
151 | + If it is not local, pcsrbar must be passed to the function. | |
152 | + Otherwise eumbbar is passed. | |
153 | + | |
154 | + If it is remote, outbound msg of the device is read. | |
155 | + Otherwise local inbound msg is read. | |
156 | + **/ | |
157 | +extern I2OSTATUS I2OMsgGet ( LOCATION, /* REMOTE/LOCAL */ | |
158 | + unsigned int base, /*pcsrbar/eumbbar */ | |
159 | + unsigned int n, /* 0 or 1 */ | |
160 | + unsigned int *msg ); | |
161 | + | |
162 | +/** | |
163 | + Write to nth Msg register either on local outbound msg 0/1, | |
164 | + or aninbound msg 0/1 of devices | |
165 | + | |
166 | + If it is not local, pcsrbar must be passed to the function. | |
167 | + Otherwise eumbbar is passed. | |
168 | + | |
169 | + If it is remote, inbound msg on the device is written. | |
170 | + Otherwise local outbound msg is written. | |
171 | + **/ | |
172 | +extern I2OSTATUS I2OMsgPost( LOCATION, /* REMOTE/LOCAL */ | |
173 | + unsigned int base, /*pcsrbar/eumbbar */ | |
174 | + unsigned int n, /* 0 or 1 */ | |
175 | + unsigned int msg ); | |
176 | + | |
177 | +/** | |
178 | + Enable the In/Out DoorBell Interrupt | |
179 | + | |
180 | + InDoorBell interrupt is generated by PCI master and serviced by local processor | |
181 | + local processor needs to enable its inbound doorbell interrupts it wants to handle | |
182 | + | |
183 | + OutDoorbell interrupt is generated by local processor and serviced by PCI master | |
184 | + PCI master needs to enable outbound doorbell interrupts of the devices it wants to handle | |
185 | + **/ | |
186 | +extern I2OSTATUS I2ODBEnable( LOCATION, /* REMOTE/LOCAL */ | |
187 | + unsigned int base, /* pcsrbar/eumbbar */ | |
188 | + unsigned int in_db );/* when LOCAL, I2O_IN_DB, MC, I2O_IN_DB|MC */ | |
189 | + | |
190 | +/** | |
191 | + Disable the In/Out DoorBell Interrupt | |
192 | + | |
193 | + local processor needs to disable its inbound doorbell interrupts it is not interested | |
194 | + | |
195 | + PCI master needs to disable outbound doorbell interrupts of devices it is not interested | |
196 | + | |
197 | + **/ | |
198 | +extern I2OSTATUS I2ODBDisable( LOCATION, /* REMOTE/LOCAL */ | |
199 | + unsigned int base, /* pcsrbar/eumbbar */ | |
200 | + unsigned int in_db ); /* when LOCAL, I2O_IN_DB, MC, I2O_IN_DB|MC */ | |
201 | + | |
202 | +/** | |
203 | + Read a local indoorbell register, or an outdoorbell of devices. | |
204 | + Reading a doorbell register, the register will be cleared. | |
205 | + | |
206 | + If it is not local, pcsrbar must be passed to the function. | |
207 | + Otherwise eumbbar is passed. | |
208 | + | |
209 | + If it is remote, outdoorbell register on the device is read. | |
210 | + Otherwise local in doorbell is read | |
211 | + **/ | |
212 | +extern unsigned int I2ODBGet( LOCATION, /* REMOTE/LOCAL */ | |
213 | + unsigned int base); /* pcsrbar/eumbbar */ | |
214 | + | |
215 | +/** | |
216 | + Write to a local outdoorbell register, or an indoorbell register of devices. | |
217 | + | |
218 | + If it is not local, pcsrbar must be passed to the function. | |
219 | + Otherwise eumbbar is passed. | |
220 | + | |
221 | + If it is remote, in doorbell register on the device is written. | |
222 | + Otherwise local out doorbell is written | |
223 | + **/ | |
224 | +extern void I2ODBPost( LOCATION, /* REMOTE/LOCAL */ | |
225 | + unsigned int base, /* pcsrbar/eumbbar */ | |
226 | + unsigned int msg ); /* in / out */ | |
227 | + | |
228 | +/** | |
229 | + Read the outbound msg unit interrupt status of devices. Reading an interrupt status register, | |
230 | + the register will be cleared. | |
231 | + | |
232 | + The outbound interrupt status is AND with the outbound | |
233 | + interrupt mask. The result is returned. | |
234 | + | |
235 | + PCI master must pass the pcsrbar to the function. | |
236 | + **/ | |
237 | +extern I2OSTATUS I2OOutMsgStatGet( unsigned int pcsrbar, I2OOMSTAT * ); | |
238 | + | |
239 | +/** | |
240 | + Read the inbound msg unit interrupt status. Reading an interrupt status register, | |
241 | + the register will be cleared. | |
242 | + | |
243 | + The inbound interrupt status is AND with the inbound | |
244 | + interrupt mask. The result is returned. | |
245 | + | |
246 | + Local process must pass its eumbbar to the function. | |
247 | +**/ | |
248 | +extern I2OSTATUS I2OInMsgStatGet( unsigned int eumbbar, I2OIMSTAT * ); | |
249 | + | |
250 | +/** | |
251 | + Configure the I2O FIFO, including QBAR, IFHPR/IFTPR,IPHPR/IPTPR,OFHPR/OFTPR, OPHPR/OPTPR, | |
252 | + MUCR. | |
253 | + **/ | |
254 | +extern I2OSTATUS I2OFIFOInit( unsigned int eumbbar, | |
255 | + QUEUE_SIZE, | |
256 | + unsigned int qba);/* queue base address that must be aligned at 1M */ | |
257 | +/** | |
258 | + Enable the circular queue | |
259 | + **/ | |
260 | +extern I2OSTATUS I2OFIFOEnable( unsigned int eumbbar ); | |
261 | + | |
262 | +/** | |
263 | + Disable the circular queue | |
264 | + **/ | |
265 | +extern void I2OFIFODisable( unsigned int eumbbar ); | |
266 | + | |
267 | +/** | |
268 | + Enable the circular queue interrupt | |
269 | + PCI master enables outbound FIFO interrupt of device | |
270 | + Device enables its inbound FIFO interrupt | |
271 | + **/ | |
272 | +extern void I2OFIFOIntEnable( LOCATION, unsigned int base ); | |
273 | + | |
274 | +/** | |
275 | + Disable the circular queue interrupt | |
276 | + PCI master disables outbound FIFO interrupt of device | |
277 | + Device disables its inbound FIFO interrupt | |
278 | + **/ | |
279 | +extern void I2OFIFOIntDisable( LOCATION, unsigned int base ); | |
280 | + | |
281 | +/** | |
282 | + Enable the circular queue overflow interrupt | |
283 | + **/ | |
284 | +extern void I2OFIFOOverflowIntEnable( unsigned int eumbbar ); | |
285 | + | |
286 | +/** | |
287 | + Disable the circular queue overflow interrupt | |
288 | + **/ | |
289 | +extern void I2OFIFOOverflowIntDisable( unsigned int eumbbar ); | |
290 | + | |
291 | +/** | |
292 | + Allocate a free msg frame from free FIFO. | |
293 | + | |
294 | + PCI Master allocates a free msg frame through inbound queue port of device(IFQPR) | |
295 | + while local processor allocates a free msg frame from outbound free queue(OFTPR) | |
296 | + | |
297 | + Unless both free queues are initialized, allocating a free MF will return 0xffffffff | |
298 | + **/ | |
299 | +extern I2OSTATUS I2OFIFOAlloc( LOCATION, | |
300 | + unsigned int base, | |
301 | + void **pMsg); | |
302 | +/** | |
303 | + Free a used msg frame back to free queue | |
304 | + PCI Master frees a MFA through outbound queue port of device(OFQPR) | |
305 | + while local processor frees a MFA into its inbound free queue(IFHPR) | |
306 | + | |
307 | + Used msg frame does not need to be recycled in the order they | |
308 | + read | |
309 | + | |
310 | + This function has to be called by PCI master to initialize Inbound free queue | |
311 | + and by device to initialize Outbound free queue before I2OFIFOAlloc can be used. | |
312 | + **/ | |
313 | +extern I2OSTATUS I2OFIFOFree( LOCATION, | |
314 | + unsigned int base, | |
315 | + void *pMsg ); | |
316 | + | |
317 | +/** | |
318 | + Post a msg into FIFO | |
319 | + PCI Master posts a msg through inbound queue port of device(IFQPR) | |
320 | + while local processor post a msg into its outbound post queue(OPHPR) | |
321 | + | |
322 | + The total number of msg must be less than the max size of the queue | |
323 | + Otherwise queue overflow interrupt will assert. | |
324 | + **/ | |
325 | +extern I2OSTATUS I2OFIFOPost( LOCATION, | |
326 | + unsigned int base, | |
327 | + void *pMsg ); | |
328 | + | |
329 | +/** | |
330 | + Read a msg from FIFO | |
331 | + PCI Master reads a msg through outbound queue port of device(OFQPR) | |
332 | + while local processor reads a msg from its inbound post queue(IPTPR) | |
333 | + **/ | |
334 | +extern I2OSTATUS I2OFIFOGet( LOCATION, | |
335 | + unsigned int base, | |
336 | + void **pMsg ); | |
337 | + | |
338 | +/** | |
339 | + Get the I2O PCI configuration identification register | |
340 | + **/ | |
341 | +extern I2OSTATUS I2OPCIConfigGet( LOCATION, | |
342 | + unsigned int base, | |
343 | + I2OIOP *); | |
344 | + | |
345 | +#endif |
cpu/mpc824x/drivers/i2o/i2o1.c
1 | +/********************************************************* | |
2 | + * $Id | |
3 | + * | |
4 | + * copyright @ Motorola, 1999 | |
5 | + *********************************************************/ | |
6 | +#include "i2o.h" | |
7 | + | |
8 | +extern unsigned int load_runtime_reg( unsigned int eumbbar, unsigned int reg ); | |
9 | +#pragma Alias( load_runtime_reg, "load_runtime_reg" ); | |
10 | + | |
11 | +extern void store_runtime_reg( unsigned int eumbbar, unsigned int reg, unsigned int val ); | |
12 | +#pragma Alias( store_runtime_reg, "store_runtime_reg" ); | |
13 | + | |
14 | +typedef struct _fifo_stat | |
15 | +{ | |
16 | + QUEUE_SIZE qsz; | |
17 | + unsigned int qba; | |
18 | +} FIFOSTAT; | |
19 | + | |
20 | +FIFOSTAT fifo_stat = { QSIZE_4K, 0xffffffff }; | |
21 | + | |
22 | +/********************************************************************************** | |
23 | + * function: I2OMsgEnable | |
24 | + * | |
25 | + * description: Enable the interrupt associated with in/out bound msg | |
26 | + * return I2OSUCCESS if no error, otherwise return I2OMSGINVALID. | |
27 | + * | |
28 | + * All previously enabled interrupts are preserved. | |
29 | + * note: | |
30 | + * Inbound message interrupt generated by PCI master and serviced by local processor | |
31 | + * Outbound message interrupt generated by local processor and serviced by PCI master | |
32 | + * | |
33 | + * local processor needs to enable its inbound interrupts it wants to handle(LOCAL) | |
34 | + * PCI master needs to enable the outbound interrupts of devices it wants to handle(REMOTE) | |
35 | + ************************************************************************************/ | |
36 | +I2OSTATUS I2OMsgEnable ( LOCATION loc, /* REMOTE/LOCAL */ | |
37 | + unsigned int base, /* pcsrbar/eumbbar */ | |
38 | + unsigned char n ) /* b'1' - msg 0 | |
39 | + * b'10'- msg 1 | |
40 | + * b'11'- both | |
41 | + */ | |
42 | +{ | |
43 | + unsigned int reg, val; | |
44 | + if ( ( n & 0x3 ) == 0 ) | |
45 | + { | |
46 | + /* neither msg 0, nor msg 1 */ | |
47 | + return I2OMSGINVALID; | |
48 | + } | |
49 | + | |
50 | + n = (~n) & 0x3; | |
51 | + /* LOCATION - REMOTE : enable outbound message of device, pcsrbar as base | |
52 | + * LOCAL : enable local inbound message, eumbbar as base | |
53 | + */ | |
54 | + reg = ( loc == REMOTE ? I2O_OMIMR : I2O_IMIMR ); | |
55 | + val = load_runtime_reg( base, reg ); | |
56 | + | |
57 | + val &= 0xfffffffc; /* masked out the msg interrupt bits */ | |
58 | + val |= n; /* LSB are the one we want */ | |
59 | + store_runtime_reg( base, reg, val ); | |
60 | + | |
61 | + return I2OSUCCESS; | |
62 | +} | |
63 | + | |
64 | +/********************************************************************************* | |
65 | + * function: I2OMsgDisable | |
66 | + * | |
67 | + * description: Disable the interrupt associated with in/out bound msg | |
68 | + * Other previously enabled interrupts are preserved. | |
69 | + * return I2OSUCCESS if no error otherwise return I2OMSGINVALID | |
70 | + * | |
71 | + * note: | |
72 | + * local processor needs to disable its inbound interrupts it is not interested(LOCAL) | |
73 | + * PCI master needs to disable outbound interrupts of devices it is not interested(REMOTE) | |
74 | + *********************************************************************************/ | |
75 | +I2OSTATUS I2OMsgDisable( LOCATION loc, /* REMOTE/LOCAL */ | |
76 | + unsigned int base, /* pcsrbar/eumbbar */ | |
77 | + unsigned char n ) /* b'1' - msg 0 | |
78 | + * b'10'- msg 1 | |
79 | + * b'11'- both | |
80 | + */ | |
81 | +{ | |
82 | + unsigned int reg, val; | |
83 | + | |
84 | + if ( ( n & 0x3 ) == 0 ) | |
85 | + { | |
86 | + /* neither msg 0, nor msg 1 */ | |
87 | + return I2OMSGINVALID; | |
88 | + } | |
89 | + | |
90 | + /* LOCATION - REMOTE : disable outbound message interrupt of device, pcsrbar as base | |
91 | + * LOCAL : disable local inbound message interrupt, eumbbar as base | |
92 | + */ | |
93 | + reg = ( loc == REMOTE ? I2O_OMIMR : I2O_IMIMR ); | |
94 | + val = load_runtime_reg( base, reg ); | |
95 | + | |
96 | + val &= 0xfffffffc; /* masked out the msg interrupt bits */ | |
97 | + val |= ( n & 0x3 ); | |
98 | + store_runtime_reg( base, reg, val ); | |
99 | + | |
100 | + return I2OSUCCESS; | |
101 | + | |
102 | +} | |
103 | + | |
104 | +/************************************************************************** | |
105 | + * function: I2OMsgGet | |
106 | + * | |
107 | + * description: Local processor reads the nth Msg register from its inbound msg, | |
108 | + * or a PCI Master reads nth outbound msg from device | |
109 | + * | |
110 | + * return I2OSUCCESS if no error, otherwise return I2OMSGINVALID. | |
111 | + * | |
112 | + * note: | |
113 | + * If it is not local, pcsrbar must be passed to the function. Otherwise eumbbar is passed. | |
114 | + * If it is remote, outbound msg on the device is read; otherwise local inbound msg is read | |
115 | + *************************************************************************/ | |
116 | +I2OSTATUS I2OMsgGet ( LOCATION loc, /* REMOTE/LOCAL */ | |
117 | + unsigned int base, /*pcsrbar/eumbbar */ | |
118 | + unsigned int n, /* 0 or 1 */ | |
119 | + unsigned int *msg ) | |
120 | +{ | |
121 | + if ( n >= I2O_NUM_MSG || msg == 0 ) | |
122 | + { | |
123 | + return I2OMSGINVALID; | |
124 | + } | |
125 | + | |
126 | + if ( loc == REMOTE ) | |
127 | + { | |
128 | + /* read the outbound msg of the device, pcsrbar as base */ | |
129 | + *msg = load_runtime_reg( base, I2O_OMR0+n*I2O_REG_OFFSET ); | |
130 | + } | |
131 | + else | |
132 | + { | |
133 | + /* read the inbound msg sent by PCI master, eumbbar as base */ | |
134 | + *msg = load_runtime_reg( base, I2O_IMR0+n*I2O_REG_OFFSET ); | |
135 | + } | |
136 | + | |
137 | + return I2OSUCCESS; | |
138 | +} | |
139 | + | |
140 | +/*************************************************************** | |
141 | + * function: I2OMsgPost | |
142 | + * | |
143 | + * description: Kahlua writes to its nth outbound msg register | |
144 | + * PCI master writes to nth inbound msg register of device | |
145 | + * | |
146 | + * return I2OSUCCESS if no error, otherwise return I2OMSGINVALID. | |
147 | + * | |
148 | + * note: | |
149 | + * If it is not local, pcsrbar must be passed to the function. Otherwise eumbbar is passed. | |
150 | + * | |
151 | + * If it is remote, inbound msg on the device is written; otherwise local outbound msg is written | |
152 | + ***************************************************************/ | |
153 | +I2OSTATUS I2OMsgPost( LOCATION loc, /* REMOTE/LOCAL */ | |
154 | + unsigned int base, /*pcsrbar/eumbbar */ | |
155 | + unsigned int n, /* 0 or 1 */ | |
156 | + unsigned int msg ) | |
157 | +{ | |
158 | + if ( n >= I2O_NUM_MSG ) | |
159 | + { | |
160 | + return I2OMSGINVALID; | |
161 | + } | |
162 | + | |
163 | + if ( loc == REMOTE ) | |
164 | + { | |
165 | + /* write to the inbound msg register of the device, pcsrbar as base */ | |
166 | + store_runtime_reg( base, I2O_IMR0+n*I2O_REG_OFFSET, msg ); | |
167 | + } | |
168 | + else | |
169 | + { | |
170 | + /* write to the outbound msg register for PCI master to read, eumbbar as base */ | |
171 | + store_runtime_reg( base, I2O_OMR0+n*I2O_REG_OFFSET, msg ); | |
172 | + } | |
173 | + | |
174 | + return I2OSUCCESS; | |
175 | +} | |
176 | + | |
177 | +/*********************************************************************** | |
178 | + * function: I2ODBEnable | |
179 | + * | |
180 | + * description: Local processor enables it's inbound doorbell interrupt | |
181 | + * PCI master enables outbound doorbell interrupt of devices | |
182 | + * Other previously enabled interrupts are preserved. | |
183 | + * Return I2OSUCCESS if no error otherwise return I2ODBINVALID | |
184 | + * | |
185 | + * note: | |
186 | + * In DoorBell interrupt is generated by PCI master and serviced by local processor | |
187 | + * Out Doorbell interrupt is generated by local processor and serviced by PCI master | |
188 | + * | |
189 | + * Out Doorbell interrupt is generated by local processor and serviced by PCI master | |
190 | + * PCI master needs to enable the outbound doorbell interrupts of device it wants to handle | |
191 | + **********************************************************************/ | |
192 | +I2OSTATUS I2ODBEnable( LOCATION loc, /* REMOTE/LOCAL */ | |
193 | + unsigned int base, /* pcsrbar/eumbbar */ | |
194 | + unsigned int in_db ) /* when LOCAL, I2O_IN_DB, MC, I2O_IN_DB|MC */ | |
195 | +{ | |
196 | + | |
197 | + /* LOCATION - REMOTE : PCI master initializes outbound doorbell message of device | |
198 | + * LOCAL : Kahlua initializes its inbound doorbell message | |
199 | + */ | |
200 | + unsigned int val; | |
201 | + | |
202 | + if ( loc == LOCAL && ( in_db & 0x3 ) == 0 ) | |
203 | + { | |
204 | + return I2ODBINVALID; | |
205 | + } | |
206 | + | |
207 | + if ( loc == REMOTE ) | |
208 | + { | |
209 | + /* pcsrbar is base */ | |
210 | + val = load_runtime_reg( base, I2O_OMIMR ); | |
211 | + val &= 0xfffffff7; | |
212 | + store_runtime_reg( base, I2O_OMIMR , val ); | |
213 | + } | |
214 | + else | |
215 | + { | |
216 | + /* eumbbar is base */ | |
217 | + val = load_runtime_reg( base, I2O_IMIMR); | |
218 | + in_db = ( (~in_db) & 0x3 ) << 3; | |
219 | + val = ( val & 0xffffffe7) | in_db; | |
220 | + store_runtime_reg( base, I2O_IMIMR, val ); | |
221 | + } | |
222 | + | |
223 | + return I2OSUCCESS; | |
224 | +} | |
225 | + | |
226 | +/********************************************************************************** | |
227 | + * function: I2ODBDisable | |
228 | + * | |
229 | + * description: local processor disables its inbound DoorBell Interrupt | |
230 | + * PCI master disables outbound DoorBell interrupt of device | |
231 | + * Other previously enabled interrupts are preserved. | |
232 | + * return I2OSUCCESS if no error.Otherwise return I2ODBINVALID | |
233 | + * | |
234 | + * note: | |
235 | + * local processor needs to disable its inbound doorbell interrupts it is not interested | |
236 | + * | |
237 | + * PCI master needs to disable outbound doorbell interrupts of device it is not interested | |
238 | + ************************************************************************************/ | |
239 | +I2OSTATUS I2ODBDisable( LOCATION loc, /* REMOTE/LOCAL */ | |
240 | + unsigned int base, /* pcsrbar/eumbbar */ | |
241 | + unsigned int in_db ) /* when LOCAL, I2O_IN_DB, MC, I2O_IN_DB|MC */ | |
242 | +{ | |
243 | + /* LOCATION - REMOTE : handle device's out bound message initialization | |
244 | + * LOCAL : handle local in bound message initialization | |
245 | + */ | |
246 | + unsigned int val; | |
247 | + | |
248 | + if ( loc == LOCAL && ( in_db & 0x3 ) == 0 ) | |
249 | + { | |
250 | + return I2ODBINVALID; | |
251 | + } | |
252 | + | |
253 | + if ( loc == REMOTE ) | |
254 | + { | |
255 | + /* pcsrbar is the base */ | |
256 | + val = load_runtime_reg( base, I2O_OMIMR ); | |
257 | + val |= 0x8; | |
258 | + store_runtime_reg( base, I2O_OMIMR, val ); | |
259 | + } | |
260 | + else | |
261 | + { | |
262 | + val = load_runtime_reg( base, I2O_IMIMR); | |
263 | + in_db = ( in_db & 0x3 ) << 3; | |
264 | + val |= in_db; | |
265 | + store_runtime_reg( base, I2O_IMIMR, val ); | |
266 | + } | |
267 | + | |
268 | + return I2OSUCCESS; | |
269 | +} | |
270 | + | |
271 | +/********************************************************************************** | |
272 | + * function: I2ODBGet | |
273 | + * | |
274 | + * description: Local processor reads its in doorbell register, | |
275 | + * PCI master reads the outdoorbell register of device. | |
276 | + * After a doorbell register is read, the whole register will be cleared. | |
277 | + * Otherwise, HW keeps generating interrupt. | |
278 | + * | |
279 | + * note: | |
280 | + * If it is not local, pcsrbar must be passed to the function. | |
281 | + * Otherwise eumbbar is passed. | |
282 | + * | |
283 | + * If it is remote, out doorbell register on the device is read. | |
284 | + * Otherwise local in doorbell is read | |
285 | + * | |
286 | + * If the register is not cleared by write to it, any remaining bit of b'1's | |
287 | + * will cause interrupt pending. | |
288 | + *********************************************************************************/ | |
289 | +unsigned int I2ODBGet( LOCATION loc, /* REMOTE/LOCAL */ | |
290 | + unsigned int base) /* pcsrbar/eumbbar */ | |
291 | +{ | |
292 | + unsigned int msg, val; | |
293 | + | |
294 | + if ( loc == REMOTE ) | |
295 | + { | |
296 | + /* read outbound doorbell register of device, pcsrbar is the base */ | |
297 | + val = load_runtime_reg( base, I2O_ODBR ); | |
298 | + msg = val & 0xe0000000; | |
299 | + store_runtime_reg( base, I2O_ODBR, val ); /* clear the register */ | |
300 | + } | |
301 | + else | |
302 | + { | |
303 | + /* read the inbound doorbell register, eumbbar is the base */ | |
304 | + val = load_runtime_reg( base, I2O_IDBR ); | |
305 | + store_runtime_reg( base, I2O_IDBR, val ); /* clear the register */ | |
306 | + msg = val; | |
307 | + } | |
308 | + | |
309 | + return msg; | |
310 | +} | |
311 | + | |
312 | +/********************************************************************** | |
313 | + * function: I2ODBPost | |
314 | + * | |
315 | + * description: local processor writes to a outbound doorbell register, | |
316 | + * PCI master writes to the inbound doorbell register of device | |
317 | + * | |
318 | + * note: | |
319 | + * If it is not local, pcsrbar must be passed to the function. | |
320 | + * Otherwise eumbbar is passed. | |
321 | + * | |
322 | + * If it is remote, in doorbell register on the device is written. | |
323 | + * Otherwise local out doorbell is written | |
324 | + *********************************************************************/ | |
325 | +void I2ODBPost( LOCATION loc, /* REMOTE/LOCAL */ | |
326 | + unsigned int base, /* pcsrbar/eumbbar */ | |
327 | + unsigned int msg ) /* in / out */ | |
328 | +{ | |
329 | + if ( loc == REMOTE ) | |
330 | + { | |
331 | + /* write to inbound doorbell register of device, pcsrbar is the base */ | |
332 | + store_runtime_reg( base, I2O_IDBR, msg ); | |
333 | + } | |
334 | + else | |
335 | + { | |
336 | + /* write to local outbound doorbell register, eumbbar is the base */ | |
337 | + store_runtime_reg( base, I2O_ODBR, msg & 0x1fffffff ); | |
338 | + } | |
339 | + | |
340 | +} | |
341 | + | |
342 | +/******************************************************************** | |
343 | + * function: I2OOutMsgStatGet | |
344 | + * | |
345 | + * description: PCI master reads device's outbound msg unit interrupt status. | |
346 | + * Reading an interrupt status register, | |
347 | + * the register will be cleared. | |
348 | + * | |
349 | + * The value of the status register is AND with the outbound | |
350 | + * interrupt mask and result is returned. | |
351 | + * | |
352 | + * note: | |
353 | + * pcsrbar must be passed to the function. | |
354 | + ********************************************************************/ | |
355 | +I2OSTATUS I2OOutMsgStatGet( unsigned int pcsrbar, I2OOMSTAT *val ) | |
356 | +{ | |
357 | + unsigned int stat; | |
358 | + unsigned int mask; | |
359 | + | |
360 | + if ( val == 0 ) | |
361 | + { | |
362 | + return I2OINVALID; | |
363 | + } | |
364 | + | |
365 | + /* read device's outbound status */ | |
366 | + stat = load_runtime_reg( pcsrbar, I2O_OMISR ); | |
367 | + mask = load_runtime_reg( pcsrbar, I2O_OMIMR ); | |
368 | + store_runtime_reg( pcsrbar, I2O_OMISR, stat & 0xffffffd7); | |
369 | + | |
370 | + stat &= mask; | |
371 | + val->rsvd0 = ( stat & 0xffffffc0 ) >> 6; | |
372 | + val->opqi = ( stat & 0x00000020 ) >> 5; | |
373 | + val->rsvd1 = ( stat & 0x00000010 ) >> 4; | |
374 | + val->odi = ( stat & 0x00000008 ) >> 3; | |
375 | + val->rsvd2 = ( stat & 0x00000004 ) >> 2; | |
376 | + val->om1i = ( stat & 0x00000002 ) >> 1; | |
377 | + val->om0i = ( stat & 0x00000001 ); | |
378 | + | |
379 | + return I2OSUCCESS; | |
380 | +} | |
381 | + | |
382 | +/******************************************************************** | |
383 | + * function: I2OInMsgStatGet | |
384 | + * | |
385 | + * description: Local processor reads its inbound msg unit interrupt status. | |
386 | + * Reading an interrupt status register, | |
387 | + * the register will be cleared. | |
388 | + * | |
389 | + * The inbound msg interrupt status is AND with the inbound | |
390 | + * msg interrupt mask and result is returned. | |
391 | + * | |
392 | + * note: | |
393 | + * eumbbar must be passed to the function. | |
394 | + ********************************************************************/ | |
395 | +I2OSTATUS I2OInMsgStatGet(unsigned int eumbbar, I2OIMSTAT *val) | |
396 | +{ | |
397 | + unsigned int stat; | |
398 | + unsigned int mask; | |
399 | + | |
400 | + if ( val == 0 ) | |
401 | + { | |
402 | + return I2OINVALID; | |
403 | + } | |
404 | + | |
405 | + /* read device's outbound status */ | |
406 | + stat = load_runtime_reg( eumbbar, I2O_OMISR ); | |
407 | + mask = load_runtime_reg( eumbbar, I2O_OMIMR ); | |
408 | + store_runtime_reg( eumbbar, I2O_OMISR, stat & 0xffffffe7 ); | |
409 | + | |
410 | + stat &= mask; | |
411 | + val->rsvd0 = ( stat & 0xfffffe00 ) >> 9; | |
412 | + val->ofoi = ( stat & 0x00000100 ) >> 8; | |
413 | + val->ipoi = ( stat & 0x00000080 ) >> 7; | |
414 | + val->rsvd1 = ( stat & 0x00000040 ) >> 6; | |
415 | + val->ipqi = ( stat & 0x00000020 ) >> 5; | |
416 | + val->mci = ( stat & 0x00000010 ) >> 4; | |
417 | + val->idi = ( stat & 0x00000008 ) >> 3; | |
418 | + val->rsvd2 = ( stat & 0x00000004 ) >> 2; | |
419 | + val->im1i = ( stat & 0x00000002 ) >> 1; | |
420 | + val->im0i = ( stat & 0x00000001 ); | |
421 | + | |
422 | + return I2OSUCCESS; | |
423 | + | |
424 | +} | |
425 | + | |
426 | +/*********************************************************** | |
427 | + * function: I2OFIFOInit | |
428 | + * | |
429 | + * description: Configure the I2O FIFO, including QBAR, | |
430 | + * IFHPR/IFTPR, IPHPR/IPTPR, OFHPR/OFTPR, | |
431 | + * OPHPR/OPTPR, MUCR. | |
432 | + * | |
433 | + * return I2OSUCCESS if no error, | |
434 | + * otherwise return I2OQUEINVALID | |
435 | + * | |
436 | + * note: It is NOT this driver's responsibility of initializing | |
437 | + * MFA blocks, i.e., FIFO queue itself. The MFA blocks | |
438 | + * must be initialized before I2O unit can be used. | |
439 | + ***********************************************************/ | |
440 | +I2OSTATUS I2OFIFOInit( unsigned int eumbbar, | |
441 | + QUEUE_SIZE sz, /* value of CQS of MUCR */ | |
442 | + unsigned int qba) /* queue base address that must be aligned at 1M */ | |
443 | +{ | |
444 | + | |
445 | + if ( ( qba & 0xfffff ) != 0 ) | |
446 | + { | |
447 | + /* QBA must be aligned at 1Mbyte boundary */ | |
448 | + return I2OQUEINVALID; | |
449 | + } | |
450 | + | |
451 | + store_runtime_reg( eumbbar, I2O_QBAR, qba ); | |
452 | + store_runtime_reg( eumbbar, I2O_MUCR, (unsigned int)sz ); | |
453 | + store_runtime_reg( eumbbar, I2O_IFHPR, qba ); | |
454 | + store_runtime_reg( eumbbar, I2O_IFTPR, qba ); | |
455 | + store_runtime_reg( eumbbar, I2O_IPHPR, qba + 1 * ( sz << 11 )); | |
456 | + store_runtime_reg( eumbbar, I2O_IPTPR, qba + 1 * ( sz << 11 )); | |
457 | + store_runtime_reg( eumbbar, I2O_OFHPR, qba + 2 * ( sz << 11 )); | |
458 | + store_runtime_reg( eumbbar, I2O_OFTPR, qba + 2 * ( sz << 11 )); | |
459 | + store_runtime_reg( eumbbar, I2O_OPHPR, qba + 3 * ( sz << 11 )); | |
460 | + store_runtime_reg( eumbbar, I2O_OPTPR, qba + 3 * ( sz << 11 )); | |
461 | + | |
462 | + fifo_stat.qsz = sz; | |
463 | + fifo_stat.qba = qba; | |
464 | + | |
465 | + return I2OSUCCESS; | |
466 | +} | |
467 | + | |
468 | +/************************************************** | |
469 | + * function: I2OFIFOEnable | |
470 | + * | |
471 | + * description: Enable the circular queue | |
472 | + * return I2OSUCCESS if no error. | |
473 | + * Otherwise I2OQUEINVALID is returned. | |
474 | + * | |
475 | + * note: | |
476 | + *************************************************/ | |
477 | +I2OSTATUS I2OFIFOEnable( unsigned int eumbbar ) | |
478 | +{ | |
479 | + unsigned int val; | |
480 | + | |
481 | + if ( fifo_stat.qba == 0xfffffff ) | |
482 | + { | |
483 | + return I2OQUEINVALID; | |
484 | + } | |
485 | + | |
486 | + val = load_runtime_reg( eumbbar, I2O_MUCR ); | |
487 | + store_runtime_reg( eumbbar, I2O_MUCR, val | 0x1 ); | |
488 | + | |
489 | + return I2OSUCCESS; | |
490 | +} | |
491 | + | |
492 | +/************************************************** | |
493 | + * function: I2OFIFODisable | |
494 | + * | |
495 | + * description: Disable the circular queue | |
496 | + * | |
497 | + * note: | |
498 | + *************************************************/ | |
499 | +void I2OFIFODisable( unsigned int eumbbar ) | |
500 | +{ | |
501 | + if ( fifo_stat.qba == 0xffffffff ) | |
502 | + { | |
503 | + /* not enabled */ | |
504 | + return; | |
505 | + } | |
506 | + | |
507 | + unsigned int val = load_runtime_reg( eumbbar, I2O_MUCR ); | |
508 | + store_runtime_reg( eumbbar, I2O_MUCR, val & 0xfffffffe ); | |
509 | +} | |
510 | + | |
511 | +/**************************************************** | |
512 | + * function: I2OFIFOAlloc | |
513 | + * | |
514 | + * description: Allocate a free MFA from free FIFO. | |
515 | + * return I2OSUCCESS if no error. | |
516 | + * return I2OQUEEMPTY if no more free MFA. | |
517 | + * return I2OINVALID on other errors. | |
518 | + * | |
519 | + * A free MFA must be allocated before a | |
520 | + * message can be posted. | |
521 | + * | |
522 | + * note: | |
523 | + * PCI Master allocates a free MFA from inbound queue of device | |
524 | + * (pcsrbar is the base,) through the inbound queue port of device | |
525 | + * while local processor allocates a free MFA from its outbound | |
526 | + * queue (eumbbar is the base.) | |
527 | + * | |
528 | + ****************************************************/ | |
529 | +I2OSTATUS I2OFIFOAlloc( LOCATION loc, | |
530 | + unsigned int base, | |
531 | + void **pMsg ) | |
532 | +{ | |
533 | + I2OSTATUS stat = I2OSUCCESS; | |
534 | + void *pHdr, *pTil; | |
535 | + | |
536 | + if ( pMsg == 0 || *pMsg == 0 || fifo_stat.qba == 0xffffffff ) | |
537 | + { | |
538 | + /* not configured */ | |
539 | + return I2OQUEINVALID; | |
540 | + } | |
541 | + | |
542 | + if ( loc == REMOTE ) | |
543 | + { | |
544 | + /* pcsrbar is the base and read the inbound free tail ptr */ | |
545 | + pTil = (void *)load_runtime_reg( base, I2O_IFQPR ); | |
546 | + if ( ( (unsigned int)pTil & 0xFFFFFFF ) == 0xFFFFFFFF ) | |
547 | + { | |
548 | + stat = I2OQUEEMPTY; | |
549 | + } | |
550 | + else | |
551 | + { | |
552 | + *pMsg = pTil; | |
553 | + } | |
554 | + } | |
555 | + else | |
556 | + { | |
557 | + /* eumbbar is the base and read the outbound free tail ptr */ | |
558 | + pHdr = (void *)load_runtime_reg( base, I2O_OFHPR ); /* queue head */ | |
559 | + pTil = (void *)load_runtime_reg( base, I2O_OFTPR ); /* queue tail */ | |
560 | + | |
561 | + /* check underflow */ | |
562 | + if ( pHdr == pTil ) | |
563 | + { | |
564 | + /* hdr and til point to the same fifo item, no free MFA */ | |
565 | + stat = I2OQUEEMPTY; | |
566 | + } | |
567 | + else | |
568 | + { | |
569 | + /* update OFTPR */ | |
570 | + *pMsg = (void *)(*(unsigned char *)pTil); | |
571 | + pTil = (void *)((unsigned int)pTil + 4); | |
572 | + if ( (unsigned int)pTil == fifo_stat.qba + ( 4 * ( fifo_stat.qsz << 11 ) ) ) | |
573 | + { | |
574 | + /* reach the upper limit */ | |
575 | + pTil = (void *)(fifo_stat.qba + ( 3 * (fifo_stat.qsz << 11) )); | |
576 | + } | |
577 | + store_runtime_reg( base, I2O_OFTPR, (unsigned int)pTil ); | |
578 | + } | |
579 | + } | |
580 | + | |
581 | + return stat; | |
582 | +} | |
583 | + | |
584 | +/****************************************************** | |
585 | + * function: I2OFIFOFree | |
586 | + * | |
587 | + * description: Free a used MFA back to free queue after | |
588 | + * use. | |
589 | + * return I2OSUCCESS if no error. | |
590 | + * return I2OQUEFULL if inbound free queue | |
591 | + * overflow | |
592 | + * | |
593 | + * note: PCI Master frees a MFA into device's outbound queue | |
594 | + * (OFQPR) while local processor frees a MFA into its | |
595 | + * inbound queue (IFHPR). | |
596 | + *****************************************************/ | |
597 | +I2OSTATUS I2OFIFOFree( LOCATION loc, | |
598 | + unsigned int base, | |
599 | + void *pMsg ) | |
600 | +{ | |
601 | + void **pHdr, **pTil; | |
602 | + I2OSTATUS stat = I2OSUCCESS; | |
603 | + | |
604 | + if ( fifo_stat.qba == 0xffffffff || pMsg == 0 ) | |
605 | + { | |
606 | + return I2OQUEINVALID; | |
607 | + } | |
608 | + | |
609 | + if ( loc == REMOTE ) | |
610 | + { | |
611 | + /* pcsrbar is the base */ | |
612 | + store_runtime_reg( base, I2O_OFQPR, (unsigned int)pMsg ); | |
613 | + } | |
614 | + else | |
615 | + { | |
616 | + /* eumbbar is the base */ | |
617 | + pHdr = (void **)load_runtime_reg( base, I2O_IFHPR ); | |
618 | + pTil = (void **)load_runtime_reg( base, I2O_IFTPR ); | |
619 | + | |
620 | + /* store MFA */ | |
621 | + *pHdr = pMsg; | |
622 | + | |
623 | + /* update IFHPR */ | |
624 | + pHdr += 4; | |
625 | + | |
626 | + if ( (unsigned int)pHdr == fifo_stat.qba + ( fifo_stat.qsz << 11 ) ) | |
627 | + { | |
628 | + /* reach the upper limit */ | |
629 | + pHdr = (void **)fifo_stat.qba; | |
630 | + } | |
631 | + | |
632 | + /* check inbound free queue overflow */ | |
633 | + if ( pHdr != pTil ) | |
634 | + { | |
635 | + store_runtime_reg( base, I2O_OPHPR, (unsigned int)pHdr); | |
636 | + } | |
637 | + else | |
638 | + { | |
639 | + stat = I2OQUEFULL; | |
640 | + } | |
641 | + | |
642 | + } | |
643 | + | |
644 | + return stat; | |
645 | + | |
646 | +} | |
647 | + | |
648 | +/********************************************* | |
649 | + * function: I2OFIFOPost | |
650 | + * | |
651 | + * description: Post a msg into FIFO post queue | |
652 | + * the value of msg must be the one | |
653 | + * returned by I2OFIFOAlloc | |
654 | + * | |
655 | + * note: PCI Master posts a msg into device's inbound queue | |
656 | + * (IFQPR) while local processor post a msg into device's | |
657 | + * outbound queue (OPHPR) | |
658 | + *********************************************/ | |
659 | +I2OSTATUS I2OFIFOPost( LOCATION loc, | |
660 | + unsigned int base, | |
661 | + void *pMsg ) | |
662 | +{ | |
663 | + void **pHdr, **pTil; | |
664 | + I2OSTATUS stat = I2OSUCCESS; | |
665 | + | |
666 | + if ( fifo_stat.qba == 0xffffffff || pMsg == 0 ) | |
667 | + { | |
668 | + return I2OQUEINVALID; | |
669 | + } | |
670 | + | |
671 | + if ( loc == REMOTE ) | |
672 | + { | |
673 | + /* pcsrbar is the base */ | |
674 | + store_runtime_reg( base, I2O_IFQPR, (unsigned int)pMsg ); | |
675 | + } | |
676 | + else | |
677 | + { | |
678 | + /* eumbbar is the base */ | |
679 | + pHdr = (void **)load_runtime_reg( base, I2O_OPHPR ); | |
680 | + pTil = (void **)load_runtime_reg( base, I2O_OPTPR ); | |
681 | + | |
682 | + /* store MFA */ | |
683 | + *pHdr = pMsg; | |
684 | + | |
685 | + /* update IFHPR */ | |
686 | + pHdr += 4; | |
687 | + | |
688 | + if ( (unsigned int)pHdr == fifo_stat.qba + 3 * ( fifo_stat.qsz << 11 ) ) | |
689 | + { | |
690 | + /* reach the upper limit */ | |
691 | + pHdr = (void **)(fifo_stat.qba + 2 * ( fifo_stat.qsz << 11 ) ); | |
692 | + } | |
693 | + | |
694 | + /* check post queue overflow */ | |
695 | + if ( pHdr != pTil ) | |
696 | + { | |
697 | + store_runtime_reg( base, I2O_OPHPR, (unsigned int)pHdr); | |
698 | + } | |
699 | + else | |
700 | + { | |
701 | + stat = I2OQUEFULL; | |
702 | + } | |
703 | + } | |
704 | + | |
705 | + return stat; | |
706 | +} | |
707 | + | |
708 | +/************************************************ | |
709 | + * function: I2OFIFOGet | |
710 | + * | |
711 | + * description: Read a msg from FIFO | |
712 | + * This function should be called | |
713 | + * only when there is a corresponding | |
714 | + * msg interrupt. | |
715 | + * | |
716 | + * note: PCI Master reads a msg from device's outbound queue | |
717 | + * (OFQPR) while local processor reads a msg from device's | |
718 | + * inbound queue (IPTPR) | |
719 | + ************************************************/ | |
720 | +I2OSTATUS I2OFIFOGet( LOCATION loc, | |
721 | + unsigned int base, | |
722 | + void **pMsg ) | |
723 | +{ | |
724 | + I2OSTATUS stat = I2OSUCCESS; | |
725 | + void *pHdr, *pTil; | |
726 | + | |
727 | + if ( pMsg == 0 || *pMsg == 0 || fifo_stat.qba == 0xffffffff ) | |
728 | + { | |
729 | + /* not configured */ | |
730 | + return I2OQUEINVALID; | |
731 | + } | |
732 | + | |
733 | + if ( loc == REMOTE ) | |
734 | + { | |
735 | + /* pcsrbar is the base */ | |
736 | + pTil = (void *)load_runtime_reg( base, I2O_OFQPR ); | |
737 | + if ( ( (unsigned int)pTil & 0xFFFFFFF ) == 0xFFFFFFFF ) | |
738 | + { | |
739 | + stat = I2OQUEEMPTY; | |
740 | + } | |
741 | + else | |
742 | + { | |
743 | + *pMsg = pTil; | |
744 | + } | |
745 | + } | |
746 | + else | |
747 | + { | |
748 | + /* eumbbar is the base and read the outbound free tail ptr */ | |
749 | + pHdr = (void *)load_runtime_reg( base, I2O_IPHPR ); /* queue head */ | |
750 | + pTil = (void *)load_runtime_reg( base, I2O_IPTPR ); /* queue tail */ | |
751 | + | |
752 | + /* check underflow */ | |
753 | + if ( pHdr == pTil ) | |
754 | + { | |
755 | + /* no free MFA */ | |
756 | + stat = I2OQUEEMPTY; | |
757 | + } | |
758 | + else | |
759 | + { | |
760 | + /* update OFTPR */ | |
761 | + *pMsg = (void *)(*(unsigned char *)pTil); | |
762 | + pTil = (void *)((unsigned int)pTil + 4); | |
763 | + if ( (unsigned int)pTil == fifo_stat.qba + 2 * ( fifo_stat.qsz << 11 ) ) | |
764 | + { | |
765 | + /* reach the upper limit */ | |
766 | + pTil = (void *)(fifo_stat.qba + 1 * (fifo_stat.qsz << 11) ); | |
767 | + } | |
768 | + | |
769 | + store_runtime_reg( base, I2O_IPTPR, (unsigned int)pTil ); | |
770 | + } | |
771 | + } | |
772 | + | |
773 | + return stat; | |
774 | +} | |
775 | + | |
776 | +/******************************************************** | |
777 | + * function: I2OIOP | |
778 | + * | |
779 | + * description: Get the I2O PCI configuration identification | |
780 | + * register. | |
781 | + * | |
782 | + * note: PCI master should pass pcsrbar while local processor | |
783 | + * should pass eumbbar. | |
784 | + *********************************************************/ | |
785 | +I2OSTATUS I2OPCIConfigGet( LOCATION loc, | |
786 | + unsigned int base, | |
787 | + I2OIOP * val) | |
788 | +{ | |
789 | + unsigned int tmp; | |
790 | + if ( val == 0 ) | |
791 | + { | |
792 | + return I2OINVALID; | |
793 | + } | |
794 | + tmp = load_runtime_reg( base, PCI_CFG_CLA ); | |
795 | + val->base_class = ( tmp & 0xFF) << 16; | |
796 | + tmp = load_runtime_reg( base, PCI_CFG_SCL ); | |
797 | + val->sub_class= ( (tmp & 0xFF) << 8 ); | |
798 | + tmp = load_runtime_reg( base, PCI_CFG_PIC ); | |
799 | + val->prg_code = (tmp & 0xFF); | |
800 | + return I2OSUCCESS; | |
801 | +} | |
802 | + | |
803 | +/********************************************************* | |
804 | + * function: I2OFIFOIntEnable | |
805 | + * | |
806 | + * description: Enable the circular post queue interrupt | |
807 | + * | |
808 | + * note: | |
809 | + * PCI master enables outbound FIFO interrupt of device | |
810 | + * pscrbar is the base | |
811 | + * Device enables its inbound FIFO interrupt | |
812 | + * eumbbar is the base | |
813 | + *******************************************************/ | |
814 | +void I2OFIFOIntEnable( LOCATION loc, unsigned int base ) | |
815 | +{ | |
816 | + unsigned int reg, val; | |
817 | + | |
818 | + /* LOCATION - REMOTE : enable outbound message of device, pcsrbar as base | |
819 | + * LOCAL : enable local inbound message, eumbbar as base | |
820 | + */ | |
821 | + reg = ( loc == REMOTE ? I2O_OMIMR : I2O_IMIMR ); | |
822 | + val = load_runtime_reg( base, reg ); | |
823 | + | |
824 | + val &= 0xffffffdf; /* clear the msg interrupt bits */ | |
825 | + store_runtime_reg( base, reg, val ); | |
826 | + | |
827 | +} | |
828 | + | |
829 | +/**************************************************** | |
830 | + * function: I2OFIFOIntDisable | |
831 | + * | |
832 | + * description: Disable the circular post queue interrupt | |
833 | + * | |
834 | + * note: | |
835 | + * PCI master disables outbound FIFO interrupt of device | |
836 | + * (pscrbar is the base) | |
837 | + * Device disables its inbound FIFO interrupt | |
838 | + * (eumbbar is the base) | |
839 | + *****************************************************/ | |
840 | +void I2OFIFOIntDisable( LOCATION loc, unsigned int base ) | |
841 | +{ | |
842 | + | |
843 | + /* LOCATION - REMOTE : disable outbound message interrupt of device, pcsrbar as base | |
844 | + * LOCAL : disable local inbound message interrupt, eumbbar as base | |
845 | + */ | |
846 | + unsigned int reg = ( loc == REMOTE ? I2O_OMIMR : I2O_IMIMR ); | |
847 | + unsigned int val = load_runtime_reg( base, reg ); | |
848 | + | |
849 | + val |= 0x00000020; /* masked out the msg interrupt bits */ | |
850 | + store_runtime_reg( base, reg, val ); | |
851 | + | |
852 | +} | |
853 | + | |
854 | +/********************************************************* | |
855 | + * function: I2OFIFOOverflowIntEnable | |
856 | + * | |
857 | + * description: Enable the circular queue overflow interrupt | |
858 | + * | |
859 | + * note: | |
860 | + * Device enables its inbound FIFO post overflow interrupt | |
861 | + * and outbound free overflow interrupt. | |
862 | + * eumbbar is the base | |
863 | + *******************************************************/ | |
864 | +void I2OFIFOOverflowIntEnable( unsigned int eumbbar ) | |
865 | +{ | |
866 | + unsigned int val = load_runtime_reg( eumbbar, I2O_IMIMR ); | |
867 | + | |
868 | + val &= 0xfffffe7f; /* clear the two overflow interrupt bits */ | |
869 | + store_runtime_reg( eumbbar, I2O_IMIMR, val ); | |
870 | + | |
871 | +} | |
872 | + | |
873 | +/**************************************************** | |
874 | + * function: I2OFIFOOverflowIntDisable | |
875 | + * | |
876 | + * description: Disable the circular queue overflow interrupt | |
877 | + * | |
878 | + * note: | |
879 | + * Device disables its inbound post FIFO overflow interrupt | |
880 | + * and outbound free FIFO overflow interrupt | |
881 | + * (eumbbar is the base) | |
882 | + *****************************************************/ | |
883 | +void I2OFIFOOverflowIntDisable( unsigned int eumbbar ) | |
884 | +{ | |
885 | + | |
886 | + unsigned int val = load_runtime_reg( eumbbar, I2O_IMIMR ); | |
887 | + | |
888 | + val |= 0x00000180; /* masked out the msg overflow interrupt bits */ | |
889 | + store_runtime_reg( eumbbar, I2O_IMIMR, val ); | |
890 | +} |
cpu/mpc824x/drivers/i2o/i2o2.S
1 | +/************************************** | |
2 | + * | |
3 | + * copyright @ Motorola, 1999 | |
4 | + * | |
5 | + **************************************/ | |
6 | + | |
7 | +/********************************************************** | |
8 | + * function: load_runtime_reg | |
9 | + * | |
10 | + * input: r3 - value of eumbbar | |
11 | + * r4 - register offset in embedded utility space | |
12 | + * | |
13 | + * output: r3 - register content | |
14 | + **********************************************************/ | |
15 | + .text | |
16 | + .align 2 | |
17 | + .global load_runtime_reg | |
18 | + | |
19 | +load_runtime_reg: | |
20 | + | |
21 | + xor r5,r5,r5 | |
22 | + or r5,r5,r3 /* save eumbbar */ | |
23 | + | |
24 | + lwbrx r3,r4,r5 | |
25 | + sync | |
26 | + | |
27 | + bclr 20, 0 | |
28 | + | |
29 | +/**************************************************************** | |
30 | + * function: store_runtime_reg | |
31 | + * | |
32 | + * input: r3 - value of eumbbar | |
33 | + * r4 - register offset in embedded utility space | |
34 | + * r5 - new value to be stored | |
35 | + * | |
36 | + ****************************************************************/ | |
37 | + .text | |
38 | + .align 2 | |
39 | + .global store_runtime_reg | |
40 | +store_runtime_reg: | |
41 | + | |
42 | + xor r0,r0,r0 | |
43 | + | |
44 | + stwbrx r5, r4, r3 | |
45 | + sync | |
46 | + | |
47 | + bclr 20,0 |