/[dynamips]/upstream/dynamips-0.2.8-RC1/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

Diff of /upstream/dynamips-0.2.8-RC1/dev_mpc860.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

upstream/dynamips-0.2.7/dev_mpc860.c revision 10 by dpavlin, Sat Oct 6 16:29:14 2007 UTC upstream/dynamips-0.2.8-RC1/dev_mpc860.c revision 11 by dpavlin, Sat Oct 6 16:33:40 2007 UTC
# Line 22  Line 22 
22  /* Debugging flags */  /* Debugging flags */
23  #define DEBUG_ACCESS    0  #define DEBUG_ACCESS    0
24  #define DEBUG_UNKNOWN   1  #define DEBUG_UNKNOWN   1
25  #define DEBUG_IDMA      1  #define DEBUG_IDMA      0
26    #define DEBUG_SPI       0
27    #define DEBUG_SCC       0
28    #define DEBUG_FEC       1
29    
30    #define MPC860_TXRING_PASS_COUNT  16
31    
32  /* Dual-Port RAM */  /* Dual-Port RAM */
33  #define MPC860_DPRAM_OFFSET   0x2000  #define MPC860_DPRAM_OFFSET   0x2000
34  #define MPC860_DPRAM_SIZE     0x2000  #define MPC860_DPRAM_SIZE     0x2000
35  #define MPC860_DPRAM_END      (MPC860_DPRAM_OFFSET + MPC860_DPRAM_SIZE)  #define MPC860_DPRAM_END      (MPC860_DPRAM_OFFSET + MPC860_DPRAM_SIZE)
36    
37    /* 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  /* CIPR (CPM Interrupt Pending Register) */  /* CIPR (CPM Interrupt Pending Register) */
71  #define MPC860_CIPR_PC15      0x80000000  #define MPC860_CIPR_PC15      0x80000000
72  #define MPC860_CIPR_SCC1      0x40000000  #define MPC860_CIPR_SCC1      0x40000000
# Line 59  Line 97 
97  #define MPC860_CIPR_PC5       0x00000004  #define MPC860_CIPR_PC5       0x00000004
98  #define MPC860_CIPR_PC4       0x00000002  #define MPC860_CIPR_PC4       0x00000002
99    
100    /* 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  /* IDMA Status Register */  /* IDMA Status Register */
123  #define MPC860_IDSR_OB        0x0001    /* Out of Buffers */  #define MPC860_IDSR_OB        0x0001    /* Out of Buffers */
124  #define MPC860_IDSR_DONE      0x0002    /* Buffer chain done */  #define MPC860_IDSR_DONE      0x0002    /* Buffer chain done */
# Line 89  struct mpc860_idma_bd { Line 149  struct mpc860_idma_bd {
149     m_uint32_t dst_bp;      /* Destination buffer pointer */     m_uint32_t dst_bp;      /* Destination buffer pointer */
150  };  };
151    
152    /* ======================================================================== */
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  /* MPC860 private data */  /* MPC860 private data */
364  struct mpc860_data {  struct mpc860_data {
365     char *name;     char *name;
# Line 109  struct mpc860_data { Line 380  struct mpc860_data {
380     /* IDMA status and mask registers */     /* IDMA status and mask registers */
381     m_uint8_t idsr[2],idmr[2];     m_uint8_t idsr[2],idmr[2];
382    
383       /* 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     /* Dual-Port RAM */     /* Dual-Port RAM */
410     m_uint8_t dpram[MPC860_DPRAM_SIZE];     m_uint8_t dpram[MPC860_DPRAM_SIZE];
411  };  };
# Line 177  static void mpc860_update_irq_status(str Line 474  static void mpc860_update_irq_status(str
474     cpu->irq_check = cpu->irq_pending;     cpu->irq_check = cpu->irq_pending;
475  }  }
476    
477    /* 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  /* Update CPM interrupt status */  /* Update CPM interrupt status */
484  static void mpc860_update_cpm_int_status(struct mpc860_data *d)  static void mpc860_update_cpm_int_status(struct mpc860_data *d)
485  {  {
486     if (d->cipr & d->cimr)     u_int level,siu_bit;
487        mpc860_set_pending_irq(d,24);  
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     else     else
494        mpc860_clear_pending_irq(d,24);        mpc860_clear_pending_irq(d,siu_bit);
495  }  }
496    
497    /* ======================================================================== */
498    /* IDMA                                                                     */
499    /* ======================================================================== */
500    
501  /* Update an IDMA status register */  /* Update an IDMA status register */
502  static int mpc860_idma_update_idsr(struct mpc860_data *d,u_int id)  static int mpc860_idma_update_idsr(struct mpc860_data *d,u_int id)
503  {  {
# Line 222  static void mpc860_idma_transfer(struct Line 534  static void mpc860_idma_transfer(struct
534  static int mpc860_idma_fetch_bd(struct mpc860_data *d,m_uint16_t bd_addr,  static int mpc860_idma_fetch_bd(struct mpc860_data *d,m_uint16_t bd_addr,
535                                  struct mpc860_idma_bd *bd)                                  struct mpc860_idma_bd *bd)
536  {  {
    void *ptr;  
   
537     if ((bd_addr < MPC860_DPRAM_OFFSET) || (bd_addr > MPC860_DPRAM_END))     if ((bd_addr < MPC860_DPRAM_OFFSET) || (bd_addr > MPC860_DPRAM_END))
538        return(-1);        return(-1);
539    
540     bd->offset = bd_addr - MPC860_DPRAM_OFFSET;     bd->offset = bd_addr - MPC860_DPRAM_OFFSET;
    ptr = &d->dpram[bd->offset];  
541    
542     /* Fetch control word */     /* Fetch control word */
543     bd->ctrl = dpram_r16(d,bd->offset+0x00);     bd->ctrl = dpram_r16(d,bd->offset+0x00);
# Line 304  static int mpc860_idma_start_channel(str Line 613  static int mpc860_idma_start_channel(str
613     return(0);     return(0);
614  }  }
615    
616    /* ======================================================================== */
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  /*  /*
1731   * dev_mpc860_access()   * dev_mpc860_access()
1732   */   */
# Line 331  void *dev_mpc860_access(cpu_gen_t *cpu,s Line 1754  void *dev_mpc860_access(cpu_gen_t *cpu,s
1754     if ((offset >= MPC860_DPRAM_OFFSET) && (offset < MPC860_DPRAM_END))     if ((offset >= MPC860_DPRAM_OFFSET) && (offset < MPC860_DPRAM_END))
1755        return(d->dpram + (offset - MPC860_DPRAM_OFFSET));        return(d->dpram + (offset - MPC860_DPRAM_OFFSET));
1756    
1757       /* 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     switch(offset) {     switch(offset) {
1773        /* SWSR - Software Service Register (Watchdog) */        /* SWSR - Software Service Register (Watchdog) */
1774        case 0x000e:        case MPC860_REG_SWSR:
1775           break;           break;
1776    
1777        /* SIU Interrupt Pending Register */        /* SIU Interrupt Pending Register */
1778        case 0x0010:        case MPC860_REG_SIPEND:
1779           if (op_type == MTS_READ)           if (op_type == MTS_READ)
1780              *data = d->sipend;              *data = d->sipend;
1781           break;           break;
1782    
1783        /* SIU Interrupt Mask Register */        /* SIU Interrupt Mask Register */
1784        case 0x0014:        case MPC860_REG_SIMASK:
1785           if (op_type == MTS_READ) {           if (op_type == MTS_READ) {
1786              *data = d->simask;              *data = d->simask;
1787           } else {           } else {
# Line 356  void *dev_mpc860_access(cpu_gen_t *cpu,s Line 1794  void *dev_mpc860_access(cpu_gen_t *cpu,s
1794         * Cisco 2600:         * Cisco 2600:
1795         *   Bit 30: 0=NM in slot 1         *   Bit 30: 0=NM in slot 1
1796         */         */
1797        case 0x00f0:        case MPC860_REG_PIPR:
1798           if (op_type == MTS_READ)           if (op_type == MTS_READ)
1799              *data = 0x3F00F600;              *data = 0x3F00F600;
1800           break;           break;
1801    
1802        /* PISCR - Periodic Interrupt Status and Control Register */        /* PISCR - Periodic Interrupt Status and Control Register */
1803        case 0x0240:        case MPC860_REG_PISCR:
1804          if (op_type == MTS_WRITE) {          if (op_type == MTS_WRITE) {
1805             if (*data & 0x80) {             if (*data & 0x80) {
1806                d->sipend &= ~0x40000000;                d->sipend &= ~0x40000000;
# Line 371  void *dev_mpc860_access(cpu_gen_t *cpu,s Line 1809  void *dev_mpc860_access(cpu_gen_t *cpu,s
1809          }          }
1810          break;          break;
1811    
1812        case 0x200:        case MPC860_REG_TBSCR:
1813           if (op_type == MTS_READ)           if (op_type == MTS_READ)
1814              *data = 0x45;              *data = 0x45;
1815           break;           break;
1816    
1817        /* IDMA1 Status and Mask Registers */        /* IDMA1 Status and Mask Registers */
1818        case 0x910:        case MPC860_REG_IDSR1:
1819           if (op_type == MTS_READ) {           if (op_type == MTS_READ) {
1820              *data = d->idsr[0];              *data = d->idsr[0];
1821           } else {           } else {
# Line 385  void *dev_mpc860_access(cpu_gen_t *cpu,s Line 1823  void *dev_mpc860_access(cpu_gen_t *cpu,s
1823           }           }
1824           break;           break;
1825    
1826        case 0x914:        case MPC860_REG_IDMR1:
1827           if (op_type == MTS_READ)           if (op_type == MTS_READ)
1828              *data = d->idmr[0];              *data = d->idmr[0];
1829           else           else
# Line 393  void *dev_mpc860_access(cpu_gen_t *cpu,s Line 1831  void *dev_mpc860_access(cpu_gen_t *cpu,s
1831           break;           break;
1832    
1833        /* IDMA2 Status and Mask Registers */        /* IDMA2 Status and Mask Registers */
1834        case 0x918:        case MPC860_REG_IDSR2:
1835           if (op_type == MTS_READ)           if (op_type == MTS_READ)
1836              *data = d->idsr[1];              *data = d->idsr[1];
1837           else           else
1838              d->idsr[1] &= ~(*data);              d->idsr[1] &= ~(*data);
1839           break;           break;
1840    
1841        case 0x91c:        case MPC860_REG_IDMR2:
1842           if (op_type == MTS_READ)           if (op_type == MTS_READ)
1843              *data = d->idmr[1];              *data = d->idmr[1];
1844           else           else
1845              d->idmr[1] = *data;              d->idmr[1] = *data;
1846           break;           break;
1847    
1848          /* 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        /* CIPR - CPM Interrupt Pending Register */        /* CIPR - CPM Interrupt Pending Register */
1857        case 0x944:        case MPC860_REG_CIPR:
1858           if (op_type == MTS_READ)           if (op_type == MTS_READ)
1859              *data = d->cipr;              *data = d->cipr;
1860           else {           else {
# Line 418  void *dev_mpc860_access(cpu_gen_t *cpu,s Line 1864  void *dev_mpc860_access(cpu_gen_t *cpu,s
1864           break;           break;
1865    
1866        /* CIMR - CPM Interrupt Mask Register */        /* CIMR - CPM Interrupt Mask Register */
1867        case 0x948:        case MPC860_REG_CIMR:
1868           if (op_type == MTS_READ)           if (op_type == MTS_READ)
1869              *data = d->cimr;              *data = d->cimr;
1870           else {           else {
# Line 428  void *dev_mpc860_access(cpu_gen_t *cpu,s Line 1874  void *dev_mpc860_access(cpu_gen_t *cpu,s
1874           break;           break;
1875    
1876        /* PCSO - Port C Special Options Register */        /* PCSO - Port C Special Options Register */
1877        case 0x964:        case MPC860_REG_PCSO:
1878           if (op_type == MTS_WRITE) {           if (op_type == MTS_WRITE) {
1879              if (*data & 0x01) {              if (*data & 0x01) {
1880    #if DEBUG_IDMA
1881                 MPC_LOG(d,"activating IDMA0\n");                 MPC_LOG(d,"activating IDMA0\n");
1882    #endif
1883                 mpc860_idma_start_channel(d,0);                 mpc860_idma_start_channel(d,0);
1884              }              }
1885           }           }
1886           break;           break;
1887    
1888        case 0x0966:        /* 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           break;           break;
1895    
1896        case 0x9c0:        /* PBDAT - Port B Data Register */
1897           if (op_type == MTS_WRITE) {        case MPC860_REG_PBDAT:
1898              printf("OPCODE=0x%llx, CHANNEL=0x%llx\n",           if (op_type == MTS_WRITE)
1899                     (*data >> 8) & 0xF, (*data >> 4) & 0xF);              d->pbdat = *data;
1900           }           else
1901                *data = d->pbdat;
1902             break;
1903    
1904          /* 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  #if DEBUG_UNKNOWN  #if DEBUG_UNKNOWN
1917        default:        default:
# Line 515  int dev_mpc860_init(vm_instance_t *vm,ch Line 1982  int dev_mpc860_init(vm_instance_t *vm,ch
1982     d->dev.phys_addr = paddr;     d->dev.phys_addr = paddr;
1983     d->dev.phys_len  = len;     d->dev.phys_len  = len;
1984     d->dev.handler   = dev_mpc860_access;     d->dev.handler   = dev_mpc860_access;
1985      
1986       /* Set the default SPI base address */
1987       dpram_w16(d,MPC860_SPI_BASE_ADDR,MPC860_SPI_BASE);
1988    
1989     /* Map this device to the VM */     /* Map this device to the VM */
1990     vm_bind_device(vm,&d->dev);     vm_bind_device(vm,&d->dev);

Legend:
Removed from v.10  
changed lines
  Added in v.11

  ViewVC Help
Powered by ViewVC 1.1.26