Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /* $Id: telespci.c,v 2.23.2.3 2004/01/13 14:31:26 keil Exp $
  2  *
  3  * low level stuff for Teles PCI isdn cards
  4  *
  5  * Author       Ton van Rosmalen
  6  *              Karsten Keil
  7  * Copyright    by Ton van Rosmalen
  8  *              by Karsten Keil      <keil@isdn4linux.de>
  9  * 
 10  * This software may be used and distributed according to the terms
 11  * of the GNU General Public License, incorporated herein by reference.
 12  *
 13  */
 14 
 15 #include <linux/init.h>
 16 #include "hisax.h"
 17 #include "isac.h"
 18 #include "hscx.h"
 19 #include "isdnl1.h"
 20 #include <linux/pci.h>
 21 
 22 extern const char *CardType[];
 23 static const char *telespci_revision = "$Revision: 2.23.2.3 $";
 24 
 25 #define ZORAN_PO_RQ_PEN 0x02000000
 26 #define ZORAN_PO_WR     0x00800000
 27 #define ZORAN_PO_GID0   0x00000000
 28 #define ZORAN_PO_GID1   0x00100000
 29 #define ZORAN_PO_GREG0  0x00000000
 30 #define ZORAN_PO_GREG1  0x00010000
 31 #define ZORAN_PO_DMASK  0xFF
 32 
 33 #define WRITE_ADDR_ISAC (ZORAN_PO_WR | ZORAN_PO_GID0 | ZORAN_PO_GREG0)
 34 #define READ_DATA_ISAC  (ZORAN_PO_GID0 | ZORAN_PO_GREG1)
 35 #define WRITE_DATA_ISAC (ZORAN_PO_WR | ZORAN_PO_GID0 | ZORAN_PO_GREG1)
 36 #define WRITE_ADDR_HSCX (ZORAN_PO_WR | ZORAN_PO_GID1 | ZORAN_PO_GREG0)
 37 #define READ_DATA_HSCX  (ZORAN_PO_GID1 | ZORAN_PO_GREG1)
 38 #define WRITE_DATA_HSCX (ZORAN_PO_WR | ZORAN_PO_GID1 | ZORAN_PO_GREG1)
 39 
 40 #define ZORAN_WAIT_NOBUSY       do { \
 41                                         portdata = readl(adr + 0x200); \
 42                                 } while (portdata & ZORAN_PO_RQ_PEN)
 43 
 44 static inline u_char
 45 readisac(void __iomem *adr, u_char off)
 46 {
 47         register unsigned int portdata;
 48 
 49         ZORAN_WAIT_NOBUSY;
 50         
 51         /* set address for ISAC */
 52         writel(WRITE_ADDR_ISAC | off, adr + 0x200);
 53         ZORAN_WAIT_NOBUSY;
 54         
 55         /* read data from ISAC */
 56         writel(READ_DATA_ISAC, adr + 0x200);
 57         ZORAN_WAIT_NOBUSY;
 58         return((u_char)(portdata & ZORAN_PO_DMASK));
 59 }
 60 
 61 static inline void
 62 writeisac(void __iomem *adr, u_char off, u_char data)
 63 {
 64         register unsigned int portdata;
 65 
 66         ZORAN_WAIT_NOBUSY;
 67         
 68         /* set address for ISAC */
 69         writel(WRITE_ADDR_ISAC | off, adr + 0x200);
 70         ZORAN_WAIT_NOBUSY;
 71 
 72         /* write data to ISAC */
 73         writel(WRITE_DATA_ISAC | data, adr + 0x200);
 74         ZORAN_WAIT_NOBUSY;
 75 }
 76 
 77 static inline u_char
 78 readhscx(void __iomem *adr, int hscx, u_char off)
 79 {
 80         register unsigned int portdata;
 81 
 82         ZORAN_WAIT_NOBUSY;
 83         /* set address for HSCX */
 84         writel(WRITE_ADDR_HSCX | ((hscx ? 0x40:0) + off), adr + 0x200);
 85         ZORAN_WAIT_NOBUSY;
 86         
 87         /* read data from HSCX */
 88         writel(READ_DATA_HSCX, adr + 0x200);
 89         ZORAN_WAIT_NOBUSY;
 90         return ((u_char)(portdata & ZORAN_PO_DMASK));
 91 }
 92 
 93 static inline void
 94 writehscx(void __iomem *adr, int hscx, u_char off, u_char data)
 95 {
 96         register unsigned int portdata;
 97 
 98         ZORAN_WAIT_NOBUSY;
 99         /* set address for HSCX */
100         writel(WRITE_ADDR_HSCX | ((hscx ? 0x40:0) + off), adr + 0x200);
101         ZORAN_WAIT_NOBUSY;
102 
103         /* write data to HSCX */
104         writel(WRITE_DATA_HSCX | data, adr + 0x200);
105         ZORAN_WAIT_NOBUSY;
106 }
107 
108 static inline void
109 read_fifo_isac(void __iomem *adr, u_char * data, int size)
110 {
111         register unsigned int portdata;
112         register int i;
113 
114         ZORAN_WAIT_NOBUSY;
115         /* read data from ISAC */
116         for (i = 0; i < size; i++) {
117                 /* set address for ISAC fifo */
118                 writel(WRITE_ADDR_ISAC | 0x1E, adr + 0x200);
119                 ZORAN_WAIT_NOBUSY;
120                 writel(READ_DATA_ISAC, adr + 0x200);
121                 ZORAN_WAIT_NOBUSY;
122                 data[i] = (u_char)(portdata & ZORAN_PO_DMASK);
123         }
124 }
125 
126 static void
127 write_fifo_isac(void __iomem *adr, u_char * data, int size)
128 {
129         register unsigned int portdata;
130         register int i;
131 
132         ZORAN_WAIT_NOBUSY;
133         /* write data to ISAC */
134         for (i = 0; i < size; i++) {
135                 /* set address for ISAC fifo */
136                 writel(WRITE_ADDR_ISAC | 0x1E, adr + 0x200);
137                 ZORAN_WAIT_NOBUSY;
138                 writel(WRITE_DATA_ISAC | data[i], adr + 0x200);
139                 ZORAN_WAIT_NOBUSY;
140         }
141 }
142 
143 static inline void
144 read_fifo_hscx(void __iomem *adr, int hscx, u_char * data, int size)
145 {
146         register unsigned int portdata;
147         register int i;
148 
149         ZORAN_WAIT_NOBUSY;
150         /* read data from HSCX */
151         for (i = 0; i < size; i++) {
152                 /* set address for HSCX fifo */
153                 writel(WRITE_ADDR_HSCX |(hscx ? 0x5F:0x1F), adr + 0x200);
154                 ZORAN_WAIT_NOBUSY;
155                 writel(READ_DATA_HSCX, adr + 0x200);
156                 ZORAN_WAIT_NOBUSY;
157                 data[i] = (u_char) (portdata & ZORAN_PO_DMASK);
158         }
159 }
160 
161 static inline void
162 write_fifo_hscx(void __iomem *adr, int hscx, u_char * data, int size)
163 {
164         unsigned int portdata;
165         register int i;
166 
167         ZORAN_WAIT_NOBUSY;
168         /* write data to HSCX */
169         for (i = 0; i < size; i++) {
170                 /* set address for HSCX fifo */
171                 writel(WRITE_ADDR_HSCX |(hscx ? 0x5F:0x1F), adr + 0x200);
172                 ZORAN_WAIT_NOBUSY;
173                 writel(WRITE_DATA_HSCX | data[i], adr + 0x200);
174                 ZORAN_WAIT_NOBUSY;
175                 udelay(10);
176         }
177 }
178 
179 /* Interface functions */
180 
181 static u_char
182 ReadISAC(struct IsdnCardState *cs, u_char offset)
183 {
184         return (readisac(cs->hw.teles0.membase, offset));
185 }
186 
187 static void
188 WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
189 {
190         writeisac(cs->hw.teles0.membase, offset, value);
191 }
192 
193 static void
194 ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
195 {
196         read_fifo_isac(cs->hw.teles0.membase, data, size);
197 }
198 
199 static void
200 WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
201 {
202         write_fifo_isac(cs->hw.teles0.membase, data, size);
203 }
204 
205 static u_char
206 ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
207 {
208         return (readhscx(cs->hw.teles0.membase, hscx, offset));
209 }
210 
211 static void
212 WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
213 {
214         writehscx(cs->hw.teles0.membase, hscx, offset, value);
215 }
216 
217 /*
218  * fast interrupt HSCX stuff goes here
219  */
220 
221 #define READHSCX(cs, nr, reg) readhscx(cs->hw.teles0.membase, nr, reg)
222 #define WRITEHSCX(cs, nr, reg, data) writehscx(cs->hw.teles0.membase, nr, reg, data)
223 #define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt)
224 #define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt)
225 
226 #include "hscx_irq.c"
227 
228 static irqreturn_t
229 telespci_interrupt(int intno, void *dev_id)
230 {
231         struct IsdnCardState *cs = dev_id;
232         u_char hval, ival;
233         u_long flags;
234 
235         spin_lock_irqsave(&cs->lock, flags);
236         hval = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA);
237         if (hval)
238                 hscx_int_main(cs, hval);
239         ival = readisac(cs->hw.teles0.membase, ISAC_ISTA);
240         if ((hval | ival) == 0) {
241                 spin_unlock_irqrestore(&cs->lock, flags);
242                 return IRQ_NONE;
243         }
244         if (ival)
245                 isac_interrupt(cs, ival);
246         /* Clear interrupt register for Zoran PCI controller */
247         writel(0x70000000, cs->hw.teles0.membase + 0x3C);
248 
249         writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0xFF);
250         writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0xFF);
251         writeisac(cs->hw.teles0.membase, ISAC_MASK, 0xFF);
252         writeisac(cs->hw.teles0.membase, ISAC_MASK, 0x0);
253         writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0x0);
254         writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0x0);
255         spin_unlock_irqrestore(&cs->lock, flags);
256         return IRQ_HANDLED;
257 }
258 
259 static void
260 release_io_telespci(struct IsdnCardState *cs)
261 {
262         iounmap(cs->hw.teles0.membase);
263 }
264 
265 static int
266 TelesPCI_card_msg(struct IsdnCardState *cs, int mt, void *arg)
267 {
268         u_long flags;
269 
270         switch (mt) {
271                 case CARD_RESET:
272                         return(0);
273                 case CARD_RELEASE:
274                         release_io_telespci(cs);
275                         return(0);
276                 case CARD_INIT:
277                         spin_lock_irqsave(&cs->lock, flags);
278                         inithscxisac(cs, 3);
279                         spin_unlock_irqrestore(&cs->lock, flags);
280                         return(0);
281                 case CARD_TEST:
282                         return(0);
283         }
284         return(0);
285 }
286 
287 static struct pci_dev *dev_tel __devinitdata = NULL;
288 
289 int __devinit
290 setup_telespci(struct IsdnCard *card)
291 {
292         struct IsdnCardState *cs = card->cs;
293         char tmp[64];
294 
295 #ifdef __BIG_ENDIAN
296 #error "not running on big endian machines now"
297 #endif
298 
299         strcpy(tmp, telespci_revision);
300         printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp));
301         if (cs->typ != ISDN_CTYPE_TELESPCI)
302                 return (0);
303 
304         if ((dev_tel = pci_find_device (PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_tel))) {
305                 if (pci_enable_device(dev_tel))
306                         return(0);
307                 cs->irq = dev_tel->irq;
308                 if (!cs->irq) {
309                         printk(KERN_WARNING "Teles: No IRQ for PCI card found\n");
310                         return(0);
311                 }
312                 cs->hw.teles0.membase = ioremap(pci_resource_start(dev_tel, 0),
313                         PAGE_SIZE);
314                 printk(KERN_INFO "Found: Zoran, base-address: 0x%llx, irq: 0x%x\n",
315                         (unsigned long long)pci_resource_start(dev_tel, 0),
316                         dev_tel->irq);
317         } else {
318                 printk(KERN_WARNING "TelesPCI: No PCI card found\n");
319                 return(0);
320         }
321 
322         /* Initialize Zoran PCI controller */
323         writel(0x00000000, cs->hw.teles0.membase + 0x28);
324         writel(0x01000000, cs->hw.teles0.membase + 0x28);
325         writel(0x01000000, cs->hw.teles0.membase + 0x28);
326         writel(0x7BFFFFFF, cs->hw.teles0.membase + 0x2C);
327         writel(0x70000000, cs->hw.teles0.membase + 0x3C);
328         writel(0x61000000, cs->hw.teles0.membase + 0x40);
329         /* writel(0x00800000, cs->hw.teles0.membase + 0x200); */
330 
331         printk(KERN_INFO
332                "HiSax: %s config irq:%d mem:%p\n",
333                CardType[cs->typ], cs->irq,
334                cs->hw.teles0.membase);
335 
336         setup_isac(cs);
337         cs->readisac = &ReadISAC;
338         cs->writeisac = &WriteISAC;
339         cs->readisacfifo = &ReadISACfifo;
340         cs->writeisacfifo = &WriteISACfifo;
341         cs->BC_Read_Reg = &ReadHSCX;
342         cs->BC_Write_Reg = &WriteHSCX;
343         cs->BC_Send_Data = &hscx_fill_fifo;
344         cs->cardmsg = &TelesPCI_card_msg;
345         cs->irq_func = &telespci_interrupt;
346         cs->irq_flags |= IRQF_SHARED;
347         ISACVersion(cs, "TelesPCI:");
348         if (HscxVersion(cs, "TelesPCI:")) {
349                 printk(KERN_WARNING
350                  "TelesPCI: wrong HSCX versions check IO/MEM addresses\n");
351                 release_io_telespci(cs);
352                 return (0);
353         }
354         return (1);
355 }
356 
  This page was automatically generated by the LXR engine.