X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lincan.git/blobdiff_plain/4ddb8468e0688f83f24fc041cfb62512ee45194a..4cf24de229090b1ab6279570a564d224e13dd706:/lincan/src/smartcan.c diff --git a/lincan/src/smartcan.c b/lincan/src/smartcan.c new file mode 100644 index 0000000..c41c2d6 --- /dev/null +++ b/lincan/src/smartcan.c @@ -0,0 +1,154 @@ +/* smartcan.c + * Linux CAN-bus device driver. + * Written by Arnaud Westenberg email:arnaud@wanadoo.nl + * This software is released under the GPL-License. + * Version 0.7 6 Aug 2001 + */ + +#include +#if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS) +#define MODVERSIONS +#endif + +#if defined (MODVERSIONS) +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include "../include/main.h" +#include "../include/smartcan.h" +#include "../include/i82527.h" + +int smartcan_irq=-1; +unsigned long smartcan_base=0x0; + +int smartcan_request_io(unsigned long io_addr) +{ + int err=0; + + if ( (err=check_region(io_addr,0x04)) < 0 ) { + CANMSG("Unable to open port: 0x%lx\n",io_addr); + return -ENODEV; + } + else { + request_region(io_addr,0x04,DEVICE_NAME); + DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr, io_addr + 0x04 - 1); + } + return 0; +} + +int smartcan_release_io(unsigned long io_addr) +{ + release_region(io_addr,0x04); + + return 0; +} + +int smartcan_reset(int card) +{ + int i=0; + + DEBUGMSG("Resetting smartcan hardware ...\n"); + outb(0x00,candevices_p[card]->res_addr); + while (i < 1000000) { + i++; + outb(0x01,candevices_p[card]->res_addr); + } + outb(0x00,candevices_p[card]->res_addr); + + /* Check hardware reset status */ + i=0; + outb(candevices_p[card]->io_addr+iCPU,candevices_p[card]->io_addr); + while ( (inb(candevices_p[card]->io_addr+1)&0x80) && (i<=15) ) { + udelay(20000); + i++; + } + if (i>=15) { + CANMSG("Reset status timeout!\n"); + CANMSG("Please check your hardware.\n"); + return -ENODEV; + } + else + DEBUGMSG("Chip0 reset status ok.\n"); + + return 0; +} + +int smartcan_init_hw_data(int card) +{ + candevices_p[card]->res_addr=candevices_p[card]->io_addr+0x02; + candevices_p[card]->nr_82527_chips=1; + candevices_p[card]->nr_sja1000_chips=0; + + return 0; +} + +int smartcan_init_chip_data(int card, int chipnr) +{ + candevices_p[card]->chip[chipnr]->chip_type="i82527"; + candevices_p[card]->chip[chipnr]->chip_base_addr=candevices_p[card]->io_addr; + candevices_p[card]->chip[chipnr]->clock = 16000000; + candevices_p[card]->chip[chipnr]->int_cpu_reg = iCPU_DSC; + candevices_p[card]->chip[chipnr]->int_clk_reg = iCLK_SL1; + candevices_p[card]->chip[chipnr]->int_bus_reg = iBUS_CBY; + candevices_p[card]->chip[chipnr]->sja_cdr_reg = 0; + candevices_p[card]->chip[chipnr]->sja_ocr_reg = 0; + smartcan_irq=candevices_p[card]->chip[chipnr]->chip_irq; + smartcan_base=candevices_p[card]->chip[chipnr]->chip_base_addr; + + return 0; +} + +int smartcan_init_obj_data(int chipnr, int objnr) +{ + chips_p[chipnr]->msgobj[objnr]->obj_base_addr=(objnr+1)*0x10; + chips_p[chipnr]->msgobj[objnr]->flags=0; + + return 0; +} + + +void smartcan_write_register(unsigned char data, unsigned long address) +{ + disable_irq(smartcan_irq); + outb(address-smartcan_base,smartcan_base); + outb(data,smartcan_base+1); + enable_irq(smartcan_irq); +} + +unsigned smartcan_read_register(unsigned long address) +{ + unsigned ret; + disable_irq(smartcan_irq); + outb(address-smartcan_base,smartcan_base); + ret=inb(smartcan_base+1); + enable_irq(smartcan_irq); + return ret; +} + +int smartcan_program_irq(int card) +{ + CANMSG("The 'smartcan' card doesn't have programmable interrupts\n"); + return 0; +} + +/* !!! Don't change this function !!! */ +int smartcan_register(struct hwspecops_t *hwspecops) +{ + hwspecops->request_io = smartcan_request_io; + hwspecops->release_io = smartcan_release_io; + hwspecops->reset = smartcan_reset; + hwspecops->init_hw_data = smartcan_init_hw_data; + hwspecops->init_chip_data = smartcan_init_chip_data; + hwspecops->init_obj_data = smartcan_init_obj_data; + hwspecops->write_register = smartcan_write_register; + hwspecops->read_register = smartcan_read_register; + hwspecops->program_irq = smartcan_program_irq; + return 0; +}