96 |
#define MUESLIX_XYMEM_LEN 0x100 |
#define MUESLIX_XYMEM_LEN 0x100 |
97 |
|
|
98 |
/* Maximum packet size */ |
/* Maximum packet size */ |
99 |
#define MUESLIX_MAX_PKT_SIZE 2048 |
#define MUESLIX_MAX_PKT_SIZE 18000 |
100 |
|
|
101 |
/* Send up to 16 packets in a TX ring scan pass */ |
/* Send up to 16 packets in a TX ring scan pass */ |
102 |
#define MUESLIX_TXRING_PASS_COUNT 16 |
#define MUESLIX_TXRING_PASS_COUNT 16 |
109 |
#define MUESLIX_RXDESC_IGNORED 0x08000000 /* Ignored */ |
#define MUESLIX_RXDESC_IGNORED 0x08000000 /* Ignored */ |
110 |
#define MUESLIX_RXDESC_ABORT 0x04000000 /* Abort */ |
#define MUESLIX_RXDESC_ABORT 0x04000000 /* Abort */ |
111 |
#define MUESLIX_RXDESC_CRC 0x02000000 /* CRC error */ |
#define MUESLIX_RXDESC_CRC 0x02000000 /* CRC error */ |
112 |
#define MUESLIX_RXDESC_LEN_MASK 0xfff |
#define MUESLIX_RXDESC_LEN_MASK 0xffff |
113 |
|
|
114 |
/* TX descriptors */ |
/* TX descriptors */ |
115 |
#define MUESLIX_TXDESC_OWN 0x80000000 /* Ownership */ |
#define MUESLIX_TXDESC_OWN 0x80000000 /* Ownership */ |
121 |
#define MUESLIX_TXDESC_PAD 0x00c00000 /* Sort of padding info ? */ |
#define MUESLIX_TXDESC_PAD 0x00c00000 /* Sort of padding info ? */ |
122 |
#define MUESLIX_TXDESC_PAD_SHIFT 22 |
#define MUESLIX_TXDESC_PAD_SHIFT 22 |
123 |
|
|
124 |
#define MUESLIX_TXDESC_LEN_MASK 0xfff |
#define MUESLIX_TXDESC_LEN_MASK 0xffff |
125 |
|
|
126 |
/* RX Descriptor */ |
/* RX Descriptor */ |
127 |
struct rx_desc { |
struct rx_desc { |
141 |
/* Channel ID */ |
/* Channel ID */ |
142 |
u_int id; |
u_int id; |
143 |
|
|
|
/* RX/TX status */ |
|
|
u_int rx_tx_status; |
|
|
|
|
144 |
/* Channel status (0=disabled) */ |
/* Channel status (0=disabled) */ |
145 |
u_int status; |
u_int status; |
146 |
|
|
163 |
/* Mueslix Data */ |
/* Mueslix Data */ |
164 |
struct mueslix_data { |
struct mueslix_data { |
165 |
char *name; |
char *name; |
166 |
|
|
167 |
|
/* Lock */ |
168 |
|
pthread_mutex_t lock; |
169 |
|
|
170 |
|
/* IRQ status and mask */ |
171 |
|
m_uint32_t irq_status,irq_mask; |
172 |
|
u_int irq_clearing_count; |
173 |
|
|
174 |
/* TPU options */ |
/* TPU options */ |
175 |
m_uint32_t tpu_options; |
m_uint32_t tpu_options; |
176 |
|
|
208 |
MUESLIX_CHANNEL2_OFFSET, MUESLIX_CHANNEL3_OFFSET, |
MUESLIX_CHANNEL2_OFFSET, MUESLIX_CHANNEL3_OFFSET, |
209 |
}; |
}; |
210 |
|
|
211 |
|
/* Lock/Unlock primitives */ |
212 |
|
#define MUESLIX_LOCK(d) pthread_mutex_lock(&(d)->lock) |
213 |
|
#define MUESLIX_UNLOCK(d) pthread_mutex_unlock(&(d)->lock) |
214 |
|
|
215 |
/* Log a Mueslix message */ |
/* Log a Mueslix message */ |
216 |
#define MUESLIX_LOG(d,msg...) vm_log((d)->vm,(d)->name,msg) |
#define MUESLIX_LOG(d,msg...) vm_log((d)->vm,(d)->name,msg) |
217 |
|
|
222 |
return((d->channel_enable_mask >> (id << 1)) & 0x03); |
return((d->channel_enable_mask >> (id << 1)) & 0x03); |
223 |
} |
} |
224 |
|
|
225 |
|
/* Update IRQ status */ |
226 |
|
static inline void dev_mueslix_update_irq_status(struct mueslix_data *d) |
227 |
|
{ |
228 |
|
if (d->irq_status & d->irq_mask) |
229 |
|
pci_dev_trigger_irq(d->vm,d->pci_dev); |
230 |
|
else { |
231 |
|
if (++d->irq_clearing_count == 3) { |
232 |
|
pci_dev_clear_irq(d->vm,d->pci_dev); |
233 |
|
d->irq_clearing_count = 0; |
234 |
|
} |
235 |
|
} |
236 |
|
} |
237 |
|
|
238 |
/* |
/* |
239 |
* Access to channel registers. |
* Access to channel registers. |
240 |
*/ |
*/ |
344 |
u_int op_size,u_int op_type,m_uint64_t *data) |
u_int op_size,u_int op_type,m_uint64_t *data) |
345 |
{ |
{ |
346 |
struct mueslix_data *d = dev->priv_data; |
struct mueslix_data *d = dev->priv_data; |
|
struct mueslix_channel *channel; |
|
|
m_uint32_t irq_status; |
|
347 |
int i; |
int i; |
348 |
|
|
349 |
#if DEBUG_ACCESS >= 2 |
#if DEBUG_ACCESS >= 2 |
380 |
if ((offset >= channel_offset[i]) && |
if ((offset >= channel_offset[i]) && |
381 |
(offset < (channel_offset[i] + MUESLIX_CHANNEL_LEN))) |
(offset < (channel_offset[i] + MUESLIX_CHANNEL_LEN))) |
382 |
{ |
{ |
383 |
|
MUESLIX_LOCK(d); |
384 |
dev_mueslix_chan_access(cpu,&d->channel[i], |
dev_mueslix_chan_access(cpu,&d->channel[i], |
385 |
offset - channel_offset[i], |
offset - channel_offset[i], |
386 |
op_size,op_type,data); |
op_size,op_type,data); |
387 |
|
MUESLIX_UNLOCK(d); |
388 |
return NULL; |
return NULL; |
389 |
} |
} |
390 |
|
|
391 |
|
MUESLIX_LOCK(d); |
392 |
|
|
393 |
/* Generic case */ |
/* Generic case */ |
394 |
switch(offset) { |
switch(offset) { |
395 |
/* this reg is accessed when an interrupt occurs */ |
/* this reg is accessed when an interrupt occurs */ |
396 |
case 0x0: |
case 0x0: |
397 |
if (op_type == MTS_READ) { |
if (op_type == MTS_READ) { |
398 |
irq_status = 0; |
*data = d->irq_status; |
|
|
|
|
for(i=0;i<MUESLIX_NR_CHANNELS;i++) { |
|
|
channel = &d->channel[i]; |
|
|
|
|
|
if ((dev_mueslix_is_rx_tx_enabled(d,i) & MUESLIX_TX_ENABLE) && |
|
|
(channel->rx_tx_status & MUESLIX_CHANNEL_STATUS_RX)) |
|
|
irq_status |= MUESLIX_RX_IRQ << i; |
|
|
|
|
|
if ((dev_mueslix_is_rx_tx_enabled(d,i) & MUESLIX_TX_ENABLE) && |
|
|
(channel->rx_tx_status & MUESLIX_CHANNEL_STATUS_TX)) |
|
|
irq_status |= MUESLIX_TX_IRQ << i; |
|
|
} |
|
|
|
|
|
/* |
|
|
* Hack: we re-trigger an interrupt here. This was necessary |
|
|
* because the Mueslix driver was not working properly with |
|
|
* a C3620 platform. |
|
|
*/ |
|
|
if (irq_status) |
|
|
pci_dev_trigger_irq(d->vm,d->pci_dev); |
|
|
|
|
|
*data = irq_status; |
|
399 |
} else { |
} else { |
400 |
for(i=0;i<MUESLIX_NR_CHANNELS;i++) { |
d->irq_status &= ~(*data); |
401 |
channel = &d->channel[i]; |
dev_mueslix_update_irq_status(d); |
|
channel->rx_tx_status = 0; |
|
|
} |
|
402 |
} |
} |
403 |
break; |
break; |
404 |
|
|
405 |
/* maybe interrupt mask */ |
/* Maybe interrupt mask */ |
406 |
case 0x10: |
case 0x10: |
407 |
if (op_type == MTS_READ) |
if (op_type == MTS_READ) { |
408 |
*data = 0x2FF; |
*data = d->irq_mask; |
409 |
|
} else { |
410 |
|
d->irq_mask = *data; |
411 |
|
dev_mueslix_update_irq_status(d); |
412 |
|
} |
413 |
break; |
break; |
414 |
|
|
415 |
case 0x14: |
case 0x14: |
489 |
#endif |
#endif |
490 |
} |
} |
491 |
|
|
492 |
|
MUESLIX_UNLOCK(d); |
493 |
return NULL; |
return NULL; |
494 |
} |
} |
495 |
|
|
658 |
/* Indicate that we have a frame ready (XXX something to do ?) */ |
/* Indicate that we have a frame ready (XXX something to do ?) */ |
659 |
|
|
660 |
/* Generate IRQ on CPU */ |
/* Generate IRQ on CPU */ |
661 |
channel->rx_tx_status |= MUESLIX_CHANNEL_STATUS_RX; |
d->irq_status |= MUESLIX_RX_IRQ << channel->id; |
662 |
pci_dev_trigger_irq(d->vm,d->pci_dev); |
dev_mueslix_update_irq_status(d); |
663 |
} |
} |
664 |
|
|
665 |
/* Handle the Mueslix RX ring of the specified channel */ |
/* Handle the Mueslix RX ring of the specified channel */ |
666 |
static int dev_mueslix_handle_rxring(netio_desc_t *nio, |
static int dev_mueslix_handle_rxring(netio_desc_t *nio, |
667 |
u_char *pkt,ssize_t pkt_len, |
u_char *pkt,ssize_t pkt_len, |
668 |
struct mueslix_channel *channel) |
struct mueslix_channel *channel) |
669 |
{ |
{ |
|
#if DEBUG_RECEIVE |
|
670 |
struct mueslix_data *d = channel->parent; |
struct mueslix_data *d = channel->parent; |
671 |
|
|
672 |
|
#if DEBUG_RECEIVE |
673 |
MUESLIX_LOG(d,"channel %u: receiving a packet of %d bytes\n", |
MUESLIX_LOG(d,"channel %u: receiving a packet of %d bytes\n", |
674 |
channel->id,pkt_len); |
channel->id,pkt_len); |
675 |
mem_dump(log_file,pkt,pkt_len); |
mem_dump(log_file,pkt,pkt_len); |
676 |
#endif |
#endif |
677 |
|
|
678 |
dev_mueslix_receive_pkt(channel,pkt,pkt_len); |
MUESLIX_LOCK(d); |
679 |
|
if (dev_mueslix_is_rx_tx_enabled(d,channel->id) & MUESLIX_RX_ENABLE) |
680 |
|
dev_mueslix_receive_pkt(channel,pkt,pkt_len); |
681 |
|
MUESLIX_UNLOCK(d); |
682 |
return(TRUE); |
return(TRUE); |
683 |
} |
} |
684 |
|
|
816 |
physmem_copy_u32_to_vm(d->vm,tx_start,0); |
physmem_copy_u32_to_vm(d->vm,tx_start,0); |
817 |
|
|
818 |
/* Interrupt on completion ? */ |
/* Interrupt on completion ? */ |
819 |
channel->rx_tx_status |= MUESLIX_CHANNEL_STATUS_TX; |
d->irq_status |= MUESLIX_TX_IRQ << channel->id; |
820 |
pci_dev_trigger_irq(d->vm,d->pci_dev); |
dev_mueslix_update_irq_status(d); |
821 |
return(TRUE); |
return(TRUE); |
822 |
} |
} |
823 |
|
|
824 |
/* Handle the TX ring of a specific channel */ |
/* Handle the TX ring of a specific channel */ |
825 |
static int dev_mueslix_handle_txring(struct mueslix_channel *channel) |
static int dev_mueslix_handle_txring(struct mueslix_channel *channel) |
826 |
{ |
{ |
827 |
int i; |
struct mueslix_data *d = channel->parent; |
828 |
|
int res,i; |
829 |
|
|
830 |
for(i=0;i<MUESLIX_TXRING_PASS_COUNT;i++) |
if (!dev_mueslix_is_rx_tx_enabled(d,channel->id) & MUESLIX_TX_ENABLE) |
831 |
if (!dev_mueslix_handle_txring_single(channel)) |
return(FALSE); |
832 |
|
|
833 |
|
for(i=0;i<MUESLIX_TXRING_PASS_COUNT;i++) { |
834 |
|
MUESLIX_LOCK(d); |
835 |
|
res = dev_mueslix_handle_txring_single(channel); |
836 |
|
MUESLIX_UNLOCK(d); |
837 |
|
|
838 |
|
if (!res) |
839 |
break; |
break; |
840 |
|
} |
841 |
|
|
842 |
return(TRUE); |
return(TRUE); |
843 |
} |
} |
889 |
} |
} |
890 |
|
|
891 |
memset(d,0,sizeof(*d)); |
memset(d,0,sizeof(*d)); |
892 |
|
pthread_mutex_init(&d->lock,NULL); |
893 |
d->chip_mode = chip_mode; |
d->chip_mode = chip_mode; |
894 |
|
|
895 |
for(i=0;i<MUESLIX_NR_CHANNELS;i++) |
for(i=0;i<MUESLIX_NR_CHANNELS;i++) |