|
|
1.1 root 1: /* $Id: am7990.c,v 1.3 2007/03/25 21:18:50 fredette Exp $ */
2:
3: /* ic/am7990.c - implementation of Am7990 emulation: */
4:
5: /*
6: * Copyright (c) 2006 Matt Fredette
7: * All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. All advertising materials mentioning features or use of this software
18: * must display the following acknowledgement:
19: * This product includes software developed by Matt Fredette.
20: * 4. The name of the author may not be used to endorse or promote products
21: * derived from this software without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
27: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33: * POSSIBILITY OF SUCH DAMAGE.
34: */
35:
36: #include <tme/common.h>
37: _TME_RCSID("$Id: am7990.c,v 1.3 2007/03/25 21:18:50 fredette Exp $");
38:
39: /* includes: */
40: #include <tme/generic/bus-device.h>
41: #include <tme/generic/ethernet.h>
42:
43: /* macros: */
44:
45: /* CSR0: */
46: #define TME_AM7990_CSR0_ERR TME_BIT(15)
47: #define TME_AM7990_CSR0_BABL TME_BIT(14)
48: #define TME_AM7990_CSR0_CERR TME_BIT(13)
49: #define TME_AM7990_CSR0_MISS TME_BIT(12)
50: #define TME_AM7990_CSR0_MERR TME_BIT(11)
51: #define TME_AM7990_CSR0_RINT TME_BIT(10)
52: #define TME_AM7990_CSR0_TINT TME_BIT(9)
53: #define TME_AM7990_CSR0_IDON TME_BIT(8)
54: #define TME_AM7990_CSR0_INTR TME_BIT(7)
55: #define TME_AM7990_CSR0_INEA TME_BIT(6)
56: #define TME_AM7990_CSR0_RXON TME_BIT(5)
57: #define TME_AM7990_CSR0_TXON TME_BIT(4)
58: #define TME_AM7990_CSR0_TDMD TME_BIT(3)
59: #define TME_AM7990_CSR0_STOP TME_BIT(2)
60: #define TME_AM7990_CSR0_STRT TME_BIT(1)
61: #define TME_AM7990_CSR0_INIT TME_BIT(0)
62: #define TME_AM7990_CSR0_READ_ONLY \
63: (TME_AM7990_CSR0_ERR \
64: | TME_AM7990_CSR0_INTR \
65: | TME_AM7990_CSR0_RXON \
66: | TME_AM7990_CSR0_TXON)
67: #define TME_AM7990_CSR0_WRITE_ONE_TO_CLEAR \
68: (TME_AM7990_CSR0_BABL \
69: | TME_AM7990_CSR0_CERR \
70: | TME_AM7990_CSR0_MISS \
71: | TME_AM7990_CSR0_MERR \
72: | TME_AM7990_CSR0_RINT \
73: | TME_AM7990_CSR0_TINT \
74: | TME_AM7990_CSR0_IDON)
75: #define TME_AM7990_CSR0_WRITE_ONE_ONLY \
76: (TME_AM7990_CSR0_TDMD \
77: | TME_AM7990_CSR0_STOP \
78: | TME_AM7990_CSR0_STRT \
79: | TME_AM7990_CSR0_INIT)
80:
81: /* CSR3: */
82: #define TME_AM7990_CSR3_BSWAP TME_BIT(2)
83: #define TME_AM7990_CSR3_ACON TME_BIT(1)
84: #define TME_AM7990_CSR3_BCON TME_BIT(0)
85:
86: /* Mode: */
87: #define TME_AM7990_MODE_PROM TME_BIT(15)
88: #define TME_AM7990_MODE_EMBA TME_BIT(7)
89: #define TME_AM7990_MODE_INTL TME_BIT(6)
90: #define TME_AM7990_MODE_DRTY TME_BIT(5)
91: #define TME_AM7990_MODE_COLL TME_BIT(4)
92: #define TME_AM7990_MODE_DTCR TME_BIT(3)
93: #define TME_AM7990_MODE_LOOP TME_BIT(2)
94: #define TME_AM7990_MODE_DTX TME_BIT(1)
95: #define TME_AM7990_MODE_DRX TME_BIT(0)
96:
97: /* a Descriptor Ring Pointer: */
98: #define TME_AM7990_DRP_XDRA (0x00fffff8)
99: #define TME_AM7990_DRP_XLEN_LOG2 (0xe0000000)
100:
101: /* a descriptor table entry: */
102: #define TME_AM7990_DTE_OFFSET_XMD0 (0 * sizeof(tme_uint16_t))
103: #define TME_AM7990_DTE_OFFSET_XMD1 (1 * sizeof(tme_uint16_t))
104: #define TME_AM7990_DTE_OFFSET_XMD2 (2 * sizeof(tme_uint16_t))
105: #define TME_AM7990_DTE_OFFSET_XMD3 (3 * sizeof(tme_uint16_t))
106: #define TME_AM7990_DTE_SIZE (4 * sizeof(tme_uint16_t))
107:
108: /* common parts of TMD1 and RMD1: */
109: #define TME_AM7990_XMD1_OWN TME_BIT(15)
110: #define TME_AM7990_XMD1_ERR TME_BIT(14)
111: #define TME_AM7990_XMD1_STP TME_BIT(9)
112: #define TME_AM7990_XMD1_ENP TME_BIT(8)
113: #define TME_AM7990_XMD1_HADR (0x00ff)
114:
115: /* common parts of TMD2 and RMD2: */
116: #define TME_AM7990_XMD2_BCNT (0x0fff)
117:
118: /* TMD1: */
119: #define TME_AM7990_TMD1_ADD_FCS TME_BIT(13)
120:
121: /* TMD3: */
122: #define TME_AM7990_TMD3_BUFF TME_BIT(15)
123:
124: /* RMD1: */
125: #define TME_AM7990_RMD1_BUFF TME_BIT(10)
126:
127: /* the callout flags: */
128: #define TME_AM7990_CALLOUTS_RUNNING TME_BIT(0)
129: #define TME_AM7990_CALLOUTS_MASK (-2)
130: #define TME_AM7990_CALLOUT_RECEIVE TME_BIT(1)
131: #define TME_AM7990_CALLOUT_TRANSMIT_SCAN TME_BIT(2)
132: #define TME_AM7990_CALLOUT_CONFIG TME_BIT(3)
133: #define TME_AM7990_CALLOUT_DMA_READ TME_BIT(4)
134: #define TME_AM7990_CALLOUT_DMA_WRITE TME_BIT(5)
135:
136: /* the default locks: */
137: #define TME_AM7990_LOCKS_DEFAULT (0)
138:
139: /* the size of the TLB entry hash: */
140: #define TME_AM7990_TLB_HASH_SIZE (512)
141:
142: /* structures: */
143:
144: /* the chip: */
145: struct tme_am7990 {
146:
147: /* our simple bus device header: */
148: struct tme_bus_device tme_am7990_device;
149: #define tme_am7990_element tme_am7990_device.tme_bus_device_element
150:
151: /* the Ethernet connection: */
152: struct tme_ethernet_connection *tme_am7990_eth_connection;
153:
154: /* the mutex protecting the chip: */
155: tme_mutex_t tme_am7990_mutex;
156:
157: /* the callout flags: */
158: int tme_am7990_callout_flags;
159:
160: /* our DMA TLB hash: */
161: struct tme_bus_tlb * tme_shared tme_am7990_tlb_hash;
162: tme_rwlock_t tme_am7990_tlb_hash_rwlock;
163:
164: /* our bus addresses: */
165: tme_bus_addr_t tme_am7990_offset_rap;
166: tme_bus_addr_t tme_am7990_offset_rdp;
167:
168: /* registers: */
169: tme_uint16_t tme_am7990_rap;
170: tme_uint16_t tme_am7990_csrs[4];
171: #define tme_am7990_csr0 tme_am7990_csrs[0]
172:
173: /* the initialization block: */
174: tme_uint16_t tme_am7990_init[12];
175: #define tme_am7990_mode tme_am7990_init[0]
176: #define tme_am7990_padr tme_am7990_init[1]
177: #define tme_am7990_ladrf tme_am7990_init[4]
178: #define tme_am7990_rdra tme_am7990_init[8]
179: #define tme_am7990_rlen_rdra tme_am7990_init[9]
180: #define tme_am7990_tdra tme_am7990_init[10]
181: #define tme_am7990_tlen_tdra tme_am7990_init[11]
182:
183: /* the transmit ring: */
184: unsigned int tme_am7990_transmit_dte_index_mask;
185: tme_uint32_t tme_am7990_transmit_dte_address;
186:
187: /* the current transmit DTE index, and any previously read TMD1
188: value: */
189: unsigned int tme_am7990_transmit_dte_index;
190: tme_uint16_t tme_am7990_transmit_dte_tmd1;
191:
192: /* the receive buffer: */
193: tme_uint8_t tme_am7990_receive_buffer[TME_ETHERNET_FRAME_MAX];
194: unsigned int tme_am7990_receive_buffer_length;
195:
196: /* the receive ring: */
197: unsigned int tme_am7990_receive_dte_index_mask;
198: tme_uint32_t tme_am7990_receive_dte_address;
199:
200: /* the current receive DTE index: */
201: unsigned int tme_am7990_receive_dte_index;
202:
203: /* this is nonzero if the interrupt is asserted: */
204: int tme_am7990_int_asserted;
205:
206: /* the input and output Ethernet controls: */
207: unsigned int tme_am7990_ether_ctrl_out;
208: unsigned int tme_am7990_ether_ctrl_in;
209: };
210:
211: /* prototypes: */
212: static int _tme_am7990_transmit _TME_P((struct tme_ethernet_connection *,
213: tme_ethernet_fid_t *,
214: struct tme_ethernet_frame_chunk *,
215: unsigned int));
216:
217: /* this resets the am7990: */
218: static void
219: _tme_am7990_reset(struct tme_am7990 *am7990)
220: {
221:
222: tme_log(&am7990->tme_am7990_element->tme_element_log_handle,
223: 100, TME_OK,
224: (&am7990->tme_am7990_element->tme_element_log_handle,
225: "reset"));
226:
227: /* clear all pending callouts: */
228: am7990->tme_am7990_callout_flags &= TME_AM7990_CALLOUTS_MASK;
229:
230: /* reset CSR0: */
231: am7990->tme_am7990_csr0 = TME_AM7990_CSR0_STOP;
232:
233: /* reset CSR3: */
234: am7990->tme_am7990_csrs[3] = 0;
235:
236: /* "EMBA is cleared by activation of the RESET pin or setting the
237: STOP bit." */
238: am7990->tme_am7990_mode &= ~TME_AM7990_MODE_EMBA;
239: }
240:
241: /* this hashes an address into a TLB entry: */
242: static struct tme_bus_tlb *
243: _tme_am7990_tlb_hash(void *_am7990,
244: tme_bus_addr_t linear_address,
245: unsigned int cycles)
246: {
247: struct tme_am7990 *am7990;
248:
249: /* recover our data structure: */
250: am7990 = (struct tme_am7990 *) _am7990;
251:
252: /* return the TLB entry: */
253: return (tme_memory_atomic_pointer_read(struct tme_bus_tlb *,
254: am7990->tme_am7990_tlb_hash,
255: &am7990->tme_am7990_tlb_hash_rwlock)
256: + ((linear_address >> 10) & (TME_AM7990_TLB_HASH_SIZE - 1)));
257: }
258:
259: /* this locks the mutex: */
260: static void
261: _tme_am7990_lock(void *_am7990,
262: unsigned int locks)
263: {
264: struct tme_am7990 *am7990;
265:
266: /* recover our data structure: */
267: am7990 = (struct tme_am7990 *) _am7990;
268:
269: /* lock the mutex: */
270: tme_mutex_lock(&am7990->tme_am7990_mutex);
271: }
272:
273: /* this unlocks the mutex: */
274: static void
275: _tme_am7990_unlock(void *_am7990,
276: unsigned int locks)
277: {
278: struct tme_am7990 *am7990;
279:
280: /* recover our data structure: */
281: am7990 = (struct tme_am7990 *) _am7990;
282:
283: /* unlock the mutex: */
284: tme_mutex_unlock(&am7990->tme_am7990_mutex);
285: }
286:
287: /* this does a DMA: */
288: static int
289: _tme_am7990_dma(struct tme_am7990 *am7990,
290: tme_uint32_t callout_flags,
291: tme_uint32_t address,
292: unsigned int count,
293: tme_uint8_t *buffer)
294: {
295: int rc;
296:
297: /* make the callout: */
298: rc = ((callout_flags & TME_AM7990_CALLOUT_DMA_READ)
299: ? tme_bus_device_dma_read_16(&am7990->tme_am7990_device,
300: address,
301: count,
302: buffer,
303: TME_AM7990_LOCKS_DEFAULT)
304: : tme_bus_device_dma_write_16(&am7990->tme_am7990_device,
305: address,
306: count,
307: buffer,
308: TME_AM7990_LOCKS_DEFAULT));
309:
310: /* if we got a bus error: */
311: if (rc != TME_OK) {
312:
313: /* set MERR: */
314: am7990->tme_am7990_csr0 |= TME_AM7990_CSR0_MERR;
315:
316: /* we were cancelled: */
317: return (TRUE);
318: }
319:
320: /* we weren't cancelled: */
321: return (FALSE);
322: }
323:
324: /* this returns the address for a 16-bit DTE read or write: */
325: static inline tme_uint32_t
326: _tme_am7990_dte_address(struct tme_am7990 *am7990,
327: tme_uint32_t callout_flags,
328: tme_uint32_t dte_offset)
329: {
330: tme_uint32_t dte_address;
331: tme_uint32_t dte_index;
332: tme_uint32_t dte_index_mask;
333:
334: /* get the DTE address, index, and index mask: */
335: if (callout_flags & TME_AM7990_CALLOUT_RECEIVE) {
336: dte_address = am7990->tme_am7990_receive_dte_address;
337: dte_index = am7990->tme_am7990_receive_dte_index;
338: dte_index_mask = am7990->tme_am7990_receive_dte_index_mask;
339: }
340: else {
341: dte_address = am7990->tme_am7990_transmit_dte_address;
342: dte_index = am7990->tme_am7990_transmit_dte_index;
343: dte_index_mask = am7990->tme_am7990_transmit_dte_index_mask;
344: }
345:
346: /* get the DTE address to read or write: */
347: dte_address
348: += (((dte_index * TME_AM7990_DTE_SIZE)
349: + dte_offset)
350: & ((dte_index_mask * TME_AM7990_DTE_SIZE)
351: | (TME_AM7990_DTE_SIZE - 1)));
352: assert ((dte_address % sizeof(tme_uint16_t)) == 0);
353:
354: return (dte_address);
355: }
356:
357: /* this does a 16-bit DTE read: */
358: static tme_uint16_t
359: _tme_am7990_read(struct tme_am7990 *am7990,
360: tme_uint32_t callout_flags,
361: tme_uint32_t dte_offset,
362: int *_cancelled)
363: {
364: tme_uint16_t value;
365:
366: /* do the DMA read: */
367: *_cancelled =
368: _tme_am7990_dma(am7990,
369: callout_flags,
370: _tme_am7990_dte_address(am7990,
371: callout_flags,
372: dte_offset),
373: sizeof(value),
374: (tme_uint8_t *) &value);
375:
376: /* possibly byteswap the value read: */
377: assert (am7990->tme_am7990_device.tme_bus_device_router != NULL);
378: if (am7990->tme_am7990_device.tme_bus_device_router
379: != (TME_ENDIAN_NATIVE == TME_ENDIAN_LITTLE
380: ? tme_bus_device_router_16el
381: : tme_bus_device_router_16eb)) {
382: value = tme_bswap_u16(value);
383: }
384:
385: return (value);
386: }
387: #define _tme_am7990_tx_read(am7990, dte_offset, _cancelled) \
388: _tme_am7990_read((am7990), TME_AM7990_CALLOUT_DMA_READ, (dte_offset), (_cancelled))
389: #define _tme_am7990_rx_read(am7990, dte_offset, _cancelled) \
390: _tme_am7990_read((am7990), TME_AM7990_CALLOUT_DMA_READ | TME_AM7990_CALLOUT_RECEIVE, (dte_offset), (_cancelled))
391:
392: /* this does a 16-bit DTE write: */
393: static int
394: _tme_am7990_write(struct tme_am7990 *am7990,
395: tme_uint32_t callout_flags,
396: tme_uint32_t dte_offset,
397: tme_uint16_t value)
398: {
399:
400: /* possibly byteswap the value to write: */
401: assert (am7990->tme_am7990_device.tme_bus_device_router != NULL);
402: if (am7990->tme_am7990_device.tme_bus_device_router
403: != (TME_ENDIAN_NATIVE == TME_ENDIAN_LITTLE
404: ? tme_bus_device_router_16el
405: : tme_bus_device_router_16eb)) {
406: value = tme_bswap_u16(value);
407: }
408:
409: /* do the DMA write: */
410: return (_tme_am7990_dma(am7990,
411: callout_flags,
412: _tme_am7990_dte_address(am7990,
413: callout_flags,
414: dte_offset),
415: sizeof(value),
416: (tme_uint8_t *) &value));
417: }
418: #define _tme_am7990_tx_write(am7990, dte_offset, value) \
419: _tme_am7990_write((am7990), TME_AM7990_CALLOUT_DMA_WRITE, (dte_offset), (value))
420: #define _tme_am7990_rx_write(am7990, dte_offset, value) \
421: _tme_am7990_write((am7990), TME_AM7990_CALLOUT_DMA_WRITE | TME_AM7990_CALLOUT_RECEIVE, (dte_offset), (value))
422:
423: /* this initializes the am7990: */
424: static void
425: _tme_am7990_init(struct tme_am7990 *am7990)
426: {
427: tme_uint32_t iadr;
428: int cancelled;
429: unsigned int init_i;
430: tme_uint16_t csr0;
431: tme_uint32_t drp;
432:
433: /* DMA in the initialization block: */
434: iadr = am7990->tme_am7990_csrs[2];
435: iadr = (iadr << 16) + am7990->tme_am7990_csrs[1];
436: cancelled
437: = _tme_am7990_dma(am7990,
438: TME_AM7990_CALLOUT_DMA_READ,
439: iadr,
440: sizeof(am7990->tme_am7990_init),
441: (tme_uint8_t *) am7990->tme_am7990_init);
442: if (cancelled) {
443: return;
444: }
445:
446: /* possibly byteswap the 16-bit words of the initialization block: */
447: assert (am7990->tme_am7990_device.tme_bus_device_router != NULL);
448: if (am7990->tme_am7990_device.tme_bus_device_router
449: != (TME_ENDIAN_NATIVE == TME_ENDIAN_LITTLE
450: ? tme_bus_device_router_16el
451: : tme_bus_device_router_16eb)) {
452: for (init_i = 0; init_i < TME_ARRAY_ELS(am7990->tme_am7990_init); init_i++) {
453: am7990->tme_am7990_init[init_i] = tme_bswap_u16(am7990->tme_am7990_init[init_i]);
454: }
455: }
456:
457: /* the least significant byte of PADR is actually the "first" byte
458: of the Ethernet address as is is normally seen, but otherwise the
459: 16-bit words of PADR are in the correct order. so we only need
460: to swap those words into little-endian order: */
461: (&am7990->tme_am7990_padr)[0] = tme_htole_u16((&am7990->tme_am7990_padr)[0]);
462: (&am7990->tme_am7990_padr)[1] = tme_htole_u16((&am7990->tme_am7990_padr)[1]);
463: (&am7990->tme_am7990_padr)[2] = tme_htole_u16((&am7990->tme_am7990_padr)[2]);
464:
465: tme_log(&am7990->tme_am7990_element->tme_element_log_handle,
466: 100, TME_OK,
467: (&am7990->tme_am7990_element->tme_element_log_handle,
468: "init CSR0 0x%04x IADR 0x%08x MODE 0x%04x",
469: (unsigned int) am7990->tme_am7990_csr0,
470: iadr,
471: (unsigned int) am7990->tme_am7990_mode));
472:
473: /* get CSR0: */
474: csr0 = am7990->tme_am7990_csr0;
475:
476: /* set IDON: */
477: csr0 |= TME_AM7990_CSR0_IDON;
478:
479: /* "RXON is cleared when IDON is set from setting the INIT bit and
480: DRX = 1 in the MODE register" */
481: if (am7990->tme_am7990_mode & TME_AM7990_MODE_DRX) {
482: csr0 &= ~TME_AM7990_CSR0_RXON;
483: }
484:
485: /* "TXON is cleared when IDON is set and DTX = 1 in the MODE
486: register" */
487: if (am7990->tme_am7990_mode & TME_AM7990_MODE_DTX) {
488: csr0 &= ~TME_AM7990_CSR0_TXON;
489: }
490:
491: /* clear STOP: */
492: csr0 &= ~TME_AM7990_CSR0_STOP;
493:
494: /* update CSR0: */
495: am7990->tme_am7990_csr0 = csr0;
496:
497: /* call out an Ethernet configuration update: */
498: am7990->tme_am7990_callout_flags |= TME_AM7990_CALLOUT_CONFIG;
499:
500: /* if we're not in internal loopback mode, and the Ethernet
501: connection is readable, call out an Ethernet receive: */
502: if (!(am7990->tme_am7990_mode & TME_AM7990_MODE_INTL)
503: && (am7990->tme_am7990_ether_ctrl_in & TME_ETHERNET_CTRL_OK_READ)) {
504: am7990->tme_am7990_callout_flags |= TME_AM7990_CALLOUT_RECEIVE;
505: }
506:
507: /* initialize for the receive ring: */
508: drp = am7990->tme_am7990_rlen_rdra;
509: drp = (drp << 16) | am7990->tme_am7990_rdra;
510: am7990->tme_am7990_receive_dte_address = drp & TME_AM7990_DRP_XDRA;
511: am7990->tme_am7990_receive_dte_index_mask = (1 << TME_FIELD_MASK_EXTRACTU(drp, TME_AM7990_DRP_XLEN_LOG2)) - 1;
512: am7990->tme_am7990_receive_dte_index = 0;
513:
514: /* initialize for the transmit ring: */
515: drp = am7990->tme_am7990_tlen_tdra;
516: drp = (drp << 16) | am7990->tme_am7990_tdra;
517: am7990->tme_am7990_transmit_dte_address = drp & TME_AM7990_DRP_XDRA;
518: am7990->tme_am7990_transmit_dte_index_mask = (1 << TME_FIELD_MASK_EXTRACTU(drp, TME_AM7990_DRP_XLEN_LOG2)) - 1;
519: am7990->tme_am7990_transmit_dte_index = 0;
520: am7990->tme_am7990_transmit_dte_tmd1 = 0;
521: }
522:
523: /* this starts the am7990: */
524: static void
525: _tme_am7990_start(struct tme_am7990 *am7990)
526: {
527: tme_uint16_t csr0;
528:
529: tme_log(&am7990->tme_am7990_element->tme_element_log_handle,
530: 100, TME_OK,
531: (&am7990->tme_am7990_element->tme_element_log_handle,
532: "start CSR0 0x%04x MODE 0x%04x",
533: (unsigned int) am7990->tme_am7990_csr0,
534: (unsigned int) am7990->tme_am7990_mode));
535:
536: /* get CSR0: */
537: csr0 = am7990->tme_am7990_csr0;
538:
539: /* "RXON is set when STRT is set if DRX = 0 in the MODE register" */
540: if (!(am7990->tme_am7990_mode & TME_AM7990_MODE_DRX)) {
541: csr0 |= TME_AM7990_CSR0_RXON;
542: }
543:
544: /* "TXON is set when STRT is set if DTX = 0 in the MODE register" */
545: if (!(am7990->tme_am7990_mode & TME_AM7990_MODE_DTX)) {
546: csr0 |= TME_AM7990_CSR0_TXON;
547: }
548:
549: /* clear STOP: */
550: csr0 &= ~TME_AM7990_CSR0_STOP;
551:
552: /* update CSR0: */
553: am7990->tme_am7990_csr0 = csr0;
554: }
555:
556: /* this scans for a start-of-packet transmit buffer owned by us: */
557: static void
558: _tme_am7990_transmit_scan(struct tme_am7990 *am7990)
559: {
560: tme_uint16_t transmit_dte_tmd1;
561: int cancelled;
562:
563: /* if the transmitter is not on, return now: */
564: if (!(am7990->tme_am7990_csr0 & TME_AM7990_CSR0_TXON)) {
565: return;
566: }
567:
568: /* clear TDMD: */
569: am7990->tme_am7990_csr0 &= ~TME_AM7990_CSR0_TDMD;
570:
571: /* loop forever: */
572: for (;;) {
573:
574: /* if we own the current transmit buffer: */
575: transmit_dte_tmd1 = am7990->tme_am7990_transmit_dte_tmd1;
576: if (transmit_dte_tmd1 & TME_AM7990_XMD1_OWN) {
577:
578: /* if the current transmit buffer is also for the start of a
579: packet, return now: */
580: if (transmit_dte_tmd1 & TME_AM7990_XMD1_STP) {
581: return;
582: }
583:
584: /* write TMD1 to clear OWN: */
585: cancelled
586: = _tme_am7990_tx_write(am7990,
587: TME_AM7990_DTE_OFFSET_XMD1,
588: (transmit_dte_tmd1
589: & ~TME_AM7990_XMD1_OWN));
590: if (cancelled) {
591: return;
592: }
593:
594: /* advance to the next transmit buffer and request a transmit
595: interrupt: */
596: am7990->tme_am7990_transmit_dte_index
597: = ((am7990->tme_am7990_transmit_dte_index
598: + 1)
599: & am7990->tme_am7990_transmit_dte_index_mask);
600: am7990->tme_am7990_transmit_dte_tmd1 = 0;
601: am7990->tme_am7990_csr0 |= TME_AM7990_CSR0_TINT;
602: }
603:
604: /* otherwise, we must not own the current transmit buffer: */
605: else {
606:
607: /* read TMD1: */
608: transmit_dte_tmd1
609: = _tme_am7990_tx_read(am7990,
610: TME_AM7990_DTE_OFFSET_XMD1,
611: &cancelled);
612: if (cancelled) {
613: return;
614: }
615: am7990->tme_am7990_transmit_dte_tmd1 = transmit_dte_tmd1;
616:
617: /* if we still don't own the current transmit buffer, return now: */
618: if (!(transmit_dte_tmd1 & TME_AM7990_XMD1_OWN)) {
619: return;
620: }
621: }
622: }
623: /* NOTREACHED */
624: }
625:
626: /* this receives a frame: */
627: static void
628: _tme_am7990_receive(struct tme_am7990 *am7990)
629: {
630: struct tme_ethernet_frame_chunk frame_chunk_buffer;
631: struct tme_ethernet_connection *conn_eth;
632: tme_ethernet_fid_t frame_id;
633: int resid;
634: tme_uint8_t *frame_chunk_bytes;
635: unsigned int frame_chunk_bytes_count;
636: struct tme_ethernet_header *ether_header;
637: tme_uint32_t crc32;
638: tme_uint16_t receive_dte_rmd0;
639: tme_uint16_t receive_dte_rmd1;
640: tme_uint16_t receive_dte_rmd2;
641: tme_uint16_t receive_dte_rmd1_next;
642: tme_uint32_t receive_buffer_address;
643: tme_uint16_t receive_buffer_count;
644: int cancelled;
645: int stop;
646:
647: /* assume that there is no loopback packet: */
648: resid = 0;
649:
650: /* if we're in loopback mode: */
651: if (am7990->tme_am7990_mode & TME_AM7990_MODE_LOOP) {
652:
653: /* get and clear any loopback packet length: */
654: resid = am7990->tme_am7990_receive_buffer_length;
655: am7990->tme_am7990_receive_buffer_length = 0;
656:
657: /* "The C-LANCE will not receive any packets externally when it is
658: in internal loopback mode." */
659: if (resid == 0
660: && (am7990->tme_am7990_mode & TME_AM7990_MODE_INTL)) {
661: return;
662: }
663: }
664:
665: /* if there isn't any loopback packet, and the Ethernet connection
666: is not readable, return now: */
667: if (resid == 0
668: && !(am7990->tme_am7990_ether_ctrl_in & TME_ETHERNET_CTRL_OK_READ)) {
669: return;
670: }
671:
672: /* receive the packet into the internal buffer: */
673: frame_chunk_buffer.tme_ethernet_frame_chunk_next = NULL;
674: frame_chunk_buffer.tme_ethernet_frame_chunk_bytes_count = sizeof(am7990->tme_am7990_receive_buffer);
675: frame_chunk_buffer.tme_ethernet_frame_chunk_bytes = &am7990->tme_am7990_receive_buffer[0];
676:
677: /* if there isn't any loopback packet: */
678: if (resid == 0) {
679:
680: /* assume that the Ethernet read will fail: */
681: am7990->tme_am7990_ether_ctrl_in &= ~TME_ETHERNET_CTRL_OK_READ;
682:
683: /* get the Ethernet connection: */
684: conn_eth = am7990->tme_am7990_eth_connection;
685:
686: /* unlock the mutex: */
687: tme_mutex_unlock(&am7990->tme_am7990_mutex);
688:
689: /* do the callout: */
690: resid = (conn_eth == NULL
691: ? 0
692: : ((*conn_eth->tme_ethernet_connection_read)
693: (conn_eth,
694: &frame_id,
695: &frame_chunk_buffer,
696: TME_ETHERNET_READ_NEXT)));
697:
698: /* lock the mutex: */
699: tme_mutex_lock(&am7990->tme_am7990_mutex);
700:
701: /* if the read failed, return now: */
702: if (resid <= 0) {
703: return;
704: }
705:
706: /* assume that the Ethernet connection is still readable: */
707: am7990->tme_am7990_ether_ctrl_in |= TME_ETHERNET_CTRL_OK_READ;
708:
709: /* append four dummy CRC bytes: */
710: resid = TME_MIN((unsigned int) resid + TME_ETHERNET_CRC_SIZE,
711: sizeof(am7990->tme_am7990_receive_buffer));
712: }
713:
714: /* assume that we should callout another receive after this one: */
715: am7990->tme_am7990_callout_flags |= TME_AM7990_CALLOUT_RECEIVE;
716:
717: /* if the receiver is not on, return now: */
718: if (!(am7990->tme_am7990_csr0 & TME_AM7990_CSR0_RXON)) {
719: return;
720: }
721:
722: /* if this packet is not addressed to our physical address: */
723: ether_header = (struct tme_ethernet_header *) &am7990->tme_am7990_receive_buffer[0];
724: if (memcmp(ðer_header->tme_ethernet_header_dst[0],
725: &am7990->tme_am7990_padr,
726: TME_ETHERNET_ADDR_SIZE) != 0) {
727:
728: /* if this is not a multicast packet, return now: */
729: if (!(ether_header->tme_ethernet_header_dst[0] & 0x1)) {
730: return;
731: }
732:
733: /* if this is not a broadcast packet: */
734: if (memcmp(ðer_header->tme_ethernet_header_dst[0],
735: &tme_ethernet_addr_broadcast[0],
736: TME_ETHERNET_ADDR_SIZE) != 0) {
737:
738: /* calculate the CRC of the destination address: */
739: crc32 = tme_ethernet_crc32_el(ðer_header->tme_ethernet_header_dst[0],
740: TME_ETHERNET_ADDR_SIZE);
741:
742: /* the am7990 only uses the most significant six bits of the CRC: */
743: crc32 >>= (32 - 6);
744:
745: /* if the bit in the logical address filter is clear, return now: */
746: if (((&am7990->tme_am7990_ladrf)[crc32 / (8 * sizeof(am7990->tme_am7990_ladrf))]
747: & TME_BIT(crc32 % (8 * sizeof(am7990->tme_am7990_ladrf)))) == 0) {
748: return;
749: }
750: }
751: }
752:
753: /* read RMD1: */
754: receive_dte_rmd1
755: = _tme_am7990_rx_read(am7990,
756: TME_AM7990_DTE_OFFSET_XMD1,
757: &cancelled);
758: if (cancelled) {
759: return;
760: }
761:
762: /* if we don't own this receive buffer: */
763: if (!(receive_dte_rmd1 & TME_AM7990_XMD1_OWN)) {
764:
765: if ((am7990->tme_am7990_csr0 & TME_AM7990_CSR0_MISS) == 0) {
766: tme_log(&am7990->tme_am7990_element->tme_element_log_handle,
767: 500, TME_OK,
768: (&am7990->tme_am7990_element->tme_element_log_handle,
769: "receive MISS"));
770: }
771:
772: /* set MISS in CSR0 and return now: */
773: am7990->tme_am7990_csr0 |= TME_AM7990_CSR0_MISS;
774: return;
775: }
776:
777: /* set STP in RMD1: */
778: receive_dte_rmd1 |= TME_AM7990_XMD1_STP;
779:
780: /* while we have bytes to write: */
781: frame_chunk_bytes = &am7990->tme_am7990_receive_buffer[0];
782: frame_chunk_bytes_count = resid;
783: do {
784:
785: /* read RMD0 and RMD2: */
786: receive_dte_rmd0
787: = _tme_am7990_rx_read(am7990,
788: TME_AM7990_DTE_OFFSET_XMD0,
789: &cancelled);
790: if (cancelled) {
791: break;
792: }
793: receive_dte_rmd2
794: = _tme_am7990_rx_read(am7990,
795: TME_AM7990_DTE_OFFSET_XMD2,
796: &cancelled);
797: if (cancelled) {
798: break;
799: }
800:
801: /* get the receive buffer address and count: */
802: receive_buffer_address = (receive_dte_rmd1 & TME_AM7990_XMD1_HADR);
803: receive_buffer_address = (receive_buffer_address << 16) + receive_dte_rmd0;
804: receive_buffer_count = (0 - receive_dte_rmd2) & TME_AM7990_XMD2_BCNT;
805:
806: /* get the count of bytes to write in this iteration: */
807: receive_buffer_count = TME_MIN(frame_chunk_bytes_count, receive_buffer_count);
808:
809: /* do the write: */
810: cancelled
811: = _tme_am7990_dma(am7990,
812: (TME_AM7990_CALLOUT_DMA_WRITE
813: | TME_AM7990_CALLOUT_RECEIVE),
814: receive_buffer_address,
815: receive_buffer_count,
816: frame_chunk_bytes);
817: if (cancelled) {
818: break;
819: }
820:
821: /* advance: */
822: frame_chunk_bytes += receive_buffer_count;
823: frame_chunk_bytes_count -= receive_buffer_count;
824:
825: /* if this is the last buffer for this packet: */
826: if (frame_chunk_bytes_count == 0) {
827:
828: /* write RMD3 to set MCNT: */
829: cancelled
830: = _tme_am7990_rx_write(am7990,
831: TME_AM7990_DTE_OFFSET_XMD3,
832: (unsigned int) resid);
833: if (cancelled) {
834: break;
835: }
836:
837: /* set ENP in RMD1: */
838: receive_dte_rmd1 |= TME_AM7990_XMD1_ENP;
839:
840: /* we don't read RMD1 for the next receive buffer: */
841: receive_dte_rmd1_next = 0;
842:
843: /* stop now: */
844: stop = TRUE;
845: }
846:
847: /* otherwise, this is not the last buffer for this packet: */
848: else {
849:
850: /* read RMD1 for the next transmit buffer: */
851: receive_dte_rmd1_next
852: = _tme_am7990_rx_read(am7990,
853: (TME_AM7990_DTE_SIZE
854: + TME_AM7990_DTE_OFFSET_XMD1),
855: &cancelled);
856: if (cancelled) {
857: break;
858: }
859:
860: /* if we don't own the next buffer: */
861: stop = !(receive_dte_rmd1_next & TME_AM7990_XMD1_OWN);
862: if (stop) {
863:
864: tme_log(&am7990->tme_am7990_element->tme_element_log_handle,
865: 500, TME_OK,
866: (&am7990->tme_am7990_element->tme_element_log_handle,
867: "receive BUFF"));
868:
869: /* set BUFF and ERR in RMD1: */
870: receive_dte_rmd1 |= TME_AM7990_RMD1_BUFF | TME_AM7990_XMD1_ERR;
871: }
872: }
873:
874: /* write RMD1 to clear OWN: */
875: cancelled
876: = _tme_am7990_rx_write(am7990,
877: TME_AM7990_DTE_OFFSET_XMD1,
878: (receive_dte_rmd1
879: & ~TME_AM7990_XMD1_OWN));
880: if (cancelled) {
881: break;
882: }
883:
884: /* advance to the next receive buffer: */
885: am7990->tme_am7990_receive_dte_index
886: = ((am7990->tme_am7990_receive_dte_index
887: + 1)
888: & am7990->tme_am7990_receive_dte_index_mask);
889: receive_dte_rmd1 = receive_dte_rmd1_next;
890: } while (!stop);
891:
892: /* if nothing was cancelled: */
893: if (!cancelled) {
894:
895: /* generate a receive interrupt: */
896: am7990->tme_am7990_csr0 |= TME_AM7990_CSR0_RINT;
897: }
898: }
899:
900: /* the am7990 callout function. it must be called with the mutex locked: */
901: static void
902: _tme_am7990_callout(struct tme_am7990 *am7990)
903: {
904: struct tme_ethernet_connection *conn_eth;
905: struct tme_ethernet_connection conn_eth_buffer;
906: struct tme_bus_connection *conn_bus;
907: unsigned int ctrl;
908: struct tme_ethernet_config config;
909: const tme_uint8_t *config_addrs[2];
910: int again;
911: int rc;
912: int int_asserted;
913:
914: /* if this function is already running in another thread, simply
915: return now. the other thread will do our work: */
916: if (am7990->tme_am7990_callout_flags & TME_AM7990_CALLOUTS_RUNNING) {
917: return;
918: }
919:
920: /* callouts are now running: */
921: am7990->tme_am7990_callout_flags |= TME_AM7990_CALLOUTS_RUNNING;
922:
923: /* loop while we have work to do: */
924: do {
925: again = FALSE;
926:
927: /* if we need to do a transmit scan: */
928: if (am7990->tme_am7990_callout_flags & TME_AM7990_CALLOUT_TRANSMIT_SCAN) {
929: again = TRUE;
930:
931: /* clear the callout flag: */
932: am7990->tme_am7990_callout_flags &= ~TME_AM7990_CALLOUT_TRANSMIT_SCAN;
933:
934: /* do the transmit scan: */
935: _tme_am7990_transmit_scan(am7990);
936: }
937:
938: /* form our ctrl: */
939: ctrl = 0;
940:
941: /* if the transmitter is on and the next transmit buffer is for
942: the start of a packet and is owned by us, we are readable: */
943: if ((am7990->tme_am7990_csr0
944: & TME_AM7990_CSR0_TXON)
945: && ((am7990->tme_am7990_transmit_dte_tmd1
946: & (TME_AM7990_XMD1_OWN
947: | TME_AM7990_XMD1_STP))
948: == (TME_AM7990_XMD1_OWN
949: | TME_AM7990_XMD1_STP))) {
950: ctrl |= TME_ETHERNET_CTRL_OK_READ;
951: }
952:
953: /* if we are readable and in loopback mode: */
954: if ((ctrl & TME_ETHERNET_CTRL_OK_READ)
955: && (am7990->tme_am7990_mode & TME_AM7990_MODE_LOOP)) {
956: again = TRUE;
957:
958: /* unlock the mutex: */
959: tme_mutex_unlock(&am7990->tme_am7990_mutex);
960:
961: /* call out a loopback transmit: */
962: conn_eth_buffer.tme_ethernet_connection.tme_connection_element = am7990->tme_am7990_element;
963: _tme_am7990_transmit(&conn_eth_buffer,
964: NULL,
965: NULL,
966: 0);
967:
968: /* lock the mutex: */
969: tme_mutex_lock(&am7990->tme_am7990_mutex);
970:
971: /* don't call out any new control information for now: */
972: ctrl = am7990->tme_am7990_ether_ctrl_out;
973: }
974:
975: /* if we need to call out new control information: */
976: if (am7990->tme_am7990_ether_ctrl_out != ctrl) {
977: again = TRUE;
978:
979: /* note the new state of the called-out control information: */
980: am7990->tme_am7990_ether_ctrl_out = ctrl;
981:
982: /* get this card's connection: */
983: conn_eth = am7990->tme_am7990_eth_connection;
984:
985: /* unlock the mutex: */
986: tme_mutex_unlock(&am7990->tme_am7990_mutex);
987:
988: /* do the callout: */
989: rc = (conn_eth != NULL
990: ? ((*conn_eth->tme_ethernet_connection_ctrl)
991: (conn_eth,
992: ctrl))
993: : TME_OK);
994: assert (rc == TME_OK);
995:
996: /* lock the mutex: */
997: tme_mutex_lock(&am7990->tme_am7990_mutex);
998: }
999:
1000: /* if we need to call out new config information: */
1001: if (am7990->tme_am7990_callout_flags & TME_AM7990_CALLOUT_CONFIG) {
1002: again = TRUE;
1003:
1004: /* clear the callout flag: */
1005: am7990->tme_am7990_callout_flags &= ~TME_AM7990_CALLOUT_CONFIG;
1006:
1007: /* form the new config: */
1008: memset(&config, 0, sizeof(config));
1009:
1010: /* if we're in promiscuous mode or any bits the logical address
1011: filter are nonzero: */
1012: if ((am7990->tme_am7990_mode & TME_AM7990_MODE_PROM)
1013: || (&am7990->tme_am7990_ladrf)[0]
1014: || (&am7990->tme_am7990_ladrf)[1]
1015: || (&am7990->tme_am7990_ladrf)[2]
1016: || (&am7990->tme_am7990_ladrf)[3]) {
1017:
1018: /* we have to be in promiscuous mode: */
1019: config.tme_ethernet_config_flags |= TME_ETHERNET_CONFIG_PROMISC;
1020: }
1021:
1022: /* otherwise, we only need to see packets addressed to our
1023: physical address, and broadcast packets: */
1024: else {
1025:
1026: /* our Ethernet addresses: */
1027: config.tme_ethernet_config_addr_count = 2;
1028: config_addrs[0] = (tme_uint8_t *) &am7990->tme_am7990_padr;
1029: config_addrs[1] = &tme_ethernet_addr_broadcast[0];
1030: config.tme_ethernet_config_addrs = config_addrs;
1031: }
1032:
1033: /* get this card's connection: */
1034: conn_eth = am7990->tme_am7990_eth_connection;
1035:
1036: /* unlock the mutex: */
1037: tme_mutex_unlock(&am7990->tme_am7990_mutex);
1038:
1039: /* do the callout: */
1040: rc = (conn_eth == NULL
1041: ? TME_OK
1042: : ((*conn_eth->tme_ethernet_connection_config)
1043: (conn_eth,
1044: &config)));
1045: assert (rc == TME_OK);
1046:
1047: /* lock the mutex: */
1048: tme_mutex_lock(&am7990->tme_am7990_mutex);
1049: }
1050:
1051: /* if we need to receive a frame: */
1052: if (am7990->tme_am7990_callout_flags & TME_AM7990_CALLOUT_RECEIVE) {
1053: again = TRUE;
1054:
1055: /* clear the callout flag: */
1056: am7990->tme_am7990_callout_flags &= ~TME_AM7990_CALLOUT_RECEIVE;
1057:
1058: /* do the receive: */
1059: _tme_am7990_receive(am7990);
1060: }
1061:
1062: /* if we need to call out an interrupt: */
1063: if (am7990->tme_am7990_csr0
1064: & (TME_AM7990_CSR0_TINT
1065: | TME_AM7990_CSR0_BABL
1066: | TME_AM7990_CSR0_MISS
1067: | TME_AM7990_CSR0_MERR
1068: | TME_AM7990_CSR0_RINT
1069: | TME_AM7990_CSR0_TINT
1070: | TME_AM7990_CSR0_IDON)) {
1071: am7990->tme_am7990_csr0 |= TME_AM7990_CSR0_INTR;
1072: }
1073: else {
1074: am7990->tme_am7990_csr0 &= ~TME_AM7990_CSR0_INTR;
1075: }
1076: int_asserted
1077: = ((am7990->tme_am7990_csr0
1078: & (TME_AM7990_CSR0_INTR
1079: | TME_AM7990_CSR0_INEA))
1080: == (TME_AM7990_CSR0_INTR
1081: | TME_AM7990_CSR0_INEA));
1082: if (!!am7990->tme_am7990_int_asserted != int_asserted) {
1083: again = TRUE;
1084:
1085: /* note the new state of the interrupt signal: */
1086: am7990->tme_am7990_int_asserted = int_asserted;
1087:
1088: /* get our bus connection: */
1089: conn_bus = tme_memory_atomic_pointer_read(struct tme_bus_connection *,
1090: am7990->tme_am7990_device.tme_bus_device_connection,
1091: &am7990->tme_am7990_device.tme_bus_device_connection_rwlock);
1092:
1093: /* unlock our mutex: */
1094: tme_mutex_unlock(&am7990->tme_am7990_mutex);
1095:
1096: /* call out the bus interrupt signal edge: */
1097: rc = (*conn_bus->tme_bus_signal)
1098: (conn_bus,
1099: TME_BUS_SIGNAL_INT_UNSPEC
1100: | (int_asserted
1101: ? TME_BUS_SIGNAL_LEVEL_ASSERTED
1102: : TME_BUS_SIGNAL_LEVEL_NEGATED));
1103: assert (rc == TME_OK);
1104:
1105: /* lock our mutex: */
1106: tme_mutex_lock(&am7990->tme_am7990_mutex);
1107: }
1108: } while (again);
1109:
1110: /* clear that callouts are running: */
1111: am7990->tme_am7990_callout_flags &= ~TME_AM7990_CALLOUTS_RUNNING;
1112: }
1113:
1114: /* the am7990 bus signal handler: */
1115: static int
1116: _tme_am7990_signal(void *_am7990,
1117: unsigned int signal)
1118: {
1119: struct tme_am7990 *am7990;
1120: unsigned int level;
1121:
1122: /* recover our data structure: */
1123: am7990 = (struct tme_am7990 *) _am7990;
1124:
1125: /* lock the mutex: */
1126: tme_mutex_lock(&am7990->tme_am7990_mutex);
1127:
1128: /* take out the signal level: */
1129: level = signal & TME_BUS_SIGNAL_LEVEL_MASK;
1130: signal = TME_BUS_SIGNAL_WHICH(signal);
1131:
1132: /* dispatch on the generic bus signals: */
1133: switch (signal) {
1134: case TME_BUS_SIGNAL_RESET:
1135: if (level == TME_BUS_SIGNAL_LEVEL_ASSERTED) {
1136: _tme_am7990_reset(am7990);
1137: }
1138: break;
1139: default:
1140: signal = TME_BUS_SIGNAL_IGNORE;
1141: break;
1142: }
1143:
1144: /* if we didn't ignore this bus signal: */
1145: if (signal != TME_BUS_SIGNAL_IGNORE) {
1146:
1147: /* make any new callouts: */
1148: _tme_am7990_callout(am7990);
1149: }
1150:
1151: /* unlock the mutex: */
1152: tme_mutex_unlock(&am7990->tme_am7990_mutex);
1153:
1154: /* no faults: */
1155: return (TME_OK);
1156: }
1157:
1158: /* this is called when a device changes its configuration: */
1159: static int
1160: _tme_am7990_config(struct tme_ethernet_connection *conn_eth,
1161: struct tme_ethernet_config *config)
1162: {
1163: /* we don't care when other devices on the Ethernet
1164: reconfigure themselves: */
1165: return (TME_OK);
1166: }
1167:
1168: /* this is called when control lines change: */
1169: static int
1170: _tme_am7990_ctrl(struct tme_ethernet_connection *conn_eth,
1171: unsigned int ctrl)
1172: {
1173: struct tme_am7990 *am7990;
1174:
1175: /* recover our data structures: */
1176: am7990 = conn_eth->tme_ethernet_connection.tme_connection_element->tme_element_private;
1177:
1178: /* lock the mutex: */
1179: tme_mutex_lock(&am7990->tme_am7990_mutex);
1180:
1181: /* note the new state of the controls: */
1182: am7990->tme_am7990_ether_ctrl_in = ctrl;
1183:
1184: /* if this connection is readable, call out a read: */
1185: if (ctrl & TME_ETHERNET_CTRL_OK_READ) {
1186: am7990->tme_am7990_callout_flags |= TME_AM7990_CALLOUT_RECEIVE;
1187: }
1188:
1189: /* make any new callouts: */
1190: _tme_am7990_callout(am7990);
1191:
1192: /* unlock the mutex: */
1193: tme_mutex_unlock(&am7990->tme_am7990_mutex);
1194:
1195: return (TME_OK);
1196: }
1197:
1198: /* this transmits a frame: */
1199: static int
1200: _tme_am7990_transmit(struct tme_ethernet_connection *conn_eth,
1201: tme_ethernet_fid_t *_frame_id,
1202: struct tme_ethernet_frame_chunk *frame_chunk,
1203: unsigned int flags)
1204: {
1205: struct tme_am7990 *am7990;
1206: struct tme_ethernet_frame_chunk frame_chunk_buffer;
1207: tme_uint8_t frame_chunk_bytes_buffer[32];
1208: tme_uint8_t *frame_chunk_bytes;
1209: unsigned int frame_chunk_bytes_count;
1210: tme_uint16_t transmit_dte_tmd0;
1211: tme_uint16_t transmit_dte_tmd1;
1212: tme_uint16_t transmit_dte_tmd2;
1213: tme_uint16_t transmit_dte_tmd1_next;
1214: tme_uint32_t transmit_buffer_address;
1215: tme_uint16_t transmit_buffer_count;
1216: unsigned int count;
1217: int rc;
1218: int add_fcs;
1219: int stop;
1220: int cancelled;
1221:
1222: /* recover our data structures: */
1223: am7990 = conn_eth->tme_ethernet_connection.tme_connection_element->tme_element_private;
1224:
1225: /* lock our mutex: */
1226: tme_mutex_lock(&am7990->tme_am7990_mutex);
1227:
1228: /* assume that we will have no packet to transmit: */
1229: rc = 0;
1230:
1231: /* if the transmitter is on, and the current transmit buffer is for
1232: the start of a packet and is owned by us: */
1233: if ((am7990->tme_am7990_csr0
1234: & TME_AM7990_CSR0_TXON)
1235: && ((am7990->tme_am7990_transmit_dte_tmd1
1236: & (TME_AM7990_XMD1_OWN
1237: | TME_AM7990_XMD1_STP))
1238: == (TME_AM7990_XMD1_OWN
1239: | TME_AM7990_XMD1_STP))) {
1240:
1241: /* see if we will add the FCS to this transmitted packet.
1242: "ADD_FCS is only valid when STP=1." */
1243: add_fcs =
1244: (!(am7990->tme_am7990_mode
1245: & TME_AM7990_MODE_DTCR)
1246: || (am7990->tme_am7990_transmit_dte_tmd1
1247: & TME_AM7990_TMD1_ADD_FCS));
1248:
1249: /* if we're in loopback mode, transmit this packet directly into
1250: the receive buffer: */
1251: if (am7990->tme_am7990_mode & TME_AM7990_MODE_LOOP) {
1252: frame_chunk_buffer.tme_ethernet_frame_chunk_bytes = &am7990->tme_am7990_receive_buffer[0];
1253: frame_chunk_buffer.tme_ethernet_frame_chunk_bytes_count = sizeof(am7990->tme_am7990_receive_buffer);
1254: frame_chunk_buffer.tme_ethernet_frame_chunk_next = NULL;
1255: frame_chunk = &frame_chunk_buffer;
1256: }
1257:
1258: do {
1259:
1260: /* recover the previously read TMD1: */
1261: transmit_dte_tmd1 = am7990->tme_am7990_transmit_dte_tmd1;
1262:
1263: /* read TMD0 and TMD2: */
1264: transmit_dte_tmd0
1265: = _tme_am7990_tx_read(am7990,
1266: TME_AM7990_DTE_OFFSET_XMD0,
1267: &cancelled);
1268: if (cancelled) {
1269: break;
1270: }
1271: transmit_dte_tmd2
1272: = _tme_am7990_tx_read(am7990,
1273: TME_AM7990_DTE_OFFSET_XMD2,
1274: &cancelled);
1275: if (cancelled) {
1276: break;
1277: }
1278:
1279: /* get the transmit buffer address and count: */
1280: transmit_buffer_address = (transmit_dte_tmd1 & TME_AM7990_XMD1_HADR);
1281: transmit_buffer_address = (transmit_buffer_address << 16) + transmit_dte_tmd0;
1282: transmit_buffer_count = (0 - transmit_dte_tmd2) & TME_AM7990_XMD2_BCNT;
1283:
1284: /* read this transmit buffer into the frame chunks: */
1285: frame_chunk_bytes = NULL;
1286: frame_chunk_bytes_count = 0;
1287: for (; transmit_buffer_count > 0; ) {
1288:
1289: /* if we have exhausted the previous chunk: */
1290: if (frame_chunk_bytes_count == 0) {
1291:
1292: /* advance to the next chunk: */
1293: if (frame_chunk == NULL) {
1294: frame_chunk_bytes = &frame_chunk_bytes_buffer[0];
1295: frame_chunk_bytes_count = sizeof(frame_chunk_bytes_buffer);
1296: }
1297: else {
1298: frame_chunk_bytes = frame_chunk->tme_ethernet_frame_chunk_bytes;
1299: frame_chunk_bytes_count = frame_chunk->tme_ethernet_frame_chunk_bytes_count;
1300: frame_chunk = frame_chunk->tme_ethernet_frame_chunk_next;
1301: continue;
1302: }
1303: }
1304:
1305: /* get the count of bytes to read in this iteration: */
1306: count = TME_MIN(frame_chunk_bytes_count, transmit_buffer_count);
1307:
1308: /* do the read: */
1309: cancelled
1310: = _tme_am7990_dma(am7990,
1311: TME_AM7990_CALLOUT_DMA_READ,
1312: transmit_buffer_address,
1313: count,
1314: frame_chunk_bytes);
1315: if (cancelled) {
1316: break;
1317: }
1318:
1319: /* advance: */
1320: frame_chunk_bytes += count;
1321: frame_chunk_bytes_count -= count;
1322: transmit_buffer_address += count;
1323: transmit_buffer_count -= count;
1324: rc += count;
1325: }
1326: if (cancelled) {
1327: break;
1328: }
1329:
1330: /* if this is the last transmit buffer in the packet: */
1331: if (transmit_dte_tmd1 & TME_AM7990_XMD1_ENP) {
1332:
1333: /* we can't suppress CRC generation: */
1334: if (!add_fcs) {
1335: abort();
1336: }
1337:
1338: /* clear TMD1 for the next transmit buffer: */
1339: transmit_dte_tmd1_next = 0;
1340:
1341: /* this is the last transmit buffer: */
1342: stop = TRUE;
1343: }
1344:
1345: /* otherwise, this is not the last transmit buffer in the packet: */
1346: else {
1347:
1348: /* read TMD1 for the next transmit buffer: */
1349: transmit_dte_tmd1_next
1350: = _tme_am7990_tx_read(am7990,
1351: (TME_AM7990_DTE_SIZE
1352: + TME_AM7990_DTE_OFFSET_XMD1),
1353: &cancelled);
1354: if (cancelled) {
1355: break;
1356: }
1357:
1358: /* if we don't own the next transmit buffer: */
1359: stop = !(transmit_dte_tmd1_next & TME_AM7990_XMD1_OWN);
1360: if (stop) {
1361:
1362: tme_log(&am7990->tme_am7990_element->tme_element_log_handle,
1363: 500, TME_OK,
1364: (&am7990->tme_am7990_element->tme_element_log_handle,
1365: "transmit BUFF"));
1366:
1367: /* write a TMD3 with BUFF set: */
1368: cancelled
1369: = _tme_am7990_tx_write(am7990,
1370: TME_AM7990_DTE_OFFSET_XMD3,
1371: TME_AM7990_TMD3_BUFF);
1372: if (cancelled) {
1373: break;
1374: }
1375:
1376: /* turn off the transmitter: */
1377: am7990->tme_am7990_csr0 &= ~TME_AM7990_CSR0_TXON;
1378: }
1379: }
1380:
1381: /* write TMD1 to clear OWN: */
1382: cancelled
1383: = _tme_am7990_tx_write(am7990,
1384: TME_AM7990_DTE_OFFSET_XMD1,
1385: (transmit_dte_tmd1
1386: & ~TME_AM7990_XMD1_OWN));
1387: if (cancelled) {
1388: break;
1389: }
1390:
1391: /* advance to the next transmit buffer: */
1392: am7990->tme_am7990_transmit_dte_index
1393: = ((am7990->tme_am7990_transmit_dte_index
1394: + 1)
1395: & am7990->tme_am7990_transmit_dte_index_mask);
1396: am7990->tme_am7990_transmit_dte_tmd1 = transmit_dte_tmd1_next;
1397: } while (!stop);
1398:
1399: /* if nothing was cancelled: */
1400: if (!cancelled) {
1401:
1402: /* generate a transmit interrupt: */
1403: am7990->tme_am7990_csr0 |= TME_AM7990_CSR0_TINT;
1404: }
1405: }
1406:
1407: /* if we're in loopback mode: */
1408: if (am7990->tme_am7990_mode & TME_AM7990_MODE_LOOP) {
1409:
1410: /* if we have a loopback packet: */
1411: if (rc > 0) {
1412:
1413: /* append the CRC bytes: */
1414: if ((rc + sizeof(tme_uint32_t)) > sizeof(am7990->tme_am7990_receive_buffer)) {
1415: abort();
1416: }
1417: rc += sizeof(tme_uint32_t);
1418:
1419: /* set the receive buffer length: */
1420: am7990->tme_am7990_receive_buffer_length = rc;
1421: }
1422:
1423: /* if we have a loopback packet, call out a receive: */
1424: if (am7990->tme_am7990_receive_buffer_length > 0) {
1425: am7990->tme_am7990_callout_flags |= TME_AM7990_CALLOUT_RECEIVE;
1426: }
1427: }
1428:
1429: /* otherwise, if we're not returning a packet: */
1430: else if (rc <= 0) {
1431:
1432: /* we aren't considered readable any more: */
1433: am7990->tme_am7990_ether_ctrl_out &= ~TME_ETHERNET_CTRL_OK_READ;
1434: }
1435:
1436: /* start a scan for the first buffer in the next packet to transmit: */
1437: am7990->tme_am7990_callout_flags |= TME_AM7990_CALLOUT_TRANSMIT_SCAN;
1438:
1439: /* make any new callouts: */
1440: _tme_am7990_callout(am7990);
1441:
1442: /* unlock our mutex: */
1443: tme_mutex_unlock(&am7990->tme_am7990_mutex);
1444:
1445: /* done: */
1446: return (rc);
1447:
1448: /* unused: */
1449: _frame_id = 0;
1450: flags = 0;
1451: }
1452:
1453: /* the am7990 descriptor polling thread: */
1454: static void
1455: _tme_am7990_poll_th(struct tme_am7990 *am7990)
1456: {
1457:
1458: /* lock our mutex: */
1459: tme_mutex_lock(&am7990->tme_am7990_mutex);
1460:
1461: /* loop forever: */
1462: for (;;) {
1463:
1464: /* call out a transmit scan: */
1465: am7990->tme_am7990_callout_flags |= TME_AM7990_CALLOUT_TRANSMIT_SCAN;
1466:
1467: /* make any callouts: */
1468: _tme_am7990_callout(am7990);
1469:
1470: /* unlock our mutex: */
1471: tme_mutex_unlock(&am7990->tme_am7990_mutex);
1472:
1473: /* "[T]he C-LANCE will automatically poll the transmit ring in the
1474: memory once it has started .. every 1.6ms" */
1475: tme_thread_sleep_yield(0, 16000);
1476:
1477: /* lock our mutex: */
1478: tme_mutex_unlock(&am7990->tme_am7990_mutex);
1479: }
1480: /* NOTREACHED */
1481: }
1482:
1483: /* the am7990 bus cycle handler: */
1484: static int
1485: _tme_am7990_bus_cycle(void *_am7990, struct tme_bus_cycle *cycle_init)
1486: {
1487: struct tme_am7990 *am7990;
1488: tme_bus_addr_t address, am7990_address_last;
1489: tme_uint16_t value;
1490: tme_uint32_t reg;
1491: tme_uint16_t csr0_old;
1492: tme_uint16_t csr0_new;
1493: tme_uint8_t port_init;
1494: unsigned int routing_index;
1495:
1496: /* recover our data structure: */
1497: am7990 = (struct tme_am7990 *) _am7990;
1498:
1499: /* the address must be within range: */
1500: am7990_address_last = am7990->tme_am7990_device.tme_bus_device_address_last;
1501: assert(cycle_init->tme_bus_cycle_address <= am7990_address_last);
1502: assert(cycle_init->tme_bus_cycle_size <= (am7990_address_last - cycle_init->tme_bus_cycle_address) + 1);
1503:
1504: /* get the register being accessed: */
1505: address = cycle_init->tme_bus_cycle_address;
1506: reg = (address & ((am7990_address_last + 1) / 2));
1507:
1508: /* save the initiator's port description: */
1509: port_init = cycle_init->tme_bus_cycle_port;
1510:
1511: /* lock the mutex: */
1512: tme_mutex_lock(&am7990->tme_am7990_mutex);
1513:
1514: /* if this is a write: */
1515: if (cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) {
1516:
1517: /* run the bus cycle: */
1518: tme_bus_cycle_xfer_reg(cycle_init,
1519: &value,
1520: TME_BUS16_LOG2);
1521:
1522: /* if this was a write to the RAP: */
1523: if (reg == am7990->tme_am7990_offset_rap) {
1524:
1525: /* set the new RAP: */
1526: am7990->tme_am7990_rap = value % TME_ARRAY_ELS(am7990->tme_am7990_csrs);
1527: }
1528:
1529: /* otherwise, this was a write to the RDP: */
1530: else {
1531: assert (reg == am7990->tme_am7990_offset_rdp);
1532:
1533: /* if this is a write to CSR0: */
1534: if (am7990->tme_am7990_rap == 0) {
1535:
1536: /* get the previous value of CSR0: */
1537: csr0_old = am7990->tme_am7990_csr0;
1538:
1539: /* handle the read-only, write-1-to-clear, and write-1-only
1540: bits: */
1541: csr0_new = ((value & ~TME_AM7990_CSR0_READ_ONLY)
1542: | (csr0_old
1543: & (TME_AM7990_CSR0_READ_ONLY
1544: | TME_AM7990_CSR0_WRITE_ONE_ONLY)));
1545: csr0_new = ((csr0_new ^ TME_AM7990_CSR0_WRITE_ONE_TO_CLEAR)
1546: & (csr0_old | ~TME_AM7990_CSR0_WRITE_ONE_TO_CLEAR));
1547:
1548: /* update ERR: */
1549: csr0_new &= ~TME_AM7990_CSR0_ERR;
1550: if (csr0_new
1551: & (TME_AM7990_CSR0_BABL
1552: | TME_AM7990_CSR0_CERR
1553: | TME_AM7990_CSR0_MISS
1554: | TME_AM7990_CSR0_MERR)) {
1555: csr0_new |= TME_AM7990_CSR0_ERR;
1556: }
1557:
1558: /* set the initial new CSR0 value: */
1559: am7990->tme_am7990_csr0 = csr0_new;
1560:
1561: /* "If STRT, INIT and STOP are all set together, STOP will
1562: override the other bits and only STOP will be set." */
1563: if (value & TME_AM7990_CSR0_STOP) {
1564:
1565: /* reset the am7990: */
1566: _tme_am7990_reset(am7990);
1567: }
1568:
1569: /* otherwise, STOP is not set in the new CSR0 value: */
1570: else {
1571:
1572: /* if INIT is set in the CSR0 value written, and STOP is set
1573: in the old CSR0 value: */
1574: if ((value & TME_AM7990_CSR0_INIT)
1575: && (csr0_old & TME_AM7990_CSR0_STOP)) {
1576:
1577: /* run the initialization procedure: */
1578: _tme_am7990_init(am7990);
1579: }
1580:
1581: /* if STRT is set in the CSR0 value written, and STRT is not
1582: set in the old CSR0 value: */
1583: if ((value & TME_AM7990_CSR0_STRT)
1584: && !(csr0_old & TME_AM7990_CSR0_STRT)) {
1585:
1586: /* start the am7990: */
1587: _tme_am7990_start(am7990);
1588: }
1589:
1590: /* if TDMD is set in the CSR0 value written, call out a
1591: transmit scan: */
1592: if (value & TME_AM7990_CSR0_TDMD) {
1593: am7990->tme_am7990_callout_flags |= TME_AM7990_CALLOUT_TRANSMIT_SCAN;
1594: }
1595: }
1596: }
1597:
1598: /* otherwise, this is writing another CSR: */
1599: else {
1600:
1601: tme_log(&am7990->tme_am7990_element->tme_element_log_handle,
1602: 100, TME_OK,
1603: (&am7990->tme_am7990_element->tme_element_log_handle,
1604: "CSR%u <- 0x%04x",
1605: am7990->tme_am7990_rap,
1606: value));
1607:
1608: am7990->tme_am7990_csrs[am7990->tme_am7990_rap] = value;
1609: }
1610: }
1611: }
1612:
1613: /* otherwise, this is a read: */
1614: else {
1615: assert (cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_READ);
1616:
1617: /* get the value to read: */
1618: if (reg == am7990->tme_am7990_offset_rap) {
1619: value = am7990->tme_am7990_rap;
1620: }
1621: else {
1622: assert (reg == am7990->tme_am7990_offset_rdp);
1623: value = am7990->tme_am7990_csrs[am7990->tme_am7990_rap];
1624: }
1625:
1626: /* run the bus cycle: */
1627: tme_bus_cycle_xfer_reg(cycle_init,
1628: &value,
1629: TME_BUS16_LOG2);
1630: }
1631:
1632: /* NB: the generic memory implementation doesn't know its own port
1633: size or endianness, and instead just follows the endianness of
1634: whatever reads and writes it (see tme_bus_cycle_xfer_memory()).
1635: this is sort of a fragile system, but does allow the same generic
1636: memory implementation to work with all kinds of CPU emulations.
1637:
1638: the fragility shows with a chip like the am7990. for all of its
1639: non-Ethernet data bus mastering, the real chip doesn't need to
1640: know memory's endianness; it just reads a 16-bit quantity from a
1641: 16-bit aligned address and expects that the most-significant
1642: eight bits will be on D8..D15. but since the memory doesn't know
1643: its own endianness, we have to use a bus routing that matches the
1644: endianness of the bus routing used by the CPU that wrote the
1645: memory.
1646:
1647: fortunately, we can learn the endianness of the CPU when it reads
1648: or writes us. we do this here: */
1649: if (am7990->tme_am7990_device.tme_bus_device_router == NULL) {
1650:
1651: /* get the index into the bus routing used by the initiator for
1652: this cycle. if the initiator's least lane is zero, then this
1653: is also a lane number: */
1654: routing_index
1655: = (TME_BUS_CYCLE_PORT_LANE_LEAST(cycle_init->tme_bus_cycle_port)
1656: - TME_BUS_CYCLE_PORT_LANE_LEAST(port_init));
1657:
1658: /* if the initiator routed a byte from a lower address to the byte
1659: lane of lesser significance, then we assume that memory is
1660: little-endian: */
1661: am7990->tme_am7990_device.tme_bus_device_router
1662: = ((cycle_init->tme_bus_cycle_lane_routing[routing_index + 0]
1663: < cycle_init->tme_bus_cycle_lane_routing[routing_index + 1])
1664: ? tme_bus_device_router_16el
1665: : tme_bus_device_router_16eb);
1666: }
1667:
1668: /* make any new callouts: */
1669: _tme_am7990_callout(am7990);
1670:
1671: /* unlock the mutex: */
1672: tme_mutex_unlock(&am7990->tme_am7990_mutex);
1673:
1674: /* no faults: */
1675: return (TME_OK);
1676: }
1677:
1678: /* the am7990 TLB filler: */
1679: static int
1680: _tme_am7990_tlb_fill(void *_am7990,
1681: struct tme_bus_tlb *tlb,
1682: tme_bus_addr_t address,
1683: unsigned int cycles)
1684: {
1685: struct tme_am7990 *am7990;
1686: tme_bus_addr_t am7990_address_last;
1687:
1688: /* recover our data structure: */
1689: am7990 = (struct tme_am7990 *) _am7990;
1690:
1691: /* the address must be within range: */
1692: am7990_address_last = am7990->tme_am7990_device.tme_bus_device_address_last;
1693: assert(address <= am7990_address_last);
1694:
1695: /* initialize the TLB entry: */
1696: tme_bus_tlb_initialize(tlb);
1697:
1698: /* this TLB entry can cover the whole device: */
1699: tlb->tme_bus_tlb_addr_first = 0;
1700: tlb->tme_bus_tlb_addr_last = am7990_address_last;
1701:
1702: /* allow reading and writing: */
1703: tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE;
1704:
1705: /* our bus cycle handler: */
1706: tlb->tme_bus_tlb_cycle_private = am7990;
1707: tlb->tme_bus_tlb_cycle = _tme_am7990_bus_cycle;
1708:
1709: return (TME_OK);
1710: }
1711:
1712: /* this makes a new Ethernet connection: */
1713: static int
1714: _tme_am7990_connection_make_eth(struct tme_connection *conn, unsigned int state)
1715: {
1716: struct tme_am7990 *am7990;
1717: struct tme_ethernet_connection *conn_eth;
1718: struct tme_ethernet_connection *conn_eth_other;
1719:
1720: /* recover our data structures: */
1721: am7990 = conn->tme_connection_element->tme_element_private;
1722: conn_eth = (struct tme_ethernet_connection *) conn;
1723: conn_eth_other = (struct tme_ethernet_connection *) conn->tme_connection_other;
1724:
1725: /* both sides must be Ethernet connections: */
1726: assert(conn->tme_connection_type == TME_CONNECTION_ETHERNET);
1727: assert(conn->tme_connection_other->tme_connection_type == TME_CONNECTION_ETHERNET);
1728:
1729: /* we're always set up to answer calls across the connection, so we
1730: only have to do work when the connection has gone full, namely
1731: taking the other side of the connection: */
1732: if (state == TME_CONNECTION_FULL) {
1733:
1734: /* lock our mutex: */
1735: tme_mutex_lock(&am7990->tme_am7990_mutex);
1736:
1737: /* save our connection: */
1738: am7990->tme_am7990_eth_connection = conn_eth_other;
1739:
1740: /* unlock our mutex: */
1741: tme_mutex_unlock(&am7990->tme_am7990_mutex);
1742: }
1743:
1744: return (TME_OK);
1745: }
1746:
1747: /* this makes a new bus connection: */
1748: static int
1749: _tme_am7990_connection_make_bus(struct tme_connection *conn,
1750: unsigned int state)
1751: {
1752: struct tme_am7990 *am7990;
1753: struct tme_bus_connection *conn_bus;
1754: int rc;
1755:
1756: /* recover our data structure: */
1757: am7990 = conn->tme_connection_element->tme_element_private;
1758:
1759: /* call the bus device connection maker: */
1760: rc = tme_bus_device_connection_make(conn, state);
1761:
1762: /* if the full connection was successful, and we don't have a TLB
1763: hash yet, allocate it: */
1764: if (rc == TME_OK
1765: && state == TME_CONNECTION_FULL
1766: && tme_memory_atomic_pointer_read(struct tme_bus_tlb *,
1767: am7990->tme_am7990_tlb_hash,
1768: &am7990->tme_am7990_tlb_hash_rwlock) == NULL) {
1769:
1770: /* get our bus connection: */
1771: conn_bus
1772: = tme_memory_atomic_pointer_read(struct tme_bus_connection *,
1773: am7990->tme_am7990_device.tme_bus_device_connection,
1774: &am7990->tme_am7990_device.tme_bus_device_connection_rwlock);
1775:
1776: /* allocate the TLB set: */
1777: rc = ((*conn_bus->tme_bus_tlb_set_allocate)
1778: (conn_bus,
1779: TME_AM7990_TLB_HASH_SIZE,
1780: sizeof(struct tme_bus_tlb),
1781: &am7990->tme_am7990_tlb_hash,
1782: &am7990->tme_am7990_device.tme_bus_device_connection_rwlock));
1783: assert (rc == TME_OK);
1784: }
1785:
1786: return (rc);
1787: }
1788:
1789: /* this breaks a connection: */
1790: static int
1791: _tme_am7990_connection_break(struct tme_connection *conn, unsigned int state)
1792: {
1793: abort();
1794: }
1795:
1796: /* this makes a new connection side for a am7990: */
1797: static int
1798: _tme_am7990_connections_new(struct tme_element *element,
1799: const char * const *args,
1800: struct tme_connection **_conns,
1801: char **_output)
1802: {
1803: struct tme_am7990 *am7990;
1804: struct tme_ethernet_connection *conn_eth;
1805: struct tme_connection *conn;
1806: int rc;
1807:
1808: /* recover our data structure: */
1809: am7990 = (struct tme_am7990 *) element->tme_element_private;
1810:
1811: /* make the generic bus device connection side: */
1812: rc = tme_bus_device_connections_new(element, args, _conns, _output);
1813: if (rc != TME_OK) {
1814: return (rc);
1815: }
1816:
1817: /* since we need to allocate our TLB hash when we make our bus
1818: connection, make sure any generic bus device connection sides use
1819: our connection maker: */
1820: for (conn = *_conns;
1821: conn != NULL;
1822: conn = conn->tme_connection_next) {
1823: if ((conn->tme_connection_type
1824: == TME_CONNECTION_BUS_GENERIC)
1825: && (conn->tme_connection_make
1826: == tme_bus_device_connection_make)) {
1827: conn->tme_connection_make
1828: = _tme_am7990_connection_make_bus;
1829: }
1830: }
1831:
1832: /* if we don't have an Ethernet connection, make one: */
1833: if (am7990->tme_am7990_eth_connection == NULL) {
1834:
1835: /* allocate the new Ethernet connection: */
1836: conn_eth = tme_new0(struct tme_ethernet_connection, 1);
1837: conn = &conn_eth->tme_ethernet_connection;
1838:
1839: /* fill in the generic connection: */
1840: conn->tme_connection_next = *_conns;
1841: conn->tme_connection_type = TME_CONNECTION_ETHERNET;
1842: conn->tme_connection_score = tme_ethernet_connection_score;
1843: conn->tme_connection_make = _tme_am7990_connection_make_eth;
1844: conn->tme_connection_break = _tme_am7990_connection_break;
1845:
1846: /* fill in the Ethernet connection: */
1847: conn_eth->tme_ethernet_connection_config = _tme_am7990_config;
1848: conn_eth->tme_ethernet_connection_ctrl = _tme_am7990_ctrl;
1849: conn_eth->tme_ethernet_connection_read = _tme_am7990_transmit;
1850:
1851: /* return the connection side possibility: */
1852: *_conns = conn;
1853: }
1854:
1855: /* done: */
1856: return (TME_OK);
1857: }
1858:
1859: /* the new am7990 function: */
1860: TME_ELEMENT_X_NEW_DECL(tme_ic_,am7990,am7990) {
1861: struct tme_am7990 *am7990;
1862: int arg_i;
1863: int usage;
1864: tme_uint32_t reg_size;
1865:
1866: /* check our arguments: */
1867: usage = 0;
1868: arg_i = 1;
1869: for (;;) {
1870:
1871: if (0) {
1872: }
1873:
1874: /* if we ran out of arguments: */
1875: else if (args[arg_i] == NULL) {
1876:
1877: break;
1878: }
1879:
1880: /* otherwise this is a bad argument: */
1881: else {
1882: tme_output_append_error(_output,
1883: "%s %s, ",
1884: args[arg_i],
1885: _("unexpected"));
1886: usage = TRUE;
1887: break;
1888: }
1889: }
1890:
1891: if (usage) {
1892: tme_output_append_error(_output,
1893: "%s %s",
1894: _("usage:"),
1895: args[0]);
1896: return (EINVAL);
1897: }
1898:
1899: /* start the am7990 structure: */
1900: am7990 = tme_new0(struct tme_am7990, 1);
1901: am7990->tme_am7990_element = element;
1902: tme_mutex_init(&am7990->tme_am7990_mutex);
1903:
1904: /* set the register offsets: */
1905: /* XXX FIXME - these should come from a socket structure: */
1906: am7990->tme_am7990_offset_rdp = 0;
1907: am7990->tme_am7990_offset_rap = sizeof(tme_uint16_t);
1908:
1909: /* get the total register size: */
1910: assert ((am7990->tme_am7990_offset_rdp & (am7990->tme_am7990_offset_rdp - 1)) == 0);
1911: assert ((am7990->tme_am7990_offset_rap & (am7990->tme_am7990_offset_rap - 1)) == 0);
1912: reg_size = TME_MAX(am7990->tme_am7990_offset_rdp, am7990->tme_am7990_offset_rap) * 2;
1913:
1914: /* initialize our simple bus device descriptor: */
1915: am7990->tme_am7990_device.tme_bus_device_element = element;
1916: am7990->tme_am7990_device.tme_bus_device_tlb_fill = _tme_am7990_tlb_fill;
1917: am7990->tme_am7990_device.tme_bus_device_address_last = reg_size - 1;
1918: am7990->tme_am7990_device.tme_bus_device_signal = _tme_am7990_signal;
1919: am7990->tme_am7990_device.tme_bus_device_lock = _tme_am7990_lock;
1920: am7990->tme_am7990_device.tme_bus_device_unlock = _tme_am7990_unlock;
1921: am7990->tme_am7990_device.tme_bus_device_tlb_hash = _tme_am7990_tlb_hash;
1922:
1923: /* fill the element: */
1924: element->tme_element_private = am7990;
1925: element->tme_element_connections_new = _tme_am7990_connections_new;
1926:
1927: /* start the descriptor polling thread: */
1928: tme_thread_create((tme_thread_t) _tme_am7990_poll_th, am7990);
1929:
1930: /* reset the am7990: */
1931: _tme_am7990_reset(am7990);
1932:
1933: return (TME_OK);
1934: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.