|
|
1.1 root 1: /* $Id: stp222x-main.c,v 1.4 2009/09/07 15:41:07 fredette Exp $ */
2:
3: /* ic/stp222x-main.c - main emulation of the UPA to SBus interface
4: controller (STP2220) and the UPA to PCI interface controller
5: (STP2222): */
6:
7: /*
8: * Copyright (c) 2009 Matt Fredette
9: * All rights reserved.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
19: * 3. All advertising materials mentioning features or use of this software
20: * must display the following acknowledgement:
21: * This product includes software developed by Matt Fredette.
22: * 4. The name of the author may not be used to endorse or promote products
23: * derived from this software without specific prior written permission.
24: *
25: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
29: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35: * POSSIBILITY OF SUCH DAMAGE.
36: */
37:
38: #include <tme/common.h>
39: _TME_RCSID("$Id: stp222x-main.c,v 1.4 2009/09/07 15:41:07 fredette Exp $");
40:
41: /* includes: */
42: #include <tme/generic/bus-device.h>
43: #include "stp222x-impl.h"
44:
45: /* macros: */
46:
47: /* common register offsets: */
48: #define TME_STP222X_REG00_UPA_PORT_ID (0x0000)
49: #define TME_STP222X_REG00_UPA_PORT_CONFIG (0x0008)
50: #define TME_STP222X_REG00_CSR (0x0010)
51: /* 0x0018 unused */
52: #define TME_STP222X_REG00_ECC_CONTROL (0x0020)
53: /* 0x0028 unused */
54: #define TME_STP222X_REG00_UE_AFSR (0x0030)
55: #define TME_STP222X_REG00_UE_AFAR (0x0038)
56: #define TME_STP222X_REG00_CE_AFSR (0x0040)
57: #define TME_STP222X_REG00_CE_AFAR (0x0048)
58: #define TME_STP222X_REG01_PM_CR (0x0100)
59: #define TME_STP222X_REG01_PM_COUNT (0x0108)
60:
61: /* the control/status register: */
62: #define TME_STP222X_CSR_IMPL ((((tme_uint64_t) 2) << 63) - (((tme_uint64_t) 1) << 60))
63: #define TME_STP222X_CSR_VER ((((tme_uint64_t) 2) << 59) - (((tme_uint64_t) 1) << 56))
64: #define TME_STP222X_CSR_MID ((((tme_uint64_t) 2) << 55) - (((tme_uint64_t) 1) << 51))
65: #define TME_STP222X_CSR_IGN ((((tme_uint64_t) 2) << 50) - (((tme_uint64_t) 1) << 46))
66: #define TME_STP222X_CSR_APCKEN (1 << 3)
67: #define TME_STP222X_CSR_APERR (1 << 2)
68: #define TME_STP222X_CSR_IAP (1 << 1)
69: #define TME_STP222X_CSR_MODE (1 << 0)
70:
71: /* stp2220-specific registers: */
72: #define TME_STP2220_REG20_SBUS_CSR (0x2000)
73: /* 0x2028 unused */
74: #define TME_STP2220_REG20_SBUS_AFSR (0x2010)
75: #define TME_STP2220_REG20_SBUS_AFAR (0x2018)
76: #define TME_STP2220_REG20_SBUS_CONFIG(n) (0x2020 + (TME_STP222X_REG_SIZE * (n)))
77:
78: /* the stp2220 slot size: */
79: #define TME_STP2220_SLOT_SIZE (256 * 1024 * 1024)
80:
81: /* this gives the raw stp2220 address for a slot and offset: */
82: #define TME_STP2220_SBUS_ADDRESS(slot, offset) (((slot) * TME_STP2220_SLOT_SIZE) + (offset))
83:
84: /* reset states: */
85: #define TME_STP222X_RESET_STATE_NEGATED (0)
86: #define TME_STP222X_RESET_STATE_NEGATING (TME_STP222X_RESET_STATE_NEGATED + TME_STP222X_CONN_NULL)
87: #define TME_STP222X_RESET_STATE_ASSERTED (TME_STP222X_RESET_STATE_NEGATING + 1)
88: #define TME_STP222X_RESET_STATE_ASSERTING (TME_STP222X_RESET_STATE_ASSERTED + TME_STP222X_CONN_NULL)
89:
90: /* globals: */
91:
92: /* the simple 64-bit register bus router: */
93: static const tme_bus_lane_t _tme_stp222x_bus_router_regs[sizeof(tme_uint64_t)] = {
94: TME_BUS_LANE_ROUTE(0),
95: TME_BUS_LANE_ROUTE(1),
96: TME_BUS_LANE_ROUTE(2),
97: TME_BUS_LANE_ROUTE(3),
98: TME_BUS_LANE_ROUTE(4),
99: TME_BUS_LANE_ROUTE(5),
100: TME_BUS_LANE_ROUTE(6),
101: TME_BUS_LANE_ROUTE(7)
102: };
103:
104: /* the STP2220 mapping from obio slot and offset to IDI: */
105: static const struct {
106: tme_uint32_t _tme_stp2220_obio_slot;
107: tme_uint32_t _tme_stp2220_obio_offset;
108: tme_uint32_t _tme_stp2220_obio_idi;
109: } _tme_stp2220_obios[] = {
110: { TME_STP2220_SLOT_AUDIO, 0x0000000, TME_STP2220_IDI_AUDIO, },
111: { TME_STP2220_SLOT_MACIO, 0x8800000, TME_STP222X_IDI_SCSI },
112: { TME_STP2220_SLOT_MACIO, 0x8c00000, TME_STP222X_IDI_ETHER },
113: { TME_STP2220_SLOT_MACIO, 0xc800000, TME_STP222X_IDI_BPP },
114: { TME_STP2220_SLOT_SLAVIO, 0x1100000, TME_STP2220_IDI_ZS0_ZS1 },
115: { TME_STP2220_SLOT_SLAVIO, 0x1000000, TME_STP2220_IDI_ZS0_ZS1 },
116: { TME_STP2220_SLOT_SLAVIO, 0x1400000, TME_STP2220_IDI_FD },
117: };
118:
119: /* this converts an I/O connection into a connection index: */
120: static tme_uint32_t
121: _tme_stp222x_io_conn_index(const struct tme_stp222x *stp222x,
122: const struct tme_bus_connection *io_conn_bus)
123: {
124: tme_uint32_t connid;
125: tme_uint32_t conn_index;
126:
127: /* this must be an I/O connection: */
128: assert (io_conn_bus
129: != stp222x->tme_stp222x.tme_stp22xx_conns[TME_STP222X_CONN_UPA].tme_stp22xx_conn_bus);
130:
131: /* get the connection id: */
132: connid = io_conn_bus->tme_bus_connection.tme_connection_id;
133:
134: /* if this is a card connection: */
135: if ((connid
136: & TME_STP222X_CONNID_TYPE)
137: == TME_STP222X_CONNID_TYPE_CARD) {
138:
139: /* if this is an stp2220: */
140: if (TME_STP222X_IS_2220(stp222x)) {
141:
142: /* assume that this is the first master connection for this
143: card, which uses the card's primary master connection
144: index: */
145: conn_index = TME_FIELD_MASK_EXTRACTU(connid, TME_STP2220_CONNID_CARD_WHICH);
146:
147: /* if this is an alternate connection for the card: */
148: if (connid & TME_STP2220_CONNID_CARD_ALTERNATE) {
149:
150: /* starting from the first alternate master connection index
151: for this card and moving forward, search all remaining
152: connection indices: */
153: conn_index
154: = (TME_STP2220_SLOTS_CARD
155: + (connid & TME_STP2220_CONNID_CARD_WHICH));
156: for (; stp222x->tme_stp222x.tme_stp22xx_conns[conn_index].tme_stp22xx_conn_bus != io_conn_bus; ) {
157: conn_index++;
158: assert (conn_index < stp222x->tme_stp222x_slave_conn_index_next);
159: }
160: }
161: }
162:
163: /* otherwise, this is an stp2222: */
164: else {
165: abort();
166: }
167: }
168:
169: /* otherwise, this is an obio connection id: */
170: else {
171:
172: /* assume that this is an obio short connection id, and get the
173: connection index: */
174: conn_index = TME_FIELD_MASK_EXTRACTU(connid, TME_STP222X_CONNID_OBIO_SHORT_CONN_WHICH);
175:
176: /* if this is an obio long connection id: */
177: if ((connid
178: & TME_STP222X_CONNID_OBIO_TYPE)
179: == TME_STP222X_CONNID_OBIO_TYPE_LONG) {
180:
181: /* search all connection indices: */
182: conn_index = 0;
183: for (; stp222x->tme_stp222x.tme_stp22xx_conns[conn_index].tme_stp22xx_conn_bus != io_conn_bus; ) {
184: conn_index++;
185: assert (conn_index < stp222x->tme_stp222x_slave_conn_index_next);
186: }
187: }
188: }
189:
190: assert (stp222x->tme_stp222x.tme_stp22xx_conns[conn_index].tme_stp22xx_conn_bus == io_conn_bus);
191: return (conn_index);
192: }
193:
194: /* this converts an I/O connection and interrupt signal into an
195: IDI: */
196: static tme_uint32_t
197: _tme_stp222x_io_idi(const struct tme_stp222x *stp222x,
198: const struct tme_bus_connection *io_conn_bus,
199: unsigned int signal_int)
200: {
201: tme_uint32_t connid;
202: tme_uint32_t idi;
203: tme_uint32_t idi_addend;
204:
205: /* this must be an I/O connection: */
206: assert (io_conn_bus
207: != stp222x->tme_stp222x.tme_stp22xx_conns[TME_STP222X_CONN_UPA].tme_stp22xx_conn_bus);
208:
209: /* get the connection id: */
210: connid = io_conn_bus->tme_bus_connection.tme_connection_id;
211:
212: /* if this is a card connection: */
213: if ((connid
214: & TME_STP222X_CONNID_TYPE)
215: == TME_STP222X_CONNID_TYPE_CARD) {
216:
217: /* if this is an stp2220, bits 1..2 of a card connection id are
218: the card (slot) number, which are bits 3..4 of the connection's
219: base IDI. otherwise, this is an stp2222, and bits 1..3 of a
220: card connection id are the bus and slot number, which are bits
221: 2..4 of the connection's base IDI. we take advantage of this
222: to quickly make the base IDI: */
223: #if TME_STP222X_CONNID_TYPE != (0x1 << 0)
224: #error "TME_STP222X_CONNID_TYPE changed"
225: #endif
226: #if TME_STP222X_CONNID_TYPE_CARD != 0
227: #error "TME_STP222X_CONNID_TYPE_CARD changed"
228: #endif
229: #if (TME_STP2222_CONNID_BUS_WHICH + TME_STP2222_CONNID_DEVICE_WHICH) != (0x7 << 1)
230: #error "TME_STP2222_CONNID_BUS_WHICH or TME_STP2222_CONNID_DEVICE_WHICH changed"
231: #endif
232: #if TME_STP2220_CONNID_CARD_WHICH != (0x3 << 1)
233: #error "TME_STP2220_CONN_CARD_WHICH changed"
234: #endif
235: idi = connid << 1;
236: if (TME_STP222X_IS_2220(stp222x)) {
237: idi <<= 1;
238: }
239: idi %= TME_STP222X_IDI0_OBIO;
240:
241: /* the interrupt signal can't be unspecified: */
242: assert (signal_int != TME_BUS_SIGNAL_INT_UNSPEC);
243:
244: /* convert the interrupt signal into an IDI addend: */
245: idi_addend = TME_BUS_SIGNAL_INDEX_INT(signal_int);
246:
247: /* the IDI addend must be within range: */
248: assert (idi_addend
249: < (TME_STP222X_IS_2220(stp222x)
250: ? TME_SBUS_SLOT_INTS
251: : TME_PCI_SLOT_INTS));
252:
253: /* add in the IDI addend: */
254: idi += idi_addend;
255: }
256:
257: /* otherwise, this is an obio connection: */
258: else {
259:
260: /* this must be a obio short connection id: */
261: assert ((connid
262: & TME_STP222X_CONNID_OBIO_TYPE)
263: == TME_STP222X_CONNID_OBIO_TYPE_SHORT);
264:
265: /* get the connection's base IDI: */
266: idi = TME_FIELD_MASK_EXTRACTU(connid, TME_STP222X_CONNID_OBIO_SHORT_IDI);
267:
268: /* if the interrupt signal is specified: */
269: if (signal_int != TME_BUS_SIGNAL_INT_UNSPEC) {
270:
271: /* the audio connection is the only obio connection allowed to
272: specify its interrupt signal - zero is used for record, one
273: for playback: */
274: assert (signal_int == TME_BUS_SIGNAL_INT(0)
275: || signal_int == TME_BUS_SIGNAL_INT(1));
276: if (!TME_STP222X_IS_2220(stp222x)) {
277: assert (idi == TME_STP2220_IDI_AUDIO);
278:
279: /* nothing to do */
280: }
281: else {
282: #if TME_STP2222_IDI_AUDIO_PLAYBACK != (TME_STP2222_IDI_AUDIO_RECORD + 1)
283: #error "TME_STP2222_IDI_AUDIO_ values changed"
284: #endif
285: assert (idi == TME_STP2222_IDI_AUDIO_RECORD);
286: idi += TME_BUS_SIGNAL_INDEX_INT(signal_int);
287: }
288: }
289: }
290:
291: return (idi);
292: }
293:
294: /* this converts an address into an address space: */
295: static tme_uint32_t
296: _tme_stp222x_lookup_address(const struct tme_stp222x *stp222x,
297: tme_bus_addr64_t address,
298: tme_bus_addr32_t *_region_size_m1)
299: {
300: tme_bus_addr32_t region_size_m1;
301: unsigned int aspace_i;
302: tme_uint32_t address_16_47;
303:
304: /* if this is an stp2220: */
305: if (TME_STP222X_IS_2220(stp222x)) {
306:
307: /* only the upper half of our UPA address space is mapped to the
308: SBus address space: */
309: region_size_m1 = 0xffffffff;
310: aspace_i
311: = (address <= region_size_m1
312: ? TME_STP222X_ASPACE_NULL
313: : TME_STP2220_ASPACE_SBUS);
314: }
315:
316: /* otherwise, this is an stp2222: */
317: else {
318:
319: /* get bits 16..47 of the UPA address: */
320: address_16_47 = (address >> 16);
321: assert (address_16_47 == (address >> 16));
322:
323: /* if this is a PCI bus memory space: */
324: if (address_16_47 >= 0x10000) {
325: assert (address_16_47 <= 0x1ffff);
326: region_size_m1 = 0x7fffffff;
327: aspace_i
328: = TME_STP2222_ASPACE_PCI_MEMORY(((address_16_47 & 0x8000) == 0)
329: == !TME_STP2222_BOOT_BUS(stp222x));
330: }
331:
332: /* otherwise, if this is a PCI bus I/O space: */
333: else if ((address_16_47 | 1) == 0x00201) {
334: region_size_m1 = 0xffff;
335: aspace_i = TME_STP2222_ASPACE_PCI_IO(address_16_47 & 1);
336: }
337:
338: /* otherwise, if this is PCI configuration space: */
339: else if (address_16_47 == 0x00100) {
340: region_size_m1 = 0xffffff;
341: aspace_i = TME_STP2222_ASPACE_PCI_CONFIGURATION;
342: }
343:
344: /* otherwise, this address is in the register space: */
345: else {
346: region_size_m1 = 0xffff;
347: aspace_i = TME_STP222X_ASPACE_NULL;
348: }
349: }
350:
351: /* return the region size and address space: */
352: *_region_size_m1 = region_size_m1;
353: return (aspace_i);
354: }
355:
356: /* the 0x00 register group register handler: */
357: static void
358: _tme_stp222x_reg00_regs(struct tme_stp222x *stp222x,
359: struct tme_stp222x_reg *reg)
360: {
361:
362: /* if this is a write: */
363: if (reg->tme_stp222x_reg_write) {
364:
365: /* dispatch on the register: */
366: switch (TME_STP222X_REGGROUP_INDEX(reg->tme_stp222x_reg_address)) {
367: case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_UPA_PORT_CONFIG):
368: stp222x->tme_stp222x_upa_port_config
369: = (reg->tme_stp222x_reg_value
370: & TME_UPA_PORT_CONFIG_SCIQ0);
371: break;
372: case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_CSR):
373: stp222x->tme_stp222x_csr
374: = ((stp222x->tme_stp222x_csr | ~TME_STP222X_CSR_APCKEN)
375: & (reg->tme_stp222x_reg_value ^ TME_STP222X_CSR_APCKEN));
376: tme_stp222x_mdu_ign_update(stp222x,
377: TME_FIELD_MASK_EXTRACTU(stp222x->tme_stp222x_csr,
378: TME_STP222X_CSR_IGN));
379: break;
380: case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_ECC_CONTROL):
381: stp222x->tme_stp222x_ecc_control = (reg->tme_stp222x_reg_value >> 61);
382: break;
383: case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_UPA_PORT_ID):
384: case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_UE_AFSR):
385: case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_UE_AFAR):
386: case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_CE_AFSR):
387: case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_CE_AFAR):
388: break;
389: default:
390: return;
391: }
392: }
393:
394: /* otherwise, this is a read: */
395: else {
396:
397: /* dispatch on the register: */
398: switch (TME_STP222X_REGGROUP_INDEX(reg->tme_stp222x_reg_address)) {
399: case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_UPA_PORT_ID):
400: reg->tme_stp222x_reg_value
401: = (TME_UPA_PORT_ID_COOKIE
402: + !TME_UPA_PORT_ID_ECC_NOT_VALID
403: + !TME_UPA_PORT_ID_ONEREAD
404: + !TME_UPA_PORT_ID_PINT_RDQ
405: + (8 * _TME_FIELD_MASK_FACTOR(TME_UPA_PORT_ID_PREQ_DQ))
406: + (2 * _TME_FIELD_MASK_FACTOR(TME_UPA_PORT_ID_PREQ_RQ))
407: + ((TME_UPA_UPACAP_MASTER
408: + !TME_UPA_UPACAP_CACHEMASTER
409: + !TME_UPA_UPACAP_SLAVE_INT_L
410: + TME_UPA_UPACAP_INTERRUPTMASTER
411: + !TME_UPA_UPACAP_HANDLERSLAVE)
412: * _TME_FIELD_MASK_FACTOR(TME_UPA_PORT_ID_UPACAP))
413: + ((TME_STP222X_IS_2220(stp222x)
414: ? 0xef07
415: : 0x1954)
416: * _TME_FIELD_MASK_FACTOR(TME_UPA_PORT_ID_ID)));
417: break;
418: case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_UPA_PORT_CONFIG):
419: reg->tme_stp222x_reg_value = stp222x->tme_stp222x_upa_port_config;
420: break;
421: case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_CSR):
422: reg->tme_stp222x_reg_value
423: = ((stp222x->tme_stp222x_csr
424: & (TME_STP222X_CSR_MID
425: | TME_STP222X_CSR_IGN
426: | TME_STP222X_CSR_APCKEN
427: | TME_STP222X_CSR_APERR
428: | TME_STP222X_CSR_IAP
429: | TME_STP222X_CSR_MODE))
430: + (TME_STP222X_IS_2220(stp222x)
431: ? ((0x0 * _TME_FIELD_MASK_FACTOR(TME_STP222X_CSR_IMPL))
432: + (0x1 * _TME_FIELD_MASK_FACTOR(TME_STP222X_CSR_VER)))
433: : ((0x0 * _TME_FIELD_MASK_FACTOR(TME_STP222X_CSR_IMPL))
434: + (0x0 * _TME_FIELD_MASK_FACTOR(TME_STP222X_CSR_VER)))));
435: break;
436: case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_ECC_CONTROL):
437: reg->tme_stp222x_reg_value
438: = (((tme_uint64_t) stp222x->tme_stp222x_ecc_control)
439: << 61);
440: break;
441: case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_UE_AFSR):
442: case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_UE_AFAR):
443: case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_CE_AFSR):
444: case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG00_CE_AFAR):
445: reg->tme_stp222x_reg_value = 0;
446: break;
447: default:
448: return;
449: }
450: }
451:
452: /* this register access has been completed: */
453: reg->tme_stp222x_reg_completed = TRUE;
454: }
455:
456: /* the stp2220 SBus register handler: */
457: static void
458: _tme_stp2220_sbus_regs(struct tme_stp222x *stp222x,
459: struct tme_stp222x_reg *reg)
460: {
461: tme_uint64_t mask_w;
462: tme_uint64_t mask_ro;
463: tme_uint64_t zero;
464: tme_uint64_t *_value;
465:
466: /* assume that all bits of the register are writable: */
467: mask_w = 0 - (tme_uint64_t) 1;
468:
469: /* assume that all read-only bits of the register are zero: */
470: mask_ro = 0;
471:
472: /* make a dummy zero register: */
473: zero = 0;
474:
475: /* if this is the SBus control/status register: */
476: if (reg->tme_stp222x_reg_address == TME_STP2220_REG20_SBUS_CSR) {
477: _value = &stp222x->tme_stp2220_sbus_csr;
478: mask_w
479: = (TME_BIT(10) /* shortens PIO access latency */
480: + TME_BIT(8) /* enables interrupts for SBus errors */
481: + TME_BIT(5) /* enables DVMA for slot 15 */
482: + TME_BIT(4) /* enables DVMA for slot 14 */
483: + 0xf); /* enables DVMA for slots 0..3 */
484: }
485:
486: /* otherwise, if this is the SBus AFSR or AFAR: */
487: else if (reg->tme_stp222x_reg_address == TME_STP2220_REG20_SBUS_AFSR
488: || reg->tme_stp222x_reg_address == TME_STP2220_REG20_SBUS_AFAR) {
489: _value = &zero;
490: }
491:
492: /* otherwise, if this is an SBus slot configuration register: */
493: else if ((reg->tme_stp222x_reg_address
494: >= TME_STP2220_REG20_SBUS_CONFIG(0))
495: && (reg->tme_stp222x_reg_address
496: <= TME_STP2220_REG20_SBUS_CONFIG(TME_STP2220_SLOTS_CARD + TME_STP2220_SLOTS_OBIO - 1))) {
497: _value
498: = (&stp222x->tme_stp2220_sbus_config_card
499: [(reg->tme_stp222x_reg_address
500: - TME_STP2220_REG20_SBUS_CONFIG(0))
501: / TME_STP222X_REG_SIZE]);
502: mask_w
503: = (TME_BIT(14) /* enables extended transfers */
504: + TME_BIT(4) /* enables 64-byte bursts */
505: + TME_BIT(3) /* enables 32-byte bursts */
506: + TME_BIT(2) /* enables 16-byte bursts */
507: + TME_BIT(1) /* enables 8-byte bursts */
508: );
509: }
510:
511: /* otherwise, this is an unknown register: */
512: else {
513: return;
514: }
515:
516: /* if this is a write: */
517: if (reg->tme_stp222x_reg_write) {
518: *_value = reg->tme_stp222x_reg_value & mask_w;
519: }
520:
521: /* otherwise, this is a read: */
522: else {
523: reg->tme_stp222x_reg_value = *_value | mask_ro;
524: }
525:
526: /* this register access has been completed: */
527: reg->tme_stp222x_reg_completed = TRUE;
528: }
529:
530: /* this completes a bus operation between master and slave: */
531: #define _tme_stp222x_complete_master tme_stp22xx_complete_master
532:
533: /* this completes a reset assertion or negation: */
534: static void
535: _tme_stp222x_complete_reset(struct tme_stp22xx *stp22xx,
536: struct tme_completion *completion,
537: void *arg)
538: {
539: struct tme_stp222x *stp222x;
540: tme_uint32_t reset_state;
541:
542: /* recover our data structure: */
543: stp222x = (struct tme_stp222x *) stp22xx;
544:
545: /* get the next reset state: */
546: reset_state = stp222x->tme_stp222x_reset_state - 1;
547:
548: /* if we have finished asserting RESET on the I/O bus, and
549: the UPA bus reset signal is negated: */
550: if (reset_state == TME_STP222X_RESET_STATE_ASSERTED
551: && stp222x->tme_stp222x_reset_level == TME_BUS_SIGNAL_LEVEL_NEGATED) {
552:
553: /* start negating RESET on the I/O bus: */
554: reset_state = TME_STP222X_RESET_STATE_NEGATING;
555: }
556:
557: /* update the reset state: */
558: stp222x->tme_stp222x_reset_state = reset_state;
559:
560: /* unused: */
561: completion = 0;
562: arg = 0;
563: }
564:
565: /* this completes a bus request assertion or negation: */
566: static void
567: _tme_stp222x_complete_br(struct tme_stp22xx *stp22xx,
568: struct tme_completion *completion,
569: void *arg)
570: {
571: struct tme_stp222x *stp222x;
572:
573: /* recover our data structure: */
574: stp222x = (struct tme_stp222x *) stp22xx;
575:
576: /* our bus request has been flipped: */
577: stp222x->tme_stp222x_br = !stp222x->tme_stp222x_br;
578:
579: /* unused: */
580: completion = 0;
581: arg = 0;
582: }
583:
584: /* this completes a bus grant: */
585: #define _tme_stp222x_complete_bg tme_stp22xx_complete_bg
586:
587: /* this calls out a bus signal to a connection: */
588: #define _tme_stp222x_callout_signal(stp222x, conn_index, signal, completion_handler) \
589: tme_stp22xx_callout_signal(&(stp222x)->tme_stp222x, conn_index, signal, completion_handler)
590:
591: /* the run function: */
592: static void
593: _tme_stp222x_run(struct tme_stp22xx *stp22xx)
594: {
595: struct tme_stp222x *stp222x;
596: unsigned int reset_state;
597: unsigned int io_conn_index;
598: unsigned int master_conn_index;
599: tme_uint32_t io_brs;
600:
601: /* recover our data structure: */
602: stp222x = (struct tme_stp222x *) stp22xx;
603:
604: /* loop forever: */
605: for (;;) {
606:
607: /* if we need to assert reset to another I/O connection: */
608: reset_state = stp222x->tme_stp222x_reset_state;
609: if (reset_state > TME_STP222X_RESET_STATE_ASSERTED) {
610:
611: /* assert reset to the next I/O connection: */
612: io_conn_index = reset_state - (TME_STP222X_RESET_STATE_ASSERTED + 1);
613: _tme_stp222x_callout_signal(stp222x,
614: io_conn_index,
615: (TME_BUS_SIGNAL_RESET
616: | TME_BUS_SIGNAL_EDGE
617: | TME_BUS_SIGNAL_LEVEL_ASSERTED),
618: _tme_stp222x_complete_reset);
619: continue;
620: }
621:
622: /* if there is a current master: */
623: master_conn_index = stp222x->tme_stp222x_master_conn_index;
624: if (master_conn_index != TME_STP222X_CONN_NULL) {
625: assert (master_conn_index < TME_STP222X_CONN_SLAVE0);
626:
627: /* if the current master is still requesting the bus: */
628: if (stp222x->tme_stp222x_io_brs & (1 << master_conn_index)) {
629:
630: /* stop now. we can't do anything else until the current
631: master releases the bus: */
632: break;
633: }
634:
635: /* there should be no master completion pending: */
636: assert (stp222x->tme_stp222x.tme_stp22xx_master_completion == NULL);
637:
638: /* there is no current master: */
639: stp222x->tme_stp222x_master_conn_index = TME_STP222X_CONN_NULL;
640:
641: /* negate bus grant to the former master: */
642: _tme_stp222x_callout_signal(stp222x,
643: master_conn_index,
644: (TME_BUS_SIGNAL_BG
645: | TME_BUS_SIGNAL_EDGE
646: | TME_BUS_SIGNAL_LEVEL_NEGATED),
647: tme_stp22xx_complete_nop);
648: continue;
649: }
650:
651: /* we need the UPA bus if an I/O connection is requesting the bus,
652: or if we have an interrupt to dispatch, or if we have a
653: streaming cache to flush. if our UPA bus request line doesn't
654: reflect whether we need the UPA bus: */
655: if (!stp222x->tme_stp222x_br
656: == (stp222x->tme_stp222x_io_brs != 0
657: #if TME_STP222X_MDU_BUFFER_COUNT != 2
658: #error "TME_STP222X_MDU_BUFFER_COUNT changed"
659: #endif
660: || (stp222x->tme_stp222x_mdu_dispatch_imr[0] != 0 /* !TME_STP222X_MDU_IMR_V */
661: && stp222x->tme_stp222x_mdu_dispatch_state[0] == 0) /* TME_STP222X_MDU_DISPATCH_NOW */
662: || (stp222x->tme_stp222x_mdu_dispatch_imr[1] != 0 /* !TME_STP222X_MDU_IMR_V */
663: && stp222x->tme_stp222x_mdu_dispatch_state[1] == 0) /* TME_STP222X_MDU_DISPATCH_NOW */
664: #if TME_STP222X_STC_COUNT != 2
665: #error "TME_STP222X_STC_COUNT changed"
666: #endif
667: || stp222x->tme_stp222x_stcs[0].tme_stp222x_stc_pgflush
668: || stp222x->tme_stp222x_stcs[1].tme_stp222x_stc_pgflush
669: )) {
670:
671: /* assert or negate our bus request on the UPA bus: */
672: _tme_stp222x_callout_signal(stp222x,
673: TME_STP222X_CONN_UPA,
674: (TME_BUS_SIGNAL_BR
675: | TME_BUS_SIGNAL_EDGE
676: | (stp222x->tme_stp222x_br
677: ? TME_BUS_SIGNAL_LEVEL_NEGATED
678: : TME_BUS_SIGNAL_LEVEL_ASSERTED)),
679: _tme_stp222x_complete_br);
680: continue;
681: }
682:
683: /* if we need to negate reset to another I/O connection: */
684: reset_state = stp222x->tme_stp222x_reset_state;
685: if (reset_state > TME_STP222X_RESET_STATE_NEGATED
686: && reset_state < TME_STP222X_RESET_STATE_ASSERTED) {
687:
688: /* negate reset to the next I/O connection: */
689: io_conn_index = reset_state - (TME_STP222X_RESET_STATE_NEGATED + 1);
690: _tme_stp222x_callout_signal(stp222x,
691: io_conn_index,
692: (TME_BUS_SIGNAL_RESET
693: | TME_BUS_SIGNAL_EDGE
694: | TME_BUS_SIGNAL_LEVEL_NEGATED),
695: _tme_stp222x_complete_reset);
696: continue;
697: }
698:
699: /* if we don't own the UPA bus: */
700: if (!stp222x->tme_stp222x_bg) {
701:
702: /* stop now. we can't do anything else until we own the UPA
703: bus: */
704: break;
705: }
706:
707: /* dispatch any interrupt: */
708: if (tme_stp222x_mdu_dispatch(stp222x)) {
709: continue;
710: }
711:
712: /* flush any streaming cache: */
713: if (tme_stp222x_stc_flush(stp222x)) {
714: continue;
715: }
716:
717: /* if one or more I/O connections are requesting the bus: */
718: io_brs = stp222x->tme_stp222x_io_brs;
719: if (io_brs != 0) {
720:
721: /* get the connection index for the next master: */
722: /* XXX FIXME - should we do something fair here? */
723: for (master_conn_index = 0;
724: (io_brs & 1) == 0;
725: io_brs >>= 1, master_conn_index++);
726:
727: /* set the pending master: */
728: stp222x->tme_stp222x_master_conn_index_pending = master_conn_index;
729:
730: /* assert bus grant to the current master: */
731: _tme_stp222x_callout_signal(stp222x,
732: master_conn_index,
733: (TME_BUS_SIGNAL_BG
734: | TME_BUS_SIGNAL_EDGE
735: | TME_BUS_SIGNAL_LEVEL_ASSERTED),
736: _tme_stp222x_complete_bg);
737: continue;
738: }
739:
740: /* no other callouts are needed: */
741: break;
742: }
743: }
744:
745: /* this handles a bus signal: */
746: static void
747: _tme_stp222x_signal(struct tme_bus_connection *conn_bus,
748: unsigned int signal,
749: struct tme_completion *completion)
750: {
751: struct tme_stp222x *stp222x;
752: tme_uint32_t level;
753: tme_uint32_t io_conn_index;
754: tme_uint32_t br_mask;
755: tme_uint32_t idi;
756:
757: /* enter: */
758: stp222x = tme_stp222x_enter_bus(conn_bus);
759:
760: /* get the level. this must be an edge: */
761: assert (signal & TME_BUS_SIGNAL_EDGE);
762: level = signal - TME_BUS_SIGNAL_EDGE;
763: signal = TME_BUS_SIGNAL_WHICH(signal);
764: level ^= signal;
765:
766: /* if this bus signal is on the UPA connection: */
767: if (conn_bus == stp222x->tme_stp222x.tme_stp22xx_conns[TME_STP222X_CONN_UPA].tme_stp22xx_conn_bus) {
768:
769: /* if this is the bus grant signal: */
770: if (signal == TME_BUS_SIGNAL_BG) {
771:
772: /* mark our bus grant as either asserted or negated: */
773: assert (level == TME_BUS_SIGNAL_LEVEL_NEGATED
774: || level == TME_BUS_SIGNAL_LEVEL_ASSERTED);
775: stp222x->tme_stp222x_bg = (level == TME_BUS_SIGNAL_LEVEL_ASSERTED);
776: }
777:
778: /* otherwise, this must be reset signal: */
779: else {
780: assert (signal == TME_BUS_SIGNAL_RESET);
781:
782: /* update the level of the UPA reset signal: */
783: stp222x->tme_stp222x_reset_level = level;
784:
785: /* if the UPA reset signal is asserted: */
786: if (level == TME_BUS_SIGNAL_LEVEL_ASSERTED) {
787:
788: /* start asserting RESET on the I/O bus: */
789: stp222x->tme_stp222x_reset_state = TME_STP222X_RESET_STATE_ASSERTING;
790: }
791:
792: /* otherwise, the UPA reset signal must be negated: */
793: else {
794: assert (level == TME_BUS_SIGNAL_LEVEL_NEGATED);
795:
796: /* if RESET is currently asserted on the I/O bus, start
797: negating it: */
798: assert (stp222x->tme_stp222x_reset_state >= TME_STP222X_RESET_STATE_ASSERTED);
799: if (stp222x->tme_stp222x_reset_state == TME_STP222X_RESET_STATE_ASSERTED) {
800: stp222x->tme_stp222x_reset_state = TME_STP222X_RESET_STATE_NEGATING;
801: }
802: }
803: }
804: }
805:
806: /* otherwise, this bus signal is on an I/O connection: */
807: else {
808:
809: /* if this is the bus request signal: */
810: if (signal == TME_BUS_SIGNAL_BR) {
811:
812: /* get this I/O connection's bus request mask: */
813: io_conn_index = _tme_stp222x_io_conn_index(stp222x, conn_bus);
814: assert (io_conn_index < TME_STP222X_CONN_SLAVE0);
815: br_mask = (1 << io_conn_index);
816:
817: /* mark this caller's bus request line as either asserted or
818: negated: */
819: assert (level == TME_BUS_SIGNAL_LEVEL_NEGATED
820: || level == TME_BUS_SIGNAL_LEVEL_ASSERTED);
821: stp222x->tme_stp222x_io_brs
822: = ((stp222x->tme_stp222x_io_brs
823: | br_mask)
824: & (level == TME_BUS_SIGNAL_LEVEL_ASSERTED
825: ? 0
826: : ~br_mask));
827: }
828:
829: /* otherwise, this must be an interrupt signal: */
830: else {
831: assert (signal == TME_BUS_SIGNAL_INT_UNSPEC
832: || TME_BUS_SIGNAL_IS_INT(signal));
833:
834: /* get the IDI: */
835: idi = _tme_stp222x_io_idi(stp222x, conn_bus, signal);
836:
837: /* update the interrupt concentrator: */
838: tme_stp222x_mdu_intcon(stp222x, idi, level);
839: }
840: }
841:
842: /* leave: */
843: tme_stp222x_completion_validate(stp222x, completion);
844: tme_stp222x_leave(stp222x);
845: }
846:
847: /* this handles a bus cycle: */
848: static void
849: _tme_stp222x_cycle(struct tme_bus_connection *master_conn_bus,
850: struct tme_bus_cycle *master_cycle,
851: tme_uint32_t *_master_fast_cycle_types,
852: struct tme_completion *master_completion)
853: {
854: struct tme_stp222x *stp222x;
855: tme_bus_addr64_t slave_address;
856: tme_uint32_t aspace_i;
857: unsigned int slave_conn_index;
858: tme_bus_addr32_t region_size_m1;
859: struct tme_stp222x_reg reg;
860: tme_uint32_t reggroup;
861:
862: /* enter: */
863: stp222x = tme_stp222x_enter_master_bus(master_conn_bus);
864:
865: /* convert the master's address into an address space, slave
866: connection index and address: */
867: slave_address = master_cycle->tme_bus_cycle_address;
868: aspace_i
869: = _tme_stp222x_lookup_address(stp222x,
870: slave_address,
871: ®ion_size_m1);
872: slave_address &= region_size_m1;
873: slave_conn_index
874: = (aspace_i == TME_STP222X_ASPACE_NULL
875: ? TME_STP222X_CONN_NULL
876: : tme_stp222x_aspace_lookup(stp222x,
877: aspace_i,
878: &slave_address));
879: master_cycle->tme_bus_cycle_address = slave_address;
880:
881: /* dispatch on the address space: */
882: switch (aspace_i) {
883:
884: case TME_STP2222_ASPACE_PCI_CONFIGURATION:
885: assert (!TME_STP222X_IS_2220(stp222x));
886: #if 0
887: master_cycle->tme_bus_cycle_type |= TME_PCI_CYCLE_CONFIGURATION;
888: #endif
889: abort();
890:
891: case TME_STP2222_ASPACE_PCI_IO(0):
892: case TME_STP2222_ASPACE_PCI_IO(1):
893: assert (!TME_STP222X_IS_2220(stp222x));
894: #if 0
895: master_cycle->tme_bus_cycle_type |= TME_PCI_CYCLE_IO;
896: #endif
897: abort();
898:
899: case TME_STP2220_ASPACE_SBUS:
900: assert (TME_STP222X_IS_2220(stp222x));
901: break;
902:
903: default:
904: assert (!TME_STP222X_IS_2220(stp222x));
905: assert (aspace_i == TME_STP2222_ASPACE_PCI_MEMORY(0)
906: || aspace_i == TME_STP2222_ASPACE_PCI_MEMORY(1));
907: abort();
908:
909: case TME_STP222X_ASPACE_NULL:
910:
911: /* if this isn't an aligned 64-bit access: */
912: if (__tme_predict_false((slave_address % TME_STP222X_REG_SIZE) != 0
913: || master_cycle->tme_bus_cycle_size != TME_STP222X_REG_SIZE)) {
914: abort();
915: }
916:
917: /* NB: read the _tme_stp103x_bus_port() comment about bus routing
918: information coming out of the CPU: */
919: /* replace the bus cycle routing information: */
920: assert (TME_STP222X_REG_SIZE == (1 << TME_BUS64_LOG2));
921: master_cycle->tme_bus_cycle_port = TME_BUS_CYCLE_PORT(0, TME_BUS64_LOG2);
922: master_cycle->tme_bus_cycle_lane_routing
923: = (_tme_stp222x_bus_router_regs
924: - TME_BUS_ROUTER_INDEX(TME_BUS64_LOG2, TME_BUS64_LOG2, 0));
925:
926: /* set the register address, poisoning it if it's too big for the
927: structure: */
928: reg.tme_stp222x_reg_address = slave_address;
929: if (reg.tme_stp222x_reg_address != slave_address) {
930: reg.tme_stp222x_reg_address = 0xffff;
931: }
932:
933: /* if this is a write: */
934: reg.tme_stp222x_reg_write = (master_cycle->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE);
935: if (reg.tme_stp222x_reg_write) {
936:
937: /* get value being written: */
938: tme_bus_cycle_xfer_memory(master_cycle,
939: ((tme_uint8_t *) ®.tme_stp222x_reg_value) - slave_address,
940: slave_address + sizeof(tme_uint64_t) - 1);
941: reg.tme_stp222x_reg_value = tme_betoh_u64(reg.tme_stp222x_reg_value);
942: }
943:
944: /* otherwise, this must be a read: */
945: else if (__tme_predict_false(master_cycle->tme_bus_cycle_type != TME_BUS_CYCLE_READ)) {
946: abort();
947: }
948:
949: /* assume that this register access won't be completed: */
950: reg.tme_stp222x_reg_completed = FALSE;
951:
952: /* dispatch on the register group: */
953: reggroup = TME_STP222X_REGGROUP_WHICH(reg.tme_stp222x_reg_address);
954: switch (reggroup) {
955:
956: case 0x00:
957: _tme_stp222x_reg00_regs(stp222x, ®);
958: break;
959:
960: case 0x01:
961: switch (TME_STP222X_REGGROUP_INDEX(reg.tme_stp222x_reg_address)) {
962: case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG01_PM_CR):
963: abort();
964: case TME_STP222X_REGGROUP_INDEX(TME_STP222X_REG01_PM_COUNT):
965: abort();
966: default:
967: break;
968: }
969: break;
970:
971: case 0x24:
972: case 0x02:
973: if (reggroup
974: == (TME_STP222X_IS_2220(stp222x)
975: ? 0x24
976: : 0x02)) {
977: tme_stp222x_iommu_regs(stp222x, ®);
978: }
979: break;
980:
981: case 0x2c:
982: case 0x0c:
983: case 0x30:
984: case 0x10:
985: case 0x1a:
986: case 0x60:
987: case 0x80:
988: tme_stp222x_mdu_regs_imr_retry(stp222x, ®);
989: break;
990:
991: case 0x20:
992: if (TME_STP222X_IS_2220(stp222x)) {
993: _tme_stp2220_sbus_regs(stp222x, ®);
994: }
995: break;
996:
997: case 0x34:
998: case 0x14:
999: case 0x38:
1000: case 0x18:
1001: tme_stp222x_mdu_regs_clear(stp222x, ®);
1002: break;
1003:
1004: case 0x3c:
1005: case 0x1c:
1006: if ((reggroup < 0x30) == !TME_STP222X_IS_2220(stp222x)) {
1007: tme_stp222x_timer_regs(stp222x, ®);
1008: }
1009: break;
1010:
1011: case 0x28:
1012: tme_stp222x_stc_regs(stp222x, 0, ®);
1013: break;
1014:
1015: case 0x40:
1016: abort();
1017:
1018: case 0x48:
1019: if (TME_STP222X_IS_2220(stp222x)) {
1020: tme_stp222x_mdu_regs_diag(stp222x, ®);
1021: }
1022: else {
1023: tme_stp222x_stc_regs(stp222x, 1, ®);
1024: }
1025: break;
1026:
1027: case 0xa0:
1028: abort();
1029:
1030: case 0x44:
1031: case 0x45:
1032: case 0x46:
1033: case 0xa4:
1034: case 0xa5:
1035: case 0xa6:
1036: if ((reggroup >= 0xa0) == !TME_STP222X_IS_2220(stp222x)) {
1037: tme_stp222x_iommu_regs_diag(stp222x, ®);
1038: }
1039: break;
1040:
1041: case 0xa8:
1042: if (!TME_STP222X_IS_2220(stp222x)) {
1043: tme_stp222x_mdu_regs_diag(stp222x, ®);
1044: }
1045: break;
1046:
1047: default:
1048: if (TME_STP222X_IS_2220(stp222x)
1049: ? (reggroup >= 0x50
1050: && reggroup <= 0x59)
1051: : (reggroup >= 0xb0
1052: && reggroup <= 0xb9)) {
1053: tme_stp222x_stc_regs_diag(stp222x, 0, ®);
1054: }
1055: else if (!TME_STP222X_IS_2220(stp222x)
1056: && reggroup >= 0xc0
1057: && reggroup <= 0xc9) {
1058: tme_stp222x_stc_regs_diag(stp222x, 1, ®);
1059: }
1060: break;
1061: }
1062:
1063: /* if this register access was not completed: */
1064: if (__tme_predict_false(!reg.tme_stp222x_reg_completed)) {
1065:
1066: tme_log(TME_STP222X_LOG_HANDLE(stp222x), 100, TME_OK,
1067: (TME_STP222X_LOG_HANDLE(stp222x),
1068: _("unknown[0x%04x] %s 0x%" TME_PRIx64),
1069: reg.tme_stp222x_reg_address,
1070: (reg.tme_stp222x_reg_write
1071: ? "<-"
1072: : "->"),
1073: reg.tme_stp222x_reg_value));
1074: }
1075:
1076: /* if this was a read: */
1077: if (!reg.tme_stp222x_reg_write) {
1078:
1079: /* return the value: */
1080: reg.tme_stp222x_reg_value = tme_htobe_u64(reg.tme_stp222x_reg_value);
1081: tme_bus_cycle_xfer_memory(master_cycle,
1082: ((tme_uint8_t *) ®.tme_stp222x_reg_value) - slave_address,
1083: slave_address + sizeof(tme_uint64_t) - 1);
1084: }
1085:
1086: /* complete the cycle: */
1087: master_completion->tme_completion_error = TME_OK;
1088: tme_stp222x_completion_validate(stp222x, master_completion);
1089: master_completion = NULL;
1090: *_master_fast_cycle_types = 0;
1091: break;
1092: }
1093:
1094: /* if we didn't complete the cycle ourselves: */
1095: if (master_completion != NULL) {
1096:
1097: /* start this cycle: */
1098: assert (stp222x->tme_stp222x_master_completion == NULL);
1099: stp222x->tme_stp222x_master_completion = &master_completion;
1100:
1101: /* run the slave bus cycle: */
1102: tme_stp22xx_slave_cycle(master_conn_bus,
1103: slave_conn_index,
1104: master_cycle,
1105: _master_fast_cycle_types,
1106: &master_completion);
1107: }
1108:
1109: /* leave: */
1110: tme_stp222x_leave(stp222x);
1111: }
1112:
1113: /* this receives an interrupt: */
1114: static void
1115: _tme_stp222x_interrupt(struct tme_upa_bus_connection *master_conn_upa,
1116: tme_uint32_t slave_mid,
1117: const tme_uint64_t *data,
1118: struct tme_completion *master_completion)
1119: {
1120: abort();
1121: }
1122:
1123: /* this fills a TLB entry: */
1124: static void
1125: _tme_stp222x_tlb_fill(struct tme_bus_connection *agent_conn_bus,
1126: struct tme_bus_tlb *tlb,
1127: tme_bus_addr_t agent_address_wider,
1128: unsigned int cycle_type)
1129: {
1130: struct tme_stp222x *stp222x;
1131: tme_bus_addr64_t slave_address;
1132: tme_uint32_t aspace_i;
1133: tme_uint32_t slave_conn_index;
1134: tme_bus_addr32_t region_size_m1;
1135: tme_bus_addr64_t agent_address;
1136: struct tme_bus_tlb tlb_mapping;
1137:
1138: /* enter: */
1139: stp222x = tme_stp222x_enter_bus(agent_conn_bus);
1140:
1141: /* convert the agent's address into an address space, slave
1142: connection index and address: */
1143: slave_address = agent_address_wider;
1144: aspace_i
1145: = _tme_stp222x_lookup_address(stp222x,
1146: agent_address_wider,
1147: ®ion_size_m1);
1148: slave_address &= region_size_m1;
1149: slave_conn_index
1150: = (aspace_i == TME_STP222X_ASPACE_NULL
1151: ? TME_STP222X_CONN_NULL
1152: : tme_stp222x_aspace_lookup(stp222x,
1153: aspace_i,
1154: &slave_address));
1155:
1156: /* fill this TLB entry: */
1157: tme_stp22xx_tlb_fill(agent_conn_bus,
1158: tlb,
1159: slave_conn_index,
1160: slave_address,
1161: cycle_type);
1162:
1163: /* leave: */
1164: tme_stp222x_leave(stp222x);
1165:
1166: /* map the filled TLB entry: */
1167: agent_address = ~ (tme_bus_addr64_t) region_size_m1;
1168: agent_address &= agent_address_wider;
1169: tlb_mapping.tme_bus_tlb_addr_first = agent_address;
1170: agent_address |= region_size_m1;
1171: tlb_mapping.tme_bus_tlb_addr_last = agent_address;
1172: #if TME_STP22XX_BUS_TRANSITION
1173: tlb_mapping.tme_bus_tlb_cycles_ok = (TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE);
1174: #endif /* TME_STP22XX_BUS_TRANSITION */
1175: tme_bus_tlb_map(tlb, slave_address, &tlb_mapping, agent_address_wider);
1176: }
1177:
1178: #if TME_STP22XX_BUS_TRANSITION
1179:
1180: /* this is the bus signal transition glue: */
1181: static int
1182: _tme_stp222x_signal_transition(struct tme_bus_connection *conn_bus,
1183: unsigned int signal)
1184: {
1185: struct tme_completion completion_buffer;
1186: tme_completion_init(&completion_buffer);
1187: _tme_stp222x_signal(conn_bus,
1188: signal,
1189: &completion_buffer);
1190: return (TME_OK);
1191: }
1192: #define _tme_stp222x_signal _tme_stp222x_signal_transition
1193:
1194: /* this is the bus cycle transition glue: */
1195: static int
1196: _tme_stp222x_cycle_transition(void *_master_conn_bus,
1197: struct tme_bus_cycle *master_cycle)
1198: {
1199: struct tme_completion completion_buffer;
1200: struct tme_stp222x *stp222x;
1201: struct tme_bus_connection *master_conn_bus;
1202: tme_uint32_t master_fast_cycle_types;
1203:
1204: tme_completion_init(&completion_buffer);
1205:
1206: master_conn_bus = (struct tme_bus_connection *) _master_conn_bus;
1207: stp222x = (struct tme_stp222x *) master_conn_bus->tme_bus_connection.tme_connection_element->tme_element_private;
1208: (master_conn_bus == stp222x->tme_stp222x.tme_stp22xx_conns[TME_STP222X_CONN_UPA].tme_stp22xx_conn_bus
1209: ? _tme_stp222x_cycle
1210: : tme_stp222x_iommu_cycle)
1211: (master_conn_bus,
1212: master_cycle,
1213: &master_fast_cycle_types,
1214: &completion_buffer);
1215: return (completion_buffer.tme_completion_error);
1216: }
1217:
1218: /* the bus TLB fill transition glue: */
1219: static int
1220: _tme_stp222x_tlb_fill_transition(struct tme_bus_connection *agent_conn_bus,
1221: struct tme_bus_tlb *tlb,
1222: tme_bus_addr_t agent_address_wider,
1223: unsigned int cycle_type)
1224: {
1225: struct tme_stp222x *stp222x;
1226:
1227: stp222x = (struct tme_stp222x *) agent_conn_bus->tme_bus_connection.tme_connection_element->tme_element_private;
1228: (agent_conn_bus == stp222x->tme_stp222x.tme_stp22xx_conns[TME_STP222X_CONN_UPA].tme_stp22xx_conn_bus
1229: ? _tme_stp222x_tlb_fill
1230: : tme_stp222x_iommu_tlb_fill)
1231: (agent_conn_bus,
1232: tlb,
1233: agent_address_wider,
1234: cycle_type);
1235:
1236: /* we always handle any slow cycles: */
1237: tlb->tme_bus_tlb_cycles_ok |= cycle_type;
1238: tlb->tme_bus_tlb_addr_offset = 0;
1239: tlb->tme_bus_tlb_addr_shift = 0;
1240: tlb->tme_bus_tlb_cycle = _tme_stp222x_cycle_transition;
1241: tlb->tme_bus_tlb_cycle_private = agent_conn_bus;
1242: assert (tlb->tme_bus_tlb_fault_handler_count == 0);
1243:
1244: return (TME_OK);
1245: }
1246: #define _tme_stp222x_tlb_fill _tme_stp222x_tlb_fill_transition
1247: #define tme_stp222x_iommu_tlb_fill _tme_stp222x_tlb_fill_transition
1248:
1249: #endif /* TME_STP22XX_BUS_TRANSITION */
1250:
1251: /* the connection scorer: */
1252: static int
1253: _tme_stp222x_connection_score(struct tme_connection *conn,
1254: unsigned int *_score)
1255: {
1256: struct tme_bus_connection *conn_bus;
1257: struct tme_stp222x *stp222x;
1258: unsigned int score;
1259: struct tme_upa_bus_connection *conn_upa_other;
1260: struct tme_bus_connection *conn_bus_other;
1261:
1262: /* recover the bus connection: */
1263: conn_bus = (struct tme_bus_connection *) conn;
1264:
1265: /* enter: */
1266: stp222x = tme_stp222x_enter_bus(conn_bus);
1267:
1268: /* assume that this connection is useless: */
1269: score = 0;
1270:
1271: /* dispatch on the connection type: */
1272: conn_upa_other = (struct tme_upa_bus_connection *) conn->tme_connection_other;
1273: conn_bus_other = (struct tme_bus_connection *) conn->tme_connection_other;
1274: switch (conn->tme_connection_type) {
1275:
1276: /* this must be a UPA controller, and not another agent: */
1277: case TME_CONNECTION_BUS_UPA:
1278: if (conn_upa_other->tme_upa_bus_connection.tme_bus_tlb_set_add != NULL
1279: && conn_upa_other->tme_upa_bus_interrupt != NULL) {
1280: score = 10;
1281: }
1282: break;
1283:
1284: /* this must be a bus device: */
1285: case TME_CONNECTION_BUS_GENERIC:
1286: if (conn_bus_other->tme_bus_tlb_set_add == NULL) {
1287: score = 1;
1288: }
1289: break;
1290:
1291: default: abort();
1292: }
1293:
1294: /* leave: */
1295: tme_stp222x_leave(stp222x);
1296: *_score = score;
1297: return (TME_OK);
1298: }
1299:
1300: /* this makes a new connection: */
1301: static int
1302: _tme_stp222x_connection_make(struct tme_connection *conn, unsigned int state)
1303: {
1304: struct tme_upa_bus_connection *conn_upa;
1305: struct tme_bus_connection *conn_bus;
1306: struct tme_stp222x *stp222x;
1307: unsigned int conn_index;
1308: tme_uint32_t slot;
1309: tme_bus_addr32_t offset;
1310: int slaveonly;
1311: tme_uint32_t connid;
1312: unsigned int obio_i;
1313:
1314: /* ignore a half-connection: */
1315: if (state == TME_CONNECTION_HALF) {
1316: return (TME_OK);
1317: }
1318:
1319: /* recover the bus connection: */
1320: conn_upa = (struct tme_upa_bus_connection *) conn;
1321: conn_bus = (struct tme_bus_connection *) conn;
1322:
1323: /* enter: */
1324: stp222x = tme_stp222x_enter_bus(conn_bus);
1325:
1326: /* if this is the UPA bus connection: */
1327: if (conn->tme_connection_type == TME_CONNECTION_BUS_UPA) {
1328:
1329: /* save the UPA bus connection: */
1330: stp222x->tme_stp222x.tme_stp22xx_conns[TME_STP222X_CONN_UPA].tme_stp22xx_conn_upa = conn_upa;
1331: }
1332:
1333: /* otherwise, this is a device bus connection: */
1334: else {
1335:
1336: /* if this is an stp2220: */
1337: if (TME_STP222X_IS_2220(stp222x)) {
1338:
1339: /* split the temporary connection id into the slot, offset, and
1340: slaveonly flag: */
1341: offset = conn->tme_connection_id;
1342: slot = (offset / TME_STP2220_SLOT_SIZE);
1343: offset %= TME_STP2220_SLOT_SIZE;
1344: slaveonly
1345: = (slot > TME_STP2220_SLOT_CARD(TME_STP2220_SLOTS_CARD - 1)
1346: && slot < TME_STP2220_SLOT_OBIO(0));
1347: if (slaveonly) {
1348: slot ^= TME_STP2220_SLOT_CARD(TME_STP2220_SLOTS_CARD);
1349: }
1350:
1351: /* if this is a card: */
1352: if (slot >= TME_STP2220_SLOT_CARD(0)
1353: && slot <= TME_STP2220_SLOT_CARD(TME_STP2220_SLOTS_CARD - 1)) {
1354:
1355: /* start the card connection ID: */
1356: connid = TME_STP222X_CONNID_TYPE_CARD;
1357: TME_FIELD_MASK_DEPOSITU(connid,
1358: TME_STP2220_CONNID_CARD_WHICH,
1359: (slot - TME_STP2220_SLOT_CARD(0)));
1360: TME_FIELD_MASK_DEPOSITU(connid,
1361: TME_STP2220_CONNID_CARD_OFFSET,
1362: offset);
1363:
1364: /* if this is a slave connection: */
1365: if (slaveonly) {
1366:
1367: /* this connection will use the next slave connection index,
1368: which is an alternate connection index: */
1369: conn_index = stp222x->tme_stp222x_slave_conn_index_next++;
1370: connid |= TME_STP2220_CONNID_CARD_ALTERNATE;
1371: }
1372:
1373: else {
1374:
1375: /* assume that this is the first master connection for this
1376: card, which will use the card's primary master connection
1377: index: */
1378: conn_index = TME_FIELD_MASK_EXTRACTU(connid, TME_STP2220_CONNID_CARD_WHICH);
1379:
1380: /* if this is not the first master connection for this card: */
1381: if (stp222x->tme_stp222x.tme_stp22xx_conns[conn_index].tme_stp22xx_conn_bus != NULL) {
1382:
1383: /* this connection will use an alternate master connection
1384: index: */
1385: connid |= TME_STP2220_CONNID_CARD_ALTERNATE;
1386:
1387: /* starting from the first alternate master connection
1388: index for this card and moving forward, search the
1389: remaining master connection indices for a free one: */
1390: /* NB: this means if you have an SBus card with a lot of
1391: different masters on it, you should put it in the last
1392: card slot, to save the preferred alternate master
1393: connection indices for the other card slots: */
1394: conn_index
1395: = (TME_STP2220_SLOTS_CARD
1396: + (connid & TME_STP2220_CONNID_CARD_WHICH));
1397: for (; stp222x->tme_stp222x.tme_stp22xx_conns[conn_index].tme_stp22xx_conn_bus != NULL;) {
1398: if (++conn_index == TME_STP222X_CONN_SLAVE0) {
1399: abort();
1400: }
1401: }
1402: }
1403: }
1404: }
1405:
1406: /* otherwise, this is an obio device: */
1407: else {
1408:
1409: /* if this is the slave I/O slot, force slaveonly: */
1410: if (slot == TME_STP2220_SLOT_SLAVIO) {
1411: slaveonly = TRUE;
1412: }
1413:
1414: /* if this is a slave connection: */
1415: if (slaveonly) {
1416:
1417: /* this connection will use the next slave connection index: */
1418: conn_index = stp222x->tme_stp222x_slave_conn_index_next++;
1419: }
1420:
1421: /* otherwise, this is a master connection: */
1422: else {
1423:
1424: /* starting from the last master connection index and
1425: moving backwards, search for a free one: */
1426: conn_index = TME_STP222X_CONN_SLAVE0 - 1;
1427: for (; stp222x->tme_stp222x.tme_stp22xx_conns[conn_index].tme_stp22xx_conn_bus != NULL;) {
1428: if (conn_index-- == 0) {
1429: abort();
1430: }
1431: }
1432: }
1433:
1434: /* assume that this is not a known obio connection, and make
1435: the obio long connection id: */
1436: connid
1437: = (TME_STP222X_CONNID_TYPE_OBIO
1438: | TME_STP222X_CONNID_OBIO_TYPE_LONG);
1439: TME_FIELD_MASK_DEPOSITU(connid,
1440: TME_STP222X_CONNID_OBIO_LONG_WHICH,
1441: (slot - TME_STP2220_SLOT_OBIO(0)));
1442: TME_FIELD_MASK_DEPOSITU(connid,
1443: TME_STP222X_CONNID_OBIO_LONG_OFFSET,
1444: offset);
1445:
1446: /* if this is a known obio connection: */
1447: for (obio_i = 0; obio_i < TME_ARRAY_ELS(_tme_stp2220_obios); obio_i++) {
1448: if (_tme_stp2220_obios[obio_i]._tme_stp2220_obio_slot == slot
1449: && _tme_stp2220_obios[obio_i]._tme_stp2220_obio_offset == offset) {
1450:
1451: /* make the obio short connection id: */
1452: connid
1453: = (TME_STP222X_CONNID_TYPE_OBIO
1454: | TME_STP222X_CONNID_OBIO_TYPE_SHORT);
1455: TME_FIELD_MASK_DEPOSITU(connid,
1456: TME_STP222X_CONNID_OBIO_SHORT_IDI,
1457: _tme_stp2220_obios[obio_i]._tme_stp2220_obio_idi);
1458: TME_FIELD_MASK_DEPOSITU(connid,
1459: TME_STP222X_CONNID_OBIO_SHORT_CONN_WHICH,
1460: conn_index);
1461: break;
1462: }
1463: }
1464: }
1465:
1466: /* save the SBus offset for this connection: */
1467: assert (conn_index < TME_STP222X_CONN_NULL);
1468: stp222x->tme_stp2220_conn_offset[conn_index] = TME_STP2220_SBUS_ADDRESS(slot, offset);
1469: }
1470:
1471: /* otherwise, this is an stp222x: */
1472: else {
1473: abort();
1474: }
1475:
1476: /* update this connection's id: */
1477: conn->tme_connection_id = connid;
1478:
1479: /* add this connection to the list: */
1480: assert (conn_index < TME_STP222X_CONN_NULL);
1481: if (conn->tme_connection_type == TME_CONNECTION_BUS_GENERIC) {
1482: assert (TME_STP222X_IS_2220(stp222x));
1483: stp222x->tme_stp222x.tme_stp22xx_conns[conn_index].tme_stp22xx_conn_bus = conn_bus;
1484: }
1485: else {
1486: assert (FALSE);
1487: }
1488:
1489: /* rebuild the address spaces: */
1490: if (tme_stp222x_aspaces_rebuild(stp222x)) {
1491: abort();
1492: }
1493: }
1494:
1495: /* leave: */
1496: tme_stp222x_leave(stp222x);
1497: return (TME_OK);
1498: }
1499:
1500: /* this breaks a connection: */
1501: static int
1502: _tme_stp222x_connection_break(struct tme_connection *conn, unsigned int state)
1503: {
1504: abort();
1505: }
1506:
1507: /* this makes new connection sides: */
1508: static int
1509: _tme_stp222x_connections_new(struct tme_element *element,
1510: const char * const *args,
1511: struct tme_connection **_conns,
1512: char **_output)
1513: {
1514: int rc;
1515: struct tme_stp222x *stp222x;
1516: struct tme_upa_bus_connection *conn_upa;
1517: struct tme_bus_connection *conn_bus;
1518: struct tme_connection *conn;
1519: tme_bus_addr_t slot_wider;
1520: tme_bus_addr_t offset_wider;
1521: int slaveonly;
1522:
1523: /* assume that we will succeed: */
1524: rc = TME_OK;
1525:
1526: /* recover our data structure: */
1527: stp222x = (struct tme_stp222x *) element->tme_element_private;
1528:
1529: /* lock the mutex: */
1530: tme_mutex_lock(&stp222x->tme_stp222x.tme_stp22xx_mutex);
1531:
1532: /* if we have no arguments, this is the UPA connection: */
1533: if (args[1] == NULL) {
1534:
1535: /* if we already have the UPA connection: */
1536: if (stp222x->tme_stp222x.tme_stp22xx_conns[TME_STP222X_CONN_UPA].tme_stp22xx_conn_upa != NULL) {
1537: rc = EEXIST;
1538: }
1539:
1540: /* otherwise, we don't have a UPA connection yet: */
1541: else {
1542:
1543: /* create a UPA connection: */
1544: conn_upa = tme_new0(struct tme_upa_bus_connection, 1);
1545: conn_upa->tme_upa_bus_connection.tme_bus_connection.tme_connection_type = TME_CONNECTION_BUS_UPA;
1546: conn_upa->tme_upa_bus_interrupt = _tme_stp222x_interrupt;
1547:
1548: /* fill in the generic bus connection: */
1549: conn_bus = &conn_upa->tme_upa_bus_connection;
1550: conn_bus->tme_bus_signals_add = NULL;
1551: conn_bus->tme_bus_signal = _tme_stp222x_signal;
1552: conn_bus->tme_bus_intack = NULL;
1553: conn_bus->tme_bus_tlb_set_add = NULL;
1554: conn_bus->tme_bus_tlb_fill = _tme_stp222x_tlb_fill;
1555:
1556: /* fill in the generic connection: */
1557: conn = &conn_bus->tme_bus_connection;
1558: conn->tme_connection_score = _tme_stp222x_connection_score;
1559: conn->tme_connection_make = _tme_stp222x_connection_make;
1560: conn->tme_connection_break = _tme_stp222x_connection_break;
1561:
1562: /* add in this connection side possibility: */
1563: conn->tme_connection_next = *_conns;
1564: *_conns = conn;
1565: }
1566: }
1567:
1568: /* otherwise, if this is an stp2220 and we have "slot" and "offset"
1569: arguments, and an optional "slaveonly" argument, this is an SBus
1570: connection: */
1571: else if (TME_STP222X_IS_2220(stp222x)
1572: && TME_ARG_IS(args[1], "slot")
1573: && args[2] != NULL
1574: && TME_ARG_IS(args[3], "offset")
1575: && args[4] != NULL
1576: && (((slaveonly = TME_ARG_IS(args[5], "slaveonly"))
1577: && args[6] == NULL)
1578: || args[5] == NULL)) {
1579:
1580: /* convert the slot and base offset: */
1581: slot_wider = tme_bus_addr_parse(args[2], TME_STP2220_SLOT_OBIO(TME_STP2220_SLOTS_OBIO));
1582: offset_wider = tme_bus_addr_parse(args[4], TME_STP2220_SLOT_SIZE);
1583:
1584: /* if this is a bad slot: */
1585: if ((slot_wider < TME_STP2220_SLOT_CARD(0)
1586: || slot_wider > TME_STP2220_SLOT_CARD(TME_STP2220_SLOTS_CARD - 1))
1587: && (slot_wider < TME_STP2220_SLOT_OBIO(0)
1588: || slot_wider > TME_STP2220_SLOT_OBIO(TME_STP2220_SLOTS_OBIO - 1))) {
1589: tme_output_append_error(_output,
1590: "%s %s",
1591: _("bad slot"),
1592: args[2]);
1593: rc = EINVAL;
1594: }
1595:
1596: /* if this is a bad offset: */
1597: else if (offset_wider >= TME_STP2220_SLOT_SIZE) {
1598: tme_output_append_error(_output,
1599: "%s %s",
1600: _("bad offset"),
1601: args[4]);
1602: rc = EINVAL;
1603: }
1604:
1605: /* otherwise, the arguments are ok: */
1606: else {
1607:
1608: /* create a generic bus connection: */
1609: conn_bus = tme_new0(struct tme_bus_connection, 1);
1610: conn_bus->tme_bus_connection.tme_connection_type = TME_CONNECTION_BUS_GENERIC;
1611:
1612: /* fill in the generic bus connection: */
1613: conn_bus->tme_bus_signals_add = NULL;
1614: conn_bus->tme_bus_signal = _tme_stp222x_signal;
1615: conn_bus->tme_bus_intack = NULL;
1616: conn_bus->tme_bus_tlb_set_add = tme_stp22xx_tlb_set_add;
1617: conn_bus->tme_bus_tlb_fill = tme_stp222x_iommu_tlb_fill;
1618:
1619: /* fill in the generic connection: */
1620: /* NB: this connection's temporary id is the SBus address, with
1621: the slot exclusive-ORed with the maximum number of cards if
1622: the "slaveonly" flag was given: */
1623: conn = &conn_bus->tme_bus_connection;
1624: conn->tme_connection_id
1625: = TME_STP2220_SBUS_ADDRESS((slot_wider
1626: ^ (slaveonly
1627: ? TME_STP2220_SLOT_CARD(TME_STP2220_SLOTS_CARD)
1628: : 0)),
1629: offset_wider);
1630: conn->tme_connection_score = _tme_stp222x_connection_score;
1631: conn->tme_connection_make = _tme_stp222x_connection_make;
1632: conn->tme_connection_break = _tme_stp222x_connection_break;
1633:
1634: /* add in this connection side possibility: */
1635: conn->tme_connection_next = *_conns;
1636: *_conns = conn;
1637: }
1638: }
1639:
1640: /* otherwise, the arguments are unknown: */
1641: else {
1642: if (TME_STP222X_IS_2220(stp222x)) {
1643: tme_output_append_error(_output,
1644: "%s %s [ slot %s offset %s [ slaveonly ] ]",
1645: _("usage:"),
1646: args[0],
1647: _("SLOT"),
1648: _("OFFSET"));
1649: }
1650: rc = EINVAL;
1651: }
1652:
1653: /* unlock the mutex: */
1654: tme_mutex_unlock(&stp222x->tme_stp222x.tme_stp22xx_mutex);
1655:
1656: return (rc);
1657: }
1658:
1659: /* this creates a new stp222x element: */
1660: static int
1661: _tme_stp222x_new(struct tme_element *element,
1662: const char * const *args,
1663: const void *extra,
1664: char **_output,
1665: unsigned int is_2220)
1666: {
1667: struct tme_stp222x *stp222x;
1668: int arg_i;
1669: int usage;
1670:
1671: /* check our arguments: */
1672: usage = 0;
1673: arg_i = 1;
1674: for (;;) {
1675:
1676: if (0) {
1677: }
1678:
1679: /* if we ran out of arguments: */
1680: else if (args[arg_i] == NULL) {
1681:
1682: break;
1683: }
1684:
1685: /* otherwise this is a bad argument: */
1686: else {
1687: tme_output_append_error(_output,
1688: "%s %s, ",
1689: args[arg_i],
1690: _("unexpected"));
1691: usage = TRUE;
1692: break;
1693: }
1694: }
1695:
1696: if (usage) {
1697: tme_output_append_error(_output,
1698: "%s %s",
1699: _("usage:"),
1700: args[0]);
1701: return (EINVAL);
1702: }
1703:
1704: /* start the stp222x structure: */
1705: stp222x = tme_new0(struct tme_stp222x, 1);
1706: stp222x->tme_stp222x.tme_stp22xx_element = element;
1707: stp222x->tme_stp222x.tme_stp22xx_run = _tme_stp222x_run;
1708: tme_stp22xx_init(&stp222x->tme_stp222x,
1709: sizeof(struct tme_stp222x),
1710: TME_STP222X_CONN_NULL);
1711:
1712: /* set the type: */
1713: stp222x->tme_stp222x_is_2220 = is_2220;
1714: if (TME_STP222X_IS_2220(stp222x) != is_2220) {
1715: tme_free(stp222x);
1716: return (ENXIO);
1717: }
1718:
1719: /* the UPA bus reset signal is initially negated: */
1720: stp222x->tme_stp222x_reset_level = TME_BUS_SIGNAL_LEVEL_NEGATED;
1721:
1722: /* initialize the CSR: */
1723: stp222x->tme_stp222x_csr
1724: = (0x1f * _TME_FIELD_MASK_FACTOR(TME_STP222X_CSR_MID));
1725:
1726: /* initialize the miscellaneous registers: */
1727: stp222x->tme_stp222x_upa_port_config = 1;
1728:
1729: /* initialize the connections: */
1730: stp222x->tme_stp222x_slave_conn_index_next = TME_STP222X_CONN_SLAVE0;
1731:
1732: /* initialize the timers: */
1733: tme_stp222x_timer_init(stp222x, &stp222x->tme_stp222x_timers[0]);
1734: tme_stp222x_timer_init(stp222x, &stp222x->tme_stp222x_timers[1]);
1735:
1736: /* initialize the MDU: */
1737: tme_stp222x_mdu_init(stp222x);
1738:
1739: /* initialize the IOMMU: */
1740: tme_stp222x_iommu_init(stp222x);
1741:
1742: /* initialize the streaming caches: */
1743: tme_stp222x_stc_init(&stp222x->tme_stp222x_stcs[0]);
1744: tme_stp222x_stc_init(&stp222x->tme_stp222x_stcs[1]);
1745:
1746: /* fill the element: */
1747: element->tme_element_private = stp222x;
1748: element->tme_element_connections_new = _tme_stp222x_connections_new;
1749:
1750: return (TME_OK);
1751: }
1752:
1753: /* this creates a new stp2220 element: */
1754: TME_ELEMENT_X_NEW_DECL(tme_ic_,stp22xx,stp2220) {
1755: return (_tme_stp222x_new(element, args, extra, _output, TRUE));
1756: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.