#include "../include/can.h"
#include "../include/can_sysdep.h"
#include "../include/main.h"
+#include "../include/devcommon.h"
+#include "../include/setup.h"
#include "../include/usbcan.h"
+/* our private defines. if this grows any larger, use your own .h file */
+#define MAX_TRANSFER (PAGE_SIZE - 512)
+/* MAX_TRANSFER is chosen so that the VM is not stressed by
+ allocations > PAGE_SIZE and the number of packets in a page
+ is an integer 512 is the largest possible packet on EHCI */
+#define WRITES_IN_FLIGHT 8
+/* arbitrarily chosen */
+
+/* Define these values to match your devices */
+#define USB_SKEL_VENDOR_ID 0xDEAD
+#define USB_SKEL_PRODUCT_ID 0x1001
+
+/* table of devices that work with this driver */
+static struct usb_device_id usbcan_table [] = {
+ { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, usbcan_table);
+
+extern struct file_operations can_fops;
+
+int usbcan_register(struct hwspecops_t *hwspecops);
+
/*
* IO_RANGE is the io-memory range that gets reserved, please adjust according
* your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
*/
#define IO_RANGE 0x100
+/* Structure to hold all of our device specific stuff */
+struct usb_usbcan {
+ struct usb_device *udev; /* the usb device for this device */
+ struct usb_interface *interface; /* the interface for this device */
+ struct semaphore limit_sem; /* limiting the number of writes in progress */
+ struct usb_anchor submitted; /* in case we need to retract our submissions */
+ unsigned char *bulk_in_buffer; /* the buffer to receive data */
+ size_t bulk_in_size; /* the size of the receive buffer */
+ unsigned char *int_in_buffer; /* the buffer to receive data */
+ size_t int_in_size; /* the size of the receive buffer */
+ __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */
+ __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */
+ __u8 int_in_endpointAddr; /* the address of the interrupt in endpoint */
+ int int_in_interval;
+ int errors; /* the last request tanked */
+ int open_count; /* count the number of openers */
+ spinlock_t err_lock; /* lock for errors */
+ struct mutex io_mutex; /* synchronize I/O with disconnect */
+ struct urb *irq;
+ struct candevice_t *candev;
+};
+
+static struct usb_driver usbcan_driver;
+
/**
* usbcan_request_io: - reserve io or memory range for can board
* @candev: pointer to candevice/board which asks for io. Field @io_addr
*/
int usbcan_request_io(struct candevice_t *candev)
{
- if (!can_request_io_region(candev->io_addr,IO_RANGE,DEVICE_NAME)) {
- CANMSG("Unable to open port: 0x%lx\n",candev->io_addr);
- return -ENODEV;
- }else {
- DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + IO_RANGE - 1);
- }
+ ((struct usb_ul_usb1*)candev->sysdevptr.anydev)->candev=candev;
return 0;
}
*/
int usbcan_release_io(struct candevice_t *candev)
{
- can_release_io_region(candev->io_addr,IO_RANGE);
+ struct usb_ul_usb1 *dev;
+ if (candev->sysdevptr.anydev){
+ dev=(struct usb_ul_usb1*) candev->sysdevptr.anydev;
+ usb_put_dev(dev->udev);
+ usb_kill_urb(dev->irq);
+ usb_free_urb(dev->irq);
+ kfree(dev->bulk_in_buffer);
+ kfree(dev->int_in_buffer);
+ if (dev->candev){
+ dev->candev->sysdevptr.anydev=NULL;
+ //cleanup_usbdev(dev->candev);
+ }
+ kfree(dev);
+ }
return 0;
}
return 0;
}
-/**
- * usbcan_init_chip_data - Initialize chips
- * @candev: Pointer to candevice/board structure
- * @chipnr: Number of the CAN chip on the hardware card
- *
- * The function usbcan_init_chip_data() is used to initialize the hardware
- * structure containing information about the CAN chips.
- * %CHIP_TYPE represents the type of CAN chip. %CHIP_TYPE can be "i82527" or
- * "sja1000".
- * The @chip_base_addr entry represents the start of the 'official' memory map
- * of the installed chip. It's likely that this is the same as the @io_addr
- * argument supplied at module loading time.
- * The @clock entry holds the chip clock value in Hz.
- * The entry @sja_cdr_reg holds hardware specific options for the Clock Divider
- * register. Options defined in the %sja1000.h file:
- * %sjaCDR_CLKOUT_MASK, %sjaCDR_CLK_OFF, %sjaCDR_RXINPEN, %sjaCDR_CBP, %sjaCDR_PELICAN
- * The entry @sja_ocr_reg holds hardware specific options for the Output Control
- * register. Options defined in the %sja1000.h file:
- * %sjaOCR_MODE_BIPHASE, %sjaOCR_MODE_TEST, %sjaOCR_MODE_NORMAL, %sjaOCR_MODE_CLOCK,
- * %sjaOCR_TX0_LH, %sjaOCR_TX1_ZZ.
- * The entry @int_clk_reg holds hardware specific options for the Clock Out
- * register. Options defined in the %i82527.h file:
- * %iCLK_CD0, %iCLK_CD1, %iCLK_CD2, %iCLK_CD3, %iCLK_SL0, %iCLK_SL1.
- * The entry @int_bus_reg holds hardware specific options for the Bus
- * Configuration register. Options defined in the %i82527.h file:
- * %iBUS_DR0, %iBUS_DR1, %iBUS_DT1, %iBUS_POL, %iBUS_CBY.
- * The entry @int_cpu_reg holds hardware specific options for the cpu interface
- * register. Options defined in the %i82527.h file:
- * %iCPU_CEN, %iCPU_MUX, %iCPU_SLP, %iCPU_PWD, %iCPU_DMC, %iCPU_DSC, %iCPU_RST.
- * Return Value: The function always returns zero
- * File: src/usbcan.c
- */
-int usbcan_init_chip_data(struct candevice_t *candev, int chipnr)
-{
- canchip_t chip=candev->chip[chipnr];
-
- chip->chip_type="usbcan";
- chip->max_objects=1;
- usbcan_register(chip->chipspecops);
-
- CANMSG("initializing usbcan chip operations\n");
- chipspecops->chip_config=usbcan_chip_config;
- chipspecops->baud_rate=usbcan_baud_rate;
- chipspecops->standard_mask=usbcan_standard_mask;
- chipspecops->extended_mask=usbcan_extended_mask;
- chipspecops->message15_mask=usbcan_extended_mask;
- chipspecops->clear_objects=usbcan_clear_objects;
- chipspecops->config_irqs=usbcan_config_irqs;
- chipspecops->pre_read_config=usbcan_pre_read_config;
- chipspecops->pre_write_config=usbcan_pre_write_config;
- chipspecops->send_msg=usbcan_send_msg;
- chipspecops->check_tx_stat=usbcan_check_tx_stat;
- chipspecops->wakeup_tx=usbcan_wakeup_tx;
- chipspecops->remote_request=usbcan_remote_request;
- chipspecops->enable_configuration=usbcan_enable_configuration;
- chipspecops->disable_configuration=usbcan_disable_configuration;
- chipspecops->attach_to_chip=usbcan_attach_to_chip;
- chipspecops->release_chip=usbcan_release_chip;
- chipspecops->set_btregs=usbcan_set_btregs;
- chipspecops->start_chip=usbcan_start_chip;
- chipspecops->stop_chip=usbcan_stop_chip;
- chipspecops->irq_handler=usbcan_irq_handler;
- chipspecops->irq_accept=NULL;
-
- candev->chip[chipnr]->chip_base_addr=candev->io_addr;
- candev->chip[chipnr]->clock = 16000000;
- candev->chip[chipnr]->int_cpu_reg = iCPU_DSC;
- candev->chip[chipnr]->int_clk_reg = iCLK_SL1;
- candev->chip[chipnr]->int_bus_reg = iBUS_CBY;
- candev->chip[chipnr]->sja_cdr_reg = sjaCDR_CBP | sjaCDR_CLK_OFF;
- candev->chip[chipnr]->sja_ocr_reg = sjaOCR_MODE_NORMAL |
- sjaOCR_TX0_LH;
-
- return 0;
-}
-
/**
* usbcan_init_obj_data - Initialize message buffers
* @chip: Pointer to chip specific structure
return 0;
}
+#ifdef CONFIG_OC_LINCAN_DETAILED_ERRORS
+
static const char *sja1000_ecc_errc_str[]={
"bit error",
"form error",
static void sja1000_report_error(struct canchip_t *chip,
unsigned sr, unsigned ir, unsigned ecc)
{
- if(sja1000_report_error_limit_counter>=100)
+/* if(sja1000_report_error_limit_counter>=100)
return;
CANMSG("Error: status register: 0x%x irq_register: 0x%02x error: 0x%02x\n",
*/
int usbcan_enable_configuration(struct canchip_t *chip)
{
- int i=0;
+/* int i=0;
enum sja1000_PeliCAN_MOD flags;
can_disable_irq(chip->chip_irq);
can_enable_irq(chip->chip_irq);
return -ENODEV;
}
-
+*/
return 0;
}
*/
int usbcan_disable_configuration(struct canchip_t *chip)
{
- int i=0;
+/* int i=0;
enum sja1000_PeliCAN_MOD flags;
flags=can_read_reg(chip,SJAMOD);
}
can_enable_irq(chip->chip_irq);
-
+*/
return 0;
}
*/
int usbcan_chip_config(struct canchip_t *chip)
{
- int i;
+/* int i;
unsigned char n, r;
if (usbcan_enable_configuration(chip))
return -ENODEV;
- /* Set mode, clock out, comparator */
+ // Set mode, clock out, comparator
can_write_reg(chip,sjaCDR_PELICAN|chip->sja_cdr_reg,SJACDR);
- /* Ensure, that interrupts are disabled even on the chip level now */
+ // Ensure, that interrupts are disabled even on the chip level now
can_write_reg(chip, sjaDISABLE_INTERRUPTS, SJAIER);
- /* Set driver output configuration */
+ // Set driver output configuration
can_write_reg(chip,chip->sja_ocr_reg,SJAOCR);
- /* Simple check for chip presence */
+ // Simple check for chip presence
for (i=0, n=0x5a; i<8; i++, n+=0xf) {
can_write_reg(chip,n,SJAACR0+i);
}
if (usbcan_baud_rate(chip,chip->baudrate,chip->clock,0,75,0))
return -ENODEV;
- /* Enable hardware interrupts */
+ // Enable hardware interrupts
can_write_reg(chip, sjaENABLE_INTERRUPTS, SJAIER);
usbcan_disable_configuration(chip);
-
+*/
return 0;
}
*/
int usbcan_extended_mask(struct canchip_t *chip, unsigned long code, unsigned long mask)
{
- int i;
+/* int i;
if (usbcan_enable_configuration(chip))
return -ENODEV;
DEBUGMSG("Setting acceptance mask to 0x%lx\n",(unsigned long)mask);
usbcan_disable_configuration(chip);
-
+*/
return 0;
}
int usbcan_baud_rate(struct canchip_t *chip, int rate, int clock, int sjw,
int sampl_pt, int flags)
{
- int best_error = 1000000000, error;
- int best_tseg=0, best_brp=0, best_rate=0, brp=0;
- int tseg=0, tseg1=0, tseg2=0;
-
- if (usbcan_enable_configuration(chip))
- return -ENODEV;
-
- clock /=2;
-
- /* tseg even = round down, odd = round up */
- for (tseg=(0+0+2)*2; tseg<=(sjaMAX_TSEG2+sjaMAX_TSEG1+2)*2+1; tseg++) {
- brp = clock/((1+tseg/2)*rate)+tseg%2;
- if (brp == 0 || brp > 64)
- continue;
- error = rate - clock/(brp*(1+tseg/2));
- if (error < 0)
- error = -error;
- if (error <= best_error) {
- best_error = error;
- best_tseg = tseg/2;
- best_brp = brp-1;
- best_rate = clock/(brp*(1+tseg/2));
- }
- }
- if (best_error && (rate/best_error < 10)) {
- CANMSG("baud rate %d is not possible with %d Hz clock\n",
- rate, 2*clock);
- CANMSG("%d bps. brp=%d, best_tseg=%d, tseg1=%d, tseg2=%d\n",
- best_rate, best_brp, best_tseg, tseg1, tseg2);
- return -EINVAL;
- }
- tseg2 = best_tseg-(sampl_pt*(best_tseg+1))/100;
- if (tseg2 < 0)
- tseg2 = 0;
- if (tseg2 > sjaMAX_TSEG2)
- tseg2 = sjaMAX_TSEG2;
- tseg1 = best_tseg-tseg2-2;
- if (tseg1>sjaMAX_TSEG1) {
- tseg1 = sjaMAX_TSEG1;
- tseg2 = best_tseg-tseg1-2;
- }
-
- DEBUGMSG("Setting %d bps.\n", best_rate);
- DEBUGMSG("brp=%d, best_tseg=%d, tseg1=%d, tseg2=%d, sampl_pt=%d\n",
- best_brp, best_tseg, tseg1, tseg2,
- (100*(best_tseg-tseg2)/(best_tseg+1)));
-
-
- can_write_reg(chip, sjw<<6 | best_brp, SJABTR0);
- can_write_reg(chip, ((flags & BTR1_SAM) != 0)<<7 | (tseg2<<4)
- | tseg1, SJABTR1);
-
- usbcan_disable_configuration(chip);
+// int best_error = 1000000000, error;
+// int best_tseg=0, best_brp=0, best_rate=0, brp=0;
+// int tseg=0, tseg1=0, tseg2=0;
+//
+// if (usbcan_enable_configuration(chip))
+// return -ENODEV;
+//
+// clock /=2;
+//
+// // tseg even = round down, odd = round up
+// for (tseg=(0+0+2)*2; tseg<=(sjaMAX_TSEG2+sjaMAX_TSEG1+2)*2+1; tseg++) {
+// brp = clock/((1+tseg/2)*rate)+tseg%2;
+// if (brp == 0 || brp > 64)
+// continue;
+// error = rate - clock/(brp*(1+tseg/2));
+// if (error < 0)
+// error = -error;
+// if (error <= best_error) {
+// best_error = error;
+// best_tseg = tseg/2;
+// best_brp = brp-1;
+// best_rate = clock/(brp*(1+tseg/2));
+// }
+// }
+// if (best_error && (rate/best_error < 10)) {
+// CANMSG("baud rate %d is not possible with %d Hz clock\n",
+// rate, 2*clock);
+// CANMSG("%d bps. brp=%d, best_tseg=%d, tseg1=%d, tseg2=%d\n",
+// best_rate, best_brp, best_tseg, tseg1, tseg2);
+// return -EINVAL;
+// }
+// tseg2 = best_tseg-(sampl_pt*(best_tseg+1))/100;
+// if (tseg2 < 0)
+// tseg2 = 0;
+// if (tseg2 > sjaMAX_TSEG2)
+// tseg2 = sjaMAX_TSEG2;
+// tseg1 = best_tseg-tseg2-2;
+// if (tseg1>sjaMAX_TSEG1) {
+// tseg1 = sjaMAX_TSEG1;
+// tseg2 = best_tseg-tseg1-2;
+// }
+//
+// DEBUGMSG("Setting %d bps.\n", best_rate);
+// DEBUGMSG("brp=%d, best_tseg=%d, tseg1=%d, tseg2=%d, sampl_pt=%d\n",
+// best_brp, best_tseg, tseg1, tseg2,
+// (100*(best_tseg-tseg2)/(best_tseg+1)));
+//
+//
+// can_write_reg(chip, sjw<<6 | best_brp, SJABTR0);
+// can_write_reg(chip, ((flags & BTR1_SAM) != 0)<<7 | (tseg2<<4)
+// | tseg1, SJABTR1);
+//
+// usbcan_disable_configuration(chip);
return 0;
}
* File: src/usbcan.c
*/
void usbcan_read(struct canchip_t *chip, struct msgobj_t *obj) {
- int i, flags, len, datastart;
+/* int i, flags, len, datastart;
do {
flags = can_read_reg(chip,SJAFRM);
if(flags&sjaFRM_FF) {
obj->rx_msg.data[i]=can_read_reg(chip,datastart+i);
}
- /* fill CAN message timestamp */
+ // fill CAN message timestamp
can_filltimestamp(&obj->rx_msg.timestamp);
canque_filter_msg2edges(obj->qends, &obj->rx_msg);
can_write_reg(chip, sjaCMR_RRB, SJACMR);
- } while (can_read_reg(chip, SJASR) & sjaSR_RBS);
+ } while (can_read_reg(chip, SJASR) & sjaSR_RBS);*/
}
/**
*/
int usbcan_pre_read_config(struct canchip_t *chip, struct msgobj_t *obj)
{
- int status;
+/* int status;
status=can_read_reg(chip,SJASR);
if(status & sjaSR_BS) {
- /* Try to recover from error condition */
+ // Try to recover from error condition
DEBUGMSG("usbcan_pre_read_config bus-off recover 0x%x\n",status);
usbcan_enable_configuration(chip);
can_write_reg(chip, 0, SJARXERR);
can_write_reg(chip, sjaDISABLE_INTERRUPTS, SJAIER); //disable interrupts for a moment
usbcan_read(chip, obj);
- can_write_reg(chip, sjaENABLE_INTERRUPTS, SJAIER); //enable interrupts
+ can_write_reg(chip, sjaENABLE_INTERRUPTS, SJAIER); //enable interrupts*/
return 1;
}
int usbcan_pre_write_config(struct canchip_t *chip, struct msgobj_t *obj,
struct canmsg_t *msg)
{
- int i=0;
+/* int i=0;
unsigned int id;
int status;
int len;
- /* Wait until Transmit Buffer Status is released */
+ // Wait until Transmit Buffer Status is released
while ( !((status=can_read_reg(chip, SJASR)) & sjaSR_TBS) &&
i++<MAX_TRANSMIT_WAIT_LOOPS) {
udelay(i);
}
if(status & sjaSR_BS) {
- /* Try to recover from error condition */
+ // Try to recover from error condition
DEBUGMSG("usbcan_pre_write_config bus-off recover 0x%x\n",status);
usbcan_enable_configuration(chip);
can_write_reg(chip, 0, SJARXERR);
}
len = msg->length;
if(len > CAN_MSG_LENGTH) len = CAN_MSG_LENGTH;
- /* len &= sjaFRM_DLC_M; ensured by above condition already */
+ // len &= sjaFRM_DLC_M; ensured by above condition already
can_write_reg(chip, ((msg->flags&MSG_EXT)?sjaFRM_FF:0) |
((msg->flags & MSG_RTR) ? sjaFRM_RTR : 0) | len, SJAFRM);
if(msg->flags&MSG_EXT) {
for(i=0; i < len; i++) {
can_write_reg(chip, msg->data[i], SJADATS+i);
}
- }
+ }*/
return 0;
}
int usbcan_send_msg(struct canchip_t *chip, struct msgobj_t *obj,
struct canmsg_t *msg)
{
- can_write_reg(chip, sjaCMR_TR, SJACMR);
-
+/* can_write_reg(chip, sjaCMR_TR, SJACMR);
+*/
return 0;
}
*/
int usbcan_check_tx_stat(struct canchip_t *chip)
{
- if (can_read_reg(chip,SJASR) & sjaSR_TCS)
+// if (can_read_reg(chip,SJASR) & sjaSR_TCS)
return 0;
- else
- return 1;
+// else
+// return 1;
}
/**
int usbcan_set_btregs(struct canchip_t *chip, unsigned short btr0,
unsigned short btr1)
{
- if (usbcan_enable_configuration(chip))
+/* if (usbcan_enable_configuration(chip))
return -ENODEV;
can_write_reg(chip, btr0, SJABTR0);
can_write_reg(chip, btr1, SJABTR1);
usbcan_disable_configuration(chip);
-
+*/
return 0;
}
*/
int usbcan_start_chip(struct canchip_t *chip)
{
- enum sja1000_PeliCAN_MOD flags;
+/* enum sja1000_PeliCAN_MOD flags;
flags = can_read_reg(chip, SJAMOD) & (sjaMOD_LOM|sjaMOD_STM|sjaMOD_AFM|sjaMOD_SM);
can_write_reg(chip, flags, SJAMOD);
sja1000_report_error_limit_counter=0;
-
+*/
return 0;
}
*/
int usbcan_stop_chip(struct canchip_t *chip)
{
- enum sja1000_PeliCAN_MOD flags;
+/* enum sja1000_PeliCAN_MOD flags;
flags = can_read_reg(chip, SJAMOD) & (sjaMOD_LOM|sjaMOD_STM|sjaMOD_AFM|sjaMOD_SM);
can_write_reg(chip, flags|sjaMOD_RM, SJAMOD);
-
+*/
return 0;
}
*/
int usbcan_release_chip(struct canchip_t *chip)
{
- usbcan_stop_chip(chip);
+/* usbcan_stop_chip(chip);
can_write_reg(chip, sjaDISABLE_INTERRUPTS, SJAIER);
-
+*/
return 0;
}
*/
void usbcan_irq_write_handler(struct canchip_t *chip, struct msgobj_t *obj)
{
- int cmd;
+/* int cmd;
if(obj->tx_slot){
- /* Do local transmitted message distribution if enabled */
+ // Do local transmitted message distribution if enabled
if (processlocal){
- /* fill CAN message timestamp */
+ // fill CAN message timestamp
can_filltimestamp(&obj->tx_slot->msg.timestamp);
obj->tx_slot->msg.flags |= MSG_LOCAL;
canque_filter_msg2edges(obj->qends, &obj->tx_slot->msg);
}
- /* Free transmitted slot */
+ // Free transmitted slot
canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
obj->tx_slot=NULL;
}
obj->tx_slot=NULL;
return;
}
-
+*/
}
#define MAX_RETR 10
*/
int usbcan_irq_handler(int irq, struct canchip_t *chip)
{
- int irq_register, status, error_code;
+/* int irq_register, status, error_code;
struct msgobj_t *obj=chip->msgobj[0];
int loop_cnt=CHIP_MAX_IRQLOOP;
return CANCHIP_IRQ_STUCK;
}
- /* (irq_register & sjaIR_RI) */
- /* old variant using SJAIR, collides with intended use with irq_accept */
+ // (irq_register & sjaIR_RI)
+ // old variant using SJAIR, collides with intended use with irq_accept
if (status & sjaSR_RBS) {
DEBUGMSG("sja1000_irq_handler: RI or RBS\n");
usbcan_read(chip,obj);
obj->ret = 0;
}
- /* (irq_register & sjaIR_TI) */
- /* old variant using SJAIR, collides with intended use with irq_accept */
+ // (irq_register & sjaIR_TI)
+ // old variant using SJAIR, collides with intended use with irq_accept
if (((status & sjaSR_TBS) && can_msgobj_test_fl(obj,TX_PENDING))||
(can_msgobj_test_fl(obj,TX_REQUEST))) {
DEBUGMSG("sja1000_irq_handler: TI or TX_PENDING and TBS\n");
if(error_code == 0xd9) {
obj->ret= -ENXIO;
- /* no such device or address - no ACK received */
+ // no such device or address - no ACK received
}
if(obj->tx_retry_cnt++>MAX_RETR) {
can_write_reg(chip, sjaCMR_AT, SJACMR); // cancel any transmition
if(obj->tx_slot){
canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_BUS);
- /*canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
- obj->tx_slot=NULL;*/
+ //canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
+ //obj->tx_slot=NULL;
}
} else {
} while((irq_register & (sjaIR_BEI|sjaIR_EPI|sjaIR_DOI|sjaIR_EI|sjaIR_RI)) ||
(can_msgobj_test_fl(obj,TX_REQUEST) && !can_msgobj_test_fl(obj,TX_LOCK)) ||
(status & sjaSR_RBS));
-
+*/
return CANCHIP_IRQ_HANDLED;
}
int usbcan_wakeup_tx(struct canchip_t *chip, struct msgobj_t *obj)
{
- can_preempt_disable();
+/* can_preempt_disable();
can_msgobj_set_fl(obj,TX_PENDING);
can_msgobj_set_fl(obj,TX_REQUEST);
DEBUGMSG("TX looping in usbcan_wakeup_tx\n");
}
- can_preempt_enable();
+ can_preempt_enable();*/
return 0;
}
-int usbcan_register(struct chipspecops_t *chipspecops)
+int usbcan_chipregister(struct chipspecops_t *chipspecops)
{
return 0;
}
return 0;
}
+/**
+ * usbcan_init_chip_data - Initialize chips
+ * @candev: Pointer to candevice/board structure
+ * @chipnr: Number of the CAN chip on the hardware card
+ *
+ * The function usbcan_init_chip_data() is used to initialize the hardware
+ * structure containing information about the CAN chips.
+ * %CHIP_TYPE represents the type of CAN chip. %CHIP_TYPE can be "i82527" or
+ * "sja1000".
+ * The @chip_base_addr entry represents the start of the 'official' memory map
+ * of the installed chip. It's likely that this is the same as the @io_addr
+ * argument supplied at module loading time.
+ * The @clock entry holds the chip clock value in Hz.
+ * The entry @sja_cdr_reg holds hardware specific options for the Clock Divider
+ * register. Options defined in the %sja1000.h file:
+ * %sjaCDR_CLKOUT_MASK, %sjaCDR_CLK_OFF, %sjaCDR_RXINPEN, %sjaCDR_CBP, %sjaCDR_PELICAN
+ * The entry @sja_ocr_reg holds hardware specific options for the Output Control
+ * register. Options defined in the %sja1000.h file:
+ * %sjaOCR_MODE_BIPHASE, %sjaOCR_MODE_TEST, %sjaOCR_MODE_NORMAL, %sjaOCR_MODE_CLOCK,
+ * %sjaOCR_TX0_LH, %sjaOCR_TX1_ZZ.
+ * The entry @int_clk_reg holds hardware specific options for the Clock Out
+ * register. Options defined in the %i82527.h file:
+ * %iCLK_CD0, %iCLK_CD1, %iCLK_CD2, %iCLK_CD3, %iCLK_SL0, %iCLK_SL1.
+ * The entry @int_bus_reg holds hardware specific options for the Bus
+ * Configuration register. Options defined in the %i82527.h file:
+ * %iBUS_DR0, %iBUS_DR1, %iBUS_DT1, %iBUS_POL, %iBUS_CBY.
+ * The entry @int_cpu_reg holds hardware specific options for the cpu interface
+ * register. Options defined in the %i82527.h file:
+ * %iCPU_CEN, %iCPU_MUX, %iCPU_SLP, %iCPU_PWD, %iCPU_DMC, %iCPU_DSC, %iCPU_RST.
+ * Return Value: The function always returns zero
+ * File: src/usbcan.c
+ */
+int usbcan_init_chip_data(struct candevice_t *candev, int chipnr)
+{
+ struct canchip_t *chip=candev->chip[chipnr];
+
+ chip->chip_type="usbcan";
+ chip->max_objects=1;
+ usbcan_chipregister(chip->chipspecops);
+
+ CANMSG("initializing usbcan chip operations\n");
+ chip->chipspecops->chip_config=usbcan_chip_config;
+ chip->chipspecops->baud_rate=usbcan_baud_rate;
+ chip->chipspecops->standard_mask=usbcan_standard_mask;
+ chip->chipspecops->extended_mask=usbcan_extended_mask;
+ chip->chipspecops->message15_mask=usbcan_extended_mask;
+ chip->chipspecops->clear_objects=usbcan_clear_objects;
+ chip->chipspecops->config_irqs=usbcan_config_irqs;
+ chip->chipspecops->pre_read_config=usbcan_pre_read_config;
+ chip->chipspecops->pre_write_config=usbcan_pre_write_config;
+ chip->chipspecops->send_msg=usbcan_send_msg;
+ chip->chipspecops->check_tx_stat=usbcan_check_tx_stat;
+ chip->chipspecops->wakeup_tx=usbcan_wakeup_tx;
+ chip->chipspecops->remote_request=usbcan_remote_request;
+ chip->chipspecops->enable_configuration=usbcan_enable_configuration;
+ chip->chipspecops->disable_configuration=usbcan_disable_configuration;
+ chip->chipspecops->attach_to_chip=usbcan_attach_to_chip;
+ chip->chipspecops->release_chip=usbcan_release_chip;
+ chip->chipspecops->set_btregs=usbcan_set_btregs;
+ chip->chipspecops->start_chip=usbcan_start_chip;
+ chip->chipspecops->stop_chip=usbcan_stop_chip;
+ chip->chipspecops->irq_handler=usbcan_irq_handler;
+ chip->chipspecops->irq_accept=NULL;
+
+ candev->chip[chipnr]->chip_base_addr=candev->io_addr;
+ candev->chip[chipnr]->clock = 16000000;
+/* candev->chip[chipnr]->int_cpu_reg = iCPU_DSC;
+ candev->chip[chipnr]->int_clk_reg = iCLK_SL1;
+ candev->chip[chipnr]->int_bus_reg = iBUS_CBY;
+ candev->chip[chipnr]->sja_cdr_reg = sjaCDR_CBP | sjaCDR_CLK_OFF;
+ candev->chip[chipnr]->sja_ocr_reg = sjaOCR_MODE_NORMAL |
+ sjaOCR_TX0_LH;*/
+
+ return 0;
+}
+
/* --------------------------------------------------------------------------------------------------- */
-static void ul_usb1_irq(struct urb *urb)
+static void usbcan_irq(struct urb *urb)
{
- struct usb_ul_usb1 *dev = urb->context;
- struct ul_usb1_combo devc;
+ struct usb_usbcan *dev = urb->context;
int retval;
CANMSG("Interrupt poll\n");
goto exit;
}
- devc.dev = dev;
- devc.urb = urb;
-
dev->candev->chip[0]->chipspecops->irq_handler(0,dev->candev->chip[0]);
CANMSG("Interrupt caught\n");
__FUNCTION__, retval);
}
-static void ul_usb1_delete(struct usb_ul_usb1 *dev)
+static void usbcan_delete(struct usb_usbcan *dev)
{
usb_put_dev(dev->udev);
usb_kill_urb(dev->irq);
kfree(dev);
}
-static int ul_usb1_probe(struct usb_interface *interface, const struct usb_device_id *id)
+static int usbcan_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
- struct usb_ul_usb1 *dev;
+ struct usb_usbcan *dev;
struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint;
struct candevice_t *candev;
goto error;
}
sema_init(&dev->limit_sem, WRITES_IN_FLIGHT);
- mutex_init(&dev->io_mutex);
spin_lock_init(&dev->err_lock);
init_usb_anchor(&dev->submitted);
dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
}
- if (!dev->int_in_endpointAddr &&
+/* if (!dev->int_in_endpointAddr &&
usb_endpoint_is_int_in(endpoint)) {
- /* we found an interrupt in endpoint */
+ // we found an interrupt in endpoint
buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
dev->int_in_size = buffer_size;
dev->int_in_endpointAddr = endpoint->bEndpointAddress;
err("Could not allocate int_in_buffer");
goto error;
}
- }
+ }*/
}
- if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr && dev->int_in_endpointAddr)) {
+ if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) {
err("Could not find all bulk-in, bulk-out and interrupt endpoints");
goto error;
}
/* save our data pointer in this interface device */
usb_set_intfdata(interface, dev);
- if (main_init_done==1)
- register_usbdev("ul_usb1",(void *) dev);
- else {
- mutex_lock(&usbdev_reg_mutex);
- if (main_init_done==1)
- register_usbdev("ul_usb1",(void *) dev);
- else {
- for (i=0;i<MAX_HW_CARDS;i++){
- if (usbregq[i]==NULL){
- usbregq[i]=(struct usbdev_reg_query *)can_checked_malloc(sizeof(struct usbdev_reg_query));
- if (!usbregq[i]){
- CANMSG("Error allocating usbdev_reg_query");
- mutex_unlock(&usbdev_reg_mutex);
- goto error;
- }
- sprintf (usbregq[i]->hwname,"ul_usb1");
- usbregq[i]->anydev=(void *) dev;
- break;
- }
- }
- if (i==MAX_HW_CARDS){
- CANMSG("No free space to register new card");
- mutex_unlock(&usbdev_reg_mutex);
- goto error;
- }
- }
- mutex_unlock(&usbdev_reg_mutex);
- }
+ register_usbdev("usbcan",(void *) dev);
- dev->irq = usb_alloc_urb(0, GFP_KERNEL);
+/* dev->irq = usb_alloc_urb(0, GFP_KERNEL);
if (!dev->irq){
CANMSG("Error allocating usb urb\n");
goto error;
usb_fill_int_urb(dev->irq, dev->udev,
usb_rcvintpipe(dev->udev, dev->int_in_endpointAddr),
dev->int_in_buffer, dev->int_in_size,
- ul_usb1_irq, dev, dev->int_in_interval);
+ usbcan_irq, dev, dev->int_in_interval);*/
/* usb_fill_bulk_urb(dev->irq, dev->udev,
usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr),
dev->int_in_buffer, dev->int_in_size,
- ul_usb1_irq, dev);*/
+ usbcan_irq, dev);*/
/* dev->irq->transfer_dma = wacom->data_dma;
dev->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;*/
- retval=usb_submit_urb(dev->irq, GFP_KERNEL);
- if (retval){
- CANMSG("INT URB %d\n",retval);
- return -EIO;
- }else
- CANMSG("INT URB SUCCCESS\n");
+// retval=usb_submit_urb(dev->irq, GFP_KERNEL);
+// if (retval){
+// CANMSG("INT URB %d\n",retval);
+// return -EIO;
+// }else
+// CANMSG("INT URB SUCCCESS\n");
/* let the user know what node this device is now attached to */
info("USB Skeleton device now attached");
return 0;
error:
- ul_usb1_delete(dev);
+ usbcan_delete(dev);
return retval;
}
-static void ul_usb1_disconnect(struct usb_interface *interface)
+static void usbcan_disconnect(struct usb_interface *interface)
{
- struct usb_ul_usb1 *dev;
+ struct usb_usbcan *dev;
int minor = interface->minor;
dev = usb_get_intfdata(interface);
//usb_kill_anchored_urbs(&dev->submitted);
- ul_usb1_delete(dev);
+ usbcan_delete(dev);
info("USB Skeleton now disconnected");
}
-static struct usb_driver ul_usb1_driver = {
- .name = "ul_usb1-can",
- .id_table = ul_usb1_table,
- .probe = ul_usb1_probe,
- .disconnect = ul_usb1_disconnect,
- .id_table = ul_usb1_table,
+static struct usb_driver usbcan_driver = {
+ .name = "usbcan",
+ .id_table = usbcan_table,
+ .probe = usbcan_probe,
+ .disconnect = usbcan_disconnect,
};
-int ul_usb1_init(void){
- return usb_register(&ul_usb1_driver);
+int usbcan_init(void){
+ return usb_register(&usbcan_driver);
}
-void ul_usb1_exit(void){
- usb_deregister(&ul_usb1_driver);
+void usbcan_exit(void){
+ usb_deregister(&usbcan_driver);
}