www.pudn.com > canbus4linux.rar > sja1000.c
/* * sja1000.c * Copyright (c) 2001 Jürgen Eder* * A general chipset driver for CAN cards with SJA1000 (82C200 should work * in CAN 2.0A mode). To use this, the hardware driver is needed (e.g. can200par.o * or elektor_canpar.o) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define EXPORT_SYMTAB #include #include #include #include #include #include #include #include #include #include "trace.h" #include "sja1000.h" #include "canbus4linux.h" #ifdef MODULE_LICENSE MODULE_LICENSE("GPL"); #endif int sja1000_set_baudrate(struct sja1000_admin *pSja1000Par, unsigned long baudrate); int sja1000_set_baudrate_by_constant(struct sja1000_admin *pSja1000Par, unsigned long baudrate); int sja1000_set_acceptance_filter(struct sja1000_admin *pSja1000Par, struct canbus_acceptance_filter *filter); int sja1000_check_chipset(struct sja1000_admin *pSja1000Par); int sja1000_activate_device(struct sja1000_admin *pSja1000Par); int sja1000_init_device(struct sja1000_admin *pSja1000Par); int sja1000_deactivate_device(struct sja1000_admin *pSja1000Par); int sja1000_set_register(struct sja1000_admin *pSja1000Par, int addresse, unsigned int value); int sja1000_get_register(struct sja1000_admin *pSja1000Par, int addresse, int *value); #define NUM_SJA1000_DEVICES 10 static struct sja1000_admin sja1000_admin[NUM_SJA1000_DEVICES]; #define SJA1000_DECLCHIP(x) \ struct sja1000_access * chip = &((x)->access); \ void * chip_data = (x)->pDeviceParm; \ do {} while (0) // makes the user put ';' after it #define SJA1000_TEST_DECLCHIP(x) \ struct sja1000_access * chip; \ void * chip_data; \ if (!(x)) \ return -ENODEV; \ chip = &((x)->access); \ chip_data = (x)->pDeviceParm; \ do {} while (0) // makes the user put ';' after it /***************************************************************************************/ static void sja1000_LockRegister(struct sja1000_admin *pSja1000Par) { spin_lock_irqsave(&pSja1000Par->irq_lock,pSja1000Par->lock_flags); } /***************************************************************************************/ static void sja1000_UnLockRegister(struct sja1000_admin *pSja1000Par) { spin_unlock_irqrestore(&pSja1000Par->irq_lock,pSja1000Par->lock_flags); } /***************************************************************************************/ static void sja1000_WriteRegister(struct sja1000_admin *pSja1000Par, u8 addr, u8 value) { SJA1000_DECLCHIP(pSja1000Par); sja1000_LockRegister(pSja1000Par); chip->pWriteToRegister(chip_data, addr, value); sja1000_UnLockRegister(pSja1000Par); } /***************************************************************************************/ static u8 sja1000_ReadRegister(struct sja1000_admin *pSja1000Par, u8 addr) { u8 ret=0; SJA1000_DECLCHIP(pSja1000Par); sja1000_LockRegister(pSja1000Par); ret = chip->pReadFromRegister(chip_data, addr); sja1000_UnLockRegister(pSja1000Par); return ret; } /***************************************************************************************/ static void sja1000_WriteRegisterRR(struct sja1000_admin *pSja1000Par, u8 addr, u8 value) { SJA1000_DECLCHIP(pSja1000Par); sja1000_LockRegister(pSja1000Par); chip->pWriteToRegister(chip_data, 0, chip->pReadFromRegister(chip_data,0) | 0x01); chip->pWriteToRegister(chip_data, addr, value); chip->pWriteToRegister(chip_data, 0, chip->pReadFromRegister(chip_data,0) & 0x3e); sja1000_UnLockRegister(pSja1000Par); } /***************************************************************************************/ static u8 sja1000_ReadRegisterRR(struct sja1000_admin *pSja1000Par, u8 addr) { u8 ret=0; SJA1000_DECLCHIP(pSja1000Par); sja1000_LockRegister(pSja1000Par); chip->pWriteToRegister(chip_data, 0, chip->pReadFromRegister(chip_data,0) | 0x01); ret = chip->pReadFromRegister(chip_data, addr); chip->pWriteToRegister(chip_data, 0, chip->pReadFromRegister(chip_data,0) & 0x3e); sja1000_UnLockRegister(pSja1000Par); return ret; } /***************************************************************************************/ int sja1000_open_device(struct sja1000_admin *pSja1000Par) { int ret; SJA1000_TEST_DECLCHIP(pSja1000Par); ret = chip->pOpenCanDevice(chip_data); sja1000_activate_device(pSja1000Par); return ret; } /***************************************************************************************/ int sja1000_close_device(struct sja1000_admin *pSja1000Par) { int ret; SJA1000_TEST_DECLCHIP(pSja1000Par); ret = chip->pCloseCanDevice(chip_data); sja1000_deactivate_device(pSja1000Par); return ret; } /***************************************************************************************/ int sja1000_init_device(struct sja1000_admin *pSja1000Par) { SJA1000_TEST_DECLCHIP(pSja1000Par); if (pSja1000Par->bCan_2B) { TRACE("Init Pelican"); sja1000_WriteRegisterRR(pSja1000Par, 0, 0x08); // Acceptance Filter Mode: single sja1000_WriteRegisterRR(pSja1000Par, 31, 0x80 | sja1000_ReadRegisterRR(pSja1000Par, 31)); // Pelican einschalten sja1000_WriteRegisterRR(pSja1000Par, 4, 0xff); // IRQ's sja1000_WriteRegisterRR(pSja1000Par, 8, chip->output_control_register); // Output Control sja1000_WriteRegisterRR(pSja1000Par, 12, 0); // error code capture sja1000_WriteRegisterRR(pSja1000Par, 13, 96); // error warning limit sja1000_WriteRegisterRR(pSja1000Par, 14, 0x00); // RX error counter sja1000_WriteRegisterRR(pSja1000Par, 15, 0x00); // TX error counter sja1000_ReadRegister(pSja1000Par, 3); } else { TRACE("Init BasicCan"); sja1000_WriteRegisterRR(pSja1000Par, 31, 0x7f & sja1000_ReadRegisterRR(pSja1000Par, 31)); // Pelican ausschalten sja1000_WriteRegisterRR(pSja1000Par, 0, 0x3f); // Reset Request=1 + alle IRQs freigeben sja1000_WriteRegisterRR(pSja1000Par, 8, chip->output_control_register); // Output Control sja1000_WriteRegister(pSja1000Par, 10, 0x25); // Bit ID3 bis ID10 sja1000_WriteRegister(pSja1000Par, 11, 0x88); // Bit ID0 bis ID2, RTR-Flag, Data-Length-Code } return 0; } /***************************************************************************************/ int sja1000_activate_device(struct sja1000_admin *pSja1000Par) { SJA1000_TEST_DECLCHIP(pSja1000Par); if (pSja1000Par->bCan_2B) { TRACE("Activate Pelican"); sja1000_WriteRegisterRR(pSja1000Par, 4, 0xff); // IRQ's sja1000_WriteRegisterRR(pSja1000Par, 8, chip->output_control_register); // Output Control sja1000_WriteRegister(pSja1000Par, 0, 0x00); // Reset Request =0 sja1000_ReadRegister(pSja1000Par, 3); } else { TRACE("Activate BasicCan"); sja1000_WriteRegisterRR(pSja1000Par, 0, 0x3f); // Reset Request=1 + alle IRQs freigeben sja1000_WriteRegisterRR(pSja1000Par, 8, chip->output_control_register); // Output Control sja1000_WriteRegister(pSja1000Par, 0, 0x3e); // Reset Request =0 } return 0; } /***************************************************************************************/ int sja1000_deactivate_device(struct sja1000_admin *pSja1000Par) { SJA1000_TEST_DECLCHIP(pSja1000Par); if (pSja1000Par->bCan_2B) { TRACE("Activate Pelican"); sja1000_WriteRegisterRR(pSja1000Par, 4,0); // IRQ's } else { TRACE("Activate BasicCan"); sja1000_WriteRegisterRR(pSja1000Par, 0,0); // Reset Request=1 + alle IRQs freigeben } return 0; } /***************************************************************************************/ static int iSetSJA1000Baudrate(struct sja1000_admin *pSja1000Par) { u8 tmp; unsigned long wbaud; long bpr,ts1,ts2; int ts2array[]={2,3,4,5,1,6,7,0}; int x; long testwert,neutest=50; INFO_TRACE("Calculating baudrate for frequency %d",pSja1000Par->access.chipset_frequency); wbaud = pSja1000Par->iBaudrate; if (wbaud < 5000) wbaud = 5000; if (wbaud > 2000000) wbaud = 2000000; pSja1000Par->iBaudrate = wbaud; testwert = pSja1000Par->access.chipset_frequency/(wbaud*2); while(neutest > 0) { for(x=0;x =0;ts1--) { if ((testwert % (ts1+ts2+3)) == 0) { bpr = testwert/(ts1+ts2+3)-1; if ((bpr >= 0) && (bpr < 0x40)) { bpr |= 0x40; // SJW.0 setzen tmp = (u8)((ts2 << 4) + ts1); TRACE("%ld ts2 %ld ts1 %ld BPR0 0x%lx BPR1 0x%x",testwert,ts2, ts1, bpr,tmp); sja1000_WriteRegisterRR(pSja1000Par, 6, (u8)bpr); sja1000_WriteRegisterRR(pSja1000Par, 7, tmp); return 1; } } } } testwert++; neutest--; } TRACE("Can't set baudrate"); return 0; } /***************************************************************************************/ int sja1000_set_baudrate(struct sja1000_admin *pSja1000Par, unsigned long baudrate) { if(!pSja1000Par) return -ENODEV; pSja1000Par->iBaudrate = baudrate; if(!iSetSJA1000Baudrate(pSja1000Par)) { return -EINVAL; } return 0; } /***************************************************************************************/ const unsigned long baudrate_list[]= { 20000, 50000, 100000, 125000, 150000, 200000, 500000, 1000000, 0 }; int sja1000_get_properties(struct sja1000_admin *pSja1000Par, struct canbus_properties *props) { static const int basiccan[]= { CANBUS_CMD_ENTER_STANDBY,CANBUS_CMD_ABORT_TRANSMISSION, CANBUS_CMD_CLEAR_OVERRUN,CANBUS_CMD_LEAVE_STANDBY,0 }; static const int pelican[]= { CANBUS_CMD_ENTER_STANDBY,CANBUS_CMD_ABORT_TRANSMISSION, CANBUS_CMD_CLEAR_OVERRUN,CANBUS_CMD_LEAVE_STANDBY, CANBUS_CMD_SELF_RECEPTION_REQUEST,CANBUS_CMD_LISTEN_ON, CANBUS_CMD_LISTEN_OFF,0 }; int t; props->min = 20000; props->max = 1000000; props->chipset_flags = pSja1000Par->access.bCanChipsetFlags; props->number_baudrates = 0; props->number_registers = 128*2; /* This function is called by an application to get all provided commands. */ if(!pSja1000Par) return -ENODEV; if(pSja1000Par->bCan_2B) { for(t=0;pelican[t];t++) props->commands[t] = pelican[t]; props->number_commands = t; } else { for(t=0;basiccan[t];t++) props->commands[t] = basiccan[t]; props->number_commands = t; } for(t=0;baudrate_list[t] && (t baudrates[t] = baudrate_list[t]; //props->number_baudrates = t; return 0; } /***************************************************************************************/ int sja1000_set_register(struct sja1000_admin *pSja1000Par, int addresse, unsigned int value) { int ret = -ENOSYS; /* The SJA1000 has 128 normal register and 128 'reset mode' register (in PELICAN mode) * To get a hardware abstraction in above layers, this function accepts following * addresses: * 0...7f = normal mode registers * 80..ff = reset mode register 0...7f */ if(pSja1000Par) { if((addresse >= 0x80) && (addresse <= 0xff)) // RESET Mode ? { sja1000_WriteRegisterRR(pSja1000Par,addresse,value); ret = 0; } else if((addresse >= 0) && (addresse <= 0x7f)) { sja1000_WriteRegister(pSja1000Par,addresse,value); ret = 0; } else // todo: error number if out of addresse range { ret = 0; } // todo: error number if out of addresse range } return ret; } /***************************************************************************************/ int sja1000_get_register(struct sja1000_admin *pSja1000Par, int addresse, int *value) { int ret = -ENOSYS; /* The SJA1000 has 128 normal register and 128 'reset mode' register (in PELICAN mode) * To get a hardware abstraction in above layers, this function accepts following * addresses: * 0...7f = normal mode registers * 80..ff = reset mode register 0...7f */ if(pSja1000Par && value) { if((addresse >= 0x80) && (addresse <= 0xff)) // RESET Mode ? { *value = sja1000_ReadRegisterRR(pSja1000Par,addresse); ret = 0; } else if((addresse >= 0) && (addresse <= 0x7f)) { *value = sja1000_ReadRegister(pSja1000Par,addresse); ret = 0; } else // todo: error number if out of addresse range { *value = 0; ret = 0; } } return ret; } /***************************************************************************************/ int sja1000_set_can_mode(struct sja1000_admin *pSja1000Par, int can_2b) { if(!pSja1000Par) return -ENODEV; if((can_2b == 1) && !(pSja1000Par->access.bCanChipsetFlags & CANBUS_CFS_CAN_2_0_B)) { pSja1000Par->bCan_2B = 0; sja1000_init_device(pSja1000Par); return -EINVAL; } pSja1000Par->bCan_2B = can_2b; sja1000_init_device(pSja1000Par); return 0; } /***************************************************************************************/ int sja1000_set_baudrate_by_constant(struct sja1000_admin *pSja1000Par, unsigned long constant) { /* This function is only implemented for test and demonstration. A (chipset) driver * usually implement only one function: xyz_set_baudrate() or xyz_set_baudrate_by_constant() * but not both functions. */ if (constant >= sizeof(baudrate_list)/sizeof(unsigned long)) return -ENODEV; return sja1000_set_baudrate(pSja1000Par, baudrate_list[constant]); } /***************************************************************************************/ int sja1000_set_acceptance_filter(struct sja1000_admin *pSja1000Par, struct canbus_acceptance_filter *filter) { unsigned long code = filter->code; unsigned long mask = filter->mask; SJA1000_TEST_DECLCHIP(pSja1000Par); if (pSja1000Par->bCan_2B) { sja1000_WriteRegisterRR(pSja1000Par, 16, (u8) (code >> 24) ); // ACC sja1000_WriteRegisterRR(pSja1000Par, 17, (u8) (code >> 16) ); // ACC sja1000_WriteRegisterRR(pSja1000Par, 18, (u8) (code >> 8) ); // ACC sja1000_WriteRegisterRR(pSja1000Par, 19, (u8) code ); // ACC sja1000_WriteRegisterRR(pSja1000Par, 20, (u8) (mask >> 24) ); // Mask sja1000_WriteRegisterRR(pSja1000Par, 21, (u8) (mask >> 16) ); // Mask sja1000_WriteRegisterRR(pSja1000Par, 22, (u8) (mask >> 8) ); // Mask sja1000_WriteRegisterRR(pSja1000Par, 23, (u8) mask ); // Mask } else { sja1000_WriteRegisterRR(pSja1000Par, 4, (u8) (code>>3)); // Acceptance Code schreiben sja1000_WriteRegisterRR(pSja1000Par, 5, (u8) (mask>>3)); // Acceptance Mask schreiben } return 0; } /***************************************************************************************/ int sja1000_set_command(struct sja1000_admin *pSja1000Par, int command) { struct canbus_event ev; SJA1000_TEST_DECLCHIP(pSja1000Par); TRACE("sja1000_set_command CAN 2.0A = %d",pSja1000Par->bCan_2B); if(!pSja1000Par->bCan_2B) switch(command) // BASIC CAN Modus { case CANBUS_CMD_ENTER_STANDBY: sja1000_WriteRegister(pSja1000Par, 1,0x10); ev.event = CANBUS_EVENT_ENTERING_STANDBY; if(pSja1000Par->isr) { (*pSja1000Par->isr)(pSja1000Par->pCanBusParm, pSja1000Par->pCanBusParm, &ev); } break; case CANBUS_CMD_LEAVE_STANDBY: sja1000_WriteRegister(pSja1000Par, 1,~0x10 & sja1000_ReadRegister(pSja1000Par,1)); break; case CANBUS_CMD_ABORT_TRANSMISSION: sja1000_WriteRegister(pSja1000Par, 1,0x02); sja1000_ReadRegister(pSja1000Par, 3); break; case CANBUS_CMD_CLEAR_OVERRUN: sja1000_WriteRegister(pSja1000Par, 1,0x08); break; default: return -EINVAL; } else switch(command) // Pelican Modus { case CANBUS_CMD_ENTER_STANDBY: sja1000_WriteRegister(pSja1000Par, 0,0x10 | sja1000_ReadRegister(pSja1000Par,0)); ev.event = CANBUS_EVENT_ENTERING_STANDBY; if(pSja1000Par->isr) { (*pSja1000Par->isr)(pSja1000Par->pCanBusParm, pSja1000Par->pCanBusParm, &ev); } break; case CANBUS_CMD_LEAVE_STANDBY: sja1000_WriteRegister(pSja1000Par, 0,~0x10 & sja1000_ReadRegister(pSja1000Par,0)); break; case CANBUS_CMD_ABORT_TRANSMISSION: sja1000_WriteRegister(pSja1000Par, 1,0x02); sja1000_ReadRegister(pSja1000Par, 3); break; case CANBUS_CMD_CLEAR_OVERRUN: sja1000_WriteRegister(pSja1000Par, 1,0x08); break; case CANBUS_CMD_SELF_RECEPTION_REQUEST: sja1000_WriteRegister(pSja1000Par, 1,0x10); break; case CANBUS_CMD_LISTEN_ON: sja1000_WriteRegisterRR(pSja1000Par, 0,0x02 | sja1000_ReadRegister(pSja1000Par,0)); break; case CANBUS_CMD_LISTEN_OFF: sja1000_WriteRegisterRR(pSja1000Par, 0,~0x02 & sja1000_ReadRegister(pSja1000Par,0)); break; default: return -EINVAL; } return 0; } /***************************************************************************************/ int sja1000_transmit_data(struct sja1000_admin *pSja1000Par, struct canbus_transmit_data *trans) { u8 i1,i2,len; if( !(pSja1000Par && trans && (sja1000_check_chipset(pSja1000Par) >= 0)) ) return -ENODEV; len= (trans->dlc > 8)?8:trans->dlc; // Achtung! Die Routine wird auch aus der IRQ-Routine heraus aufgerufen if (pSja1000Par->bCan_2B) { if (trans->fmt == CANBUS_TRANS_FMT_EXT) // EFF { TRACE("TransmitToSJA1000 -1-"); i1 = len; i1|= trans->rtr?0x40:0x00; i1|= 0x80; // Modus: EFF sja1000_WriteRegister(pSja1000Par, 16,i1); i1 = (u8) ((trans->identifier & 0x1f) << 3); sja1000_WriteRegister(pSja1000Par, 20,i1); i1 = (u8) ((trans->identifier >> 5) & 0xff); sja1000_WriteRegister(pSja1000Par, 19,i1); i1 = (u8) ((trans->identifier >> 13) & 0xff); sja1000_WriteRegister(pSja1000Par, 18,i1); i1 = (u8) ((trans->identifier >> 21) & 0xff); sja1000_WriteRegister(pSja1000Par, 17,i1); for(i1=0;i1 msg[i1]); sja1000_WriteRegister(pSja1000Par, 1,0x01); // Daten senden (Transmission Request) } else // SFF { // Identifier begrenzen auf 11 Bit (sonst wird später was falsches angezeigt) TRACE("TransmitToSJA1000 -2-"); trans->identifier &= 0x7ff; i1 = len; i1|= trans->rtr?0x40:0x00; sja1000_WriteRegister(pSja1000Par, 16,i1); i1 = (u8) ((trans->identifier & 7) << 5); sja1000_WriteRegister(pSja1000Par, 18,i1); i1 = (u8) ((trans->identifier >> 3) & 0xff); sja1000_WriteRegister(pSja1000Par, 17,i1); for(i1=0;i1 msg[i1]); sja1000_WriteRegister(pSja1000Par, 1,0x01); // Daten senden (Transmission Request) } } else // CAN2A { // Identifier begrenzen auf 11 Bit (sonst wird später was falsches angezeigt) TRACE("TransmitToSJA1000 -3-"); trans->identifier &= 0x7ff; i1 = (u8) ((trans->identifier >> 3) & 0xff); i2 = (u8) (trans->identifier & 0x07) << 5; i2|= trans->rtr?0x10:0x00; i2|= len; sja1000_WriteRegister(pSja1000Par, 10,i1); sja1000_WriteRegister(pSja1000Par, 11,i2); for(i1=0;i1 msg[i1]); sja1000_WriteRegister(pSja1000Par, 1,0x01); // Daten senden (Transmission Request) } return 0; } /***************************************************************************************/ int sja1000_test_device(struct sja1000_admin *pSja1000Par) { SJA1000_TEST_DECLCHIP(pSja1000Par); TRACE("sja1000_test_device"); // The Bit 0x01 in register 0x00 is never set if (sja1000_ReadRegister(pSja1000Par, 0) & 0x01) { return 0; } return 1; } /***************************************************************************************/ int sja1000_check_chipset(struct sja1000_admin *pSja1000Par) { SJA1000_TEST_DECLCHIP(pSja1000Par); TRACE("checkSJA1000"); if (sja1000_ReadRegister(pSja1000Par, 0) & 0x01) // Baustein wurde in der Zwischenzeit rückgesetzt { sja1000_init_device(pSja1000Par); return 0; } return 1; } /***************************************************************************************/ int PeliCanISR(struct sja1000_admin *pSja1000Par) { // CSerialPort::HwIntProc u8 irq; u8 status; struct canbus_event ev; unsigned long id; int t; TRACE("Pelican IRQ"); irq = sja1000_ReadRegister(pSja1000Par, 3); // Interrupt-Register lesen if (!(irq & 0xff)) return 0; TRACE("IRQ wird bearbeitet"); if(!(pSja1000Par->isr)) return 1; if (irq & 0x01) // Receive Interrupt { // Fülle Info-Struktur TRACE("Receive IRQ"); ev.event = CANBUS_EVENT_RECEIVED; status = sja1000_ReadRegister(pSja1000Par, 16); if (status & 0x80) // Extended Frame Format (EFF) { ev.data.fmt = CANBUS_TRANS_FMT_EXT; id = sja1000_ReadRegister(pSja1000Par, 17); id = (id << 8) + sja1000_ReadRegister(pSja1000Par, 18); id = (id << 8) + sja1000_ReadRegister(pSja1000Par, 19); id = (id << 8) + sja1000_ReadRegister(pSja1000Par, 20); id = id >> 3; for(t=0;t<8;t++) { ev.data.msg[t] = sja1000_ReadRegister(pSja1000Par, 21+t); } } else // Standard Frame Format (SFF) { ev.data.fmt = CANBUS_TRANS_FMT_STD; id = sja1000_ReadRegister(pSja1000Par, 17); id = (id << 8) + sja1000_ReadRegister(pSja1000Par, 18); id = id >> 5; for(t=0;t<8;t++) { ev.data.msg[t] = sja1000_ReadRegister(pSja1000Par, 19+t); } } ev.data.identifier = id; ev.data.rtr = (status & 0x40) >> 6; ev.data.dlc = (status & 0x0f); sja1000_WriteRegister(pSja1000Par, 1,0x04); // ReleaseReceiveBuffer (Rx Buffer wird dadurch ungültig) pSja1000Par->isr(pSja1000Par->pCanBusParm, pSja1000Par->pCanBusParm, &ev); } if (irq & 0x02) // Transmit Interrupt { TRACE("Transmit IRQ"); ev.event = CANBUS_EVENT_TRANSMITTED; pSja1000Par->isr(pSja1000Par->pCanBusParm, pSja1000Par->pCanBusParm, &ev); } if (irq & 0x04) // Error Warning Interrupt { TRACE("Error Warning IRQ"); //sja1000_WriteRegister(pSja1000Par, 1,0x0e); // Release Receive Buffer + ClearDataOverrun + AbortTransmission (danach erfolgt ein Transmit-IRQ) //sja1000_WriteRegister(pSja1000Par, 0, ~0x01 & sja1000_ReadRegister(pSja1000Par,0)); // resetMode löschen ev.event = CANBUS_EVENT_WARNING; pSja1000Par->isr(pSja1000Par->pCanBusParm, pSja1000Par->pCanBusParm, &ev); } if (irq & 0x08) // Overrun Interrupt { TRACE("Overrun IRQ"); sja1000_WriteRegister(pSja1000Par, 1,0x0c); // Release Receive Buffer + ClearDataOverrun ev.event = CANBUS_EVENT_OVERRUN; pSja1000Par->isr(pSja1000Par->pCanBusParm, pSja1000Par->pCanBusParm, &ev); } if (irq & 0x10) // WakeUp Interrupt { TRACE("WakeUp IRQ"); ev.event = CANBUS_EVENT_LEAVING_STANDBY; pSja1000Par->isr(pSja1000Par->pCanBusParm, pSja1000Par->pCanBusParm, &ev); } if (irq & 0x20) // Error Passive Interrupt { TRACE("Error passive IRQ"); ev.event = CANBUS_EVENT_PASSIVE; pSja1000Par->isr(pSja1000Par->pCanBusParm, pSja1000Par->pCanBusParm, &ev); } if (irq & 0x40) // Arbitration lost Interrupt { TRACE("Arbitration lost IRQ"); ev.event = CANBUS_EVENT_ARBITRATION_LOST; pSja1000Par->isr(pSja1000Par->pCanBusParm, pSja1000Par->pCanBusParm, &ev); } if (irq & 0x80) // Error Passive Interrupt { TRACE("Buserror IRQ"); sja1000_WriteRegister(pSja1000Par, 1,0x0e); // Release Receive Buffer + ClearDataOverrun + AbortTransmission (danach erfolgt ein Transmit-IRQ) sja1000_WriteRegister(pSja1000Par, 0, ~0x01 & sja1000_ReadRegister(pSja1000Par,0)); // resetMode löschen ev.event = CANBUS_EVENT_BUS_ERROR; pSja1000Par->isr(pSja1000Par->pCanBusParm, pSja1000Par->pCanBusParm, &ev); } return 1; // TRUE = IRQ wurde bedient } /***************************************************************************************/ int BasicCanISR(struct sja1000_admin *pSja1000Par) { u8 irq; u8 status; struct canbus_event ev; int t; irq = sja1000_ReadRegister(pSja1000Par, 3); // Interrupt-Register lesen TRACE("BasicCan IRQ 0x%x",irq); if (!(irq & 0x1f)) return 0; TRACE("IRQ wird bearbeitet"); if(pSja1000Par->isr) { if (irq & 0x01) // Receive Interrupt { TRACE("Receive IRQ"); ev.event = CANBUS_EVENT_RECEIVED; ev.data.identifier = sja1000_ReadRegister(pSja1000Par, 20); status = sja1000_ReadRegister(pSja1000Par, 21); ev.data.fmt = CANBUS_TRANS_FMT_STD; ev.data.identifier = (ev.data.identifier << 3) + ((status & 0xe0)>>5); ev.data.rtr = (status & 0x10) >> 4; ev.data.dlc = (status & 0x0f); for(t=0;(t<8) && (t isr(pSja1000Par->pCanBusParm, pSja1000Par->pCanBusParm, &ev); } if (irq & 0x02) // Transmit Interrupt { TRACE("Transmit IRQ"); ev.event = CANBUS_EVENT_TRANSMITTED; pSja1000Par->isr(pSja1000Par->pCanBusParm, pSja1000Par->pCanBusParm, &ev); } if (irq & 0x04) // Error Interrupt { TRACE("Error IRQ"); sja1000_WriteRegister(pSja1000Par, 1,0x0e); // Release Receive Buffer + ClearDataOverrun + AbortTransmission (danach erfolgt ein Transmit-IRQ) status = sja1000_ReadRegister(pSja1000Par, 0); // Status einlesen status = status & 0xfe; // ResetMode löschen sja1000_WriteRegister(pSja1000Par, 0,status); ev.event = CANBUS_EVENT_BUS_ERROR; pSja1000Par->isr(pSja1000Par->pCanBusParm, pSja1000Par->pCanBusParm, &ev); } if (irq & 0x08) // Overrun Interrupt { TRACE("Overrun IRQ"); sja1000_WriteRegister(pSja1000Par, 1,0x0c); // Release Receive Buffer + ClearDataOverrun ev.event = CANBUS_EVENT_OVERRUN; pSja1000Par->isr(pSja1000Par->pCanBusParm, pSja1000Par->pCanBusParm, &ev); } if (irq & 0x10) // WakeUp Interrupt { TRACE("WakeUp IRQ"); ev.event = CANBUS_EVENT_LEAVING_STANDBY; pSja1000Par->isr(pSja1000Par->pCanBusParm, pSja1000Par->pCanBusParm, &ev); } } else // Setze nur die Bits zurück { if (irq & 0x01) // Receive Interrupt { sja1000_WriteRegister(pSja1000Par, 1,0x04); // ReleaseReceiveBuffer (Rx Buffer wird dadurch ungültig) } if (irq & 0x04) // Error Interrupt { sja1000_WriteRegister(pSja1000Par, 1,0x0e); // Release Receive Buffer + ClearDataOverrun + AbortTransmission (danach erfolgt ein Transmit-IRQ) status = sja1000_ReadRegister(pSja1000Par, 0); // read state status = status & 0xfe; // clear ResetMode sja1000_WriteRegister(pSja1000Par, 0,status); } if (irq & 0x08) // Overrun Interrupt { sja1000_WriteRegister(pSja1000Par, 1,0x0c); // Release Receive Buffer + ClearDataOverrun } } return 1; // TRUE = IRQ was served } /***************************************************************************************/ /* int sja1000_interrupt(void *pSpecificPar, struct sja1000_admin *pSja1000Par) { int ret=0; int x=30; if(!pSja1000Par) return 0; // HMM: Rubini's linux device drivers has erroneous statement about spin_trylock return value // the right treatment is as follows: 0 - failed, non-0 got lock (rubini: 0 - got lock) // see Linux Device Drivers 2nd edition, page 282. // XTRACE("InterruptProcedure - before spin_trylock..."); if (!spin_trylock(&pSja1000Par->irq_lock)) { // XTRACE("...xxx"); // XTRACE("spin_is_locked: %i", spin_is_locked(&pSja1000Par->irq_lock)); return 0; // irq handling is disabled for this chip } TRACE("InterruptProcedure"); if (pSja1000Par->bCan_2B) { while(x>0) { if(PeliCanISR(pSja1000Par)) ret=1; else break; x--; } } else { while(x>0) { if(BasicCanISR(pSja1000Par)) ret=1; else break; x--; } } spin_unlock(&pSja1000Par->irq_lock); return ret; } */ int sja1000_interrupt(void *pSpecificPar, struct sja1000_admin *pSja1000Par) { int ret=0; int x=30; if(!pSja1000Par) return 0; TRACE("InterruptProcedure"); if (pSja1000Par->bCan_2B) { while(x>0) { if(PeliCanISR(pSja1000Par)) ret=1; else break; x--; } } else { while(x>0) { if(BasicCanISR(pSja1000Par)) ret=1; else break; x--; } } return ret; } /***************************************************************************************/ int sja1000_register_isr(struct sja1000_admin *pSja1000Par, canbus_isr pIsr, struct canbus_admin *pCanBusPar) { TRACE("registering isr()"); if(!pSja1000Par) return -EINVAL; pSja1000Par->isr = pIsr; pSja1000Par->pCanBusParm = pCanBusPar; return 0; } /***************************************************************************************/ int sja1000_unregister_isr(struct sja1000_admin *pSja1000Par) { TRACE("unregistering isr()"); if(!pSja1000Par) return -EINVAL; pSja1000Par->isr = 0; pSja1000Par->pCanBusParm = NULL; return 0; } /***************************************************************************************/ int sja1000_register_device(char *name, int version, void *pSpecificPar, struct sja1000_access *access, int prefered_min, int prefered_max) { int t,p; char buffer[MAX_DEVICE_NAME_LENGTH*2]; TRACE("registering can device: %s",name); for(t=0;t pRegisterIsr) (access->pRegisterIsr)(pSpecificPar, sja1000_interrupt, &sja1000_admin[t]); sja1000_admin[t].in_use = 1; caccess.pRegisterIsr = (canbus_registerIsr) sja1000_register_isr; caccess.pUnregisterIsr = (canbus_unregisterIsr) sja1000_unregister_isr; caccess.pOpen = (canbus_open_device) sja1000_open_device; caccess.pClose = (canbus_close_device) sja1000_close_device; caccess.pInit = (canbus_init_device) sja1000_init_device; caccess.pSetBaudrate = (canbus_set_baudrate) sja1000_set_baudrate; caccess.pGetProperty = (canbus_get_properties) sja1000_get_properties; caccess.pSetRegister = (canbus_set_register) sja1000_set_register; caccess.pGetRegister = (canbus_get_register) sja1000_get_register; caccess.pSetCanMode = (canbus_set_can_mode) sja1000_set_can_mode; caccess.pSetBaudrateByConstant = (canbus_set_baudrate_by_constant) sja1000_set_baudrate_by_constant; caccess.pSetAcceptanceFilter = (canbus_set_acceptance_filter) sja1000_set_acceptance_filter; caccess.pSetCommand = (canbus_set_command) sja1000_set_command; caccess.pTransmitData = (canbus_transmit_data) sja1000_transmit_data; caccess.pTestDevice = (canbus_test_device) sja1000_test_device; sja1000_admin[t].canbus_admin_number = canbus4linux_register_device(buffer, CANBUS4LINUX_VERSION, &sja1000_admin[t], &caccess, prefered_min, prefered_max); TRACE("sja1000_register_device() - finished"); return t; } } return -1; } /***************************************************************************************/ int sja1000_unregister_device(int can_num) { if (sja1000_admin[can_num].in_use == 0) return 0; TRACE("unregistering can device: %s",sja1000_admin[can_num].cDeviceName); sja1000_admin[can_num].canbus_admin_number = canbus4linux_unregister_device(sja1000_admin[can_num].canbus_admin_number); if (sja1000_admin[can_num].access.pUnregisterIsr) (sja1000_admin[can_num].access.pUnregisterIsr)(sja1000_admin[can_num].pDeviceParm); memset(&sja1000_admin[can_num],0,sizeof(struct sja1000_admin)); return 0; } /***************************************************************************************/ int init_module(void) { TRACE("init_module()"); memset(sja1000_admin,0,sizeof(sja1000_admin)); return 0; } /***************************************************************************************/ void cleanup_module(void) { TRACE("cleanup"); } /***************************************************************************************/ EXPORT_SYMBOL(sja1000_unregister_device); EXPORT_SYMBOL(sja1000_register_device); MODULE_AUTHOR("Juergen Eder "); MODULE_DESCRIPTION("SJA1000 chipset driver");