/[dynamips]/trunk/dev_mpc860.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /trunk/dev_mpc860.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 12 - (hide annotations)
Sat Oct 6 16:45:40 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 57956 byte(s)
make working copy

1 dpavlin 7 /*
2     * Cisco router simulation platform.
3     * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr)
4     *
5     * MPC860 internal devices.
6     */
7    
8     #include <stdio.h>
9     #include <stdlib.h>
10     #include <string.h>
11    
12     #include "utils.h"
13     #include "net.h"
14     #include "cpu.h"
15     #include "vm.h"
16     #include "dynamips.h"
17     #include "memory.h"
18     #include "device.h"
19     #include "net_io.h"
20     #include "dev_mpc860.h"
21    
22     /* Debugging flags */
23     #define DEBUG_ACCESS 0
24     #define DEBUG_UNKNOWN 1
25 dpavlin 11 #define DEBUG_IDMA 0
26     #define DEBUG_SPI 0
27     #define DEBUG_SCC 0
28     #define DEBUG_FEC 1
29 dpavlin 7
30 dpavlin 11 #define MPC860_TXRING_PASS_COUNT 16
31    
32 dpavlin 7 /* Dual-Port RAM */
33     #define MPC860_DPRAM_OFFSET 0x2000
34     #define MPC860_DPRAM_SIZE 0x2000
35     #define MPC860_DPRAM_END (MPC860_DPRAM_OFFSET + MPC860_DPRAM_SIZE)
36    
37 dpavlin 11 /* MPC860 registers */
38     #define MPC860_REG_SWSR 0x000e /* Software Service Register */
39     #define MPC860_REG_SIPEND 0x0010 /* SIU Interrupt Pending Register */
40     #define MPC860_REG_SIMASK 0x0014 /* SIU Interrupt Mask Register */
41     #define MPC860_REG_PIPR 0x00f0 /* PCMCIA Interface Input Pins Reg. */
42     #define MPC860_REG_TBSCR 0x0200 /* Timebase Status and Control Reg. */
43     #define MPC860_REG_PISCR 0x0240 /* Periodic Int. Status and Ctrl Reg. */
44     #define MPC860_REG_IDSR1 0x0910 /* IDMA1 Status Register */
45     #define MPC860_REG_IDMR1 0x0914 /* IDMA1 Mask Register */
46     #define MPC860_REG_IDSR2 0x0918 /* IDMA2 Status Register */
47     #define MPC860_REG_IDMR2 0x091c /* IDMA2 Mask Register */
48     #define MPC860_REG_CICR 0x0940 /* CPM Int Config Register */
49     #define MPC860_REG_CIPR 0x0944 /* CPM Int Pending Register */
50     #define MPC860_REG_CIMR 0x0948 /* CPM Int Mask Register */
51     #define MPC860_REG_PCSO 0x0964 /* Port C Special Options Register */
52     #define MPC860_REG_PCDAT 0x0966 /* Port C Data Register */
53     #define MPC860_REG_CPCR 0x09c0 /* CP Command Register */
54     #define MPC860_REG_SCC_BASE 0x0a00 /* SCC register base */
55     #define MPC860_REG_SPMODE 0x0aa0 /* SPI Mode Register */
56     #define MPC860_REG_SPIE 0x0aa6 /* SPI Event Register */
57     #define MPC860_REG_SPIM 0x0aaa /* SPI Mask Register */
58     #define MPC860_REG_SPCOM 0x0aad /* SPI Command Register */
59     #define MPC860_REG_PBDAT 0x0ac4 /* Port B Data Register */
60     #define MPC860_REG_FEC_BASE 0x0e00 /* FEC register base */
61     #define MPC860_REG_FEC_END 0x0f84 /* FEC register end */
62    
63     /* ======================================================================== */
64    
65     /* CICR (CPM Interrupt Config Register) */
66     #define MPC860_CICR_IRL_MASK 0x0000E000 /* Interrupt Level */
67     #define MPC860_CICR_IRL_SHIFT 13
68     #define MPC860_CICR_IEN 0x00000080 /* Interrupt Enable */
69    
70 dpavlin 7 /* CIPR (CPM Interrupt Pending Register) */
71     #define MPC860_CIPR_PC15 0x80000000
72     #define MPC860_CIPR_SCC1 0x40000000
73     #define MPC860_CIPR_SCC2 0x20000000
74     #define MPC860_CIPR_SCC3 0x10000000
75     #define MPC860_CIPR_SCC4 0x08000000
76     #define MPC860_CIPR_PC14 0x04000000
77     #define MPC860_CIPR_TIMER1 0x02000000
78     #define MPC860_CIPR_PC13 0x01000000
79     #define MPC860_CIPR_PC12 0x00800000
80     #define MPC860_CIPR_SDMA 0x00400000
81     #define MPC860_CIPR_IDMA1 0x00200000
82     #define MPC860_CIPR_IDMA2 0x00100000
83     #define MPC860_CIPR_TIMER2 0x00040000
84     #define MPC860_CIPR_RTT 0x00020000
85     #define MPC860_CIPR_I2C 0x00010000
86     #define MPC860_CIPR_PC11 0x00008000
87     #define MPC860_CIPR_PC10 0x00004000
88     #define MPC860_CIPR_TIMER3 0x00001000
89     #define MPC860_CIPR_PC9 0x00000800
90     #define MPC860_CIPR_PC8 0x00000400
91     #define MPC860_CIPR_PC7 0x00000200
92     #define MPC860_CIPR_TIMER4 0x00000080
93     #define MPC860_CIPR_PC6 0x00000040
94     #define MPC860_CIPR_SPI 0x00000020
95     #define MPC860_CIPR_SMC1 0x00000010
96     #define MPC860_CIPR_SMC2 0x00000008
97     #define MPC860_CIPR_PC5 0x00000004
98     #define MPC860_CIPR_PC4 0x00000002
99    
100 dpavlin 11 /* CPCR (CP Command Register) */
101     #define MPC860_CPCR_RST 0x8000 /* CP reset command */
102     #define MPC860_CPCR_FLG 0x0001 /* Command Semaphore Flag */
103    
104     #define MPC860_CPCR_CHNUM_MASK 0x00F0 /* Channel Number */
105     #define MPC860_CPCR_CHNUM_SHIFT 4
106    
107     #define MPC860_CPCR_OPCODE_MASK 0x0F00 /* Opcode */
108     #define MPC860_CPCR_OPCODE_SHIFT 8
109    
110     /* CP channels */
111     #define MPC860_CHAN_SCC1 0x00
112     #define MPC860_CHAN_I2C_IDMA1 0x01
113     #define MPC860_CHAN_SCC2 0x04
114     #define MPC860_CHAN_SPI_IDMA2_RT 0x05
115     #define MPC860_CHAN_SCC3 0x08
116     #define MPC860_CHAN_SMC1 0x09
117     #define MPC860_CHAN_SCC4 0x0c
118     #define MPC860_CHAN_SMC2_PIP 0x0d
119    
120     /* ======================================================================== */
121    
122 dpavlin 7 /* IDMA Status Register */
123     #define MPC860_IDSR_OB 0x0001 /* Out of Buffers */
124     #define MPC860_IDSR_DONE 0x0002 /* Buffer chain done */
125     #define MPC860_IDSR_AD 0x0004 /* Auxiliary done */
126    
127     /* Offsets of IDMA channels (from DPRAM base) */
128     #define MPC860_IDMA1_BASE 0x1cc0
129     #define MPC860_IDMA2_BASE 0x1dc0
130    
131     /* Size of an IDMA buffer descriptor */
132     #define MPC860_IDMA_BD_SIZE 16
133    
134     /* IDMA Buffer Descriptor Control Word */
135     #define MPC860_IDMA_CTRL_V 0x8000 /* Valid Bit */
136     #define MPC860_IDMA_CTRL_W 0x2000 /* Wrap */
137     #define MPC860_IDMA_CTRL_I 0x1000 /* Interrupt for this BD */
138     #define MPC860_IDMA_CTRL_L 0x0800 /* Last buffer of chain */
139     #define MPC860_IDMA_CTRL_CM 0x0200 /* Continuous mode */
140    
141     /* IDMA buffer descriptor */
142     struct mpc860_idma_bd {
143 dpavlin 8 m_uint16_t offset; /* Offset in DPRAM memory */
144 dpavlin 7
145     m_uint16_t ctrl; /* Control Word */
146     m_uint8_t dfcr,sfcr; /* Src/Dst Function code registers */
147     m_uint32_t buf_len; /* Buffer Length */
148     m_uint32_t src_bp; /* Source buffer pointer */
149     m_uint32_t dst_bp; /* Destination buffer pointer */
150     };
151    
152 dpavlin 11 /* ======================================================================== */
153    
154     /* SPI Mode Register (SPMODE) */
155     #define MPC860_SPMODE_LOOP 0x4000 /* Loop mode */
156     #define MPC860_SPMODE_CI 0x2000 /* Clock Invert */
157     #define MPC860_SPMODE_CP 0x1000 /* Clock Phase */
158     #define MPC860_SPMODE_DIV16 0x0800 /* Divide by 16 (SPI clock generator) */
159     #define MPC860_SPMODE_REV 0x0400 /* Reverse Data */
160     #define MPC860_SPMODE_MS 0x0200 /* Master/Slave mode select */
161     #define MPC860_SPMODE_EN 0x0100 /* Enable SPI */
162    
163     #define MPC860_SPMODE_LEN_MASK 0x00F0 /* Data length (4 - 11 bits) */
164     #define MPC860_SPMODE_LEN_SHIFT 4
165    
166     #define MPC860_SPMODE_PM_MASK 0x000F /* Prescale Modulus Select */
167    
168     /* SPI Event/Mask Registers (SPIE/SPIM) */
169     #define MPC860_SPIE_MME 0x20 /* MultiMaster Error */
170     #define MPC860_SPIE_TXE 0x10 /* TX Error */
171     #define MPC860_SPIE_BSY 0x04 /* Busy (no RX buffer available) */
172     #define MPC860_SPIE_TXB 0x02 /* TX Buffer */
173     #define MPC860_SPIE_RXB 0x01 /* RX Buffer */
174    
175     /* SPI Command Register (SPCOM) */
176     #define MPC860_SPCOM_STR 0x80 /* Start Transmit */
177    
178     /* Offsets of SPI parameters (from DPRAM base) */
179     #define MPC860_SPI_BASE 0x1d80
180     #define MPC860_SPI_BASE_ADDR 0x1dac
181    
182     /* Size of an SPI buffer descriptor */
183     #define MPC860_SPI_BD_SIZE 8
184    
185     /* SPI RX Buffer Descriptor Control Word */
186     #define MPC860_SPI_RXBD_CTRL_E 0x8000 /* Empty */
187     #define MPC860_SPI_RXBD_CTRL_W 0x2000 /* Wrap */
188     #define MPC860_SPI_RXBD_CTRL_I 0x1000 /* Interrupt */
189     #define MPC860_SPI_RXBD_CTRL_L 0x0800 /* Last */
190     #define MPC860_SPI_RXBD_CTRL_CM 0x0200 /* Continuous Mode */
191     #define MPC860_SPI_RXBD_CTRL_OV 0x0002 /* Overrun */
192     #define MPC860_SPI_RXBD_CTRL_ME 0x0001 /* MultiMaster Error */
193    
194     /* SPI TX Buffer Descriptor Control Word */
195     #define MPC860_SPI_TXBD_CTRL_R 0x8000 /* Ready Bit */
196     #define MPC860_SPI_TXBD_CTRL_W 0x2000 /* Wrap */
197     #define MPC860_SPI_TXBD_CTRL_I 0x1000 /* Interrupt */
198     #define MPC860_SPI_TXBD_CTRL_L 0x0800 /* Last */
199     #define MPC860_SPI_TXBD_CTRL_CM 0x0200 /* Continuous Mode */
200     #define MPC860_SPI_TXBD_CTRL_UN 0x0002 /* Underrun */
201     #define MPC860_SPI_TXBD_CTRL_ME 0x0001 /* MultiMaster Error */
202    
203     /* SPI buffer descriptor */
204     struct mpc860_spi_bd {
205     m_uint16_t offset; /* Offset in DPRAM memory */
206    
207     m_uint16_t ctrl; /* Control Word */
208     m_uint16_t buf_len; /* Buffer Length */
209     m_uint32_t bp; /* Buffer Pointer */
210     };
211    
212     /* ======================================================================== */
213    
214     /* Number of SCC channels */
215     #define MPC860_SCC_NR_CHAN 4
216    
217     /* Maximum buffer size for SCC */
218     #define MPC860_SCC_MAX_PKT_SIZE 32768
219    
220     /* Offsets of SCC channels (from DPRAM base) */
221     #define MPC860_SCC1_BASE 0x1c00
222     #define MPC860_SCC2_BASE 0x1d00
223     #define MPC860_SCC3_BASE 0x1e00
224     #define MPC860_SCC4_BASE 0x1f00
225    
226     /* GSMR Low register */
227     #define MPC860_GSMRL_MODE_MASK 0x0000000F
228    
229     /* SCC Modes */
230     #define MPC860_SCC_MODE_HDLC 0x00
231     #define MPC860_SCC_MODE_UART 0x04
232     #define MPC860_SCC_MODE_BISYNC 0x08
233     #define MPC860_SCC_MODE_ETH 0x0c
234    
235     /* SCC Event (SCCE) register */
236     #define MPC860_SCCE_TXB 0x0002 /* TX buffer sent */
237     #define MPC860_SCCE_RXB 0x0001 /* RX buffer ready */
238    
239     /* Size of an SCC buffer descriptor */
240     #define MPC860_SCC_BD_SIZE 8
241    
242     /* SCC RX Buffer Descriptor Control Word */
243     #define MPC860_SCC_RXBD_CTRL_E 0x8000 /* Empty */
244     #define MPC860_SCC_RXBD_CTRL_W 0x2000 /* Wrap */
245     #define MPC860_SCC_RXBD_CTRL_I 0x1000 /* Interrupt */
246     #define MPC860_SCC_RXBD_CTRL_L 0x0800 /* Last */
247     #define MPC860_SCC_RXBD_CTRL_F 0x0400 /* First */
248     #define MPC860_SCC_RXBD_CTRL_CM 0x0200 /* Continuous Mode */
249     #define MPC860_SCC_RXBD_CTRL_OV 0x0002 /* Overrun */
250    
251     /* SCC TX Buffer Descriptor Control Word */
252     #define MPC860_SCC_TXBD_CTRL_R 0x8000 /* Ready Bit */
253     #define MPC860_SCC_TXBD_CTRL_W 0x2000 /* Wrap */
254     #define MPC860_SCC_TXBD_CTRL_I 0x1000 /* Interrupt */
255     #define MPC860_SCC_TXBD_CTRL_L 0x0800 /* Last */
256     #define MPC860_SCC_TXBD_CTRL_TC 0x0400 /* Send TX CRC */
257     #define MPC860_SCC_TXBD_CTRL_CM 0x0200 /* Continuous Mode */
258     #define MPC860_SCC_TXBD_CTRL_UN 0x0002 /* Underrun */
259    
260     /* SCC buffer descriptor */
261     struct mpc860_scc_bd {
262     m_uint16_t offset; /* Offset in DPRAM memory */
263    
264     m_uint16_t ctrl; /* Control Word */
265     m_uint16_t buf_len; /* Buffer Length */
266     m_uint32_t bp; /* Buffer Pointer */
267     };
268    
269     /* ======================================================================== */
270    
271     /* FEC Ethernet Control Register */
272     #define MPC860_ECNTRL_FEC_PIN_MUX 0x00000004 /* FEC enable */
273     #define MPC860_ECNTRL_ETHER_EN 0x00000002 /* Ethernet Enable */
274     #define MPC860_ECNTRL_RESET 0x00000001 /* Reset Ethernet controller */
275    
276     /* FEC Interrupt Vector Register */
277     #define MPC860_IVEC_ILEVEL_MASK 0xE0000000 /* Interrupt Level */
278     #define MPC860_IVEC_ILEVEL_SHIFT 29
279    
280     /* FEC Interrupt Event Register */
281     #define MPC860_IEVENT_HBERR 0x80000000 /* Hearbeat Error */
282     #define MPC860_IEVENT_BABR 0x40000000 /* Babbling Receive Error */
283     #define MPC860_IEVENT_BABT 0x20000000 /* Babbling Transmit Error */
284     #define MPC860_IEVENT_GRA 0x10000000 /* Graceful Stop Complete */
285     #define MPC860_IEVENT_TFINT 0x08000000 /* Transmit Frame Interrupt */
286     #define MPC860_IEVENT_TXB 0x04000000 /* Transmit Buffer Interrupt */
287     #define MPC860_IEVENT_RFINT 0x02000000 /* Receive Frame Interrupt */
288     #define MPC860_IEVENT_RXB 0x01000000 /* Receive Buffer Interrupt */
289     #define MPC860_IEVENT_MII 0x00800000 /* MII Interrupt */
290     #define MPC860_IEVENT_EBERR 0x00400000 /* Ethernet Bus Error */
291    
292     /* MII data register */
293     #define MPC860_MII_OP_MASK 0x30000000 /* Opcode (10:read,11:write) */
294     #define MPC860_MII_OP_SHIFT 28
295     #define MPC860_MII_PHY_MASK 0x0F800000 /* PHY device */
296     #define MPC860_MII_PHY_SHIFT 23
297     #define MPC860_MII_REG_MASK 0x007C0000 /* PHY device */
298     #define MPC860_MII_REG_SHIFT 18
299    
300     /* Size of an FEC buffer descriptor */
301     #define MPC860_FEC_BD_SIZE 8
302    
303     /* Maximum packet size for FEC */
304     #define MPC860_FEC_MAX_PKT_SIZE 2048
305    
306     /* FEC RX Buffer Descriptor Control Word */
307     #define MPC860_FEC_RXBD_CTRL_E 0x8000 /* Empty */
308     #define MPC860_FEC_RXBD_CTRL_RO1 0x4000 /* For software use */
309     #define MPC860_FEC_RXBD_CTRL_W 0x2000 /* Wrap */
310     #define MPC860_FEC_RXBD_CTRL_RO2 0x1000 /* For software use */
311     #define MPC860_FEC_RXBD_CTRL_L 0x0800 /* Last */
312     #define MPC860_FEC_RXBD_CTRL_M 0x0100 /* Miss */
313     #define MPC860_FEC_RXBD_CTRL_BC 0x0080 /* Broadcast DA */
314     #define MPC860_FEC_RXBD_CTRL_MC 0x0040 /* Multicast DA */
315     #define MPC860_FEC_RXBD_CTRL_LG 0x0020 /* RX Frame length violation */
316     #define MPC860_FEC_RXBD_CTRL_NO 0x0010 /* RX non-octet aligned frame */
317     #define MPC860_FEC_RXBD_CTRL_SH 0x0008 /* Short Frame */
318     #define MPC860_FEC_RXBD_CTRL_CR 0x0004 /* RX CRC Error */
319     #define MPC860_FEC_RXBD_CTRL_OV 0x0002 /* Overrun */
320     #define MPC860_FEC_RXBD_CTRL_TR 0x0001 /* Truncated Frame */
321    
322     /* FEC TX Buffer Descriptor Control Word */
323     #define MPC860_FEC_TXBD_CTRL_R 0x8000 /* Ready Bit */
324     #define MPC860_FEC_TXBD_CTRL_TO1 0x4000 /* For software use */
325     #define MPC860_FEC_TXBD_CTRL_W 0x2000 /* Wrap */
326     #define MPC860_FEC_TXBD_CTRL_TO2 0x1000 /* For software use */
327     #define MPC860_FEC_TXBD_CTRL_L 0x0800 /* Last */
328     #define MPC860_FEC_TXBD_CTRL_TC 0x0400 /* Send TX CRC */
329     #define MPC860_FEC_TXBD_CTRL_DEF 0x0200 /* Defer Indication */
330     #define MPC860_FEC_TXBD_CTRL_HB 0x0100 /* Heartbeat Error */
331     #define MPC860_FEC_TXBD_CTRL_LC 0x0080 /* Late Collision */
332     #define MPC860_FEC_TXBD_CTRL_RL 0x0040 /* Retranmission Limit */
333     #define MPC860_FEC_TXBD_CTRL_UN 0x0002 /* Underrun */
334     #define MPC860_FEC_TXBD_CTRL_CSL 0x0001 /* Carrier Sense Lost */
335    
336     /* FEC buffer descriptor */
337     struct mpc860_fec_bd {
338     m_uint32_t bd_addr; /* Address in external memory */
339    
340     m_uint16_t ctrl; /* Control Word */
341     m_uint16_t buf_len; /* Buffer Length */
342     m_uint32_t bp; /* Buffer Pointer */
343     };
344    
345     /* ======================================================================== */
346    
347     struct mpc860_scc_chan {
348     netio_desc_t *nio;
349    
350     /* General SCC mode register (high and low parts) */
351     m_uint32_t gsmr_hi,gsmr_lo;
352    
353     /* Protocol-Specific mode register */
354     m_uint32_t psmr;
355    
356     /* SCC Event and Mask registers */
357     m_uint16_t scce,sccm;
358    
359     /* TX packet */
360     u_char tx_pkt[MPC860_SCC_MAX_PKT_SIZE];
361     };
362    
363 dpavlin 7 /* MPC860 private data */
364     struct mpc860_data {
365     char *name;
366     vm_obj_t vm_obj;
367     struct vdevice dev;
368     struct pci_device *pci_dev;
369     vm_instance_t *vm;
370    
371     /* SIU Interrupt Pending Register and Interrupt Mask Register */
372     m_uint32_t sipend,simask;
373    
374     /* CPM Interrupt Configuration Register */
375     m_uint32_t cicr;
376    
377     /* CPM Interrupt Pending Register and Interrupt Mask Register */
378     m_uint32_t cipr,cimr;
379    
380     /* IDMA status and mask registers */
381     m_uint8_t idsr[2],idmr[2];
382    
383 dpavlin 11 /* Port B Data Register */
384     m_uint32_t pbdat,pcdat;
385    
386     /* SPI callback for TX data */
387     mpc860_spi_tx_callback_t spi_tx_callback;
388     void *spi_user_arg;
389    
390     /* SCC channels */
391     struct mpc860_scc_chan scc_chan[MPC860_SCC_NR_CHAN];
392    
393     /* FEC (Fast Ethernet Controller) */
394     m_uint32_t fec_rdes_start,fec_xdes_start;
395     m_uint32_t fec_rdes_current,fec_xdes_current;
396     m_uint32_t fec_rbuf_size;
397    
398     /* FEC Interrupt Event/Mask registers */
399     m_uint32_t fec_ievent,fec_imask,fec_ivec;
400     m_uint32_t fec_ecntrl;
401    
402     /* FEC NetIO */
403     netio_desc_t *fec_nio;
404    
405     /* FEC MII registers */
406     m_uint32_t fec_mii_data;
407     m_uint16_t fec_mii_regs[32];
408    
409 dpavlin 7 /* Dual-Port RAM */
410     m_uint8_t dpram[MPC860_DPRAM_SIZE];
411     };
412    
413     /* Log a MPC message */
414     #define MPC_LOG(d,msg...) vm_log((d)->vm,(d)->name,msg)
415    
416     /* ======================================================================== */
417    
418     /* DPRAM access routines */
419     static inline m_uint8_t dpram_r8(struct mpc860_data *d,m_uint16_t offset)
420     {
421     return(d->dpram[offset]);
422     }
423    
424     static inline void dpram_w8(struct mpc860_data *d,m_uint16_t offset,
425     m_uint8_t val)
426 dpavlin 8 {
427 dpavlin 7 d->dpram[offset] = val;
428     }
429    
430     static inline m_uint16_t dpram_r16(struct mpc860_data *d,m_uint16_t offset)
431     {
432     m_uint16_t val;
433    
434     val = (m_uint16_t)d->dpram[offset] << 8;
435     val |= d->dpram[offset+1];
436     return(val);
437     }
438    
439     static inline void dpram_w16(struct mpc860_data *d,m_uint16_t offset,
440     m_uint16_t val)
441 dpavlin 8 {
442 dpavlin 7 d->dpram[offset] = val >> 8;
443     d->dpram[offset+1] = val & 0xFF;
444     }
445    
446     static inline m_uint32_t dpram_r32(struct mpc860_data *d,m_uint16_t offset)
447     {
448     m_uint32_t val;
449    
450     val = d->dpram[offset] << 24;
451     val |= d->dpram[offset+1] << 16;
452     val |= d->dpram[offset+2] << 8;
453     val |= d->dpram[offset+3];
454     return(val);
455     }
456    
457     static inline void dpram_w32(struct mpc860_data *d,m_uint16_t offset,
458     m_uint32_t val)
459     {
460     d->dpram[offset] = val >> 24;
461     d->dpram[offset+1] = val >> 16;
462     d->dpram[offset+2] = val >> 8;
463     d->dpram[offset+3] = val;
464     }
465    
466     /* ======================================================================== */
467    
468     /* Update interrupt status */
469     static void mpc860_update_irq_status(struct mpc860_data *d)
470     {
471     cpu_ppc_t *cpu = CPU_PPC32(d->vm->boot_cpu);
472    
473     cpu->irq_pending = d->sipend & d->simask;
474     cpu->irq_check = cpu->irq_pending;
475     }
476    
477 dpavlin 11 /* Map level to SIU Interrupt Pending Register bit */
478     static inline u_int mpc860_get_siu_lvl(u_int level)
479     {
480     return(16 + ((7 - level) << 1));
481     }
482    
483 dpavlin 7 /* Update CPM interrupt status */
484     static void mpc860_update_cpm_int_status(struct mpc860_data *d)
485     {
486 dpavlin 11 u_int level,siu_bit;
487    
488     level = (d->cicr & MPC860_CICR_IRL_MASK) >> MPC860_CICR_IRL_SHIFT;
489     siu_bit = mpc860_get_siu_lvl(level);
490    
491     if ((d->cipr & d->cimr) && (d->cicr & MPC860_CICR_IEN))
492     mpc860_set_pending_irq(d,siu_bit);
493 dpavlin 7 else
494 dpavlin 11 mpc860_clear_pending_irq(d,siu_bit);
495 dpavlin 7 }
496    
497 dpavlin 11 /* ======================================================================== */
498     /* IDMA */
499     /* ======================================================================== */
500    
501 dpavlin 7 /* Update an IDMA status register */
502     static int mpc860_idma_update_idsr(struct mpc860_data *d,u_int id)
503     {
504     u_int cpm_int;
505    
506     switch(id) {
507     case 0:
508     cpm_int = MPC860_CIPR_IDMA1;
509     break;
510     case 1:
511     cpm_int = MPC860_CIPR_IDMA2;
512     break;
513     default:
514     return(-1);
515     }
516    
517     if (d->idsr[id] & d->idmr[id])
518     d->cipr |= cpm_int;
519     else
520     d->cipr &= ~cpm_int;
521    
522     mpc860_update_cpm_int_status(d);
523     return(0);
524     }
525    
526     /* Process to an IDMA transfer for the specified buffer descriptor */
527     static void mpc860_idma_transfer(struct mpc860_data *d,
528     struct mpc860_idma_bd *bd)
529     {
530     physmem_dma_transfer(d->vm,bd->src_bp,bd->dst_bp,bd->buf_len);
531     }
532    
533     /* Fetch an IDMA descriptor from Dual-Port RAM */
534     static int mpc860_idma_fetch_bd(struct mpc860_data *d,m_uint16_t bd_addr,
535     struct mpc860_idma_bd *bd)
536     {
537     if ((bd_addr < MPC860_DPRAM_OFFSET) || (bd_addr > MPC860_DPRAM_END))
538     return(-1);
539    
540     bd->offset = bd_addr - MPC860_DPRAM_OFFSET;
541    
542     /* Fetch control word */
543     bd->ctrl = dpram_r16(d,bd->offset+0x00);
544    
545     /* Fetch function code registers */
546     bd->dfcr = dpram_r8(d,bd->offset+0x02);
547     bd->sfcr = dpram_r8(d,bd->offset+0x03);
548    
549     /* Fetch buffer length, source and destination addresses */
550     bd->buf_len = dpram_r32(d,bd->offset+0x04);
551     bd->src_bp = dpram_r32(d,bd->offset+0x08);
552     bd->dst_bp = dpram_r32(d,bd->offset+0x0c);
553    
554     #if DEBUG_IDMA
555     MPC_LOG(d,"fetched IDMA BD at 0x%4.4x, src_bp=0x%8.8x, dst_bp=0x%8.8x "
556     "len=%d\n",bd->offset,bd->src_bp,bd->dst_bp,bd->buf_len);
557     #endif
558    
559     return(0);
560     }
561    
562     /* Start an IDMA channel */
563     static int mpc860_idma_start_channel(struct mpc860_data *d,u_int id)
564     {
565     struct mpc860_idma_bd bd;
566     m_uint16_t dma_base,ibase,bd_offset;
567    
568     switch(id) {
569     case 0:
570     dma_base = MPC860_IDMA1_BASE;
571     break;
572     case 1:
573     dma_base = MPC860_IDMA2_BASE;
574     break;
575     default:
576     return(-1);
577     }
578    
579     /* Get the IBASE register (offset 0) */
580     ibase = bd_offset = dpram_r16(d,dma_base+0x00);
581    
582     while(1) {
583     /* Fetch a descriptor */
584     if (mpc860_idma_fetch_bd(d,bd_offset,&bd) == -1)
585     return(-1);
586    
587     if (!(bd.ctrl & MPC860_IDMA_CTRL_V)) {
588     d->idsr[id] |= MPC860_IDSR_OB;
589     break;
590     }
591    
592     /* Run the DMA transfer */
593     mpc860_idma_transfer(d,&bd);
594    
595     /* Clear the Valid bit */
596     bd.ctrl &= ~MPC860_IDMA_CTRL_V;
597 dpavlin 8 dpram_w16(d,bd_offset-MPC860_DPRAM_OFFSET+0x00,bd.ctrl);
598 dpavlin 7
599     /* Generate an interrupt for this buffer ? */
600     if (bd.ctrl & MPC860_IDMA_CTRL_I)
601     d->idsr[id] |= MPC860_IDSR_AD;
602    
603     /* Stop if this is the last buffer of chain */
604     if (bd.ctrl & MPC860_IDMA_CTRL_L) {
605     d->idsr[id] |= MPC860_IDSR_DONE;
606     break;
607     }
608    
609     bd_offset += sizeof(MPC860_IDMA_BD_SIZE);
610     }
611    
612     mpc860_idma_update_idsr(d,id);
613     return(0);
614     }
615    
616 dpavlin 11 /* ======================================================================== */
617     /* SPI (Serial Peripheral Interface) */
618     /* ======================================================================== */
619    
620     /* Initialize SPI RX parameters */
621     static void mpc860_spi_init_rx_params(struct mpc860_data *d)
622     {
623     m_uint16_t spi_base,rbase;
624    
625     spi_base = dpram_r16(d,MPC860_SPI_BASE_ADDR);
626    
627     /* Get the RBASE (offset 0) and store it in RBPTR */
628     rbase = dpram_r16(d,spi_base+0x00);
629     dpram_w16(d,spi_base+0x10,rbase);
630     }
631    
632     /* Initialize SPI TX parameters */
633     static void mpc860_spi_init_tx_params(struct mpc860_data *d)
634     {
635     m_uint16_t spi_base,tbase;
636    
637     spi_base = dpram_r16(d,MPC860_SPI_BASE_ADDR);
638    
639     /* Get the TBASE (offset 2) and store it in TBPTR */
640     tbase = dpram_r16(d,spi_base+0x02);
641     dpram_w16(d,spi_base+0x20,tbase);
642     }
643    
644     /* Initialize SPI RX/TX parameters */
645     static void mpc860_spi_init_rx_tx_params(struct mpc860_data *d)
646     {
647     mpc860_spi_init_rx_params(d);
648     mpc860_spi_init_tx_params(d);
649     }
650    
651     /* Fetch a SPI buffer descriptor */
652     static int mpc860_spi_fetch_bd(struct mpc860_data *d,m_uint16_t bd_addr,
653     struct mpc860_spi_bd *bd)
654     {
655     void *ptr;
656    
657     if ((bd_addr < MPC860_DPRAM_OFFSET) || (bd_addr > MPC860_DPRAM_END))
658     return(-1);
659    
660     bd->offset = bd_addr - MPC860_DPRAM_OFFSET;
661     ptr = &d->dpram[bd->offset];
662    
663     /* Fetch control word */
664     bd->ctrl = dpram_r16(d,bd->offset+0x00);
665    
666     /* Fetch buffer length and buffer pointer */
667     bd->buf_len = dpram_r16(d,bd->offset+0x02);
668     bd->bp = dpram_r32(d,bd->offset+0x04);
669    
670     #if DEBUG_SPI
671     MPC_LOG(d,"fetched SPI BD at 0x%4.4x, bp=0x%8.8x, len=%d\n",
672     bd->offset,bd->bp,bd->buf_len);
673     #endif
674    
675     return(0);
676     }
677    
678     /* Start SPI transmit */
679     static int mpc860_spi_start_tx(struct mpc860_data *d)
680     {
681     struct mpc860_spi_bd bd;
682     m_uint16_t bd_offset;
683     m_uint16_t spi_base;
684     u_char buffer[512];
685     u_int buf_len;
686    
687     spi_base = dpram_r16(d,MPC860_SPI_BASE_ADDR);
688    
689     /* Get the TBPTR (offset 0x20) register */
690     bd_offset = dpram_r16(d,spi_base+0x20);
691    
692     while(1) {
693     /* Fetch a TX descriptor */
694     if (mpc860_spi_fetch_bd(d,bd_offset,&bd) == -1)
695     return(FALSE);
696    
697     /* If the descriptor is not ready, stop now */
698     if (!(bd.ctrl & MPC860_SPI_TXBD_CTRL_R))
699     return(FALSE);
700    
701     /* Extract the data */
702     buf_len = bd.buf_len;
703    
704     if (bd.buf_len > sizeof(buffer)) {
705     MPC_LOG(d,"SPI: buffer too small for transmit.\n");
706     buf_len = sizeof(buffer);
707     }
708    
709     physmem_copy_from_vm(d->vm,buffer,bd.bp,buf_len);
710    
711     /* Send the data to the user callback (if specified) */
712     if (d->spi_tx_callback != NULL)
713     d->spi_tx_callback(d,buffer,buf_len,d->spi_user_arg);
714    
715     /* Clear the Ready bit of the TX descriptor */
716     bd.ctrl &= ~MPC860_SPI_TXBD_CTRL_R;
717     dpram_w16(d,bd.offset+0x00,bd.ctrl);
718    
719     /* Set pointer on next TX descriptor (wrap ring if necessary) */
720     if (bd.ctrl & MPC860_SPI_TXBD_CTRL_W) {
721     bd_offset = dpram_r16(d,spi_base+0x02);
722     } else {
723     bd_offset += MPC860_SPI_BD_SIZE;
724     }
725     dpram_w16(d,spi_base+0x20,bd_offset);
726    
727     /* Stop if this is the last buffer in chain */
728     if (bd.ctrl & MPC860_SPI_TXBD_CTRL_L)
729     break;
730     }
731    
732     return(TRUE);
733     }
734    
735     /* Put a buffer into SPI receive buffers */
736     int mpc860_spi_receive(struct mpc860_data *d,u_char *buffer,u_int len)
737     {
738     struct mpc860_spi_bd bd;
739     m_uint16_t bd_offset;
740     m_uint16_t spi_base;
741     u_int clen,mrblr;
742    
743     spi_base = dpram_r16(d,MPC860_SPI_BASE_ADDR);
744    
745     /* Get the RBPTR (offset 0x10) */
746     bd_offset = dpram_r16(d,spi_base+0x10);
747    
748     /* Get the maximum buffer size */
749     mrblr = dpram_r16(d,spi_base+0x06);
750    
751     while(len > 0) {
752     /* Fetch a RX descriptor */
753     if (mpc860_spi_fetch_bd(d,bd_offset,&bd) == -1)
754     return(FALSE);
755    
756     /* If the buffer is not empty, do not use it */
757     if (!(bd.ctrl & MPC860_SPI_RXBD_CTRL_E))
758     return(FALSE);
759    
760     /* Write data into the RX buffer */
761     clen = m_min(mrblr,len);
762     physmem_copy_to_vm(d->vm,buffer,bd.bp,clen);
763     buffer += clen;
764     len -= clen;
765    
766     /* Update the length field */
767     dpram_w16(d,bd.offset+0x02,clen);
768    
769     /* If no more data, set the "Last" bit */
770     if (!len)
771     bd.ctrl |= MPC860_SPI_RXBD_CTRL_L;
772    
773     /* Clear the Empty bit of the RX descriptor */
774     bd.ctrl &= ~MPC860_SPI_RXBD_CTRL_E;
775     dpram_w16(d,bd.offset+0x00,bd.ctrl);
776    
777     /* Set pointer on next RX descriptor */
778     if (bd.ctrl & MPC860_SPI_RXBD_CTRL_W) {
779     bd_offset = dpram_r16(d,spi_base+0x00);
780     } else {
781     bd_offset += MPC860_SPI_BD_SIZE;
782     }
783     dpram_w16(d,spi_base+0x10,bd_offset);
784     }
785    
786     if (len > 0)
787     MPC_LOG(d,"SPI: no buffers available for receive.\n");
788    
789     return(0);
790     }
791    
792     /* Set SPI TX callback */
793     void mpc860_spi_set_tx_callback(struct mpc860_data *d,
794     mpc860_spi_tx_callback_t cbk,
795     void *user_arg)
796     {
797     d->spi_tx_callback = cbk;
798     d->spi_user_arg = user_arg;
799     }
800    
801     /* ======================================================================== */
802     /* SCC (Serial Communication Controller) */
803     /* ======================================================================== */
804    
805     typedef struct {
806     u_int cipr_irq;
807     m_uint32_t dpram_base;
808     }scc_chan_info_t;
809    
810     static scc_chan_info_t scc_chan_info[MPC860_SCC_NR_CHAN] = {
811     { MPC860_CIPR_SCC1, MPC860_SCC1_BASE },
812     { MPC860_CIPR_SCC2, MPC860_SCC2_BASE },
813     { MPC860_CIPR_SCC3, MPC860_SCC3_BASE },
814     { MPC860_CIPR_SCC4, MPC860_SCC4_BASE },
815     };
816    
817     /* Initialize SCC RX parameters */
818     static void mpc860_scc_init_rx_params(struct mpc860_data *d,u_int scc_chan)
819     {
820     m_uint16_t scc_base,rbase;
821    
822     scc_base = scc_chan_info[scc_chan].dpram_base;
823    
824     /* Get the RBASE (offset 0) and store it in RBPTR */
825     rbase = dpram_r16(d,scc_base+0x00);
826     dpram_w16(d,scc_base+0x10,rbase);
827     }
828    
829     /* Initialize SCC TX parameters */
830     static void mpc860_scc_init_tx_params(struct mpc860_data *d,u_int scc_chan)
831     {
832     m_uint16_t scc_base,tbase;
833    
834     scc_base = scc_chan_info[scc_chan].dpram_base;
835    
836     /* Get the TBASE (offset 2) and store it in TBPTR */
837     tbase = dpram_r16(d,scc_base+0x02);
838     dpram_w16(d,scc_base+0x20,tbase);
839     }
840    
841     /* Initialize SCC RX/TX parameters */
842     static void mpc860_scc_init_rx_tx_params(struct mpc860_data *d,u_int scc_chan)
843     {
844     mpc860_scc_init_rx_params(d,scc_chan);
845     mpc860_scc_init_tx_params(d,scc_chan);
846     }
847    
848     /* Set an SCC interrupt */
849     static int mpc860_scc_update_irq(struct mpc860_data *d,u_int scc_chan)
850     {
851     struct mpc860_scc_chan *chan = &d->scc_chan[scc_chan];
852    
853     if (chan->scce & chan->sccm)
854     d->cipr |= scc_chan_info[scc_chan].cipr_irq;
855     else
856     d->cipr &= ~scc_chan_info[scc_chan].cipr_irq;
857    
858     mpc860_update_cpm_int_status(d);
859     return(0);
860     }
861    
862     /* Fetch a SCC buffer descriptor */
863     static int mpc860_scc_fetch_bd(struct mpc860_data *d,m_uint16_t bd_addr,
864     struct mpc860_scc_bd *bd)
865     {
866     void *ptr;
867    
868     if ((bd_addr < MPC860_DPRAM_OFFSET) || (bd_addr > MPC860_DPRAM_END))
869     return(-1);
870    
871     bd->offset = bd_addr - MPC860_DPRAM_OFFSET;
872     ptr = &d->dpram[bd->offset];
873    
874     /* Fetch control word */
875     bd->ctrl = dpram_r16(d,bd->offset+0x00);
876    
877     /* Fetch buffer length and buffer pointer */
878     bd->buf_len = dpram_r16(d,bd->offset+0x02);
879     bd->bp = dpram_r32(d,bd->offset+0x04);
880    
881     #if DEBUG_SCC
882     MPC_LOG(d,"fetched SCC BD at 0x%4.4x, bp=0x%8.8x, len=%d\n",
883     bd->offset,bd->bp,bd->buf_len);
884     #endif
885    
886     return(0);
887     }
888    
889     /* Handle the TX ring of an SCC channel (transmit a single packet) */
890     static int mpc860_scc_handle_tx_ring_single(struct mpc860_data *d,
891     u_int scc_chan)
892     {
893     struct mpc860_scc_bd txd0,ctxd,*ptxd;
894     struct mpc860_scc_chan *chan;
895     scc_chan_info_t *scc_info;
896     m_uint16_t bd_offset;
897     m_uint32_t clen,tot_len;
898     u_char *pkt_ptr;
899     int done = FALSE;
900     int irq = FALSE;
901    
902     scc_info = &scc_chan_info[scc_chan];
903     chan = &d->scc_chan[scc_chan];
904    
905     /* Get the TBPTR (offset 0x20) register */
906     bd_offset = dpram_r16(d,scc_info->dpram_base+0x20);
907    
908     /* Try to acquire the first descriptor */
909     ptxd = &txd0;
910     mpc860_scc_fetch_bd(d,bd_offset,ptxd);
911    
912     /* If we don't own the first descriptor, we cannot transmit */
913     if (!(txd0.ctrl & MPC860_SCC_TXBD_CTRL_R))
914     return(FALSE);
915    
916     /* Empty packet for now */
917     pkt_ptr = chan->tx_pkt;
918     tot_len = 0;
919    
920     do {
921     /* Copy data into the buffer */
922     clen = ptxd->buf_len;
923     physmem_copy_from_vm(d->vm,pkt_ptr,ptxd->bp,clen);
924     pkt_ptr += clen;
925     tot_len += clen;
926    
927     /* Signal IRQ ? */
928     if (ptxd->ctrl & MPC860_SCC_TXBD_CTRL_I)
929     irq = TRUE;
930    
931     /*
932     * Clear the ready bit (except for the first descriptor,
933     * which is cleared when the full packet has been sent).
934     */
935     if (ptxd != &txd0) {
936     ptxd->ctrl &= ~MPC860_SCC_TXBD_CTRL_R;
937     dpram_w16(d,ptxd->offset+0x00,ptxd->ctrl);
938     }
939    
940     /* Set pointer on next TX descriptor (wrap ring if necessary) */
941     if (ptxd->ctrl & MPC860_SCC_TXBD_CTRL_W) {
942     bd_offset = dpram_r16(d,scc_info->dpram_base+0x02);
943     } else {
944     bd_offset += MPC860_SCC_BD_SIZE;
945     }
946     dpram_w16(d,scc_info->dpram_base+0x20,bd_offset);
947    
948     /* If this is the last descriptor, we have finished */
949     if (!(ptxd->ctrl & MPC860_SCC_TXBD_CTRL_L)) {
950     mpc860_scc_fetch_bd(d,bd_offset,&ctxd);
951     ptxd = &ctxd;
952     } else {
953     done = TRUE;
954     }
955     }while(!done);
956    
957     if (tot_len != 0) {
958     #if DEBUG_SCC
959     MPC_LOG(d,"SCC%u: sending packet of %u bytes\n",scc_chan+1,tot_len);
960     mem_dump(log_file,chan->tx_pkt,tot_len);
961     #endif
962     /* send packet on wire */
963     netio_send(chan->nio,chan->tx_pkt,tot_len);
964     }
965    
966     /* Clear the Ready bit of the first TX descriptor */
967     txd0.ctrl &= ~MPC860_SCC_TXBD_CTRL_R;
968     dpram_w16(d,txd0.offset+0x00,txd0.ctrl);
969    
970     /* Trigger SCC IRQ */
971     if (irq) {
972     chan->scce |= MPC860_SCCE_TXB;
973     mpc860_scc_update_irq(d,scc_chan);
974     }
975    
976     return(TRUE);
977     }
978    
979     /* Handle the TX ring of the specified SCC channel (multiple pkts possible) */
980     static int mpc860_scc_handle_tx_ring(struct mpc860_data *d,u_int scc_chan)
981     {
982     int i;
983    
984     for(i=0;i<MPC860_TXRING_PASS_COUNT;i++)
985     if (!mpc860_scc_handle_tx_ring_single(d,scc_chan))
986     break;
987    
988     return(TRUE);
989     }
990    
991     /* Handle RX packet for an SCC channel */
992     static int mpc860_scc_handle_rx_pkt(netio_desc_t *nio,
993     u_char *pkt,ssize_t pkt_len,
994     struct mpc860_data *d,void *arg)
995     {
996     struct mpc860_scc_bd rxd0,crxd,*prxd;
997     struct mpc860_scc_chan *chan;
998     u_int scc_chan = (int)arg;
999     scc_chan_info_t *scc_info;
1000     m_uint16_t bd_offset;
1001     ssize_t clen,tot_len;
1002     u_char *pkt_ptr;
1003     u_int mrblr;
1004     int irq = FALSE;
1005    
1006     scc_info = &scc_chan_info[scc_chan];
1007     chan = &d->scc_chan[scc_chan];
1008    
1009     /* Get the RBPTR (offset 0x10) register */
1010     bd_offset = dpram_r16(d,scc_info->dpram_base+0x10);
1011    
1012     /* Get the maximum buffer size */
1013     mrblr = dpram_r16(d,scc_info->dpram_base+0x06);
1014    
1015     /* Try to acquire the first descriptor */
1016     prxd = &rxd0;
1017     mpc860_scc_fetch_bd(d,bd_offset,prxd);
1018    
1019     /* If we don't own the first descriptor, we cannot transmit */
1020     if (!(rxd0.ctrl & MPC860_SCC_RXBD_CTRL_E))
1021     return(FALSE);
1022    
1023     pkt_ptr = pkt;
1024     tot_len = pkt_len;
1025    
1026     while(tot_len > 0) {
1027     /* Write data into the RX buffer */
1028     clen = m_min(mrblr,tot_len);
1029     physmem_copy_to_vm(d->vm,pkt_ptr,prxd->bp,clen);
1030     pkt_ptr += clen;
1031     tot_len -= clen;
1032    
1033     /* Signal IRQ ? */
1034     if (prxd->ctrl & MPC860_SCC_RXBD_CTRL_I)
1035     irq = TRUE;
1036    
1037     /* Set the Last flag if we have finished */
1038     if (!tot_len) {
1039     /* Set the full length */
1040     switch(chan->gsmr_lo & MPC860_GSMRL_MODE_MASK) {
1041     case MPC860_SCC_MODE_ETH:
1042     pkt_len += 4;
1043     break;
1044     case MPC860_SCC_MODE_HDLC:
1045     pkt_len += 2;
1046     break;
1047     }
1048    
1049     dpram_w16(d,prxd->offset+0x02,pkt_len);
1050     prxd->ctrl |= MPC860_SCC_RXBD_CTRL_L;
1051     } else {
1052     /* Update the length field */
1053     dpram_w16(d,prxd->offset+0x02,clen);
1054     }
1055    
1056     /*
1057     * Clear the empty bit (except for the first descriptor,
1058     * which is cleared when the full packet has been stored).
1059     */
1060     if (prxd != &rxd0) {
1061     prxd->ctrl &= ~MPC860_SCC_RXBD_CTRL_E;
1062     dpram_w16(d,prxd->offset+0x00,prxd->ctrl);
1063     }
1064    
1065     /* Set pointer on next RX descriptor (wrap ring if necessary) */
1066     if (prxd->ctrl & MPC860_SCC_RXBD_CTRL_W) {
1067     bd_offset = dpram_r16(d,scc_info->dpram_base+0x00);
1068     } else {
1069     bd_offset += MPC860_SCC_BD_SIZE;
1070     }
1071     dpram_w16(d,scc_info->dpram_base+0x10,bd_offset);
1072    
1073     /* If this is the last descriptor, we have finished */
1074     if (!tot_len) {
1075     mpc860_scc_fetch_bd(d,bd_offset,&crxd);
1076     prxd = &crxd;
1077     }
1078     }
1079    
1080     /* Clear the Empty bit of the first RX descriptor and set First bit */
1081     rxd0.ctrl &= ~MPC860_SCC_RXBD_CTRL_E;
1082     rxd0.ctrl |= MPC860_SCC_RXBD_CTRL_F;
1083     dpram_w16(d,rxd0.offset+0x00,rxd0.ctrl);
1084    
1085     /* Trigger SCC IRQ */
1086     if (irq) {
1087     d->scc_chan[scc_chan].scce |= MPC860_SCCE_RXB;
1088     mpc860_scc_update_irq(d,scc_chan);
1089     }
1090    
1091     return(TRUE);
1092     }
1093    
1094     /* Set NIO for the specified SCC channel */
1095     int mpc860_scc_set_nio(struct mpc860_data *d,u_int scc_chan,netio_desc_t *nio)
1096     {
1097     struct mpc860_scc_chan *chan;
1098    
1099     if (!d || (scc_chan >= MPC860_SCC_NR_CHAN))
1100     return(-1);
1101    
1102     chan = &d->scc_chan[scc_chan];
1103    
1104     /* check that a NIO is not already bound */
1105     if (chan->nio != NULL)
1106     return(-1);
1107    
1108     chan->nio = nio;
1109     netio_rxl_add(nio,(netio_rx_handler_t)mpc860_scc_handle_rx_pkt,
1110     d,(void *)scc_chan);
1111     return(0);
1112     }
1113    
1114     /* Unset NIO of the specified SCC channel */
1115     int mpc860_scc_unset_nio(struct mpc860_data *d,u_int scc_chan)
1116     {
1117     struct mpc860_scc_chan *chan;
1118    
1119     if (!d || (scc_chan >= MPC860_SCC_NR_CHAN))
1120     return(-1);
1121    
1122     chan = &d->scc_chan[scc_chan];
1123    
1124     if (chan->nio != NULL) {
1125     netio_rxl_remove(chan->nio);
1126     chan->nio = NULL;
1127     }
1128    
1129     return(0);
1130     }
1131    
1132     /*
1133     * SCC register access.
1134     *
1135     * SCC1: 0x0a00 to 0x0a1f
1136     * SCC2: 0x0a20 to 0x0a3f
1137     * SCC3: 0x0a40 to 0x0a5f
1138     * SCC4: 0x0a60 to 0x0a7f
1139     */
1140     static int dev_mpc860_scc_access(struct mpc860_data *d,m_uint32_t offset,
1141     u_int op_size,u_int op_type,m_uint64_t *data)
1142     {
1143     struct mpc860_scc_chan *chan;
1144     u_int scc_chan,reg;
1145    
1146     /* Extract channel ID and register */
1147     scc_chan = (offset >> 5) & 0x03;
1148     reg = offset & 0x1F;
1149    
1150     chan = &d->scc_chan[scc_chan];
1151    
1152     switch(reg) {
1153     /* GSMRL - General SCC mode register (Low part) */
1154     case 0x00:
1155     if (op_type == MTS_READ)
1156     *data = chan->gsmr_lo;
1157     else
1158     chan->gsmr_lo = *data;
1159     break;
1160    
1161     /* GSMRH - General SCC mode register (High part) */
1162     case 0x04:
1163     if (op_type == MTS_READ)
1164     *data = chan->gsmr_hi;
1165     else
1166     chan->gsmr_hi = *data;
1167     break;
1168    
1169     /* PSMR - Protocol-Specific Mode Register */
1170     case 0x08:
1171     if (op_type == MTS_READ)
1172     *data = chan->psmr;
1173     else
1174     chan->psmr = *data;
1175     break;
1176    
1177     /* TOD - Transmit On Demand */
1178     case 0x0c:
1179     if ((op_type == MTS_WRITE) && (*data & 0x8000))
1180     mpc860_scc_handle_tx_ring(d,scc_chan);
1181     break;
1182    
1183     /* SCCE - SCC Event Register */
1184     case 0x10:
1185     if (op_type == MTS_READ)
1186     *data = chan->scce;
1187     else {
1188     chan->scce &= ~(*data);
1189     mpc860_scc_update_irq(d,scc_chan);
1190     }
1191     break;
1192    
1193     /* SCCM - SCC Mask Register */
1194     case 0x14:
1195     if (op_type == MTS_READ)
1196     *data = chan->sccm;
1197     else {
1198     chan->sccm = *data;
1199     mpc860_scc_update_irq(d,scc_chan);
1200     }
1201     break;
1202     }
1203    
1204     return(0);
1205     }
1206    
1207     /* ======================================================================== */
1208     /* FEC (Fast Ethernet Controller) */
1209     /* ======================================================================== */
1210    
1211     /* Trigger interrupt for FEC */
1212     static void mpc860_fec_update_irq_status(struct mpc860_data *d)
1213     {
1214     u_int level,siu_bit;
1215    
1216     level = (d->fec_ivec & MPC860_IVEC_ILEVEL_MASK) >> MPC860_IVEC_ILEVEL_SHIFT;
1217     siu_bit = mpc860_get_siu_lvl(level);
1218    
1219     if (d->fec_ievent & d->fec_imask)
1220     mpc860_set_pending_irq(d,siu_bit);
1221     else
1222     mpc860_clear_pending_irq(d,siu_bit);
1223     }
1224    
1225     /* Fetch a FEC buffer descriptor, located in external memory */
1226     static int mpc860_fec_fetch_bd(struct mpc860_data *d,m_uint32_t bd_addr,
1227     struct mpc860_fec_bd *bd)
1228     {
1229     m_uint32_t w0,w1;
1230    
1231     /* Set BD address */
1232     bd->bd_addr = bd_addr;
1233    
1234     w0 = physmem_copy_u32_from_vm(d->vm,bd_addr);
1235     w1 = physmem_copy_u32_from_vm(d->vm,bd_addr+4);
1236    
1237     bd->ctrl = w0 >> 16;
1238     bd->buf_len = w0 & 0xFFFF;
1239     bd->bp = w1;
1240    
1241     #if DEBUG_FEC
1242     MPC_LOG(d,"fetched FEC BD at 0x%8.8x, bp=0x%8.8x, len=%d\n",
1243     bd->bd_addr,bd->bp,bd->buf_len);
1244     #endif
1245    
1246     return(0);
1247     }
1248    
1249     /* Handle the TX ring of the FEC (transmit a single packet) */
1250     static int mpc860_fec_handle_tx_ring_single(struct mpc860_data *d)
1251     {
1252     u_char tx_pkt[MPC860_FEC_MAX_PKT_SIZE];
1253     struct mpc860_fec_bd txd0,ctxd,*ptxd;
1254     m_uint32_t clen,tot_len;
1255     u_char *pkt_ptr;
1256     int done = FALSE;
1257    
1258     if (!d->fec_xdes_current)
1259     return(FALSE);
1260    
1261     /* Try to acquire the first descriptor */
1262     ptxd = &txd0;
1263     mpc860_fec_fetch_bd(d,d->fec_xdes_current,ptxd);
1264    
1265     /* If we don't own the first descriptor, we cannot transmit */
1266     if (!(txd0.ctrl & MPC860_FEC_TXBD_CTRL_R))
1267     return(FALSE);
1268    
1269     /* Empty packet for now */
1270     pkt_ptr = tx_pkt;
1271     tot_len = 0;
1272    
1273     do {
1274     /* Copy data into the buffer */
1275     clen = ptxd->buf_len;
1276     physmem_copy_from_vm(d->vm,pkt_ptr,ptxd->bp,clen);
1277     pkt_ptr += clen;
1278     tot_len += clen;
1279    
1280     /*
1281     * Clear the ready bit (except for the first descriptor,
1282     * which is cleared when the full packet has been sent).
1283     */
1284     if (ptxd != &txd0) {
1285     ptxd->ctrl &= ~MPC860_FEC_TXBD_CTRL_R;
1286     physmem_copy_u16_to_vm(d->vm,ptxd->bd_addr+0x00,ptxd->ctrl);
1287     }
1288    
1289     /* Set pointer on next TX descriptor (wrap ring if necessary) */
1290     if (ptxd->ctrl & MPC860_FEC_TXBD_CTRL_W) {
1291     d->fec_xdes_current = d->fec_xdes_start;
1292     } else {
1293     d->fec_xdes_current += MPC860_FEC_BD_SIZE;
1294     }
1295    
1296     /* If this is the last descriptor, we have finished */
1297     if (!(ptxd->ctrl & MPC860_FEC_TXBD_CTRL_L)) {
1298     mpc860_fec_fetch_bd(d,d->fec_xdes_current,&ctxd);
1299     ptxd = &ctxd;
1300     } else {
1301     done = TRUE;
1302     }
1303     }while(!done);
1304    
1305     if (tot_len != 0) {
1306     #if DEBUG_FEC
1307     MPC_LOG(d,"FEC: sending packet of %u bytes\n",tot_len);
1308     mem_dump(log_file,tx_pkt,tot_len);
1309     #endif
1310     /* send packet on wire */
1311     netio_send(d->fec_nio,tx_pkt,tot_len);
1312     }
1313    
1314     /* Clear the Ready bit of the first TX descriptor */
1315     txd0.ctrl &= ~MPC860_FEC_TXBD_CTRL_R;
1316     physmem_copy_u16_to_vm(d->vm,txd0.bd_addr+0x00,txd0.ctrl);
1317    
1318     /* Trigger FEC IRQ */
1319     d->fec_ievent |= MPC860_IEVENT_TFINT | MPC860_IEVENT_TXB;
1320     mpc860_fec_update_irq_status(d);
1321     return(TRUE);
1322     }
1323    
1324     /* Handle the TX ring of the FEC (multiple pkts possible) */
1325     static int mpc860_fec_handle_tx_ring(struct mpc860_data *d)
1326     {
1327     int i;
1328    
1329     for(i=0;i<MPC860_TXRING_PASS_COUNT;i++)
1330     if (!mpc860_fec_handle_tx_ring_single(d))
1331     break;
1332    
1333     return(TRUE);
1334     }
1335    
1336     /* Handle RX packet for the Fast Ethernet Controller */
1337     static int mpc860_fec_handle_rx_pkt(netio_desc_t *nio,
1338     u_char *pkt,ssize_t pkt_len,
1339     struct mpc860_data *d,void *arg)
1340     {
1341     n_eth_hdr_t *hdr = (n_eth_hdr_t *)pkt;
1342     struct mpc860_fec_bd rxd0,crxd,*prxd;
1343     ssize_t clen,tot_len;
1344     u_char *pkt_ptr;
1345    
1346     if (!d->fec_rdes_current)
1347     return(FALSE);
1348    
1349     /* Try to acquire the first descriptor */
1350     prxd = &rxd0;
1351     mpc860_fec_fetch_bd(d,d->fec_rdes_current,prxd);
1352    
1353     /* If we don't own the first descriptor, we cannot transmit */
1354     if (!(rxd0.ctrl & MPC860_FEC_RXBD_CTRL_E))
1355     return(FALSE);
1356    
1357     pkt_ptr = pkt;
1358     tot_len = pkt_len;
1359    
1360     while(tot_len > 0) {
1361     /* Write data into the RX buffer */
1362     clen = m_min(d->fec_rbuf_size,tot_len);
1363     physmem_copy_to_vm(d->vm,pkt_ptr,prxd->bp,clen);
1364     pkt_ptr += clen;
1365     tot_len -= clen;
1366    
1367     /* Set the Last flag if we have finished */
1368     if (!tot_len) {
1369     /* Set the full length */
1370     physmem_copy_u16_to_vm(d->vm,prxd->bd_addr+0x02,pkt_len+4);
1371     prxd->ctrl |= MPC860_FEC_RXBD_CTRL_L;
1372    
1373     if (eth_addr_is_bcast(&hdr->daddr))
1374     prxd->ctrl |= MPC860_FEC_RXBD_CTRL_BC;
1375     else if (eth_addr_is_mcast(&hdr->daddr))
1376     prxd->ctrl |= MPC860_FEC_RXBD_CTRL_MC;
1377     } else {
1378     /* Update the length field */
1379     physmem_copy_u16_to_vm(d->vm,prxd->bd_addr+0x02,clen);
1380     }
1381    
1382     /*
1383     * Clear the empty bit (except for the first descriptor,
1384     * which is cleared when the full packet has been stored).
1385     */
1386     if (prxd != &rxd0) {
1387     prxd->ctrl &= ~MPC860_FEC_RXBD_CTRL_E;
1388     physmem_copy_u16_to_vm(d->vm,prxd->bd_addr+0x00,prxd->ctrl);
1389     }
1390    
1391     /* Set pointer on next RX descriptor (wrap ring if necessary) */
1392     if (prxd->ctrl & MPC860_FEC_RXBD_CTRL_W) {
1393     d->fec_rdes_current = d->fec_rdes_start;
1394     } else {
1395     d->fec_rdes_current += MPC860_FEC_BD_SIZE;
1396     }
1397    
1398     /* If this is the last descriptor, we have finished */
1399     if (!tot_len) {
1400     mpc860_fec_fetch_bd(d,d->fec_rdes_current,&crxd);
1401     prxd = &crxd;
1402     }
1403     }
1404    
1405     /* Clear the Empty bit of the first RX descriptor */
1406     rxd0.ctrl &= ~MPC860_FEC_RXBD_CTRL_E;
1407     physmem_copy_u16_to_vm(d->vm,rxd0.bd_addr+0x00,rxd0.ctrl);
1408    
1409     /* Trigger FEC IRQ */
1410     d->fec_ievent |= MPC860_IEVENT_RFINT | MPC860_IEVENT_RXB;
1411     mpc860_fec_update_irq_status(d);
1412     return(TRUE);
1413     }
1414    
1415     /* MII register read access */
1416     static void mpc860_fec_mii_read_access(struct mpc860_data *d,
1417     u_int phy,u_int reg)
1418     {
1419     m_uint16_t res;
1420    
1421     res = d->fec_mii_regs[reg];
1422    
1423     switch(reg) {
1424     case 0x00:
1425     res = 0x1100;
1426     break;
1427     case 0x01:
1428     if (d->fec_nio)
1429     res = 0x7829;
1430     else
1431     res = 0;
1432     break;
1433     case 0x02:
1434     res = 0x7810;
1435     break;
1436     case 0x03:
1437     res = 0x0003;
1438     break;
1439     case 0x04:
1440     res = 0x1E1;
1441     break;
1442     case 0x05:
1443     res = 0x41E1;
1444     break;
1445     case 0x06:
1446     res = 0x0004;
1447     break;
1448     case 0x10:
1449     res = 0x0084;
1450     break;
1451     case 0x11:
1452     res = 0x4780;
1453     break;
1454     case 0x12:
1455     res = 0x4000;
1456     break;
1457     case 0x13:
1458     res = 0x0094;
1459     break;
1460     case 0x14:
1461     res = 0x28c8;
1462     break;
1463     default:
1464     res = 0;
1465     }
1466    
1467     d->fec_mii_data &= 0xFFFF0000;
1468     d->fec_mii_data |= res;
1469     }
1470    
1471     /* MII register read access */
1472     static void mpc860_fec_mii_write_access(struct mpc860_data *d,
1473     u_int phy,u_int reg)
1474     {
1475     #if DEBUG_FEC
1476     MPC_LOG(d,"FEC: Writing 0x%8.8x to MII reg %d\n",
1477     d->fec_mii_data & 0xFFFF,reg);
1478     #endif
1479     d->fec_mii_regs[reg] = d->fec_mii_data & 0xFFFF;
1480     }
1481    
1482     /* MII register access */
1483     static void mpc860_fec_mii_access(struct mpc860_data *d)
1484     {
1485     u_int op,phy,reg;
1486    
1487     op = (d->fec_mii_data & MPC860_MII_OP_MASK) >> MPC860_MII_OP_SHIFT;
1488     phy = (d->fec_mii_data & MPC860_MII_PHY_MASK) >> MPC860_MII_PHY_SHIFT;
1489     reg = (d->fec_mii_data & MPC860_MII_REG_MASK) >> MPC860_MII_REG_SHIFT;
1490    
1491     switch(op) {
1492     /* MII write */
1493     case 0x01:
1494     mpc860_fec_mii_write_access(d,phy,reg);
1495     break;
1496    
1497     /* MII read */
1498     case 0x02:
1499     mpc860_fec_mii_read_access(d,phy,reg);
1500     break;
1501    
1502     default:
1503     MPC_LOG(d,"FEC: unknown MII opcode %u\n",op);
1504     }
1505    
1506     /* MII access completed */
1507     d->fec_ievent |= MPC860_IEVENT_MII;
1508     mpc860_fec_update_irq_status(d);
1509     }
1510    
1511     /*
1512     * FEC register access (0xE00 to 0xF84).
1513     */
1514     static int dev_mpc860_fec_access(struct mpc860_data *d,m_uint32_t offset,
1515     u_int op_size,u_int op_type,m_uint64_t *data)
1516     {
1517     switch(offset) {
1518     /* R_DES_START: Beginning of RxBD ring */
1519     case 0xE10:
1520     if (op_type == MTS_READ)
1521     *data = d->fec_rdes_start;
1522     else
1523     d->fec_rdes_start = *data & 0xFFFFFFFC;
1524     break;
1525    
1526     /* X_DES_START: Beginning of TxBD ring */
1527     case 0xE14:
1528     if (op_type == MTS_READ)
1529     *data = d->fec_xdes_start;
1530     else
1531     d->fec_xdes_start = *data & 0xFFFFFFFC;
1532     break;
1533    
1534     /* R_BUFF_SIZE: Receive Buffer Size */
1535     case 0xE18:
1536     if (op_type == MTS_READ)
1537     *data = d->fec_rbuf_size;
1538     else
1539     d->fec_rbuf_size = *data & 0x7F0;
1540     break;
1541    
1542     /* ECNTRL */
1543     case 0xE40:
1544     if (op_type == MTS_READ) {
1545     *data = d->fec_ecntrl;
1546     } else {
1547     if (*data & MPC860_ECNTRL_RESET)
1548     d->fec_ecntrl = 0;
1549     else {
1550     if (!(*data & MPC860_ECNTRL_ETHER_EN)) {
1551     d->fec_xdes_current = d->fec_xdes_start;
1552     d->fec_rdes_current = d->fec_rdes_start;
1553     }
1554    
1555     d->fec_ecntrl = *data;
1556     }
1557     }
1558     break;
1559    
1560     /* IEVENT: Interrupt Event Register */
1561     case 0xE44:
1562     if (op_type == MTS_READ) {
1563     *data = d->fec_ievent;
1564     } else {
1565     d->fec_ievent &= ~(*data);
1566     mpc860_fec_update_irq_status(d);
1567     }
1568     break;
1569    
1570     /* IMASK: Interrupt Mask Register */
1571     case 0xE48:
1572     if (op_type == MTS_READ) {
1573     *data = d->fec_imask;
1574     } else {
1575     d->fec_imask = *data;
1576     mpc860_fec_update_irq_status(d);
1577     }
1578     break;
1579    
1580     /* IVEC: Interrupt Vector Register */
1581     case 0xE4C:
1582     if (op_type == MTS_READ)
1583     *data = d->fec_ivec;
1584     else
1585     d->fec_ivec = *data;
1586     break;
1587    
1588     /* X_DES_ACTIVE: TxBD Active Register */
1589     case 0xE54:
1590     mpc860_fec_handle_tx_ring(d);
1591     //printf("x_des_active set\n");
1592     break;
1593    
1594     /* MII_DATA */
1595     case 0xE80:
1596     if (op_type == MTS_READ) {
1597     *data = d->fec_mii_data;
1598     } else {
1599     d->fec_mii_data = *data;
1600     mpc860_fec_mii_access(d);
1601     }
1602     break;
1603     }
1604    
1605     return(0);
1606     }
1607    
1608     /* Set NIO for the Fast Ethernet Controller */
1609     int mpc860_fec_set_nio(struct mpc860_data *d,netio_desc_t *nio)
1610     {
1611     /* check that a NIO is not already bound */
1612     if (!d || (d->fec_nio != NULL))
1613     return(-1);
1614    
1615     d->fec_nio = nio;
1616     netio_rxl_add(nio,(netio_rx_handler_t)mpc860_fec_handle_rx_pkt,d,NULL);
1617     return(0);
1618     }
1619    
1620     /* Unset NIO of the Fast Ethernet Controller */
1621     int mpc860_fec_unset_nio(struct mpc860_data *d)
1622     {
1623     if (!d)
1624     return(-1);
1625    
1626     if (d->fec_nio != NULL) {
1627     netio_rxl_remove(d->fec_nio);
1628     d->fec_nio = NULL;
1629     }
1630    
1631     return(0);
1632     }
1633    
1634     /* ======================================================================== */
1635    
1636     #define MPC860_CP_FOP(chan,op) (((chan) << 4) + (op))
1637    
1638     /* Execute a command sent through CP Command Register (CPCR) */
1639     static void mpc860_exec_cpcr(struct mpc860_data *d,m_uint32_t cpcr)
1640     {
1641     u_int channel,opcode,fop;
1642    
1643     channel = (cpcr >> 4) & 0x0F;
1644     opcode = (cpcr >> 8) & 0x0F;
1645    
1646     fop = MPC860_CP_FOP(channel,opcode);
1647    
1648     switch(fop) {
1649     /* SPI - Init RX and TX params */
1650     case MPC860_CP_FOP(MPC860_CHAN_SPI_IDMA2_RT,0):
1651     mpc860_spi_init_rx_tx_params(d);
1652     break;
1653    
1654     /* SPI - Init RX params */
1655     case MPC860_CP_FOP(MPC860_CHAN_SPI_IDMA2_RT,1):
1656     mpc860_spi_init_rx_params(d);
1657     break;
1658    
1659     /* SPI - Init TX params */
1660     case MPC860_CP_FOP(MPC860_CHAN_SPI_IDMA2_RT,2):
1661     mpc860_spi_init_tx_params(d);
1662     break;
1663    
1664     /* SCC1 - Init RX and TX params */
1665     case MPC860_CP_FOP(MPC860_CHAN_SCC1,0):
1666     mpc860_scc_init_rx_tx_params(d,0);
1667     break;
1668    
1669     /* SCC1 - Init RX params */
1670     case MPC860_CP_FOP(MPC860_CHAN_SCC1,1):
1671     mpc860_scc_init_rx_params(d,0);
1672     break;
1673    
1674     /* SCC1 - Init TX params */
1675     case MPC860_CP_FOP(MPC860_CHAN_SCC1,2):
1676     mpc860_scc_init_tx_params(d,0);
1677     break;
1678    
1679     /* SCC2 - Init RX and TX params */
1680     case MPC860_CP_FOP(MPC860_CHAN_SCC2,0):
1681     mpc860_scc_init_rx_tx_params(d,1);
1682     break;
1683    
1684     /* SCC2 - Init RX params */
1685     case MPC860_CP_FOP(MPC860_CHAN_SCC2,1):
1686     mpc860_scc_init_rx_params(d,1);
1687     break;
1688    
1689     /* SCC2 - Init TX params */
1690     case MPC860_CP_FOP(MPC860_CHAN_SCC2,2):
1691     mpc860_scc_init_tx_params(d,1);
1692     break;
1693    
1694     /* SCC3 - Init RX and TX params */
1695     case MPC860_CP_FOP(MPC860_CHAN_SCC3,0):
1696     mpc860_scc_init_rx_tx_params(d,2);
1697     break;
1698    
1699     /* SCC3 - Init RX params */
1700     case MPC860_CP_FOP(MPC860_CHAN_SCC3,1):
1701     mpc860_scc_init_rx_params(d,2);
1702     break;
1703    
1704     /* SCC3 - Init TX params */
1705     case MPC860_CP_FOP(MPC860_CHAN_SCC3,2):
1706     mpc860_scc_init_tx_params(d,2);
1707     break;
1708    
1709     /* SCC4 - Init RX and TX params */
1710     case MPC860_CP_FOP(MPC860_CHAN_SCC4,0):
1711     mpc860_scc_init_rx_tx_params(d,3);
1712     break;
1713    
1714     /* SCC4 - Init RX params */
1715     case MPC860_CP_FOP(MPC860_CHAN_SCC4,1):
1716     mpc860_scc_init_rx_params(d,3);
1717     break;
1718    
1719     /* SCC4 - Init TX params */
1720     case MPC860_CP_FOP(MPC860_CHAN_SCC4,2):
1721     mpc860_scc_init_tx_params(d,3);
1722     break;
1723    
1724     default:
1725     MPC_LOG(d,"CPCR: unknown cmd: channel=0x%4.4x, opcode=0x%4.4x\n",
1726     channel,opcode);
1727     }
1728     }
1729    
1730 dpavlin 7 /*
1731     * dev_mpc860_access()
1732     */
1733     void *dev_mpc860_access(cpu_gen_t *cpu,struct vdevice *dev,m_uint32_t offset,
1734     u_int op_size,u_int op_type,m_uint64_t *data)
1735     {
1736     struct mpc860_data *d = dev->priv_data;
1737    
1738     if (op_type == MTS_READ)
1739     *data = 0x0;
1740    
1741     #if DEBUG_ACCESS
1742     if (op_type == MTS_READ) {
1743     cpu_log(cpu,d->name,
1744     "read from offset 0x%x, pc=0x%llx (size=%u)\n",
1745     offset,cpu_get_pc(cpu),op_size);
1746     } else {
1747     cpu_log(cpu,d->name,
1748     "write to offset 0x%x, value=0x%llx, pc=0x%llx (size=%u)\n",
1749     offset,*data,cpu_get_pc(cpu),op_size);
1750     }
1751     #endif
1752    
1753     /* Handle dual-port RAM access */
1754     if ((offset >= MPC860_DPRAM_OFFSET) && (offset < MPC860_DPRAM_END))
1755     return(d->dpram + (offset - MPC860_DPRAM_OFFSET));
1756    
1757 dpavlin 11 /* Handle SCC channels */
1758     if ((offset >= MPC860_REG_SCC_BASE) &&
1759     (offset < (MPC860_REG_SCC_BASE + (4 * 0x20))))
1760     {
1761     dev_mpc860_scc_access(d,offset,op_size,op_type,data);
1762     return NULL;
1763     }
1764    
1765     /* Handle Fast Ethernet Controller (FEC) registers */
1766     if ((offset >= MPC860_REG_FEC_BASE) && (offset <= MPC860_REG_FEC_END))
1767     {
1768     dev_mpc860_fec_access(d,offset,op_size,op_type,data);
1769     return NULL;
1770     }
1771    
1772 dpavlin 7 switch(offset) {
1773     /* SWSR - Software Service Register (Watchdog) */
1774 dpavlin 11 case MPC860_REG_SWSR:
1775 dpavlin 7 break;
1776    
1777     /* SIU Interrupt Pending Register */
1778 dpavlin 11 case MPC860_REG_SIPEND:
1779 dpavlin 7 if (op_type == MTS_READ)
1780     *data = d->sipend;
1781     break;
1782    
1783     /* SIU Interrupt Mask Register */
1784 dpavlin 11 case MPC860_REG_SIMASK:
1785 dpavlin 7 if (op_type == MTS_READ) {
1786     *data = d->simask;
1787     } else {
1788     d->simask = *data;
1789     mpc860_update_irq_status(d);
1790     }
1791     break;
1792    
1793     /*
1794     * Cisco 2600:
1795     * Bit 30: 0=NM in slot 1
1796     */
1797 dpavlin 11 case MPC860_REG_PIPR:
1798 dpavlin 7 if (op_type == MTS_READ)
1799     *data = 0x3F00F600;
1800     break;
1801    
1802     /* PISCR - Periodic Interrupt Status and Control Register */
1803 dpavlin 11 case MPC860_REG_PISCR:
1804 dpavlin 7 if (op_type == MTS_WRITE) {
1805     if (*data & 0x80) {
1806     d->sipend &= ~0x40000000;
1807     mpc860_update_irq_status(d);
1808     }
1809     }
1810     break;
1811    
1812 dpavlin 11 case MPC860_REG_TBSCR:
1813 dpavlin 7 if (op_type == MTS_READ)
1814     *data = 0x45;
1815     break;
1816    
1817     /* IDMA1 Status and Mask Registers */
1818 dpavlin 11 case MPC860_REG_IDSR1:
1819 dpavlin 7 if (op_type == MTS_READ) {
1820     *data = d->idsr[0];
1821     } else {
1822     d->idsr[0] &= ~(*data);
1823     }
1824     break;
1825    
1826 dpavlin 11 case MPC860_REG_IDMR1:
1827 dpavlin 7 if (op_type == MTS_READ)
1828     *data = d->idmr[0];
1829     else
1830     d->idmr[0] = *data;
1831     break;
1832    
1833     /* IDMA2 Status and Mask Registers */
1834 dpavlin 11 case MPC860_REG_IDSR2:
1835 dpavlin 7 if (op_type == MTS_READ)
1836     *data = d->idsr[1];
1837     else
1838     d->idsr[1] &= ~(*data);
1839     break;
1840    
1841 dpavlin 11 case MPC860_REG_IDMR2:
1842 dpavlin 7 if (op_type == MTS_READ)
1843     *data = d->idmr[1];
1844     else
1845     d->idmr[1] = *data;
1846     break;
1847    
1848 dpavlin 11 /* CICR - CPM Interrupt Configuration Register */
1849     case MPC860_REG_CICR:
1850     if (op_type == MTS_READ)
1851     *data = d->cicr;
1852     else
1853     d->cicr = *data;
1854     break;
1855    
1856 dpavlin 7 /* CIPR - CPM Interrupt Pending Register */
1857 dpavlin 11 case MPC860_REG_CIPR:
1858 dpavlin 7 if (op_type == MTS_READ)
1859     *data = d->cipr;
1860     else {
1861     d->cipr &= ~(*data);
1862     mpc860_update_cpm_int_status(d);
1863     }
1864     break;
1865    
1866     /* CIMR - CPM Interrupt Mask Register */
1867 dpavlin 11 case MPC860_REG_CIMR:
1868 dpavlin 7 if (op_type == MTS_READ)
1869     *data = d->cimr;
1870     else {
1871     d->cimr = *data;
1872     mpc860_update_cpm_int_status(d);
1873     }
1874     break;
1875    
1876     /* PCSO - Port C Special Options Register */
1877 dpavlin 11 case MPC860_REG_PCSO:
1878 dpavlin 7 if (op_type == MTS_WRITE) {
1879     if (*data & 0x01) {
1880 dpavlin 11 #if DEBUG_IDMA
1881 dpavlin 7 MPC_LOG(d,"activating IDMA0\n");
1882 dpavlin 11 #endif
1883 dpavlin 7 mpc860_idma_start_channel(d,0);
1884     }
1885     }
1886     break;
1887    
1888 dpavlin 11 /* PCDAT - Port C Data Register */
1889     case MPC860_REG_PCDAT:
1890     if (op_type == MTS_WRITE)
1891     d->pcdat = *data;
1892     else
1893     *data = d->pcdat;
1894 dpavlin 7 break;
1895    
1896 dpavlin 11 /* PBDAT - Port B Data Register */
1897     case MPC860_REG_PBDAT:
1898     if (op_type == MTS_WRITE)
1899     d->pbdat = *data;
1900     else
1901     *data = d->pbdat;
1902     break;
1903 dpavlin 7
1904 dpavlin 11 /* CPCR - CP Command Register */
1905     case MPC860_REG_CPCR:
1906     if (op_type == MTS_WRITE)
1907     mpc860_exec_cpcr(d,(m_uint32_t)(*data));
1908     break;
1909    
1910     /* SPCOM - SPI Command Register */
1911     case MPC860_REG_SPCOM:
1912     if ((op_type == MTS_WRITE) && (*data & MPC860_SPCOM_STR))
1913     mpc860_spi_start_tx(d);
1914     break;
1915    
1916 dpavlin 7 #if DEBUG_UNKNOWN
1917     default:
1918     if (op_type == MTS_READ) {
1919     cpu_log(cpu,d->name,
1920     "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n",
1921     offset,cpu_get_pc(cpu),op_size);
1922     } else {
1923     cpu_log(cpu,d->name,
1924     "write to addr 0x%x, value=0x%llx, pc=0x%llx (size=%u)\n",
1925     offset,*data,cpu_get_pc(cpu),op_size);
1926     }
1927     #endif
1928     }
1929    
1930     return NULL;
1931     }
1932    
1933     /* Set IRQ pending status */
1934     void mpc860_set_pending_irq(struct mpc860_data *d,m_uint32_t val)
1935     {
1936     d->sipend |= 1 << val;
1937     mpc860_update_irq_status(d);
1938     }
1939    
1940     /* Clear a pending IRQ */
1941     void mpc860_clear_pending_irq(struct mpc860_data *d,m_uint32_t val)
1942     {
1943     d->sipend &= ~(1 << val);
1944     mpc860_update_irq_status(d);
1945     }
1946    
1947     /* Shutdown the MPC860 device */
1948     void dev_mpc860_shutdown(vm_instance_t *vm,struct mpc860_data *d)
1949     {
1950     if (d != NULL) {
1951     /* Remove the device */
1952     dev_remove(vm,&d->dev);
1953    
1954     /* Free the structure itself */
1955     free(d);
1956     }
1957     }
1958    
1959     /* Create the MPC860 device */
1960     int dev_mpc860_init(vm_instance_t *vm,char *name,
1961     m_uint64_t paddr,m_uint32_t len)
1962     {
1963     struct mpc860_data *d;
1964    
1965     if (!(d = malloc(sizeof(*d)))) {
1966     fprintf(stderr,"mpc860: unable to create device data.\n");
1967     return(-1);
1968     }
1969    
1970     memset(d,0,sizeof(*d));
1971     d->name = name;
1972     d->vm = vm;
1973    
1974     vm_object_init(&d->vm_obj);
1975     d->vm_obj.name = name;
1976     d->vm_obj.data = d;
1977     d->vm_obj.shutdown = (vm_shutdown_t)dev_mpc860_shutdown;
1978    
1979     dev_init(&d->dev);
1980     d->dev.name = name;
1981     d->dev.priv_data = d;
1982     d->dev.phys_addr = paddr;
1983     d->dev.phys_len = len;
1984     d->dev.handler = dev_mpc860_access;
1985 dpavlin 11
1986     /* Set the default SPI base address */
1987     dpram_w16(d,MPC860_SPI_BASE_ADDR,MPC860_SPI_BASE);
1988 dpavlin 7
1989     /* Map this device to the VM */
1990     vm_bind_device(vm,&d->dev);
1991     vm_object_add(vm,&d->vm_obj);
1992     return(0);
1993     }
1994    

  ViewVC Help
Powered by ViewVC 1.1.26