|
|
1.1 root 1: /* $Id: sun-sc.c,v 1.3 2003/08/07 21:56:37 fredette Exp $ */
2:
3: /* bus/multibus/sun-sc.c - implementation of Sun `sc' SCSI Multibus board emulation: */
4:
5: /*
6: * Copyright (c) 2003 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: sun-sc.c,v 1.3 2003/08/07 21:56:37 fredette Exp $");
38:
39: /* includes: */
40: #include <tme/generic/bus-device.h>
41: #include <tme/generic/scsi.h>
42:
43: /* macros: */
44:
45: /* register offsets and sizes: */
46: #define TME_SUN_SC_REG_DATA (0)
47: #define TME_SUN_SC_SIZ_DATA (sizeof(tme_uint8_t))
48: #define TME_SUN_SC_REG_CMD_STAT (2)
49: #define TME_SUN_SC_SIZ_CMD_STAT (sizeof(tme_uint8_t))
50: #define TME_SUN_SC_REG_ICR (4)
51: #define TME_SUN_SC_SIZ_ICR (sizeof(tme_uint16_t))
52: #define TME_SUN_SC_REG_DMA_H (8)
53: #define TME_SUN_SC_SIZ_DMA_H (sizeof(tme_uint16_t))
54: #define TME_SUN_SC_REG_DMA_L (10)
55: #define TME_SUN_SC_SIZ_DMA_L (sizeof(tme_uint16_t))
56: #define TME_SUN_SC_REG_DMA_LEN (12)
57: #define TME_SUN_SC_SIZ_DMA_LEN (sizeof(tme_uint16_t))
58: #define TME_SUN_SC_REG_INTVEC (15)
59: #define TME_SUN_SC_SIZ_INTVEC (sizeof(tme_uint8_t))
60: #define TME_SUN_SC_SIZ_CARD (TME_SUN_SC_REG_INTVEC + TME_SUN_SC_SIZ_INTVEC)
61:
62: /* the bits in the Interface Control Register. bits greater than
63: or equal to SUNSCPAL_ICR_BUSY are read-only: */
64: #define _TME_SUN_SC_ICR_RO_BITS (~(TME_SUN_SC_ICR_BUSY - 1))
65: #define TME_SUN_SC_ICR_PARITY_ERROR (0x8000) /* parity error */
66: #define TME_SUN_SC_ICR_BUS_ERROR (0x4000) /* bus error */
67: #define TME_SUN_SC_ICR_ODD_LENGTH (0x2000) /* odd length */
68: #define TME_SUN_SC_ICR_INT_REQUEST (0x1000) /* interrupt request */
69: #define TME_SUN_SC_ICR_REQUEST (0x0800) /* request */
70: #define TME_SUN_SC_ICR_MESSAGE (0x0400) /* message */
71: #define TME_SUN_SC_ICR_COMMAND_DATA (0x0200) /* 1=command, 0=data */
72: #define TME_SUN_SC_ICR_INPUT_OUTPUT (0x0100) /* 1=input (initiator should read), 0=output */
73: #define TME_SUN_SC_ICR_PARITY (0x0080) /* parity */
74: #define TME_SUN_SC_ICR_BUSY (0x0040) /* busy */
75: #define TME_SUN_SC_ICR_SELECT (0x0020) /* select */
76: #define TME_SUN_SC_ICR_RESET (0x0010) /* reset */
77: #define TME_SUN_SC_ICR_PARITY_ENABLE (0x0008) /* enable parity */
78: #define TME_SUN_SC_ICR_WORD_MODE (0x0004) /* word mode */
79: #define TME_SUN_SC_ICR_DMA_ENABLE (0x0002) /* enable DMA */
80: #define TME_SUN_SC_ICR_INT_ENABLE (0x0001) /* enable interrupts */
81:
82: /* this gets the current SCSI information transfer bus phase,
83: including BSY, from an ICR value: */
84: #define TME_SUN_SC_BUS_PHASE(icr) \
85: ((icr) \
86: & (TME_SUN_SC_ICR_BUSY \
87: | TME_SUN_SC_ICR_MESSAGE \
88: | TME_SUN_SC_ICR_COMMAND_DATA \
89: | TME_SUN_SC_ICR_INPUT_OUTPUT))
90:
91: /* these get and put a 16-bit register: */
92: #define TME_SUN_SC_REG16_GET(sun_sc, reg) \
93: tme_betoh_u16(*((tme_uint16_t *) &(sun_sc)->tme_sun_sc_card[reg]))
94: #define TME_SUN_SC_REG16_PUT(sun_sc, reg, val) \
95: (*((tme_uint16_t *) &(sun_sc)->tme_sun_sc_card[reg]) = tme_htobe_u16(val))
96:
97: /* these get and put the ICR: */
98: #define TME_SUN_SC_ICR_GET(sun_sc) \
99: TME_SUN_SC_REG16_GET(sun_sc, TME_SUN_SC_REG_ICR)
100: #define TME_SUN_SC_ICR_PUT(sun_sc, icr) \
101: TME_SUN_SC_REG16_PUT(sun_sc, TME_SUN_SC_REG_ICR, icr)
102:
103: /* the size of the cycle callout ring buffer: */
104: #define TME_SUN_SC_CYCLE_RING_SIZE (4)
105:
106: /* the callout flags: */
107: #define TME_SUN_SC_CALLOUT_CHECK (0)
108: #define TME_SUN_SC_CALLOUT_RUNNING TME_BIT(0)
109: #define TME_SUN_SC_CALLOUTS_MASK (-2)
110: #define TME_SUN_SC_CALLOUT_CYCLE TME_BIT(1)
111: #define TME_SUN_SC_CALLOUT_TLB_FILL TME_BIT(2)
112: #define TME_SUN_SC_CALLOUT_INT TME_BIT(3)
113:
114: #if 1
115: #define TME_SUN_SC_DEBUG
116: #endif
117:
118: /* structures: */
119:
120: /* an entry in the cycle callout ring buffer: */
121: struct tme_sun_sc_cycle {
122:
123: /* the SCSI control and data signals to assert: */
124: tme_scsi_control_t tme_sun_sc_cycle_control;
125: tme_scsi_data_t tme_sun_sc_cycle_data;
126:
127: /* the SCSI sequence to run: */
128: const struct tme_scsi_sequence *tme_sun_sc_cycle_sequence;
129:
130: /* a DMA structure needed: */
131: struct tme_scsi_dma tme_sun_sc_cycle_dma;
132:
133: /* for the cmd_stat DMA, the cmd_stat value: */
134: tme_uint8_t tme_sun_sc_cycle_cmd_stat;
135: };
136:
137: /* the card: */
138: struct tme_sun_sc {
139:
140: /* our simple bus device header: */
141: struct tme_bus_device tme_sun_sc_device;
142: #define tme_sun_sc_element tme_sun_sc_device.tme_bus_device_element
143:
144: /* the mutex protecting the card: */
145: tme_mutex_t tme_sun_sc_mutex;
146:
147: /* the rwlock protecting the card: */
148: tme_rwlock_t tme_sun_sc_rwlock;
149:
150: /* the SCSI bus connection: */
151: struct tme_scsi_connection *tme_sun_sc_scsi_connection;
152:
153: /* the callout flags: */
154: int tme_sun_sc_callout_flags;
155:
156: /* if our interrupt line is currently asserted: */
157: int tme_sun_sc_int_asserted;
158:
159: /* it's easiest to just model the card as a chunk of memory: */
160: tme_uint8_t tme_sun_sc_card[TME_SUN_SC_SIZ_CARD];
161:
162: /* the SCSI sequences: */
163: const struct tme_scsi_sequence *tme_sun_sc_sequence_info_dma_initiator;
164: const struct tme_scsi_sequence *tme_sun_sc_sequence_wait_change;
165:
166: /* the cycle ring buffer: */
167: struct tme_sun_sc_cycle tme_sun_sc_cycles[TME_SUN_SC_CYCLE_RING_SIZE];
168: int tme_sun_sc_cycle_head;
169: int tme_sun_sc_cycle_tail;
170:
171: /* our DMA TLB set: */
172: TME_ATOMIC(struct tme_bus_tlb *, tme_sun_sc_dma_tlb);
173:
174: /* the internal DMA buffer: */
175: tme_uint8_t tme_sun_sc_int_dma[2];
176:
177: #ifndef TME_NO_LOG
178: tme_uint16_t tme_sun_sc_last_log_icr;
179: #endif /* !TME_NO_LOG */
180: };
181:
182: /* globals: */
183:
184: /* the Sun sc bus router: */
185: static const tme_bus_lane_t tme_sun_sc_router[TME_BUS_ROUTER_SIZE(TME_BUS16_LOG2) * 2] = {
186:
187: /* [sc] initiator cycle size: 8 bits
188: [gen] responding port size: 8 bits
189: [gen] responding port least lane: 0: */
190: /* D7-D0 */ TME_BUS_LANE_ROUTE(0),
191: /* D15-D8 */ TME_BUS_LANE_UNDEF,
192:
193: /* [sc] initiator cycle size: 8 bits
194: [gen] responding port size: 8 bits
195: [gen] responding port least lane: 1: */
196: /* D7-D0 */ TME_BUS_LANE_ROUTE(0),
197: /* D15-D8 */ TME_BUS_LANE_UNDEF | TME_BUS_LANE_WARN,
198:
199: /* [sc] initiator cycle size: 8 bits
200: [gen] responding port size: 16 bits
201: [gen] responding port least lane: 0: */
202: /* D7-D0 */ TME_BUS_LANE_ROUTE(0),
203: /* D15-D8 */ TME_BUS_LANE_UNDEF | TME_BUS_LANE_WARN,
204:
205: /* [sc] initiator cycle size: 8 bits
206: [gen] responding port size: 16 bits
207: [gen] responding port least lane: 1 - invalid, array placeholder: */
208: /* D7-D0 */ TME_BUS_LANE_ABORT,
209: /* D15-D8 */ TME_BUS_LANE_ABORT,
210:
211: /* [sc] initiator cycle size: 16 bits
212: [gen] responding port size: 8 bits
213: [gen] responding port least lane: 0: */
214: /* D7-D0 */ TME_BUS_LANE_ROUTE(0),
215: /* D15-D8 */ TME_BUS_LANE_ROUTE(1) | TME_BUS_LANE_WARN,
216:
217: /* [sc] initiator cycle size: 16 bits
218: [gen] responding port size: 8 bits
219: [gen] responding port least lane: 1: */
220: /* D7-D0 */ TME_BUS_LANE_ROUTE(0) | TME_BUS_LANE_WARN,
221: /* D15-D8 */ TME_BUS_LANE_ROUTE(1) | TME_BUS_LANE_WARN,
222:
223: /* [sc] initiator cycle size: 16 bits
224: [gen] responding port size: 16 bits
225: [gen] responding port least lane: 0: */
226: /* D7-D0 */ TME_BUS_LANE_ROUTE(0),
227: /* D15-D8 */ TME_BUS_LANE_ROUTE(1),
228:
229: /* [sc] initiator cycle size: 16 bits
230: [gen] responding port size: 16 bits
231: [gen] responding port least lane: 1 - invalid, array placeholder: */
232: /* D7-D0 */ TME_BUS_LANE_ABORT,
233: /* D15-D8 */ TME_BUS_LANE_ABORT,
234: };
235:
236: #ifdef TME_SUN_SC_DEBUG
237: void
238: _tme_sun_sc_reg16_put(struct tme_sun_sc *sun_sc,
239: int reg,
240: tme_uint16_t val_new)
241: {
242: const char *reg_name;
243: tme_uint16_t val_old;
244:
245: val_old = TME_SUN_SC_REG16_GET(sun_sc, reg);
246: if (val_old == val_new) {
247: return;
248: }
249: TME_SUN_SC_REG16_PUT(sun_sc, reg, val_new);
250:
251: switch (reg) {
252: case TME_SUN_SC_REG_ICR:
253: reg_name = "icr";
254: break;
255: case TME_SUN_SC_REG_DMA_H:
256: case TME_SUN_SC_REG_DMA_L:
257: tme_log(&sun_sc->tme_sun_sc_element->tme_element_log_handle,
258: 100, TME_OK,
259: (&sun_sc->tme_sun_sc_element->tme_element_log_handle,
260: "dvma now 0x%04x%04x (len 0x%04x)",
261: TME_SUN_SC_REG16_GET(sun_sc,
262: TME_SUN_SC_REG_DMA_H),
263: TME_SUN_SC_REG16_GET(sun_sc,
264: TME_SUN_SC_REG_DMA_L),
265: (TME_SUN_SC_REG16_GET(sun_sc,
266: TME_SUN_SC_REG_DMA_LEN)
267: ^ 0xffff)));
268: return;
269: case TME_SUN_SC_REG_DMA_LEN:
270: reg_name = "len";
271: val_new ^= 0xffff;
272: break;
273: default:
274: reg_name = "???";
275: break;
276: }
277: tme_log(&sun_sc->tme_sun_sc_element->tme_element_log_handle,
278: 100, TME_OK,
279: (&sun_sc->tme_sun_sc_element->tme_element_log_handle,
280: "%s now 0x%04x",
281: reg_name,
282: val_new));
283: }
284: #undef TME_SUN_SC_REG16_PUT
285: #define TME_SUN_SC_REG16_PUT _tme_sun_sc_reg16_put
286: #endif /* TME_SUN_SC_DEBUG */
287:
288: /* this allocates the next cycle in the ring buffer: */
289: struct tme_sun_sc_cycle *
290: _tme_sun_sc_cycle_new(struct tme_sun_sc *sun_sc,
291: const struct tme_scsi_sequence *sequence)
292: {
293: int old_head;
294: struct tme_sun_sc_cycle *sun_sc_cycle;
295: const struct tme_sun_sc_cycle *sun_sc_cycle_old;
296:
297: /* abort if the ring buffer overflows: */
298: old_head = sun_sc->tme_sun_sc_cycle_head;
299: sun_sc->tme_sun_sc_cycle_head
300: = ((old_head
301: + 1)
302: & (TME_SUN_SC_CYCLE_RING_SIZE
303: - 1));
304: if ((sun_sc->tme_sun_sc_cycle_head
305: == sun_sc->tme_sun_sc_cycle_tail)
306: && (sun_sc->tme_sun_sc_scsi_connection
307: != NULL)) {
308: abort();
309: }
310:
311: /* initialize and return the cycle. we copy the previous cycle's
312: control signals, (and data signals too, unless the caller wants
313: the DMA sequence), so that callers only have to change the values
314: that they know are changing: */
315: sun_sc_cycle
316: = &sun_sc->tme_sun_sc_cycles[old_head];
317: memset(sun_sc_cycle, 0, sizeof(*sun_sc_cycle));
318: sun_sc_cycle_old
319: = &sun_sc->tme_sun_sc_cycles[((old_head
320: - 1)
321: & (TME_SUN_SC_CYCLE_RING_SIZE
322: - 1))];
323: sun_sc_cycle->tme_sun_sc_cycle_control
324: = sun_sc_cycle_old->tme_sun_sc_cycle_control;
325: sun_sc_cycle->tme_sun_sc_cycle_data
326: = ((sequence
327: == sun_sc->tme_sun_sc_sequence_info_dma_initiator)
328: ? 0
329: : sun_sc_cycle_old->tme_sun_sc_cycle_data);
330: sun_sc_cycle->tme_sun_sc_cycle_sequence
331: = sequence;
332: /* XXX parity? */
333: sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_flags
334: = TME_SCSI_DMA_8BIT;
335: return (sun_sc_cycle);
336: }
337:
338: /* this does a bus cycle to read or write into our internal DMA
339: buffer: */
340: static int
341: _tme_sun_sc_bus_cycle_dma(struct tme_sun_sc *sun_sc,
342: struct tme_bus_tlb *tlb,
343: tme_uint8_t cycle_type,
344: tme_bus_addr_t address,
345: int word_mode)
346: {
347: struct tme_bus_cycle cycle_init;
348: int rc;
349:
350: /* use our internal DMA buffer: */
351: cycle_init.tme_bus_cycle_buffer
352: = &sun_sc->tme_sun_sc_int_dma[0];
353:
354: /* if we're in word mode, use the 16-bit bus router
355: and a 16-bit cycle size: */
356: if (word_mode) {
357: cycle_init.tme_bus_cycle_lane_routing
358: = &tme_sun_sc_router[TME_BUS_ROUTER_SIZE(TME_BUS16_LOG2)];
359: cycle_init.tme_bus_cycle_size
360: = sizeof(tme_uint16_t);
361: }
362:
363: /* otherwise, use the 8-bit bus router and an 8-bit
364: cycle size: */
365: else {
366: cycle_init.tme_bus_cycle_lane_routing
367: = &tme_sun_sc_router[0];
368: cycle_init.tme_bus_cycle_size
369: = sizeof(tme_uint16_t);
370: }
371:
372: assert (tlb->tme_bus_tlb_addr_shift == 0);
373: cycle_init.tme_bus_cycle_address
374: = (address
375: + tlb->tme_bus_tlb_addr_offset);
376:
377: cycle_init.tme_bus_cycle_buffer_increment
378: = 1;
379:
380: cycle_init.tme_bus_cycle_type
381: = cycle_type;
382:
383: cycle_init.tme_bus_cycle_port =
384: TME_BUS_CYCLE_PORT(0, TME_BUS16_LOG2);
385:
386: /* unlock the mutex: */
387: tme_mutex_unlock(&sun_sc->tme_sun_sc_mutex);
388:
389: /* run the bus cycle: */
390: rc = ((*tlb->tme_bus_tlb_cycle)
391: (tlb->tme_bus_tlb_cycle_private,
392: &cycle_init));
393:
394: /* lock the mutex: */
395: tme_mutex_lock(&sun_sc->tme_sun_sc_mutex);
396:
397: return (rc);
398: }
399:
400: /* the Sun sc callout function. it must be called with the mutex locked: */
401: static void
402: _tme_sun_sc_callout(struct tme_sun_sc *sun_sc, int new_callouts)
403: {
404: struct tme_scsi_connection *conn_scsi;
405: struct tme_bus_connection *conn_bus;
406: struct tme_bus_tlb *tlb;
407: int old_tail;
408: struct tme_sun_sc_cycle *sun_sc_cycle;
409: int callouts, later_callouts;
410: tme_bus_addr_t address;
411: tme_uint16_t resid;
412: tme_uint8_t cycle_type;
413: tme_bus_addr_t avail;
414: tme_uint8_t *emulator_off;
415: tme_uint16_t icr;
416: int rc;
417: int int_asserted;
418:
419: /* add in any new callouts: */
420: sun_sc->tme_sun_sc_callout_flags |= new_callouts;
421:
422: /* if this function is already running in another thread, simply
423: return now. the other thread will do our work: */
424: if (sun_sc->tme_sun_sc_callout_flags
425: & TME_SUN_SC_CALLOUT_RUNNING) {
426: return;
427: }
428:
429: /* callouts are now running: */
430: sun_sc->tme_sun_sc_callout_flags
431: |= TME_SUN_SC_CALLOUT_RUNNING;
432:
433: /* assume that we won't need any later callouts: */
434: later_callouts = 0;
435:
436: /* loop while callouts are needed: */
437: for (; ((callouts
438: = sun_sc->tme_sun_sc_callout_flags)
439: & TME_SUN_SC_CALLOUTS_MASK); ) {
440:
441: /* clear the needed callouts: */
442: sun_sc->tme_sun_sc_callout_flags
443: = (callouts
444: & ~TME_SUN_SC_CALLOUTS_MASK);
445: callouts
446: &= TME_SUN_SC_CALLOUTS_MASK;
447:
448: /* get this card's bus and SCSI connections: */
449: conn_scsi = sun_sc->tme_sun_sc_scsi_connection;
450: conn_bus = TME_ATOMIC_READ(struct tme_bus_connection *,
451: sun_sc->tme_sun_sc_device.tme_bus_device_connection);
452:
453: /* if we need to call out a SCSI bus cycle: */
454: if (callouts & TME_SUN_SC_CALLOUT_CYCLE) {
455:
456: /* there must be a cycle to call out: */
457: old_tail = sun_sc->tme_sun_sc_cycle_tail;
458: assert (old_tail
459: != sun_sc->tme_sun_sc_cycle_head);
460: sun_sc_cycle
461: = &sun_sc->tme_sun_sc_cycles[old_tail];
462:
463: /* unlock the mutex: */
464: tme_mutex_unlock(&sun_sc->tme_sun_sc_mutex);
465:
466: /* do the callout: */
467: rc = (conn_scsi != NULL
468: ? ((*conn_scsi->tme_scsi_connection_cycle)
469: (conn_scsi,
470: sun_sc_cycle->tme_sun_sc_cycle_control,
471: sun_sc_cycle->tme_sun_sc_cycle_data,
472: sun_sc_cycle->tme_sun_sc_cycle_sequence,
473: ((sun_sc_cycle->tme_sun_sc_cycle_sequence
474: == sun_sc->tme_sun_sc_sequence_info_dma_initiator)
475: ? &sun_sc_cycle->tme_sun_sc_cycle_dma
476: : NULL)))
477: : TME_OK);
478:
479: /* lock the mutex: */
480: tme_mutex_lock(&sun_sc->tme_sun_sc_mutex);
481:
482: /* if the callout was unsuccessful, remember that at some later
483: time this callout should be attempted again: */
484: if (rc != TME_OK) {
485: later_callouts |= TME_SUN_SC_CALLOUT_CYCLE;
486: }
487:
488: /* otherwise, this callout was successful. if this cycle did
489: not use the DMA initiator sequence, it either used no
490: sequence or it used the wait_change sequence: */
491: else if (sun_sc_cycle->tme_sun_sc_cycle_sequence
492: != sun_sc->tme_sun_sc_sequence_info_dma_initiator) {
493:
494: /* advance the tail pointer if it hasn't been advanced
495: already: */
496: if (sun_sc->tme_sun_sc_cycle_tail
497: == old_tail) {
498: sun_sc->tme_sun_sc_cycle_tail
499: = ((sun_sc->tme_sun_sc_cycle_tail
500: + 1)
501: & (TME_SUN_SC_CYCLE_RING_SIZE
502: - 1));
503: }
504:
505: /* if there are more cycles to run, run them now: */
506: if (sun_sc->tme_sun_sc_cycle_tail
507: != sun_sc->tme_sun_sc_cycle_head) {
508: sun_sc->tme_sun_sc_callout_flags
509: |= TME_SUN_SC_CALLOUT_CYCLE;
510: }
511: }
512: }
513:
514: /* if we need to call out a TLB fill: */
515: if (callouts & TME_SUN_SC_CALLOUT_TLB_FILL) {
516:
517: /* get the current ICR value: */
518: icr = TME_SUN_SC_ICR_GET(sun_sc);
519:
520: /* get the DMA address: */
521: address
522: = TME_SUN_SC_REG16_GET(sun_sc,
523: TME_SUN_SC_REG_DMA_H);
524: address
525: = ((address
526: << 16)
527: | TME_SUN_SC_REG16_GET(sun_sc,
528: TME_SUN_SC_REG_DMA_L));
529:
530: /* get the cycle type: */
531: cycle_type
532: = ((icr
533: & TME_SUN_SC_ICR_INPUT_OUTPUT)
534: ? TME_BUS_CYCLE_WRITE
535: : TME_BUS_CYCLE_READ);
536:
537: /* get the resid: */
538: resid
539: = (TME_SUN_SC_REG16_GET(sun_sc,
540: TME_SUN_SC_REG_DMA_LEN)
541: ^ 0xffff);
542: assert (resid
543: >= ((icr
544: & TME_SUN_SC_ICR_WORD_MODE)
545: ? sizeof(tme_uint16_t)
546: : sizeof(tme_uint8_t)));
547:
548: /* get the TLB entry: */
549: tlb
550: = TME_ATOMIC_READ(struct tme_bus_tlb *,
551: sun_sc->tme_sun_sc_dma_tlb);
552:
553: /* unlock the mutex: */
554: tme_mutex_unlock(&sun_sc->tme_sun_sc_mutex);
555:
556: /* do the callout: */
557: rc = (conn_bus != NULL
558: ? ((*conn_bus->tme_bus_tlb_fill)
559: (conn_bus,
560: tlb,
561: address,
562: cycle_type))
563: : TME_OK);
564:
565: /* lock the mutex: */
566: tme_mutex_lock(&sun_sc->tme_sun_sc_mutex);
567:
568: /* if the callout was unsuccessful, remember that at some later
569: time this callout should be attempted again: */
570: if (rc != TME_OK) {
571: later_callouts |= TME_SUN_SC_CALLOUT_TLB_FILL;
572: }
573:
574: /* otherwise, use the filled TLB entry to start a SCSI
575: DMA sequence: */
576: else {
577:
578: /* get the number of bytes available in this TLB entry: */
579: avail
580: = ((TME_ATOMIC_READ(tme_bus_addr_t,
581: tlb->tme_bus_tlb_addr_last)
582: - address)
583: + 1);
584: if (avail == 0
585: || avail > resid) {
586: avail = resid;
587: }
588: assert (avail
589: >= ((icr
590: & TME_SUN_SC_ICR_WORD_MODE)
591: ? sizeof(tme_uint16_t)
592: : sizeof(tme_uint8_t)));
593:
594: /* allocate the new SCSI bus cycle: */
595: sun_sc_cycle
596: = _tme_sun_sc_cycle_new(sun_sc,
597: sun_sc->tme_sun_sc_sequence_info_dma_initiator);
598:
599: /* if this TLB entry allows fast transfers: */
600: emulator_off
601: = ((cycle_type
602: == TME_BUS_CYCLE_READ)
603: ? tlb->tme_bus_tlb_emulator_off_read
604: : tlb->tme_bus_tlb_emulator_off_write);
605: if (emulator_off
606: != TME_EMULATOR_OFF_UNDEF) {
607:
608: /* do the SCSI DMA sequence with the TLB fast transfer
609: buffer: */
610: sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_in
611: = emulator_off + address;
612: }
613:
614: /* otherwise, this TLB entry does not allow fast transfers: */
615: else {
616:
617: /* if this we need to read from this TLB, do a memory
618: read cycle into our internal DMA buffer: */
619: if (cycle_type == TME_BUS_CYCLE_READ) {
620: rc = _tme_sun_sc_bus_cycle_dma(sun_sc,
621: tlb,
622: TME_BUS_CYCLE_READ,
623: address,
624: (icr
625: & TME_SUN_SC_ICR_WORD_MODE));
626: assert (rc == TME_OK);
627: }
628:
629: /* do the SCSI DMA sequence with our internal DMA buffer: */
630: sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_in
631: = emulator_off + address;
632: avail
633: = ((icr
634: & TME_SUN_SC_ICR_WORD_MODE)
635: ? sizeof(tme_uint16_t)
636: : sizeof(tme_uint8_t));
637: }
638:
639: /* finish the SCSI cycle: */
640: sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_out
641: = sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_in;
642: sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_resid
643: = avail;
644:
645: /* we now need to call out a SCSI cycle: */
646: sun_sc->tme_sun_sc_callout_flags
647: |= TME_SUN_SC_CALLOUT_CYCLE;
648: }
649: }
650:
651: /* if we need to call out a possible change to our interrupt
652: signal: */
653: if (callouts & TME_SUN_SC_CALLOUT_INT) {
654:
655: /* get the current ICR value: */
656: icr = TME_SUN_SC_ICR_GET(sun_sc);
657:
658: /* see if the interrupt signal should be asserted or negated: */
659: int_asserted = ((icr
660: & TME_SUN_SC_ICR_INT_REQUEST)
661: && (icr
662: & TME_SUN_SC_ICR_INT_ENABLE));
663:
664: /* if the interrupt signal doesn't already have the right state: */
665: if (!int_asserted
666: != !sun_sc->tme_sun_sc_int_asserted) {
667:
668: /* unlock our mutex: */
669: tme_mutex_unlock(&sun_sc->tme_sun_sc_mutex);
670:
671: /* call out the bus interrupt signal edge: */
672: rc = (*conn_bus->tme_bus_signal)
673: (conn_bus,
674: TME_BUS_SIGNAL_INT_UNSPEC
675: | (int_asserted
676: ? TME_BUS_SIGNAL_LEVEL_ASSERTED
677: : TME_BUS_SIGNAL_LEVEL_NEGATED)
678: | TME_BUS_SIGNAL_EDGE);
679:
680: /* lock our mutex: */
681: tme_mutex_lock(&sun_sc->tme_sun_sc_mutex);
682:
683: /* if this callout was successful, note the new state of the
684: interrupt signal: */
685: if (rc == TME_OK) {
686: sun_sc->tme_sun_sc_int_asserted = int_asserted;
687: }
688:
689: /* otherwise, remember that at some later time this callout
690: should be attempted again: */
691: else {
692: later_callouts |= TME_SUN_SC_CALLOUT_INT;
693: }
694: }
695: }
696: }
697:
698: /* put in any later callouts, and clear that callouts are running: */
699: sun_sc->tme_sun_sc_callout_flags = later_callouts;
700: }
701:
702: /* the Sun sc bus cycle handler for the data and cmd_stat registers.
703: these registers are connected directly to the SCSI data signals.
704:
705: a read of one of these registers samples the SCSI data bus, and a
706: write to one of these registers changes the SCSI data bus signals
707: asserted by the card.
708:
709: additionally, depending on context, a read or write of one of these
710: registers will cause the card to execute the initiator's side of a
711: REQ/ACK handshake to transfer a byte.
712:
713: a read or write of the cmd_stat register always causes the
714: handshake. a read or write of the data register when the SCSI bus
715: is in the DATA IN or DATA OUT phase with REQ asserted also causes
716: the handshake: */
717: static int
718: _tme_sun_sc_bus_cycle_data_reg(struct tme_sun_sc *sun_sc,
719: struct tme_bus_cycle *cycle_init,
720: int is_cmd_stat)
721: {
722: tme_uint16_t icr;
723: tme_scsi_data_t data_old, data_new;
724: struct tme_sun_sc_cycle *sun_sc_cycle;
725: int new_callouts;
726:
727: /* assume we won't need any new callouts: */
728: new_callouts = 0;
729:
730: /* lock the mutex: */
731: tme_mutex_lock(&sun_sc->tme_sun_sc_mutex);
732:
733: /* get the current ICR value: */
734: icr = TME_SUN_SC_ICR_GET(sun_sc);
735:
736: /* save the old data register (really, the current
737: signals asserted on the data bus), and, in case
738: this is a read of the cmd_stat register, save
739: it in that register: */
740: data_old = sun_sc->tme_sun_sc_card[TME_SUN_SC_REG_DATA];
741: sun_sc->tme_sun_sc_card[TME_SUN_SC_REG_CMD_STAT] = data_old;
742:
743: /* run the cycle: */
744: tme_bus_cycle_xfer_memory(cycle_init,
745: sun_sc->tme_sun_sc_card,
746: sun_sc->tme_sun_sc_device.tme_bus_device_address_last);
747:
748: /* put back the old data register, but get any value that
749: may have been written: */
750: data_new
751: = (is_cmd_stat
752: ? sun_sc->tme_sun_sc_card[TME_SUN_SC_REG_CMD_STAT]
753: : sun_sc->tme_sun_sc_card[TME_SUN_SC_REG_DATA]);
754: sun_sc->tme_sun_sc_card[TME_SUN_SC_REG_DATA] = data_old;
755:
756: /* if this was a read or write of the cmd_stat register, or a read
757: or write of the data register while the bus is in the DATA IN or
758: DATA OUT phase with REQ asserted, do the initiator's side of the
759: REQ/ACK handshake: */
760: if (is_cmd_stat
761: || ((icr
762: & (TME_SUN_SC_ICR_BUSY
763: | TME_SUN_SC_ICR_MESSAGE
764: | TME_SUN_SC_ICR_COMMAND_DATA
765: | TME_SUN_SC_ICR_REQUEST))
766: == (TME_SUN_SC_ICR_BUSY
767: | TME_SUN_SC_ICR_REQUEST))) {
768:
769: /* make a new SCSI bus cycle: */
770: /* XXX parity? */
771: sun_sc_cycle
772: = _tme_sun_sc_cycle_new(sun_sc,
773: sun_sc->tme_sun_sc_sequence_info_dma_initiator);
774: sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_resid
775: = sizeof(sun_sc_cycle->tme_sun_sc_cycle_cmd_stat);
776: sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_in
777: = &sun_sc_cycle->tme_sun_sc_cycle_cmd_stat;
778: sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_out
779: = &sun_sc_cycle->tme_sun_sc_cycle_cmd_stat;
780: sun_sc_cycle->tme_sun_sc_cycle_cmd_stat
781: = data_new;
782:
783: tme_log(&sun_sc->tme_sun_sc_element->tme_element_log_handle,
784: 100, TME_OK,
785: (&sun_sc->tme_sun_sc_element->tme_element_log_handle,
786: ((cycle_init->tme_bus_cycle_type
787: == TME_BUS_CYCLE_WRITE)
788: ? (is_cmd_stat
789: ? "0x%02x -> cmd_stat"
790: : "0x%02x -> data (handshake)")
791: : (is_cmd_stat
792: ? "cmd_stat-> 0x%02x"
793: : "data -> 0x%02x (handshake)")),
794: sun_sc_cycle->tme_sun_sc_cycle_cmd_stat));
795:
796: new_callouts |= TME_SUN_SC_CALLOUT_CYCLE;
797:
798: /* since this SCSI DMA sequence won't be run right away, it's
799: important that we clear REQ now - otherwise if the sc device
800: driver happens to see REQ still set, it will think that the SCSI
801: handshake *did* happen, and that this REQ is now requesting the
802: next byte. when the DMA sequence ends we'll get a cycle call
803: that will bring us up-to-date: */
804: TME_SUN_SC_ICR_PUT(sun_sc,
805: (icr
806: & ~TME_SUN_SC_ICR_REQUEST));
807: }
808:
809: /* otherwise, if this was a write of the data register in a
810: non-handshake bus phase: */
811: else if (cycle_init->tme_bus_cycle_type
812: == TME_BUS_CYCLE_WRITE) {
813:
814: /* if the data signals that we are asserting have changed, call
815: out a cycle, then wait: */
816: sun_sc_cycle
817: = &sun_sc->tme_sun_sc_cycles[((sun_sc->tme_sun_sc_cycle_head
818: - 1)
819: & (TME_SUN_SC_CYCLE_RING_SIZE
820: - 1))];
821: if (data_new != sun_sc_cycle->tme_sun_sc_cycle_data) {
822: tme_log(&sun_sc->tme_sun_sc_element->tme_element_log_handle,
823: 100, TME_OK,
824: (&sun_sc->tme_sun_sc_element->tme_element_log_handle,
825: "0x%02x -> data (no handshake)",
826: data_new));
827: sun_sc_cycle
828: = _tme_sun_sc_cycle_new(sun_sc,
829: sun_sc->tme_sun_sc_sequence_wait_change);
830: sun_sc_cycle->tme_sun_sc_cycle_data
831: = data_new;
832: new_callouts
833: |= TME_SUN_SC_CALLOUT_CYCLE;
834: }
835: }
836:
837: /* otherwise, this was a read of the data register in a
838: non-handshake bus phase: */
839: else {
840: tme_log(&sun_sc->tme_sun_sc_element->tme_element_log_handle,
841: 100, TME_OK,
842: (&sun_sc->tme_sun_sc_element->tme_element_log_handle,
843: "data -> 0x%02x (no handshake)",
844: data_old));
845: }
846:
847: /* make any new callouts: */
848: _tme_sun_sc_callout(sun_sc, new_callouts);
849:
850: /* unlock the mutex: */
851: tme_mutex_unlock(&sun_sc->tme_sun_sc_mutex);
852:
853: /* no faults: */
854: return (TME_OK);
855: }
856:
857: /* the Sun sc bus cycle handler for the data register. this register
858: is connected directly to the SCSI data signals: */
859: static int
860: _tme_sun_sc_bus_cycle_data(void *_sun_sc,
861: struct tme_bus_cycle *cycle_init)
862: {
863: return (_tme_sun_sc_bus_cycle_data_reg((struct tme_sun_sc *) _sun_sc,
864: cycle_init,
865: FALSE));
866: }
867:
868: /* the Sun sc bus cycle handler for the command/status register. this
869: register is also connected directly to the SCSI data signals, but
870: reading or writing it additionally causes the card to execute the
871: initiator's side of a REQ/ACK handshake to transfer a byte: */
872: static int
873: _tme_sun_sc_bus_cycle_cmd_stat(void *_sun_sc,
874: struct tme_bus_cycle *cycle_init)
875: {
876: return (_tme_sun_sc_bus_cycle_data_reg((struct tme_sun_sc *) _sun_sc,
877: cycle_init,
878: TRUE));
879: }
880:
881: /* this tries to start or continue a DMA transfer: */
882: static int
883: _tme_sun_sc_dma_start(struct tme_sun_sc *sun_sc,
884: tme_uint16_t *_icr)
885: {
886: tme_uint16_t icr;
887: tme_uint16_t resid;
888:
889: /* get the current ICR value: */
890: icr = *_icr;
891:
892: /* get the resid: */
893: resid
894: = (TME_SUN_SC_REG16_GET(sun_sc,
895: TME_SUN_SC_REG_DMA_LEN)
896: ^ 0xffff);
897:
898: tme_log(&sun_sc->tme_sun_sc_element->tme_element_log_handle,
899: 100, TME_OK,
900: (&sun_sc->tme_sun_sc_element->tme_element_log_handle,
901: "dma_start: icr=0x%04x dvma=0x%04x%04x len=0x%04x",
902: icr,
903: TME_SUN_SC_REG16_GET(sun_sc,
904: TME_SUN_SC_REG_DMA_H),
905: TME_SUN_SC_REG16_GET(sun_sc,
906: TME_SUN_SC_REG_DMA_L),
907: resid));
908:
909: /* if we're not in the DATA IN or DATA OUT phases, do nothing. the
910: sun2 PROMs seem to set DMA_ENABLE when DMA is impossible: */
911: if ((icr
912: & (TME_SUN_SC_ICR_DMA_ENABLE
913: | TME_SUN_SC_ICR_BUSY
914: | TME_SUN_SC_ICR_MESSAGE
915: | TME_SUN_SC_ICR_COMMAND_DATA
916: | TME_SUN_SC_ICR_REQUEST))
917: != (TME_SUN_SC_ICR_DMA_ENABLE
918: | TME_SUN_SC_ICR_BUSY
919: | TME_SUN_SC_ICR_REQUEST)) {
920: return (TME_SUN_SC_CALLOUT_CHECK);
921: }
922:
923: /* if there are no more bytes left to transfer, we need
924: an interrupt: */
925: if (resid == 0) {
926: *_icr
927: = ((icr
928: & ~TME_SUN_SC_ICR_ODD_LENGTH)
929: | TME_SUN_SC_ICR_INT_REQUEST);
930: return (TME_SUN_SC_CALLOUT_INT);
931: }
932:
933: /* if there is only one byte left to transfer, and we're in word
934: mode, note the odd byte, and we need an interrupt: */
935: else if (resid == 1
936: && (icr
937: & TME_SUN_SC_ICR_WORD_MODE)) {
938: *_icr
939: = (icr
940: | TME_SUN_SC_ICR_ODD_LENGTH
941: | TME_SUN_SC_ICR_INT_REQUEST);
942: return (TME_SUN_SC_CALLOUT_INT);
943: }
944:
945: /* otherwise, start the DMA transfer with a TLB fill callout: */
946: return (TME_SUN_SC_CALLOUT_TLB_FILL);
947: }
948:
949: /* the Sun sc bus cycle handler for the ICR. parts of this register
950: are connected directly to the SCSI control signals: */
951: static int
952: _tme_sun_sc_bus_cycle_icr(void *_sun_sc,
953: struct tme_bus_cycle *cycle_init)
954: {
955: struct tme_sun_sc *sun_sc;
956: struct tme_sun_sc_cycle *sun_sc_cycle;
957: tme_uint16_t icr_old, icr_new, icr_diff;
958: int new_callouts;
959:
960: /* recover our data structure: */
961: sun_sc = (struct tme_sun_sc *) _sun_sc;
962:
963: /* assume we won't need any new callouts: */
964: new_callouts = 0;
965:
966: /* lock the mutex: */
967: tme_mutex_lock(&sun_sc->tme_sun_sc_mutex);
968:
969: /* save the old ICR value: */
970: icr_old = TME_SUN_SC_ICR_GET(sun_sc);
971: icr_new = icr_old;
972:
973: /* if we were requesting an interrupt, clear it now and call out an
974: interrupt change: */
975: if (icr_new & TME_SUN_SC_ICR_INT_REQUEST) {
976: icr_new &= ~TME_SUN_SC_ICR_INT_REQUEST;
977: new_callouts |= TME_SUN_SC_CALLOUT_INT;
978: }
979:
980: /* run the bus cycle: */
981: tme_bus_cycle_xfer_memory(cycle_init,
982: sun_sc->tme_sun_sc_card,
983: sun_sc->tme_sun_sc_device.tme_bus_device_address_last);
984:
985:
986: /* if this was a write: */
987: if (cycle_init->tme_bus_cycle_type
988: == TME_BUS_CYCLE_WRITE) {
989:
990: /* put back the read-only bits: */
991: icr_new = TME_SUN_SC_ICR_GET(sun_sc);
992: icr_new = ((icr_old
993: & _TME_SUN_SC_ICR_RO_BITS)
994: | (icr_new
995: & ~_TME_SUN_SC_ICR_RO_BITS));
996:
997: /* get the set of changed bits: */
998: icr_diff = icr_old ^ icr_new;
999:
1000: /* a change in RESET: */
1001: if (icr_diff & TME_SUN_SC_ICR_RESET) {
1002:
1003: /* make a new cycle that asserts no data or control signals,
1004: except possibly for RST: */
1005: sun_sc_cycle
1006: = _tme_sun_sc_cycle_new(sun_sc,
1007: sun_sc->tme_sun_sc_sequence_wait_change);
1008: sun_sc_cycle->tme_sun_sc_cycle_control
1009: = ((icr_new
1010: & TME_SUN_SC_ICR_RESET)
1011: ? TME_SCSI_SIGNAL_RST
1012: : 0);
1013: sun_sc_cycle->tme_sun_sc_cycle_data
1014: = 0;
1015: new_callouts
1016: |= TME_SUN_SC_CALLOUT_CYCLE;
1017: }
1018:
1019: /* a change in SELECT: */
1020: else if (icr_diff & TME_SUN_SC_ICR_SELECT) {
1021:
1022: /* make a new cycle that sets the new state of SEL: */
1023: sun_sc_cycle
1024: = _tme_sun_sc_cycle_new(sun_sc,
1025: sun_sc->tme_sun_sc_sequence_wait_change);
1026: sun_sc_cycle->tme_sun_sc_cycle_control
1027: = ((sun_sc_cycle->tme_sun_sc_cycle_control
1028: & ~TME_SCSI_SIGNAL_SEL)
1029: | ((icr_new
1030: & TME_SUN_SC_ICR_SELECT)
1031: ? TME_SCSI_SIGNAL_SEL
1032: : 0));
1033: new_callouts
1034: |= TME_SUN_SC_CALLOUT_CYCLE;
1035: }
1036:
1037: /* if DMA_ENABLE is now set: */
1038: if (icr_diff
1039: & icr_new
1040: & TME_SUN_SC_ICR_DMA_ENABLE) {
1041:
1042: /* try to start DMA: */
1043: new_callouts
1044: |= _tme_sun_sc_dma_start(sun_sc,
1045: &icr_new);
1046: }
1047:
1048: /* a change in INT_ENABLE: */
1049: if (icr_diff
1050: & icr_new
1051: & TME_SUN_SC_ICR_INT_ENABLE) {
1052:
1053: /* our interrupt signal may be changing: */
1054: new_callouts |= TME_SUN_SC_CALLOUT_INT;
1055: }
1056: }
1057:
1058: /* if the ICR changed, save and log the new value: */
1059: if (icr_new != icr_old) {
1060: TME_SUN_SC_ICR_PUT(sun_sc, icr_new);
1061: }
1062:
1063: /* make any new callouts: */
1064: _tme_sun_sc_callout(sun_sc, new_callouts);
1065:
1066: /* unlock the mutex: */
1067: tme_mutex_unlock(&sun_sc->tme_sun_sc_mutex);
1068:
1069: /* no faults: */
1070: return (TME_OK);
1071: }
1072:
1073: /* the Sun sc bus cycle handler for other card registers: */
1074: static int
1075: _tme_sun_sc_bus_cycle_other(void *_sun_sc,
1076: struct tme_bus_cycle *cycle_init)
1077: {
1078: struct tme_sun_sc *sun_sc;
1079:
1080: /* recover our data structure: */
1081: sun_sc = (struct tme_sun_sc *) _sun_sc;
1082:
1083: /* lock the mutex: */
1084: tme_mutex_lock(&sun_sc->tme_sun_sc_mutex);
1085:
1086: /* run the bus cycle: */
1087: tme_bus_cycle_xfer_memory(cycle_init,
1088: sun_sc->tme_sun_sc_card,
1089: sun_sc->tme_sun_sc_device.tme_bus_device_address_last);
1090:
1091: /* if this was a write, dump out the other registers: */
1092: if (cycle_init->tme_bus_cycle_type
1093: == TME_BUS_CYCLE_WRITE) {
1094: tme_log(&sun_sc->tme_sun_sc_element->tme_element_log_handle,
1095: 100, TME_OK,
1096: (&sun_sc->tme_sun_sc_element->tme_element_log_handle,
1097: "dvma=0x%04x%04x len=0x%04x",
1098: TME_SUN_SC_REG16_GET(sun_sc,
1099: TME_SUN_SC_REG_DMA_H),
1100: TME_SUN_SC_REG16_GET(sun_sc,
1101: TME_SUN_SC_REG_DMA_L),
1102: (TME_SUN_SC_REG16_GET(sun_sc,
1103: TME_SUN_SC_REG_DMA_LEN)
1104: ^ 0xffff)));
1105: }
1106:
1107: /* unlock the mutex: */
1108: tme_mutex_unlock(&sun_sc->tme_sun_sc_mutex);
1109:
1110: /* no faults: */
1111: return (TME_OK);
1112: }
1113:
1114: /* the Sun sc TLB filler: */
1115: static int
1116: _tme_sun_sc_tlb_fill(void *_sun_sc,
1117: struct tme_bus_tlb *tlb,
1118: tme_bus_addr_t address,
1119: unsigned int cycles)
1120: {
1121: struct tme_sun_sc *sun_sc;
1122:
1123: /* recover our data structure: */
1124: sun_sc = (struct tme_sun_sc *) _sun_sc;
1125:
1126: /* the address must be within range: */
1127: assert(address < TME_SUN_SC_SIZ_CARD);
1128:
1129: /* initialize the TLB entry: */
1130: tme_bus_tlb_initialize(tlb);
1131:
1132: #define TME_SUN_SC_TLB_REG(reg, siz, handler, rd)\
1133: do { \
1134: \
1135: /* if this address falls in this register: */ \
1136: if (((reg) \
1137: <= address) \
1138: && (address \
1139: < ((reg) \
1140: + (siz)))) { \
1141: \
1142: /* this TLB entry covers this register: */ \
1143: TME_ATOMIC_WRITE(tme_bus_addr_t, \
1144: tlb->tme_bus_tlb_addr_first,\
1145: (reg)); \
1146: TME_ATOMIC_WRITE(tme_bus_addr_t, \
1147: tlb->tme_bus_tlb_addr_last,\
1148: ((reg) \
1149: + (siz) \
1150: - 1)); \
1151: \
1152: /* our bus cycle handler: */ \
1153: tlb->tme_bus_tlb_cycle = (handler); \
1154: \
1155: /* if this TLB entry allows fast reading: */\
1156: if (rd) { \
1157: tlb->tme_bus_tlb_emulator_off_read \
1158: = &sun_sc->tme_sun_sc_card[0]; \
1159: } \
1160: } \
1161: } while (/* CONSTCOND */ 0)
1162:
1163: TME_SUN_SC_TLB_REG(TME_SUN_SC_REG_DATA,
1164: TME_SUN_SC_SIZ_DATA,
1165: _tme_sun_sc_bus_cycle_data,
1166: FALSE);
1167: TME_SUN_SC_TLB_REG(TME_SUN_SC_REG_CMD_STAT,
1168: TME_SUN_SC_SIZ_CMD_STAT,
1169: _tme_sun_sc_bus_cycle_cmd_stat,
1170: FALSE);
1171: TME_SUN_SC_TLB_REG(TME_SUN_SC_REG_ICR,
1172: TME_SUN_SC_SIZ_ICR,
1173: _tme_sun_sc_bus_cycle_icr,
1174: TRUE);
1175: #undef TME_SUN_SC_TLB_REG
1176:
1177: /* anything else is some other register: */
1178: if (tlb->tme_bus_tlb_cycle == NULL) {
1179:
1180: /* if this address is past the ICR, this TLB entry covers from
1181: past the ICR to the end of the card, else this TLB entry covers
1182: the byte at this address only: */
1183: if (address
1184: >= (TME_SUN_SC_REG_ICR
1185: + TME_SUN_SC_SIZ_ICR)) {
1186: TME_ATOMIC_WRITE(tme_bus_addr_t,
1187: tlb->tme_bus_tlb_addr_first,
1188: (TME_SUN_SC_REG_ICR
1189: + TME_SUN_SC_SIZ_ICR));
1190: TME_ATOMIC_WRITE(tme_bus_addr_t,
1191: tlb->tme_bus_tlb_addr_last,
1192: TME_SUN_SC_SIZ_CARD - 1);
1193: }
1194: else {
1195: TME_ATOMIC_WRITE(tme_bus_addr_t,
1196: tlb->tme_bus_tlb_addr_first,
1197: address);
1198: TME_ATOMIC_WRITE(tme_bus_addr_t,
1199: tlb->tme_bus_tlb_addr_last,
1200: address);
1201: }
1202:
1203: /* this TLB entry allows fast reading and writing: */
1204: tlb->tme_bus_tlb_emulator_off_read
1205: = &sun_sc->tme_sun_sc_card[0];
1206: tlb->tme_bus_tlb_emulator_off_write
1207: = &sun_sc->tme_sun_sc_card[0];
1208:
1209: /* bus cycles are handled by the other handler: */
1210: tlb->tme_bus_tlb_cycle = _tme_sun_sc_bus_cycle_other;
1211: }
1212:
1213: #ifdef TME_SUN_SC_DEBUG
1214: /* XXX when debugging, nothing is fast readable or writable: */
1215: tlb->tme_bus_tlb_emulator_off_read
1216: = TME_EMULATOR_OFF_UNDEF;
1217: tlb->tme_bus_tlb_emulator_off_write
1218: = TME_EMULATOR_OFF_UNDEF;
1219: #endif /* TME_SUN_SC_DEBUG */
1220:
1221: /* in case this TLB entry allows fast access: */
1222: tlb->tme_bus_tlb_rwlock = &sun_sc->tme_sun_sc_rwlock;
1223:
1224: /* allow reading and writing: */
1225: tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE;
1226:
1227: /* our bus cycle handler private data: */
1228: tlb->tme_bus_tlb_cycle_private = sun_sc;
1229:
1230: return (TME_OK);
1231: }
1232:
1233: /* this is called for an event on the SCSI bus: */
1234: static int
1235: _tme_sun_sc_scsi_cycle(struct tme_scsi_connection *conn_scsi,
1236: tme_scsi_control_t control,
1237: tme_scsi_data_t data,
1238: _tme_const struct tme_scsi_sequence *sequence,
1239: struct tme_scsi_dma *dma)
1240: {
1241: struct tme_sun_sc *sun_sc;
1242: struct tme_sun_sc_cycle *sun_sc_cycle;
1243: unsigned long count;
1244: struct tme_bus_tlb *tlb;
1245: tme_uint32_t address;
1246: tme_uint16_t resid;
1247: tme_uint16_t icr_old, icr_new;
1248: int new_callouts;
1249: int new_callouts_dma;
1250: int rc;
1251:
1252: /* recover our data structure: */
1253: sun_sc = conn_scsi->tme_scsi_connection.tme_connection_element->tme_element_private;
1254:
1255: /* assume we won't need any new callouts: */
1256: new_callouts = 0;
1257:
1258: /* lock the mutex: */
1259: tme_mutex_lock(&sun_sc->tme_sun_sc_mutex);
1260:
1261: /* get the old ICR value: */
1262: icr_old = TME_SUN_SC_ICR_GET(sun_sc);
1263:
1264: /* update the ICR to reflect the current SCSI control signals: */
1265: icr_new = icr_old;
1266: #define _TME_SUN_SC_ICR_CONTROL(_icr, _control) \
1267: do { \
1268: if (control & _control) { \
1269: icr_new |= _icr; \
1270: } \
1271: else { \
1272: icr_new &= ~_icr; \
1273: } \
1274: } while (/* CONSTCOND */ 0)
1275: _TME_SUN_SC_ICR_CONTROL(TME_SUN_SC_ICR_REQUEST,
1276: TME_SCSI_SIGNAL_REQ);
1277: _TME_SUN_SC_ICR_CONTROL(TME_SUN_SC_ICR_MESSAGE,
1278: TME_SCSI_SIGNAL_MSG);
1279: _TME_SUN_SC_ICR_CONTROL(TME_SUN_SC_ICR_COMMAND_DATA,
1280: TME_SCSI_SIGNAL_C_D);
1281: _TME_SUN_SC_ICR_CONTROL(TME_SUN_SC_ICR_INPUT_OUTPUT,
1282: TME_SCSI_SIGNAL_I_O);
1283: _TME_SUN_SC_ICR_CONTROL(TME_SUN_SC_ICR_PARITY,
1284: TME_SCSI_SIGNAL_DBP);
1285: _TME_SUN_SC_ICR_CONTROL(TME_SUN_SC_ICR_BUSY,
1286: TME_SCSI_SIGNAL_BSY);
1287: #undef _TME_SUN_SC_ICR_CONTROL
1288:
1289: /* if the bus phase has changed to the STATUS phase, call out an
1290: interrupt: */
1291: /* XXX is this really how the board behaves? the sun2 PROM seems to
1292: rely on this behavior: */
1293: if ((TME_SUN_SC_BUS_PHASE(icr_new)
1294: != TME_SUN_SC_BUS_PHASE(icr_old))
1295: && (TME_SUN_SC_BUS_PHASE(icr_new)
1296: == (TME_SUN_SC_ICR_BUSY
1297: | TME_SUN_SC_ICR_COMMAND_DATA
1298: | TME_SUN_SC_ICR_INPUT_OUTPUT))) {
1299: icr_new
1300: |= TME_SUN_SC_ICR_INT_REQUEST;
1301: new_callouts
1302: |= TME_SUN_SC_CALLOUT_INT;
1303: }
1304:
1305: /* get the last SCSI cycle that we called out: */
1306: sun_sc_cycle
1307: = &sun_sc->tme_sun_sc_cycles[sun_sc->tme_sun_sc_cycle_tail];
1308:
1309: /* if the last SCSI cycle was for a DMA sequence: */
1310: if (sun_sc_cycle->tme_sun_sc_cycle_sequence
1311: == sun_sc->tme_sun_sc_sequence_info_dma_initiator) {
1312:
1313: /* if the last SCSI cycle was for a genuine DMA sequence (as opposed
1314: to a DMA sequence to transfer the cmd_stat register), update the
1315: card's DMA engine registers: */
1316: if ((sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_out
1317: != &sun_sc_cycle->tme_sun_sc_cycle_cmd_stat)
1318: && (sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_in
1319: != &sun_sc_cycle->tme_sun_sc_cycle_cmd_stat)) {
1320:
1321: /* get the number of bytes that were transferred: */
1322: count
1323: = ((sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_out
1324: > sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_in)
1325: ? (sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_out
1326: - sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_in)
1327: : (sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_in
1328: - sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_out));
1329:
1330: /* get the TLB entry: */
1331: tlb
1332: = TME_ATOMIC_READ(struct tme_bus_tlb *,
1333: sun_sc->tme_sun_sc_dma_tlb);
1334:
1335: /* get the DMA address: */
1336: address
1337: = TME_SUN_SC_REG16_GET(sun_sc,
1338: TME_SUN_SC_REG_DMA_H);
1339: address
1340: = ((address
1341: << 16)
1342: | TME_SUN_SC_REG16_GET(sun_sc,
1343: TME_SUN_SC_REG_DMA_L));
1344:
1345: /* if we were doing a DMA write, but the TLB entry we filled
1346: doesn't allow fast writing, we need to do a memory write
1347: cycle to transfer the bytes from our internal DMA buffer into
1348: memory: */
1349: if ((icr_old
1350: & TME_SUN_SC_ICR_INPUT_OUTPUT)
1351: && (tlb->tme_bus_tlb_emulator_off_write
1352: == TME_EMULATOR_OFF_UNDEF)) {
1353: rc = _tme_sun_sc_bus_cycle_dma(sun_sc,
1354: tlb,
1355: TME_BUS_CYCLE_WRITE,
1356: address,
1357: (icr_old
1358: & TME_SUN_SC_ICR_WORD_MODE));
1359: assert (rc == TME_OK);
1360: }
1361:
1362: /* update the DMA address: */
1363: address += count;
1364: TME_SUN_SC_REG16_PUT(sun_sc,
1365: TME_SUN_SC_REG_DMA_H,
1366: address >> 16);
1367: TME_SUN_SC_REG16_PUT(sun_sc,
1368: TME_SUN_SC_REG_DMA_L,
1369: address & 0xffff);
1370:
1371: /* update the DMA length: */
1372: resid
1373: = (TME_SUN_SC_REG16_GET(sun_sc,
1374: TME_SUN_SC_REG_DMA_LEN)
1375: ^ 0xffff);
1376: assert (resid >= count);
1377: TME_SUN_SC_REG16_PUT(sun_sc,
1378: TME_SUN_SC_REG_DMA_LEN,
1379: ((resid
1380: - count)
1381: ^ 0xffff));
1382:
1383: /* XXX this idea doesn't work because the initiator can't know
1384: the amount of data returned by some commands, like REQUEST
1385: SENSE. when does this card signal BUS_ERROR, then? */
1386: #if 0
1387: /* if the DMA sequence didn't transfer all of the DMA bytes that
1388: we had made available, that usually means that the SCSI bus
1389: phase changed in the middle of the transfer, which is a bus
1390: error: */
1391: if (sun_sc_cycle->tme_sun_sc_cycle_dma.tme_scsi_dma_resid
1392: > 0) {
1393:
1394: /* note the bus error and request an interrupt: */
1395: icr_new
1396: |= (TME_SUN_SC_ICR_BUS_ERROR
1397: | TME_SUN_SC_ICR_INT_REQUEST);
1398: new_callouts |= TME_SUN_SC_CALLOUT_INT;
1399: }
1400: #endif
1401: }
1402:
1403: /* advance the tail pointer: */
1404: sun_sc->tme_sun_sc_cycle_tail
1405: = ((sun_sc->tme_sun_sc_cycle_tail
1406: + 1)
1407: & (TME_SUN_SC_CYCLE_RING_SIZE
1408: - 1));
1409: }
1410:
1411: /* always try to start or continue a DMA transfer. if one
1412: can't be started, just wait for another SCSI bus change: */
1413: new_callouts_dma
1414: = _tme_sun_sc_dma_start(sun_sc,
1415: &icr_new);
1416: if (new_callouts_dma != 0) {
1417: new_callouts |= new_callouts_dma;
1418: }
1419: else {
1420: sun_sc_cycle
1421: = _tme_sun_sc_cycle_new(sun_sc,
1422: sun_sc->tme_sun_sc_sequence_wait_change);
1423: new_callouts
1424: |= TME_SUN_SC_CALLOUT_CYCLE;
1425: }
1426:
1427: /* update the ICR and data registers: */
1428: TME_SUN_SC_ICR_PUT(sun_sc, icr_new);
1429: sun_sc->tme_sun_sc_card[TME_SUN_SC_REG_DATA] = data;
1430:
1431: /* make any new callouts: */
1432: _tme_sun_sc_callout(sun_sc, new_callouts);
1433:
1434: /* unlock the mutex: */
1435: tme_mutex_unlock(&sun_sc->tme_sun_sc_mutex);
1436:
1437: return (TME_OK);
1438: }
1439:
1440: /* this makes a new bus connection: */
1441: static int
1442: _tme_sun_sc_connection_make_bus(struct tme_connection *conn,
1443: unsigned int state)
1444: {
1445: struct tme_sun_sc *sun_sc;
1446: struct tme_bus_connection *conn_bus;
1447: int rc;
1448:
1449: /* recover our data structure: */
1450: sun_sc = conn->tme_connection_element->tme_element_private;
1451:
1452: /* call the bus device connection maker: */
1453: rc = tme_bus_device_connection_make(conn, state);
1454:
1455: /* if the full connection was successful, and we don't have a TLB
1456: set yet, allocate it: */
1457: if (rc == TME_OK
1458: && state == TME_CONNECTION_FULL
1459: && TME_ATOMIC_READ(struct tme_bus_tlb *,
1460: sun_sc->tme_sun_sc_dma_tlb) == NULL) {
1461:
1462: /* get our bus connection: */
1463: conn_bus
1464: = TME_ATOMIC_READ(struct tme_bus_connection *,
1465: sun_sc->tme_sun_sc_device.tme_bus_device_connection);
1466:
1467: /* allocate the TLB set: */
1468: rc = ((*conn_bus->tme_bus_tlb_set_allocate)
1469: (conn_bus,
1470: 1,
1471: sizeof(struct tme_bus_tlb),
1472: TME_ATOMIC_POINTER(&sun_sc->tme_sun_sc_dma_tlb)));
1473: assert (rc == TME_OK);
1474: }
1475:
1476: return (rc);
1477: }
1478:
1479: /* this makes a new SCSI connection: */
1480: static int
1481: _tme_sun_sc_connection_make_scsi(struct tme_connection *conn,
1482: unsigned int state)
1483: {
1484: struct tme_sun_sc *sun_sc;
1485: struct tme_sun_sc_cycle *sun_sc_cycle;
1486: struct tme_scsi_connection *conn_scsi;
1487: struct tme_scsi_connection *conn_scsi_other;
1488:
1489: /* recover our data structures: */
1490: sun_sc = conn->tme_connection_element->tme_element_private;
1491: conn_scsi = (struct tme_scsi_connection *) conn;
1492: conn_scsi_other = (struct tme_scsi_connection *) conn->tme_connection_other;
1493:
1494: /* both sides must be SCSI connections: */
1495: assert(conn->tme_connection_type == TME_CONNECTION_SCSI);
1496: assert(conn->tme_connection_other->tme_connection_type == TME_CONNECTION_SCSI);
1497:
1498: /* we're always set up to answer calls across the connection, so we
1499: only have to do work when the connection has gone full, namely
1500: taking the other side of the connection: */
1501: if (state == TME_CONNECTION_FULL) {
1502:
1503: /* lock our mutex: */
1504: tme_mutex_lock(&sun_sc->tme_sun_sc_mutex);
1505:
1506: /* save our connection: */
1507: sun_sc->tme_sun_sc_scsi_connection = conn_scsi_other;
1508:
1509: /* get the sequences that we need: */
1510: sun_sc->tme_sun_sc_sequence_info_dma_initiator
1511: = ((*conn_scsi_other->tme_scsi_connection_sequence_get)
1512: (conn_scsi_other,
1513: TME_SCSI_SEQUENCE_INFO_DMA_INITIATOR));
1514: sun_sc->tme_sun_sc_sequence_wait_change
1515: = ((*conn_scsi_other->tme_scsi_connection_sequence_get)
1516: (conn_scsi_other,
1517: TME_SCSI_SEQUENCE_WAIT_CHANGE));
1518:
1519: /* call out a cycle that asserts no signals and runs the
1520: wait-change sequence. this also fully-initializes
1521: this cycle - _tme_sun_sc_cycle_new copies the previous
1522: cycle into a newly allocated cycle, so this hopefully
1523: starts the chain of well-initialized cycles: */
1524: sun_sc_cycle
1525: = _tme_sun_sc_cycle_new(sun_sc,
1526: sun_sc->tme_sun_sc_sequence_wait_change);
1527: sun_sc_cycle->tme_sun_sc_cycle_control
1528: = 0;
1529: sun_sc_cycle->tme_sun_sc_cycle_data
1530: = 0;
1531: _tme_sun_sc_callout(sun_sc, TME_SUN_SC_CALLOUT_CYCLE);
1532:
1533: /* unlock our mutex: */
1534: tme_mutex_unlock(&sun_sc->tme_sun_sc_mutex);
1535: }
1536:
1537: return (TME_OK);
1538: }
1539:
1540: /* this breaks a connection: */
1541: static int
1542: _tme_sun_sc_connection_break(struct tme_connection *conn, unsigned int state)
1543: {
1544: abort();
1545: }
1546:
1547: /* this makes a new connection side for a Sun sc: */
1548: static int
1549: _tme_sun_sc_connections_new(struct tme_element *element,
1550: const char * const *args,
1551: struct tme_connection **_conns,
1552: char **_output)
1553: {
1554: struct tme_sun_sc *sun_sc;
1555: struct tme_scsi_connection *conn_scsi;
1556: struct tme_connection *conn;
1557: int rc;
1558:
1559: /* recover our data structure: */
1560: sun_sc = (struct tme_sun_sc *) element->tme_element_private;
1561:
1562: /* make the generic bus device connection side: */
1563: rc = tme_bus_device_connections_new(element, args, _conns, _output);
1564: if (rc != TME_OK) {
1565: return (rc);
1566: }
1567:
1568: /* since we need to allocate a TLB set when we make our bus
1569: connection, make sure any generic bus device connection sides
1570: use our connection maker: */
1571: for (conn = *_conns;
1572: conn != NULL;
1573: conn = conn->tme_connection_next) {
1574: if ((conn->tme_connection_type
1575: == TME_CONNECTION_BUS_GENERIC)
1576: && (conn->tme_connection_make
1577: == tme_bus_device_connection_make)) {
1578: conn->tme_connection_make
1579: = _tme_sun_sc_connection_make_bus;
1580: }
1581: }
1582:
1583: /* if we don't have a SCSI connection, make one: */
1584: if (sun_sc->tme_sun_sc_scsi_connection == NULL) {
1585:
1586: /* allocate the new SCSI connection: */
1587: conn_scsi = tme_new0(struct tme_scsi_connection, 1);
1588: conn = &conn_scsi->tme_scsi_connection;
1589:
1590: /* fill in the generic connection: */
1591: conn->tme_connection_next = *_conns;
1592: conn->tme_connection_type = TME_CONNECTION_SCSI;
1593: conn->tme_connection_score = tme_scsi_connection_score;
1594: conn->tme_connection_make = _tme_sun_sc_connection_make_scsi;
1595: conn->tme_connection_break = _tme_sun_sc_connection_break;
1596:
1597: /* fill in the SCSI connection: */
1598: conn_scsi->tme_scsi_connection_cycle = _tme_sun_sc_scsi_cycle;
1599: conn_scsi->tme_scsi_connection_sequence_get = NULL;
1600:
1601: /* return the connection side possibility: */
1602: *_conns = conn;
1603: }
1604:
1605: /* done: */
1606: return (TME_OK);
1607: }
1608:
1609: /* the new Sun sc function: */
1610: TME_ELEMENT_SUB_NEW_DECL(tme_bus_multibus,sun_sc) {
1611: struct tme_sun_sc *sun_sc;
1612: int arg_i;
1613: int usage;
1614:
1615: /* check our arguments: */
1616: usage = 0;
1617: arg_i = 1;
1618: for (;;) {
1619:
1620: if (0) {
1621: }
1622:
1623: /* if we ran out of arguments: */
1624: else if (args[arg_i] == NULL) {
1625:
1626: break;
1627: }
1628:
1629: /* otherwise this is a bad argument: */
1630: else {
1631: tme_output_append_error(_output,
1632: "%s %s, ",
1633: args[arg_i],
1634: _("unexpected"));
1635: usage = TRUE;
1636: break;
1637: }
1638: }
1639:
1640: if (usage) {
1641: tme_output_append_error(_output,
1642: "%s %s",
1643: _("usage:"),
1644: args[0]);
1645: return (EINVAL);
1646: }
1647:
1648: /* start the Sun sc structure: */
1649: sun_sc = tme_new0(struct tme_sun_sc, 1);
1650: sun_sc->tme_sun_sc_element = element;
1651: tme_mutex_init(&sun_sc->tme_sun_sc_mutex);
1652: tme_rwlock_init(&sun_sc->tme_sun_sc_rwlock);
1653:
1654: /* initialize our simple bus device descriptor: */
1655: sun_sc->tme_sun_sc_device.tme_bus_device_element = element;
1656: sun_sc->tme_sun_sc_device.tme_bus_device_tlb_fill = _tme_sun_sc_tlb_fill;
1657: sun_sc->tme_sun_sc_device.tme_bus_device_address_last = TME_SUN_SC_SIZ_CARD - 1;
1658:
1659: /* fill the element: */
1660: element->tme_element_private = sun_sc;
1661: element->tme_element_connections_new = _tme_sun_sc_connections_new;
1662:
1663: return (TME_OK);
1664: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.