diff options
| -rw-r--r-- | drivers/char/specialix.c | 663 |
1 files changed, 361 insertions, 302 deletions
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 037dc47e4cb1..c390c6cc030e 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c | |||
| @@ -77,7 +77,7 @@ | |||
| 77 | 77 | ||
| 78 | #include <linux/module.h> | 78 | #include <linux/module.h> |
| 79 | 79 | ||
| 80 | #include <asm/io.h> | 80 | #include <linux/io.h> |
| 81 | #include <linux/kernel.h> | 81 | #include <linux/kernel.h> |
| 82 | #include <linux/sched.h> | 82 | #include <linux/sched.h> |
| 83 | #include <linux/ioport.h> | 83 | #include <linux/ioport.h> |
| @@ -92,7 +92,7 @@ | |||
| 92 | #include <linux/delay.h> | 92 | #include <linux/delay.h> |
| 93 | #include <linux/pci.h> | 93 | #include <linux/pci.h> |
| 94 | #include <linux/init.h> | 94 | #include <linux/init.h> |
| 95 | #include <asm/uaccess.h> | 95 | #include <linux/uaccess.h> |
| 96 | 96 | ||
| 97 | #include "specialix_io8.h" | 97 | #include "specialix_io8.h" |
| 98 | #include "cd1865.h" | 98 | #include "cd1865.h" |
| @@ -112,7 +112,7 @@ static int sx_debug; | |||
| 112 | static int sx_rxfifo = SPECIALIX_RXFIFO; | 112 | static int sx_rxfifo = SPECIALIX_RXFIFO; |
| 113 | 113 | ||
| 114 | #ifdef DEBUG | 114 | #ifdef DEBUG |
| 115 | #define dprintk(f, str...) if (sx_debug & f) printk (str) | 115 | #define dprintk(f, str...) if (sx_debug & f) printk(str) |
| 116 | #else | 116 | #else |
| 117 | #define dprintk(f, str...) /* nothing */ | 117 | #define dprintk(f, str...) /* nothing */ |
| 118 | #endif | 118 | #endif |
| @@ -131,8 +131,8 @@ static int sx_rxfifo = SPECIALIX_RXFIFO; | |||
| 131 | #define SX_DEBUG_FIFO 0x0800 | 131 | #define SX_DEBUG_FIFO 0x0800 |
| 132 | 132 | ||
| 133 | 133 | ||
| 134 | #define func_enter() dprintk (SX_DEBUG_FLOW, "io8: enter %s\n",__func__) | 134 | #define func_enter() dprintk(SX_DEBUG_FLOW, "io8: enter %s\n", __func__) |
| 135 | #define func_exit() dprintk (SX_DEBUG_FLOW, "io8: exit %s\n", __func__) | 135 | #define func_exit() dprintk(SX_DEBUG_FLOW, "io8: exit %s\n", __func__) |
| 136 | 136 | ||
| 137 | #define jiffies_from_ms(a) ((((a) * HZ)/1000)+1) | 137 | #define jiffies_from_ms(a) ((((a) * HZ)/1000)+1) |
| 138 | 138 | ||
| @@ -169,8 +169,8 @@ static int sx_poll = HZ; | |||
| 169 | #endif | 169 | #endif |
| 170 | 170 | ||
| 171 | 171 | ||
| 172 | /* Used to be outb (0xff, 0x80); */ | 172 | /* Used to be outb(0xff, 0x80); */ |
| 173 | #define short_pause() udelay (1) | 173 | #define short_pause() udelay(1) |
| 174 | 174 | ||
| 175 | 175 | ||
| 176 | #define SPECIALIX_LEGAL_FLAGS \ | 176 | #define SPECIALIX_LEGAL_FLAGS \ |
| @@ -192,19 +192,19 @@ static struct specialix_port sx_port[SX_NBOARD * SX_NPORT]; | |||
| 192 | 192 | ||
| 193 | #ifdef SPECIALIX_TIMER | 193 | #ifdef SPECIALIX_TIMER |
| 194 | static struct timer_list missed_irq_timer; | 194 | static struct timer_list missed_irq_timer; |
| 195 | static irqreturn_t sx_interrupt(int irq, void * dev_id); | 195 | static irqreturn_t sx_interrupt(int irq, void *dev_id); |
| 196 | #endif | 196 | #endif |
| 197 | 197 | ||
| 198 | 198 | ||
| 199 | 199 | ||
| 200 | static inline int sx_paranoia_check(struct specialix_port const * port, | 200 | static inline int sx_paranoia_check(struct specialix_port const *port, |
| 201 | char *name, const char *routine) | 201 | char *name, const char *routine) |
| 202 | { | 202 | { |
| 203 | #ifdef SPECIALIX_PARANOIA_CHECK | 203 | #ifdef SPECIALIX_PARANOIA_CHECK |
| 204 | static const char *badmagic = | 204 | static const char *badmagic = KERN_ERR |
| 205 | KERN_ERR "sx: Warning: bad specialix port magic number for device %s in %s\n"; | 205 | "sx: Warning: bad specialix port magic number for device %s in %s\n"; |
| 206 | static const char *badinfo = | 206 | static const char *badinfo = KERN_ERR |
| 207 | KERN_ERR "sx: Warning: null specialix port for device %s in %s\n"; | 207 | "sx: Warning: null specialix port for device %s in %s\n"; |
| 208 | 208 | ||
| 209 | if (!port) { | 209 | if (!port) { |
| 210 | printk(badinfo, name, routine); | 210 | printk(badinfo, name, routine); |
| @@ -226,66 +226,69 @@ static inline int sx_paranoia_check(struct specialix_port const * port, | |||
| 226 | */ | 226 | */ |
| 227 | 227 | ||
| 228 | /* Get board number from pointer */ | 228 | /* Get board number from pointer */ |
| 229 | static inline int board_No (struct specialix_board * bp) | 229 | static inline int board_No(struct specialix_board *bp) |
| 230 | { | 230 | { |
| 231 | return bp - sx_board; | 231 | return bp - sx_board; |
| 232 | } | 232 | } |
| 233 | 233 | ||
| 234 | 234 | ||
| 235 | /* Get port number from pointer */ | 235 | /* Get port number from pointer */ |
| 236 | static inline int port_No (struct specialix_port const * port) | 236 | static inline int port_No(struct specialix_port const *port) |
| 237 | { | 237 | { |
| 238 | return SX_PORT(port - sx_port); | 238 | return SX_PORT(port - sx_port); |
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | 241 | ||
| 242 | /* Get pointer to board from pointer to port */ | 242 | /* Get pointer to board from pointer to port */ |
| 243 | static inline struct specialix_board * port_Board(struct specialix_port const * port) | 243 | static inline struct specialix_board *port_Board( |
| 244 | struct specialix_port const *port) | ||
| 244 | { | 245 | { |
| 245 | return &sx_board[SX_BOARD(port - sx_port)]; | 246 | return &sx_board[SX_BOARD(port - sx_port)]; |
| 246 | } | 247 | } |
| 247 | 248 | ||
| 248 | 249 | ||
| 249 | /* Input Byte from CL CD186x register */ | 250 | /* Input Byte from CL CD186x register */ |
| 250 | static inline unsigned char sx_in(struct specialix_board * bp, unsigned short reg) | 251 | static inline unsigned char sx_in(struct specialix_board *bp, |
| 252 | unsigned short reg) | ||
| 251 | { | 253 | { |
| 252 | bp->reg = reg | 0x80; | 254 | bp->reg = reg | 0x80; |
| 253 | outb (reg | 0x80, bp->base + SX_ADDR_REG); | 255 | outb(reg | 0x80, bp->base + SX_ADDR_REG); |
| 254 | return inb (bp->base + SX_DATA_REG); | 256 | return inb(bp->base + SX_DATA_REG); |
| 255 | } | 257 | } |
| 256 | 258 | ||
| 257 | 259 | ||
| 258 | /* Output Byte to CL CD186x register */ | 260 | /* Output Byte to CL CD186x register */ |
| 259 | static inline void sx_out(struct specialix_board * bp, unsigned short reg, | 261 | static inline void sx_out(struct specialix_board *bp, unsigned short reg, |
| 260 | unsigned char val) | 262 | unsigned char val) |
| 261 | { | 263 | { |
| 262 | bp->reg = reg | 0x80; | 264 | bp->reg = reg | 0x80; |
| 263 | outb (reg | 0x80, bp->base + SX_ADDR_REG); | 265 | outb(reg | 0x80, bp->base + SX_ADDR_REG); |
| 264 | outb (val, bp->base + SX_DATA_REG); | 266 | outb(val, bp->base + SX_DATA_REG); |
| 265 | } | 267 | } |
| 266 | 268 | ||
| 267 | 269 | ||
| 268 | /* Input Byte from CL CD186x register */ | 270 | /* Input Byte from CL CD186x register */ |
| 269 | static inline unsigned char sx_in_off(struct specialix_board * bp, unsigned short reg) | 271 | static inline unsigned char sx_in_off(struct specialix_board *bp, |
| 272 | unsigned short reg) | ||
| 270 | { | 273 | { |
| 271 | bp->reg = reg; | 274 | bp->reg = reg; |
| 272 | outb (reg, bp->base + SX_ADDR_REG); | 275 | outb(reg, bp->base + SX_ADDR_REG); |
| 273 | return inb (bp->base + SX_DATA_REG); | 276 | return inb(bp->base + SX_DATA_REG); |
| 274 | } | 277 | } |
| 275 | 278 | ||
| 276 | 279 | ||
| 277 | /* Output Byte to CL CD186x register */ | 280 | /* Output Byte to CL CD186x register */ |
| 278 | static inline void sx_out_off(struct specialix_board * bp, unsigned short reg, | 281 | static inline void sx_out_off(struct specialix_board *bp, |
| 279 | unsigned char val) | 282 | unsigned short reg, unsigned char val) |
| 280 | { | 283 | { |
| 281 | bp->reg = reg; | 284 | bp->reg = reg; |
| 282 | outb (reg, bp->base + SX_ADDR_REG); | 285 | outb(reg, bp->base + SX_ADDR_REG); |
| 283 | outb (val, bp->base + SX_DATA_REG); | 286 | outb(val, bp->base + SX_DATA_REG); |
| 284 | } | 287 | } |
| 285 | 288 | ||
| 286 | 289 | ||
| 287 | /* Wait for Channel Command Register ready */ | 290 | /* Wait for Channel Command Register ready */ |
| 288 | static inline void sx_wait_CCR(struct specialix_board * bp) | 291 | static inline void sx_wait_CCR(struct specialix_board *bp) |
| 289 | { | 292 | { |
| 290 | unsigned long delay, flags; | 293 | unsigned long delay, flags; |
| 291 | unsigned char ccr; | 294 | unsigned char ccr; |
| @@ -296,7 +299,7 @@ static inline void sx_wait_CCR(struct specialix_board * bp) | |||
| 296 | spin_unlock_irqrestore(&bp->lock, flags); | 299 | spin_unlock_irqrestore(&bp->lock, flags); |
| 297 | if (!ccr) | 300 | if (!ccr) |
| 298 | return; | 301 | return; |
| 299 | udelay (1); | 302 | udelay(1); |
| 300 | } | 303 | } |
| 301 | 304 | ||
| 302 | printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp)); | 305 | printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp)); |
| @@ -304,7 +307,7 @@ static inline void sx_wait_CCR(struct specialix_board * bp) | |||
| 304 | 307 | ||
| 305 | 308 | ||
| 306 | /* Wait for Channel Command Register ready */ | 309 | /* Wait for Channel Command Register ready */ |
| 307 | static inline void sx_wait_CCR_off(struct specialix_board * bp) | 310 | static inline void sx_wait_CCR_off(struct specialix_board *bp) |
| 308 | { | 311 | { |
| 309 | unsigned long delay; | 312 | unsigned long delay; |
| 310 | unsigned char crr; | 313 | unsigned char crr; |
| @@ -316,7 +319,7 @@ static inline void sx_wait_CCR_off(struct specialix_board * bp) | |||
| 316 | spin_unlock_irqrestore(&bp->lock, flags); | 319 | spin_unlock_irqrestore(&bp->lock, flags); |
| 317 | if (!crr) | 320 | if (!crr) |
| 318 | return; | 321 | return; |
| 319 | udelay (1); | 322 | udelay(1); |
| 320 | } | 323 | } |
| 321 | 324 | ||
| 322 | printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp)); | 325 | printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp)); |
| @@ -327,7 +330,7 @@ static inline void sx_wait_CCR_off(struct specialix_board * bp) | |||
| 327 | * specialix IO8+ IO range functions. | 330 | * specialix IO8+ IO range functions. |
| 328 | */ | 331 | */ |
| 329 | 332 | ||
| 330 | static inline int sx_request_io_range(struct specialix_board * bp) | 333 | static inline int sx_request_io_range(struct specialix_board *bp) |
| 331 | { | 334 | { |
| 332 | return request_region(bp->base, | 335 | return request_region(bp->base, |
| 333 | bp->flags & SX_BOARD_IS_PCI ? SX_PCI_IO_SPACE : SX_IO_SPACE, | 336 | bp->flags & SX_BOARD_IS_PCI ? SX_PCI_IO_SPACE : SX_IO_SPACE, |
| @@ -335,15 +338,15 @@ static inline int sx_request_io_range(struct specialix_board * bp) | |||
| 335 | } | 338 | } |
| 336 | 339 | ||
| 337 | 340 | ||
| 338 | static inline void sx_release_io_range(struct specialix_board * bp) | 341 | static inline void sx_release_io_range(struct specialix_board *bp) |
| 339 | { | 342 | { |
| 340 | release_region(bp->base, | 343 | release_region(bp->base, bp->flags & SX_BOARD_IS_PCI ? |
| 341 | bp->flags&SX_BOARD_IS_PCI?SX_PCI_IO_SPACE:SX_IO_SPACE); | 344 | SX_PCI_IO_SPACE : SX_IO_SPACE); |
| 342 | } | 345 | } |
| 343 | 346 | ||
| 344 | 347 | ||
| 345 | /* Set the IRQ using the RTS lines that run to the PAL on the board.... */ | 348 | /* Set the IRQ using the RTS lines that run to the PAL on the board.... */ |
| 346 | static int sx_set_irq ( struct specialix_board *bp) | 349 | static int sx_set_irq(struct specialix_board *bp) |
| 347 | { | 350 | { |
| 348 | int virq; | 351 | int virq; |
| 349 | int i; | 352 | int i; |
| @@ -353,15 +356,24 @@ static int sx_set_irq ( struct specialix_board *bp) | |||
| 353 | return 1; | 356 | return 1; |
| 354 | switch (bp->irq) { | 357 | switch (bp->irq) { |
| 355 | /* In the same order as in the docs... */ | 358 | /* In the same order as in the docs... */ |
| 356 | case 15: virq = 0;break; | 359 | case 15: |
| 357 | case 12: virq = 1;break; | 360 | virq = 0; |
| 358 | case 11: virq = 2;break; | 361 | break; |
| 359 | case 9: virq = 3;break; | 362 | case 12: |
| 360 | default: printk (KERN_ERR "Speclialix: cannot set irq to %d.\n", bp->irq); | 363 | virq = 1; |
| 361 | return 0; | 364 | break; |
| 365 | case 11: | ||
| 366 | virq = 2; | ||
| 367 | break; | ||
| 368 | case 9: | ||
| 369 | virq = 3; | ||
| 370 | break; | ||
| 371 | default:printk(KERN_ERR | ||
| 372 | "Speclialix: cannot set irq to %d.\n", bp->irq); | ||
| 373 | return 0; | ||
| 362 | } | 374 | } |
| 363 | spin_lock_irqsave(&bp->lock, flags); | 375 | spin_lock_irqsave(&bp->lock, flags); |
| 364 | for (i=0;i<2;i++) { | 376 | for (i = 0; i < 2; i++) { |
| 365 | sx_out(bp, CD186x_CAR, i); | 377 | sx_out(bp, CD186x_CAR, i); |
| 366 | sx_out(bp, CD186x_MSVRTS, ((virq >> i) & 0x1)? MSVR_RTS:0); | 378 | sx_out(bp, CD186x_MSVRTS, ((virq >> i) & 0x1)? MSVR_RTS:0); |
| 367 | } | 379 | } |
| @@ -371,7 +383,7 @@ static int sx_set_irq ( struct specialix_board *bp) | |||
| 371 | 383 | ||
| 372 | 384 | ||
| 373 | /* Reset and setup CD186x chip */ | 385 | /* Reset and setup CD186x chip */ |
| 374 | static int sx_init_CD186x(struct specialix_board * bp) | 386 | static int sx_init_CD186x(struct specialix_board *bp) |
| 375 | { | 387 | { |
| 376 | unsigned long flags; | 388 | unsigned long flags; |
| 377 | int scaler; | 389 | int scaler; |
| @@ -390,7 +402,7 @@ static int sx_init_CD186x(struct specialix_board * bp) | |||
| 390 | sx_out_off(bp, CD186x_PILR2, SX_ACK_TINT); /* Prio for transmitter intr */ | 402 | sx_out_off(bp, CD186x_PILR2, SX_ACK_TINT); /* Prio for transmitter intr */ |
| 391 | sx_out_off(bp, CD186x_PILR3, SX_ACK_RINT); /* Prio for receiver intr */ | 403 | sx_out_off(bp, CD186x_PILR3, SX_ACK_RINT); /* Prio for receiver intr */ |
| 392 | /* Set RegAckEn */ | 404 | /* Set RegAckEn */ |
| 393 | sx_out_off(bp, CD186x_SRCR, sx_in (bp, CD186x_SRCR) | SRCR_REGACKEN); | 405 | sx_out_off(bp, CD186x_SRCR, sx_in(bp, CD186x_SRCR) | SRCR_REGACKEN); |
| 394 | 406 | ||
| 395 | /* Setting up prescaler. We need 4 ticks per 1 ms */ | 407 | /* Setting up prescaler. We need 4 ticks per 1 ms */ |
| 396 | scaler = SX_OSCFREQ/SPECIALIX_TPS; | 408 | scaler = SX_OSCFREQ/SPECIALIX_TPS; |
| @@ -399,9 +411,9 @@ static int sx_init_CD186x(struct specialix_board * bp) | |||
| 399 | sx_out_off(bp, CD186x_PPRL, scaler & 0xff); | 411 | sx_out_off(bp, CD186x_PPRL, scaler & 0xff); |
| 400 | spin_unlock_irqrestore(&bp->lock, flags); | 412 | spin_unlock_irqrestore(&bp->lock, flags); |
| 401 | 413 | ||
| 402 | if (!sx_set_irq (bp)) { | 414 | if (!sx_set_irq(bp)) { |
| 403 | /* Figure out how to pass this along... */ | 415 | /* Figure out how to pass this along... */ |
| 404 | printk (KERN_ERR "Cannot set irq to %d.\n", bp->irq); | 416 | printk(KERN_ERR "Cannot set irq to %d.\n", bp->irq); |
| 405 | rv = 0; | 417 | rv = 0; |
| 406 | } | 418 | } |
| 407 | 419 | ||
| @@ -410,16 +422,16 @@ static int sx_init_CD186x(struct specialix_board * bp) | |||
| 410 | } | 422 | } |
| 411 | 423 | ||
| 412 | 424 | ||
| 413 | static int read_cross_byte (struct specialix_board *bp, int reg, int bit) | 425 | static int read_cross_byte(struct specialix_board *bp, int reg, int bit) |
| 414 | { | 426 | { |
| 415 | int i; | 427 | int i; |
| 416 | int t; | 428 | int t; |
| 417 | unsigned long flags; | 429 | unsigned long flags; |
| 418 | 430 | ||
| 419 | spin_lock_irqsave(&bp->lock, flags); | 431 | spin_lock_irqsave(&bp->lock, flags); |
| 420 | for (i=0, t=0;i<8;i++) { | 432 | for (i = 0, t = 0; i < 8; i++) { |
| 421 | sx_out_off (bp, CD186x_CAR, i); | 433 | sx_out_off(bp, CD186x_CAR, i); |
| 422 | if (sx_in_off (bp, reg) & bit) | 434 | if (sx_in_off(bp, reg) & bit) |
| 423 | t |= 1 << i; | 435 | t |= 1 << i; |
| 424 | } | 436 | } |
| 425 | spin_unlock_irqrestore(&bp->lock, flags); | 437 | spin_unlock_irqrestore(&bp->lock, flags); |
| @@ -429,21 +441,20 @@ static int read_cross_byte (struct specialix_board *bp, int reg, int bit) | |||
| 429 | 441 | ||
| 430 | 442 | ||
| 431 | #ifdef SPECIALIX_TIMER | 443 | #ifdef SPECIALIX_TIMER |
| 432 | void missed_irq (unsigned long data) | 444 | void missed_irq(unsigned long data) |
| 433 | { | 445 | { |
| 434 | unsigned char irq; | 446 | unsigned char irq; |
| 435 | unsigned long flags; | 447 | unsigned long flags; |
| 436 | struct specialix_board *bp = (struct specialix_board *)data; | 448 | struct specialix_board *bp = (struct specialix_board *)data; |
| 437 | 449 | ||
| 438 | spin_lock_irqsave(&bp->lock, flags); | 450 | spin_lock_irqsave(&bp->lock, flags); |
| 439 | irq = sx_in ((struct specialix_board *)data, CD186x_SRSR) & | 451 | irq = sx_in((struct specialix_board *)data, CD186x_SRSR) & |
| 440 | (SRSR_RREQint | | 452 | (SRSR_RREQint | SRSR_TREQint | SRSR_MREQint); |
| 441 | SRSR_TREQint | | ||
| 442 | SRSR_MREQint); | ||
| 443 | spin_unlock_irqrestore(&bp->lock, flags); | 453 | spin_unlock_irqrestore(&bp->lock, flags); |
| 444 | if (irq) { | 454 | if (irq) { |
| 445 | printk (KERN_INFO "Missed interrupt... Calling int from timer. \n"); | 455 | printk(KERN_INFO |
| 446 | sx_interrupt (-1, bp); | 456 | "Missed interrupt... Calling int from timer. \n"); |
| 457 | sx_interrupt(-1, bp); | ||
| 447 | } | 458 | } |
| 448 | mod_timer(&missed_irq_timer, jiffies + sx_poll); | 459 | mod_timer(&missed_irq_timer, jiffies + sx_poll); |
| 449 | } | 460 | } |
| @@ -471,17 +482,18 @@ static int sx_probe(struct specialix_board *bp) | |||
| 471 | 482 | ||
| 472 | /* Are the I/O ports here ? */ | 483 | /* Are the I/O ports here ? */ |
| 473 | sx_out_off(bp, CD186x_PPRL, 0x5a); | 484 | sx_out_off(bp, CD186x_PPRL, 0x5a); |
| 474 | short_pause (); | 485 | short_pause(); |
| 475 | val1 = sx_in_off(bp, CD186x_PPRL); | 486 | val1 = sx_in_off(bp, CD186x_PPRL); |
| 476 | 487 | ||
| 477 | sx_out_off(bp, CD186x_PPRL, 0xa5); | 488 | sx_out_off(bp, CD186x_PPRL, 0xa5); |
| 478 | short_pause (); | 489 | short_pause(); |
| 479 | val2 = sx_in_off(bp, CD186x_PPRL); | 490 | val2 = sx_in_off(bp, CD186x_PPRL); |
| 480 | 491 | ||
| 481 | 492 | ||
| 482 | if ((val1 != 0x5a) || (val2 != 0xa5)) { | 493 | if ((val1 != 0x5a) || (val2 != 0xa5)) { |
| 483 | printk(KERN_INFO "sx%d: specialix IO8+ Board at 0x%03x not found.\n", | 494 | printk(KERN_INFO |
| 484 | board_No(bp), bp->base); | 495 | "sx%d: specialix IO8+ Board at 0x%03x not found.\n", |
| 496 | board_No(bp), bp->base); | ||
| 485 | sx_release_io_range(bp); | 497 | sx_release_io_range(bp); |
| 486 | func_exit(); | 498 | func_exit(); |
| 487 | return 1; | 499 | return 1; |
| @@ -489,10 +501,11 @@ static int sx_probe(struct specialix_board *bp) | |||
| 489 | 501 | ||
| 490 | /* Check the DSR lines that Specialix uses as board | 502 | /* Check the DSR lines that Specialix uses as board |
| 491 | identification */ | 503 | identification */ |
| 492 | val1 = read_cross_byte (bp, CD186x_MSVR, MSVR_DSR); | 504 | val1 = read_cross_byte(bp, CD186x_MSVR, MSVR_DSR); |
| 493 | val2 = read_cross_byte (bp, CD186x_MSVR, MSVR_RTS); | 505 | val2 = read_cross_byte(bp, CD186x_MSVR, MSVR_RTS); |
| 494 | dprintk (SX_DEBUG_INIT, "sx%d: DSR lines are: %02x, rts lines are: %02x\n", | 506 | dprintk(SX_DEBUG_INIT, |
| 495 | board_No(bp), val1, val2); | 507 | "sx%d: DSR lines are: %02x, rts lines are: %02x\n", |
| 508 | board_No(bp), val1, val2); | ||
| 496 | 509 | ||
| 497 | /* They managed to switch the bit order between the docs and | 510 | /* They managed to switch the bit order between the docs and |
| 498 | the IO8+ card. The new PCI card now conforms to old docs. | 511 | the IO8+ card. The new PCI card now conforms to old docs. |
| @@ -500,7 +513,8 @@ static int sx_probe(struct specialix_board *bp) | |||
| 500 | old card. */ | 513 | old card. */ |
| 501 | val2 = (bp->flags & SX_BOARD_IS_PCI)?0x4d : 0xb2; | 514 | val2 = (bp->flags & SX_BOARD_IS_PCI)?0x4d : 0xb2; |
| 502 | if (val1 != val2) { | 515 | if (val1 != val2) { |
| 503 | printk(KERN_INFO "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n", | 516 | printk(KERN_INFO |
| 517 | "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n", | ||
| 504 | board_No(bp), val2, bp->base, val1); | 518 | board_No(bp), val2, bp->base, val1); |
| 505 | sx_release_io_range(bp); | 519 | sx_release_io_range(bp); |
| 506 | func_exit(); | 520 | func_exit(); |
| @@ -512,40 +526,43 @@ static int sx_probe(struct specialix_board *bp) | |||
| 512 | /* It's time to find IRQ for this board */ | 526 | /* It's time to find IRQ for this board */ |
| 513 | for (retries = 0; retries < 5 && irqs <= 0; retries++) { | 527 | for (retries = 0; retries < 5 && irqs <= 0; retries++) { |
| 514 | irqs = probe_irq_on(); | 528 | irqs = probe_irq_on(); |
| 515 | sx_init_CD186x(bp); /* Reset CD186x chip */ | 529 | sx_init_CD186x(bp); /* Reset CD186x chip */ |
| 516 | sx_out(bp, CD186x_CAR, 2); /* Select port 2 */ | 530 | sx_out(bp, CD186x_CAR, 2); /* Select port 2 */ |
| 517 | sx_wait_CCR(bp); | 531 | sx_wait_CCR(bp); |
| 518 | sx_out(bp, CD186x_CCR, CCR_TXEN); /* Enable transmitter */ | 532 | sx_out(bp, CD186x_CCR, CCR_TXEN); /* Enable transmitter */ |
| 519 | sx_out(bp, CD186x_IER, IER_TXRDY); /* Enable tx empty intr */ | 533 | sx_out(bp, CD186x_IER, IER_TXRDY); /* Enable tx empty intr */ |
| 520 | msleep(50); | 534 | msleep(50); |
| 521 | irqs = probe_irq_off(irqs); | 535 | irqs = probe_irq_off(irqs); |
| 522 | 536 | ||
| 523 | dprintk (SX_DEBUG_INIT, "SRSR = %02x, ", sx_in(bp, CD186x_SRSR)); | 537 | dprintk(SX_DEBUG_INIT, "SRSR = %02x, ", sx_in(bp, CD186x_SRSR)); |
| 524 | dprintk (SX_DEBUG_INIT, "TRAR = %02x, ", sx_in(bp, CD186x_TRAR)); | 538 | dprintk(SX_DEBUG_INIT, "TRAR = %02x, ", sx_in(bp, CD186x_TRAR)); |
| 525 | dprintk (SX_DEBUG_INIT, "GIVR = %02x, ", sx_in(bp, CD186x_GIVR)); | 539 | dprintk(SX_DEBUG_INIT, "GIVR = %02x, ", sx_in(bp, CD186x_GIVR)); |
| 526 | dprintk (SX_DEBUG_INIT, "GICR = %02x, ", sx_in(bp, CD186x_GICR)); | 540 | dprintk(SX_DEBUG_INIT, "GICR = %02x, ", sx_in(bp, CD186x_GICR)); |
| 527 | dprintk (SX_DEBUG_INIT, "\n"); | 541 | dprintk(SX_DEBUG_INIT, "\n"); |
| 528 | 542 | ||
| 529 | /* Reset CD186x again */ | 543 | /* Reset CD186x again */ |
| 530 | if (!sx_init_CD186x(bp)) { | 544 | if (!sx_init_CD186x(bp)) { |
| 531 | /* Hmmm. This is dead code anyway. */ | 545 | /* Hmmm. This is dead code anyway. */ |
| 532 | } | 546 | } |
| 533 | 547 | ||
| 534 | dprintk (SX_DEBUG_INIT "val1 = %02x, val2 = %02x, val3 = %02x.\n", | 548 | dprintk(SX_DEBUG_INIT |
| 535 | val1, val2, val3); | 549 | "val1 = %02x, val2 = %02x, val3 = %02x.\n", |
| 550 | val1, val2, val3); | ||
| 536 | 551 | ||
| 537 | } | 552 | } |
| 538 | 553 | ||
| 539 | #if 0 | 554 | #if 0 |
| 540 | if (irqs <= 0) { | 555 | if (irqs <= 0) { |
| 541 | printk(KERN_ERR "sx%d: Can't find IRQ for specialix IO8+ board at 0x%03x.\n", | 556 | printk(KERN_ERR |
| 542 | board_No(bp), bp->base); | 557 | "sx%d: Can't find IRQ for specialix IO8+ board at 0x%03x.\n", |
| 558 | board_No(bp), bp->base); | ||
| 543 | sx_release_io_range(bp); | 559 | sx_release_io_range(bp); |
| 544 | func_exit(); | 560 | func_exit(); |
| 545 | return 1; | 561 | return 1; |
| 546 | } | 562 | } |
| 547 | #endif | 563 | #endif |
| 548 | printk (KERN_INFO "Started with irq=%d, but now have irq=%d.\n", bp->irq, irqs); | 564 | printk(KERN_INFO "Started with irq=%d, but now have irq=%d.\n", |
| 565 | bp->irq, irqs); | ||
| 549 | if (irqs > 0) | 566 | if (irqs > 0) |
| 550 | bp->irq = irqs; | 567 | bp->irq = irqs; |
| 551 | #endif | 568 | #endif |
| @@ -560,7 +577,7 @@ static int sx_probe(struct specialix_board *bp) | |||
| 560 | bp->flags |= SX_BOARD_PRESENT; | 577 | bp->flags |= SX_BOARD_PRESENT; |
| 561 | 578 | ||
| 562 | /* Chip revcode pkgtype | 579 | /* Chip revcode pkgtype |
| 563 | GFRCR SRCR bit 7 | 580 | GFRCR SRCR bit 7 |
| 564 | CD180 rev B 0x81 0 | 581 | CD180 rev B 0x81 0 |
| 565 | CD180 rev C 0x82 0 | 582 | CD180 rev C 0x82 0 |
| 566 | CD1864 rev A 0x82 1 | 583 | CD1864 rev A 0x82 1 |
| @@ -570,24 +587,37 @@ static int sx_probe(struct specialix_board *bp) | |||
| 570 | */ | 587 | */ |
| 571 | 588 | ||
| 572 | switch (sx_in_off(bp, CD186x_GFRCR)) { | 589 | switch (sx_in_off(bp, CD186x_GFRCR)) { |
| 573 | case 0x82:chip = 1864;rev='A';break; | 590 | case 0x82: |
| 574 | case 0x83:chip = 1865;rev='A';break; | 591 | chip = 1864; |
| 575 | case 0x84:chip = 1865;rev='B';break; | 592 | rev = 'A'; |
| 576 | case 0x85:chip = 1865;rev='C';break; /* Does not exist at this time */ | 593 | break; |
| 577 | default:chip=-1;rev='x'; | 594 | case 0x83: |
| 595 | chip = 1865; | ||
| 596 | rev = 'A'; | ||
| 597 | break; | ||
| 598 | case 0x84: | ||
| 599 | chip = 1865; | ||
| 600 | rev = 'B'; | ||
| 601 | break; | ||
| 602 | case 0x85: | ||
| 603 | chip = 1865; | ||
| 604 | rev = 'C'; | ||
| 605 | break; /* Does not exist at this time */ | ||
| 606 | default: | ||
| 607 | chip = -1; | ||
| 608 | rev = 'x'; | ||
| 578 | } | 609 | } |
| 579 | 610 | ||
| 580 | dprintk (SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR) ); | 611 | dprintk(SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR)); |
| 581 | 612 | ||
| 582 | #ifdef SPECIALIX_TIMER | 613 | #ifdef SPECIALIX_TIMER |
| 583 | setup_timer(&missed_irq_timer, missed_irq, (unsigned long)bp); | 614 | setup_timer(&missed_irq_timer, missed_irq, (unsigned long)bp); |
| 584 | mod_timer(&missed_irq_timer, jiffies + sx_poll); | 615 | mod_timer(&missed_irq_timer, jiffies + sx_poll); |
| 585 | #endif | 616 | #endif |
| 586 | 617 | ||
| 587 | printk(KERN_INFO"sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n", | 618 | printk(KERN_INFO |
| 588 | board_No(bp), | 619 | "sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n", |
| 589 | bp->base, bp->irq, | 620 | board_No(bp), bp->base, bp->irq, chip, rev); |
| 590 | chip, rev); | ||
| 591 | 621 | ||
| 592 | func_exit(); | 622 | func_exit(); |
| 593 | return 0; | 623 | return 0; |
| @@ -598,20 +628,22 @@ static int sx_probe(struct specialix_board *bp) | |||
| 598 | * Interrupt processing routines. | 628 | * Interrupt processing routines. |
| 599 | * */ | 629 | * */ |
| 600 | 630 | ||
| 601 | static inline struct specialix_port * sx_get_port(struct specialix_board * bp, | 631 | static inline struct specialix_port *sx_get_port(struct specialix_board *bp, |
| 602 | unsigned char const * what) | 632 | unsigned char const *what) |
| 603 | { | 633 | { |
| 604 | unsigned char channel; | 634 | unsigned char channel; |
| 605 | struct specialix_port * port = NULL; | 635 | struct specialix_port *port = NULL; |
| 606 | 636 | ||
| 607 | channel = sx_in(bp, CD186x_GICR) >> GICR_CHAN_OFF; | 637 | channel = sx_in(bp, CD186x_GICR) >> GICR_CHAN_OFF; |
| 608 | dprintk (SX_DEBUG_CHAN, "channel: %d\n", channel); | 638 | dprintk(SX_DEBUG_CHAN, "channel: %d\n", channel); |
| 609 | if (channel < CD186x_NCH) { | 639 | if (channel < CD186x_NCH) { |
| 610 | port = &sx_port[board_No(bp) * SX_NPORT + channel]; | 640 | port = &sx_port[board_No(bp) * SX_NPORT + channel]; |
| 611 | dprintk (SX_DEBUG_CHAN, "port: %d %p flags: 0x%lx\n",board_No(bp) * SX_NPORT + channel, port, port->port.flags & ASYNC_INITIALIZED); | 641 | dprintk(SX_DEBUG_CHAN, "port: %d %p flags: 0x%lx\n", |
| 642 | board_No(bp) * SX_NPORT + channel, port, | ||
| 643 | port->port.flags & ASYNC_INITIALIZED); | ||
| 612 | 644 | ||
| 613 | if (port->port.flags & ASYNC_INITIALIZED) { | 645 | if (port->port.flags & ASYNC_INITIALIZED) { |
| 614 | dprintk (SX_DEBUG_CHAN, "port: %d %p\n", channel, port); | 646 | dprintk(SX_DEBUG_CHAN, "port: %d %p\n", channel, port); |
| 615 | func_exit(); | 647 | func_exit(); |
| 616 | return port; | 648 | return port; |
| 617 | } | 649 | } |
| @@ -622,7 +654,7 @@ static inline struct specialix_port * sx_get_port(struct specialix_board * bp, | |||
| 622 | } | 654 | } |
| 623 | 655 | ||
| 624 | 656 | ||
| 625 | static inline void sx_receive_exc(struct specialix_board * bp) | 657 | static inline void sx_receive_exc(struct specialix_board *bp) |
| 626 | { | 658 | { |
| 627 | struct specialix_port *port; | 659 | struct specialix_port *port; |
| 628 | struct tty_struct *tty; | 660 | struct tty_struct *tty; |
| @@ -633,7 +665,7 @@ static inline void sx_receive_exc(struct specialix_board * bp) | |||
| 633 | 665 | ||
| 634 | port = sx_get_port(bp, "Receive"); | 666 | port = sx_get_port(bp, "Receive"); |
| 635 | if (!port) { | 667 | if (!port) { |
| 636 | dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n"); | 668 | dprintk(SX_DEBUG_RX, "Hmm, couldn't find port.\n"); |
| 637 | func_exit(); | 669 | func_exit(); |
| 638 | return; | 670 | return; |
| 639 | } | 671 | } |
| @@ -641,19 +673,21 @@ static inline void sx_receive_exc(struct specialix_board * bp) | |||
| 641 | 673 | ||
| 642 | status = sx_in(bp, CD186x_RCSR); | 674 | status = sx_in(bp, CD186x_RCSR); |
| 643 | 675 | ||
| 644 | dprintk (SX_DEBUG_RX, "status: 0x%x\n", status); | 676 | dprintk(SX_DEBUG_RX, "status: 0x%x\n", status); |
| 645 | if (status & RCSR_OE) { | 677 | if (status & RCSR_OE) { |
| 646 | port->overrun++; | 678 | port->overrun++; |
| 647 | dprintk(SX_DEBUG_FIFO, "sx%d: port %d: Overrun. Total %ld overruns.\n", | 679 | dprintk(SX_DEBUG_FIFO, |
| 648 | board_No(bp), port_No(port), port->overrun); | 680 | "sx%d: port %d: Overrun. Total %ld overruns.\n", |
| 681 | board_No(bp), port_No(port), port->overrun); | ||
| 649 | } | 682 | } |
| 650 | status &= port->mark_mask; | 683 | status &= port->mark_mask; |
| 651 | 684 | ||
| 652 | /* This flip buffer check needs to be below the reading of the | 685 | /* This flip buffer check needs to be below the reading of the |
| 653 | status register to reset the chip's IRQ.... */ | 686 | status register to reset the chip's IRQ.... */ |
| 654 | if (tty_buffer_request_room(tty, 1) == 0) { | 687 | if (tty_buffer_request_room(tty, 1) == 0) { |
| 655 | dprintk(SX_DEBUG_FIFO, "sx%d: port %d: Working around flip buffer overflow.\n", | 688 | dprintk(SX_DEBUG_FIFO, |
| 656 | board_No(bp), port_No(port)); | 689 | "sx%d: port %d: Working around flip buffer overflow.\n", |
| 690 | board_No(bp), port_No(port)); | ||
| 657 | func_exit(); | 691 | func_exit(); |
| 658 | return; | 692 | return; |
| 659 | } | 693 | } |
| @@ -664,8 +698,9 @@ static inline void sx_receive_exc(struct specialix_board * bp) | |||
| 664 | return; | 698 | return; |
| 665 | } | 699 | } |
| 666 | if (status & RCSR_TOUT) { | 700 | if (status & RCSR_TOUT) { |
| 667 | printk(KERN_INFO "sx%d: port %d: Receiver timeout. Hardware problems ?\n", | 701 | printk(KERN_INFO |
| 668 | board_No(bp), port_No(port)); | 702 | "sx%d: port %d: Receiver timeout. Hardware problems ?\n", |
| 703 | board_No(bp), port_No(port)); | ||
| 669 | func_exit(); | 704 | func_exit(); |
| 670 | return; | 705 | return; |
| 671 | 706 | ||
| @@ -688,13 +723,13 @@ static inline void sx_receive_exc(struct specialix_board * bp) | |||
| 688 | else | 723 | else |
| 689 | flag = TTY_NORMAL; | 724 | flag = TTY_NORMAL; |
| 690 | 725 | ||
| 691 | if(tty_insert_flip_char(tty, ch, flag)) | 726 | if (tty_insert_flip_char(tty, ch, flag)) |
| 692 | tty_flip_buffer_push(tty); | 727 | tty_flip_buffer_push(tty); |
| 693 | func_exit(); | 728 | func_exit(); |
| 694 | } | 729 | } |
| 695 | 730 | ||
| 696 | 731 | ||
| 697 | static inline void sx_receive(struct specialix_board * bp) | 732 | static inline void sx_receive(struct specialix_board *bp) |
| 698 | { | 733 | { |
| 699 | struct specialix_port *port; | 734 | struct specialix_port *port; |
| 700 | struct tty_struct *tty; | 735 | struct tty_struct *tty; |
| @@ -702,15 +737,16 @@ static inline void sx_receive(struct specialix_board * bp) | |||
| 702 | 737 | ||
| 703 | func_enter(); | 738 | func_enter(); |
| 704 | 739 | ||
| 705 | if (!(port = sx_get_port(bp, "Receive"))) { | 740 | port = sx_get_port(bp, "Receive"); |
| 706 | dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n"); | 741 | if (port == NULL) { |
| 742 | dprintk(SX_DEBUG_RX, "Hmm, couldn't find port.\n"); | ||
| 707 | func_exit(); | 743 | func_exit(); |
| 708 | return; | 744 | return; |
| 709 | } | 745 | } |
| 710 | tty = port->port.tty; | 746 | tty = port->port.tty; |
| 711 | 747 | ||
| 712 | count = sx_in(bp, CD186x_RDCR); | 748 | count = sx_in(bp, CD186x_RDCR); |
| 713 | dprintk (SX_DEBUG_RX, "port: %p: count: %d\n", port, count); | 749 | dprintk(SX_DEBUG_RX, "port: %p: count: %d\n", port, count); |
| 714 | port->hits[count > 8 ? 9 : count]++; | 750 | port->hits[count > 8 ? 9 : count]++; |
| 715 | 751 | ||
| 716 | tty_buffer_request_room(tty, count); | 752 | tty_buffer_request_room(tty, count); |
| @@ -722,18 +758,19 @@ static inline void sx_receive(struct specialix_board * bp) | |||
| 722 | } | 758 | } |
| 723 | 759 | ||
| 724 | 760 | ||
| 725 | static inline void sx_transmit(struct specialix_board * bp) | 761 | static inline void sx_transmit(struct specialix_board *bp) |
| 726 | { | 762 | { |
| 727 | struct specialix_port *port; | 763 | struct specialix_port *port; |
| 728 | struct tty_struct *tty; | 764 | struct tty_struct *tty; |
| 729 | unsigned char count; | 765 | unsigned char count; |
| 730 | 766 | ||
| 731 | func_enter(); | 767 | func_enter(); |
| 732 | if (!(port = sx_get_port(bp, "Transmit"))) { | 768 | port = sx_get_port(bp, "Transmit"); |
| 769 | if (port == NULL) { | ||
| 733 | func_exit(); | 770 | func_exit(); |
| 734 | return; | 771 | return; |
| 735 | } | 772 | } |
| 736 | dprintk (SX_DEBUG_TX, "port: %p\n", port); | 773 | dprintk(SX_DEBUG_TX, "port: %p\n", port); |
| 737 | tty = port->port.tty; | 774 | tty = port->port.tty; |
| 738 | 775 | ||
| 739 | if (port->IER & IER_TXEMPTY) { | 776 | if (port->IER & IER_TXEMPTY) { |
| @@ -765,7 +802,8 @@ static inline void sx_transmit(struct specialix_board * bp) | |||
| 765 | sx_out(bp, CD186x_TDR, CD186x_C_ESC); | 802 | sx_out(bp, CD186x_TDR, CD186x_C_ESC); |
| 766 | sx_out(bp, CD186x_TDR, CD186x_C_DELAY); | 803 | sx_out(bp, CD186x_TDR, CD186x_C_DELAY); |
| 767 | sx_out(bp, CD186x_TDR, count); | 804 | sx_out(bp, CD186x_TDR, count); |
| 768 | if (!(port->break_length -= count)) | 805 | port->break_length -= count; |
| 806 | if (port->break_length == 0) | ||
| 769 | port->break_length--; | 807 | port->break_length--; |
| 770 | } else { | 808 | } else { |
| 771 | sx_out(bp, CD186x_TDR, CD186x_C_ESC); | 809 | sx_out(bp, CD186x_TDR, CD186x_C_ESC); |
| @@ -794,36 +832,37 @@ static inline void sx_transmit(struct specialix_board * bp) | |||
| 794 | sx_out(bp, CD186x_IER, port->IER); | 832 | sx_out(bp, CD186x_IER, port->IER); |
| 795 | } | 833 | } |
| 796 | if (port->xmit_cnt <= port->wakeup_chars) | 834 | if (port->xmit_cnt <= port->wakeup_chars) |
| 797 | tty_wakeup(tty); | 835 | tty_wakeup(tty); |
| 798 | 836 | ||
| 799 | func_exit(); | 837 | func_exit(); |
| 800 | } | 838 | } |
| 801 | 839 | ||
| 802 | 840 | ||
| 803 | static inline void sx_check_modem(struct specialix_board * bp) | 841 | static inline void sx_check_modem(struct specialix_board *bp) |
| 804 | { | 842 | { |
| 805 | struct specialix_port *port; | 843 | struct specialix_port *port; |
| 806 | struct tty_struct *tty; | 844 | struct tty_struct *tty; |
| 807 | unsigned char mcr; | 845 | unsigned char mcr; |
| 808 | int msvr_cd; | 846 | int msvr_cd; |
| 809 | 847 | ||
| 810 | dprintk (SX_DEBUG_SIGNALS, "Modem intr. "); | 848 | dprintk(SX_DEBUG_SIGNALS, "Modem intr. "); |
| 811 | if (!(port = sx_get_port(bp, "Modem"))) | 849 | port = sx_get_port(bp, "Modem"); |
| 850 | if (port == NULL) | ||
| 812 | return; | 851 | return; |
| 813 | 852 | ||
| 814 | tty = port->port.tty; | 853 | tty = port->port.tty; |
| 815 | 854 | ||
| 816 | mcr = sx_in(bp, CD186x_MCR); | 855 | mcr = sx_in(bp, CD186x_MCR); |
| 817 | printk ("mcr = %02x.\n", mcr); | 856 | printk("mcr = %02x.\n", mcr); /* FIXME */ |
| 818 | 857 | ||
| 819 | if ((mcr & MCR_CDCHG)) { | 858 | if ((mcr & MCR_CDCHG)) { |
| 820 | dprintk (SX_DEBUG_SIGNALS, "CD just changed... "); | 859 | dprintk(SX_DEBUG_SIGNALS, "CD just changed... "); |
| 821 | msvr_cd = sx_in(bp, CD186x_MSVR) & MSVR_CD; | 860 | msvr_cd = sx_in(bp, CD186x_MSVR) & MSVR_CD; |
| 822 | if (msvr_cd) { | 861 | if (msvr_cd) { |
| 823 | dprintk (SX_DEBUG_SIGNALS, "Waking up guys in open.\n"); | 862 | dprintk(SX_DEBUG_SIGNALS, "Waking up guys in open.\n"); |
| 824 | wake_up_interruptible(&port->port.open_wait); | 863 | wake_up_interruptible(&port->port.open_wait); |
| 825 | } else { | 864 | } else { |
| 826 | dprintk (SX_DEBUG_SIGNALS, "Sending HUP.\n"); | 865 | dprintk(SX_DEBUG_SIGNALS, "Sending HUP.\n"); |
| 827 | tty_hangup(tty); | 866 | tty_hangup(tty); |
| 828 | } | 867 | } |
| 829 | } | 868 | } |
| @@ -874,9 +913,12 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id) | |||
| 874 | 913 | ||
| 875 | spin_lock_irqsave(&bp->lock, flags); | 914 | spin_lock_irqsave(&bp->lock, flags); |
| 876 | 915 | ||
| 877 | dprintk (SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __func__, port_No(sx_get_port(bp, "INT")), SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1); | 916 | dprintk(SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __func__, |
| 917 | port_No(sx_get_port(bp, "INT")), | ||
| 918 | SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1); | ||
| 878 | if (!(bp->flags & SX_BOARD_ACTIVE)) { | 919 | if (!(bp->flags & SX_BOARD_ACTIVE)) { |
| 879 | dprintk (SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", bp->irq); | 920 | dprintk(SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", |
| 921 | bp->irq); | ||
| 880 | spin_unlock_irqrestore(&bp->lock, flags); | 922 | spin_unlock_irqrestore(&bp->lock, flags); |
| 881 | func_exit(); | 923 | func_exit(); |
| 882 | return IRQ_NONE; | 924 | return IRQ_NONE; |
| @@ -884,10 +926,11 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id) | |||
| 884 | 926 | ||
| 885 | saved_reg = bp->reg; | 927 | saved_reg = bp->reg; |
| 886 | 928 | ||
| 887 | while ((++loop < 16) && (status = (sx_in(bp, CD186x_SRSR) & | 929 | while (++loop < 16) { |
| 888 | (SRSR_RREQint | | 930 | status = sx_in(bp, CD186x_SRSR) & |
| 889 | SRSR_TREQint | | 931 | (SRSR_RREQint | SRSR_TREQint | SRSR_MREQint); |
| 890 | SRSR_MREQint)))) { | 932 | if (status == 0) |
| 933 | break; | ||
| 891 | if (status & SRSR_RREQint) { | 934 | if (status & SRSR_RREQint) { |
| 892 | ack = sx_in(bp, CD186x_RRAR); | 935 | ack = sx_in(bp, CD186x_RRAR); |
| 893 | 936 | ||
| @@ -896,8 +939,9 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id) | |||
| 896 | else if (ack == (SX_ID | GIVR_IT_REXC)) | 939 | else if (ack == (SX_ID | GIVR_IT_REXC)) |
| 897 | sx_receive_exc(bp); | 940 | sx_receive_exc(bp); |
| 898 | else | 941 | else |
| 899 | printk(KERN_ERR "sx%d: status: 0x%x Bad receive ack 0x%02x.\n", | 942 | printk(KERN_ERR |
| 900 | board_No(bp), status, ack); | 943 | "sx%d: status: 0x%x Bad receive ack 0x%02x.\n", |
| 944 | board_No(bp), status, ack); | ||
| 901 | 945 | ||
| 902 | } else if (status & SRSR_TREQint) { | 946 | } else if (status & SRSR_TREQint) { |
| 903 | ack = sx_in(bp, CD186x_TRAR); | 947 | ack = sx_in(bp, CD186x_TRAR); |
| @@ -906,14 +950,16 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id) | |||
| 906 | sx_transmit(bp); | 950 | sx_transmit(bp); |
| 907 | else | 951 | else |
| 908 | printk(KERN_ERR "sx%d: status: 0x%x Bad transmit ack 0x%02x. port: %d\n", | 952 | printk(KERN_ERR "sx%d: status: 0x%x Bad transmit ack 0x%02x. port: %d\n", |
| 909 | board_No(bp), status, ack, port_No (sx_get_port (bp, "Int"))); | 953 | board_No(bp), status, ack, |
| 954 | port_No(sx_get_port(bp, "Int"))); | ||
| 910 | } else if (status & SRSR_MREQint) { | 955 | } else if (status & SRSR_MREQint) { |
| 911 | ack = sx_in(bp, CD186x_MRAR); | 956 | ack = sx_in(bp, CD186x_MRAR); |
| 912 | 957 | ||
| 913 | if (ack == (SX_ID | GIVR_IT_MODEM)) | 958 | if (ack == (SX_ID | GIVR_IT_MODEM)) |
| 914 | sx_check_modem(bp); | 959 | sx_check_modem(bp); |
| 915 | else | 960 | else |
| 916 | printk(KERN_ERR "sx%d: status: 0x%x Bad modem ack 0x%02x.\n", | 961 | printk(KERN_ERR |
| 962 | "sx%d: status: 0x%x Bad modem ack 0x%02x.\n", | ||
| 917 | board_No(bp), status, ack); | 963 | board_No(bp), status, ack); |
| 918 | 964 | ||
| 919 | } | 965 | } |
| @@ -921,7 +967,7 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id) | |||
| 921 | sx_out(bp, CD186x_EOIR, 0); /* Mark end of interrupt */ | 967 | sx_out(bp, CD186x_EOIR, 0); /* Mark end of interrupt */ |
| 922 | } | 968 | } |
| 923 | bp->reg = saved_reg; | 969 | bp->reg = saved_reg; |
| 924 | outb (bp->reg, bp->base + SX_ADDR_REG); | 970 | outb(bp->reg, bp->base + SX_ADDR_REG); |
| 925 | spin_unlock_irqrestore(&bp->lock, flags); | 971 | spin_unlock_irqrestore(&bp->lock, flags); |
| 926 | func_exit(); | 972 | func_exit(); |
| 927 | return IRQ_HANDLED; | 973 | return IRQ_HANDLED; |
| @@ -932,7 +978,7 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id) | |||
| 932 | * Routines for open & close processing. | 978 | * Routines for open & close processing. |
| 933 | */ | 979 | */ |
| 934 | 980 | ||
| 935 | static void turn_ints_off (struct specialix_board *bp) | 981 | static void turn_ints_off(struct specialix_board *bp) |
| 936 | { | 982 | { |
| 937 | unsigned long flags; | 983 | unsigned long flags; |
| 938 | 984 | ||
| @@ -945,13 +991,13 @@ static void turn_ints_off (struct specialix_board *bp) | |||
| 945 | } | 991 | } |
| 946 | 992 | ||
| 947 | spin_lock_irqsave(&bp->lock, flags); | 993 | spin_lock_irqsave(&bp->lock, flags); |
| 948 | (void) sx_in_off (bp, 0); /* Turn off interrupts. */ | 994 | (void) sx_in_off(bp, 0); /* Turn off interrupts. */ |
| 949 | spin_unlock_irqrestore(&bp->lock, flags); | 995 | spin_unlock_irqrestore(&bp->lock, flags); |
| 950 | 996 | ||
| 951 | func_exit(); | 997 | func_exit(); |
| 952 | } | 998 | } |
| 953 | 999 | ||
| 954 | static void turn_ints_on (struct specialix_board *bp) | 1000 | static void turn_ints_on(struct specialix_board *bp) |
| 955 | { | 1001 | { |
| 956 | unsigned long flags; | 1002 | unsigned long flags; |
| 957 | 1003 | ||
| @@ -961,7 +1007,7 @@ static void turn_ints_on (struct specialix_board *bp) | |||
| 961 | /* play with the PCI chip. See comment above. */ | 1007 | /* play with the PCI chip. See comment above. */ |
| 962 | } | 1008 | } |
| 963 | spin_lock_irqsave(&bp->lock, flags); | 1009 | spin_lock_irqsave(&bp->lock, flags); |
| 964 | (void) sx_in (bp, 0); /* Turn ON interrupts. */ | 1010 | (void) sx_in(bp, 0); /* Turn ON interrupts. */ |
| 965 | spin_unlock_irqrestore(&bp->lock, flags); | 1011 | spin_unlock_irqrestore(&bp->lock, flags); |
| 966 | 1012 | ||
| 967 | func_exit(); | 1013 | func_exit(); |
| @@ -969,7 +1015,7 @@ static void turn_ints_on (struct specialix_board *bp) | |||
| 969 | 1015 | ||
| 970 | 1016 | ||
| 971 | /* Called with disabled interrupts */ | 1017 | /* Called with disabled interrupts */ |
| 972 | static inline int sx_setup_board(struct specialix_board * bp) | 1018 | static inline int sx_setup_board(struct specialix_board *bp) |
| 973 | { | 1019 | { |
| 974 | int error; | 1020 | int error; |
| 975 | 1021 | ||
| @@ -977,14 +1023,16 @@ static inline int sx_setup_board(struct specialix_board * bp) | |||
| 977 | return 0; | 1023 | return 0; |
| 978 | 1024 | ||
| 979 | if (bp->flags & SX_BOARD_IS_PCI) | 1025 | if (bp->flags & SX_BOARD_IS_PCI) |
| 980 | error = request_irq(bp->irq, sx_interrupt, IRQF_DISABLED | IRQF_SHARED, "specialix IO8+", bp); | 1026 | error = request_irq(bp->irq, sx_interrupt, |
| 1027 | IRQF_DISABLED | IRQF_SHARED, "specialix IO8+", bp); | ||
| 981 | else | 1028 | else |
| 982 | error = request_irq(bp->irq, sx_interrupt, IRQF_DISABLED, "specialix IO8+", bp); | 1029 | error = request_irq(bp->irq, sx_interrupt, |
| 1030 | IRQF_DISABLED, "specialix IO8+", bp); | ||
| 983 | 1031 | ||
| 984 | if (error) | 1032 | if (error) |
| 985 | return error; | 1033 | return error; |
| 986 | 1034 | ||
| 987 | turn_ints_on (bp); | 1035 | turn_ints_on(bp); |
| 988 | bp->flags |= SX_BOARD_ACTIVE; | 1036 | bp->flags |= SX_BOARD_ACTIVE; |
| 989 | 1037 | ||
| 990 | return 0; | 1038 | return 0; |
| @@ -1003,13 +1051,10 @@ static inline void sx_shutdown_board(struct specialix_board *bp) | |||
| 1003 | 1051 | ||
| 1004 | bp->flags &= ~SX_BOARD_ACTIVE; | 1052 | bp->flags &= ~SX_BOARD_ACTIVE; |
| 1005 | 1053 | ||
| 1006 | dprintk (SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n", | 1054 | dprintk(SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n", |
| 1007 | bp->irq, board_No (bp)); | 1055 | bp->irq, board_No(bp)); |
| 1008 | free_irq(bp->irq, bp); | 1056 | free_irq(bp->irq, bp); |
| 1009 | 1057 | turn_ints_off(bp); | |
| 1010 | turn_ints_off (bp); | ||
| 1011 | |||
| 1012 | |||
| 1013 | func_exit(); | 1058 | func_exit(); |
| 1014 | } | 1059 | } |
| 1015 | 1060 | ||
| @@ -1018,7 +1063,8 @@ static inline void sx_shutdown_board(struct specialix_board *bp) | |||
| 1018 | * Setting up port characteristics. | 1063 | * Setting up port characteristics. |
| 1019 | * Must be called with disabled interrupts | 1064 | * Must be called with disabled interrupts |
| 1020 | */ | 1065 | */ |
| 1021 | static void sx_change_speed(struct specialix_board *bp, struct specialix_port *port) | 1066 | static void sx_change_speed(struct specialix_board *bp, |
| 1067 | struct specialix_port *port) | ||
| 1022 | { | 1068 | { |
| 1023 | struct tty_struct *tty; | 1069 | struct tty_struct *tty; |
| 1024 | unsigned long baud; | 1070 | unsigned long baud; |
| @@ -1030,7 +1076,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
| 1030 | 1076 | ||
| 1031 | func_enter(); | 1077 | func_enter(); |
| 1032 | 1078 | ||
| 1033 | if (!(tty = port->port.tty) || !tty->termios) { | 1079 | tty = port->port.tty; |
| 1080 | if (!tty || !tty->termios) { | ||
| 1034 | func_exit(); | 1081 | func_exit(); |
| 1035 | return; | 1082 | return; |
| 1036 | } | 1083 | } |
| @@ -1048,7 +1095,7 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
| 1048 | else | 1095 | else |
| 1049 | port->MSVR = (sx_in(bp, CD186x_MSVR) & MSVR_RTS); | 1096 | port->MSVR = (sx_in(bp, CD186x_MSVR) & MSVR_RTS); |
| 1050 | spin_unlock_irqrestore(&bp->lock, flags); | 1097 | spin_unlock_irqrestore(&bp->lock, flags); |
| 1051 | dprintk (SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR); | 1098 | dprintk(SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR); |
| 1052 | baud = tty_get_baud_rate(tty); | 1099 | baud = tty_get_baud_rate(tty); |
| 1053 | 1100 | ||
| 1054 | if (baud == 38400) { | 1101 | if (baud == 38400) { |
| @@ -1060,21 +1107,19 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
| 1060 | 1107 | ||
| 1061 | if (!baud) { | 1108 | if (!baud) { |
| 1062 | /* Drop DTR & exit */ | 1109 | /* Drop DTR & exit */ |
| 1063 | dprintk (SX_DEBUG_TERMIOS, "Dropping DTR... Hmm....\n"); | 1110 | dprintk(SX_DEBUG_TERMIOS, "Dropping DTR... Hmm....\n"); |
| 1064 | if (!SX_CRTSCTS (tty)) { | 1111 | if (!SX_CRTSCTS(tty)) { |
| 1065 | port -> MSVR &= ~ MSVR_DTR; | 1112 | port->MSVR &= ~MSVR_DTR; |
| 1066 | spin_lock_irqsave(&bp->lock, flags); | 1113 | spin_lock_irqsave(&bp->lock, flags); |
| 1067 | sx_out(bp, CD186x_MSVR, port->MSVR ); | 1114 | sx_out(bp, CD186x_MSVR, port->MSVR); |
| 1068 | spin_unlock_irqrestore(&bp->lock, flags); | 1115 | spin_unlock_irqrestore(&bp->lock, flags); |
| 1069 | } | 1116 | } else |
| 1070 | else | 1117 | dprintk(SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n"); |
| 1071 | dprintk (SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n"); | ||
| 1072 | return; | 1118 | return; |
| 1073 | } else { | 1119 | } else { |
| 1074 | /* Set DTR on */ | 1120 | /* Set DTR on */ |
| 1075 | if (!SX_CRTSCTS (tty)) { | 1121 | if (!SX_CRTSCTS(tty)) |
| 1076 | port ->MSVR |= MSVR_DTR; | 1122 | port->MSVR |= MSVR_DTR; |
| 1077 | } | ||
| 1078 | } | 1123 | } |
| 1079 | 1124 | ||
| 1080 | /* | 1125 | /* |
| @@ -1083,28 +1128,27 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
| 1083 | 1128 | ||
| 1084 | /* Set baud rate for port */ | 1129 | /* Set baud rate for port */ |
| 1085 | tmp = port->custom_divisor ; | 1130 | tmp = port->custom_divisor ; |
| 1086 | if ( tmp ) | 1131 | if (tmp) |
| 1087 | printk (KERN_INFO "sx%d: Using custom baud rate divisor %ld. \n" | 1132 | printk(KERN_INFO |
| 1088 | "This is an untested option, please be carefull.\n", | 1133 | "sx%d: Using custom baud rate divisor %ld. \n" |
| 1089 | port_No (port), tmp); | 1134 | "This is an untested option, please be careful.\n", |
| 1135 | port_No(port), tmp); | ||
| 1090 | else | 1136 | else |
| 1091 | tmp = (((SX_OSCFREQ + baud/2) / baud + | 1137 | tmp = (((SX_OSCFREQ + baud/2) / baud + CD186x_TPC/2) / |
| 1092 | CD186x_TPC/2) / CD186x_TPC); | 1138 | CD186x_TPC); |
| 1093 | 1139 | ||
| 1094 | if ((tmp < 0x10) && time_before(again, jiffies)) { | 1140 | if (tmp < 0x10 && time_before(again, jiffies)) { |
| 1095 | again = jiffies + HZ * 60; | 1141 | again = jiffies + HZ * 60; |
| 1096 | /* Page 48 of version 2.0 of the CL-CD1865 databook */ | 1142 | /* Page 48 of version 2.0 of the CL-CD1865 databook */ |
| 1097 | if (tmp >= 12) { | 1143 | if (tmp >= 12) { |
| 1098 | printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n" | 1144 | printk(KERN_INFO "sx%d: Baud rate divisor is %ld. \n" |
| 1099 | "Performance degradation is possible.\n" | 1145 | "Performance degradation is possible.\n" |
| 1100 | "Read specialix.txt for more info.\n", | 1146 | "Read specialix.txt for more info.\n", |
| 1101 | port_No (port), tmp); | 1147 | port_No(port), tmp); |
| 1102 | } else { | 1148 | } else { |
| 1103 | printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n" | 1149 | printk(KERN_INFO "sx%d: Baud rate divisor is %ld. \n" |
| 1104 | "Warning: overstressing Cirrus chip. " | 1150 | "Warning: overstressing Cirrus chip. This might not work.\n" |
| 1105 | "This might not work.\n" | 1151 | "Read specialix.txt for more info.\n", port_No(port), tmp); |
| 1106 | "Read specialix.txt for more info.\n", | ||
| 1107 | port_No (port), tmp); | ||
| 1108 | } | 1152 | } |
| 1109 | } | 1153 | } |
| 1110 | spin_lock_irqsave(&bp->lock, flags); | 1154 | spin_lock_irqsave(&bp->lock, flags); |
| @@ -1114,7 +1158,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
| 1114 | sx_out(bp, CD186x_TBPRL, tmp & 0xff); | 1158 | sx_out(bp, CD186x_TBPRL, tmp & 0xff); |
| 1115 | spin_unlock_irqrestore(&bp->lock, flags); | 1159 | spin_unlock_irqrestore(&bp->lock, flags); |
| 1116 | if (port->custom_divisor) | 1160 | if (port->custom_divisor) |
| 1117 | baud = (SX_OSCFREQ + port->custom_divisor/2) / port->custom_divisor; | 1161 | baud = (SX_OSCFREQ + port->custom_divisor/2) / |
| 1162 | port->custom_divisor; | ||
| 1118 | baud = (baud + 5) / 10; /* Estimated CPS */ | 1163 | baud = (baud + 5) / 10; /* Estimated CPS */ |
| 1119 | 1164 | ||
| 1120 | /* Two timer ticks seems enough to wakeup something like SLIP driver */ | 1165 | /* Two timer ticks seems enough to wakeup something like SLIP driver */ |
| @@ -1129,16 +1174,16 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
| 1129 | sx_out(bp, CD186x_RTPR, tmp); | 1174 | sx_out(bp, CD186x_RTPR, tmp); |
| 1130 | spin_unlock_irqrestore(&bp->lock, flags); | 1175 | spin_unlock_irqrestore(&bp->lock, flags); |
| 1131 | switch (C_CSIZE(tty)) { | 1176 | switch (C_CSIZE(tty)) { |
| 1132 | case CS5: | 1177 | case CS5: |
| 1133 | cor1 |= COR1_5BITS; | 1178 | cor1 |= COR1_5BITS; |
| 1134 | break; | 1179 | break; |
| 1135 | case CS6: | 1180 | case CS6: |
| 1136 | cor1 |= COR1_6BITS; | 1181 | cor1 |= COR1_6BITS; |
| 1137 | break; | 1182 | break; |
| 1138 | case CS7: | 1183 | case CS7: |
| 1139 | cor1 |= COR1_7BITS; | 1184 | cor1 |= COR1_7BITS; |
| 1140 | break; | 1185 | break; |
| 1141 | case CS8: | 1186 | case CS8: |
| 1142 | cor1 |= COR1_8BITS; | 1187 | cor1 |= COR1_8BITS; |
| 1143 | break; | 1188 | break; |
| 1144 | } | 1189 | } |
| @@ -1175,7 +1220,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
| 1175 | mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD; | 1220 | mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD; |
| 1176 | mcor2 |= MCOR2_DSROD | MCOR2_CTSOD; | 1221 | mcor2 |= MCOR2_DSROD | MCOR2_CTSOD; |
| 1177 | spin_lock_irqsave(&bp->lock, flags); | 1222 | spin_lock_irqsave(&bp->lock, flags); |
| 1178 | tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) & (MSVR_CTS|MSVR_DSR)); | 1223 | tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) & |
| 1224 | (MSVR_CTS|MSVR_DSR)); | ||
| 1179 | spin_unlock_irqrestore(&bp->lock, flags); | 1225 | spin_unlock_irqrestore(&bp->lock, flags); |
| 1180 | #else | 1226 | #else |
| 1181 | port->COR2 |= COR2_CTSAE; | 1227 | port->COR2 |= COR2_CTSAE; |
| @@ -1219,7 +1265,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
| 1219 | spin_lock_irqsave(&bp->lock, flags); | 1265 | spin_lock_irqsave(&bp->lock, flags); |
| 1220 | sx_out(bp, CD186x_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3); | 1266 | sx_out(bp, CD186x_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3); |
| 1221 | /* Setting up modem option registers */ | 1267 | /* Setting up modem option registers */ |
| 1222 | dprintk (SX_DEBUG_TERMIOS, "Mcor1 = %02x, mcor2 = %02x.\n", mcor1, mcor2); | 1268 | dprintk(SX_DEBUG_TERMIOS, "Mcor1 = %02x, mcor2 = %02x.\n", |
| 1269 | mcor1, mcor2); | ||
| 1223 | sx_out(bp, CD186x_MCOR1, mcor1); | 1270 | sx_out(bp, CD186x_MCOR1, mcor1); |
| 1224 | sx_out(bp, CD186x_MCOR2, mcor2); | 1271 | sx_out(bp, CD186x_MCOR2, mcor2); |
| 1225 | spin_unlock_irqrestore(&bp->lock, flags); | 1272 | spin_unlock_irqrestore(&bp->lock, flags); |
| @@ -1238,7 +1285,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
| 1238 | 1285 | ||
| 1239 | 1286 | ||
| 1240 | /* Must be called with interrupts enabled */ | 1287 | /* Must be called with interrupts enabled */ |
| 1241 | static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port) | 1288 | static int sx_setup_port(struct specialix_board *bp, |
| 1289 | struct specialix_port *port) | ||
| 1242 | { | 1290 | { |
| 1243 | unsigned long flags; | 1291 | unsigned long flags; |
| 1244 | 1292 | ||
| @@ -1253,7 +1301,8 @@ static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port | |||
| 1253 | /* We may sleep in get_zeroed_page() */ | 1301 | /* We may sleep in get_zeroed_page() */ |
| 1254 | unsigned long tmp; | 1302 | unsigned long tmp; |
| 1255 | 1303 | ||
| 1256 | if (!(tmp = get_zeroed_page(GFP_KERNEL))) { | 1304 | tmp = get_zeroed_page(GFP_KERNEL); |
| 1305 | if (tmp == 0L) { | ||
| 1257 | func_exit(); | 1306 | func_exit(); |
| 1258 | return -ENOMEM; | 1307 | return -ENOMEM; |
| 1259 | } | 1308 | } |
| @@ -1284,7 +1333,8 @@ static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port | |||
| 1284 | 1333 | ||
| 1285 | 1334 | ||
| 1286 | /* Must be called with interrupts disabled */ | 1335 | /* Must be called with interrupts disabled */ |
| 1287 | static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port *port) | 1336 | static void sx_shutdown_port(struct specialix_board *bp, |
| 1337 | struct specialix_port *port) | ||
| 1288 | { | 1338 | { |
| 1289 | struct tty_struct *tty; | 1339 | struct tty_struct *tty; |
| 1290 | int i; | 1340 | int i; |
| @@ -1298,11 +1348,11 @@ static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port * | |||
| 1298 | } | 1348 | } |
| 1299 | 1349 | ||
| 1300 | if (sx_debug & SX_DEBUG_FIFO) { | 1350 | if (sx_debug & SX_DEBUG_FIFO) { |
| 1301 | dprintk(SX_DEBUG_FIFO, "sx%d: port %d: %ld overruns, FIFO hits [ ", | 1351 | dprintk(SX_DEBUG_FIFO, |
| 1302 | board_No(bp), port_No(port), port->overrun); | 1352 | "sx%d: port %d: %ld overruns, FIFO hits [ ", |
| 1303 | for (i = 0; i < 10; i++) { | 1353 | board_No(bp), port_No(port), port->overrun); |
| 1354 | for (i = 0; i < 10; i++) | ||
| 1304 | dprintk(SX_DEBUG_FIFO, "%ld ", port->hits[i]); | 1355 | dprintk(SX_DEBUG_FIFO, "%ld ", port->hits[i]); |
| 1305 | } | ||
| 1306 | dprintk(SX_DEBUG_FIFO, "].\n"); | 1356 | dprintk(SX_DEBUG_FIFO, "].\n"); |
| 1307 | } | 1357 | } |
| 1308 | 1358 | ||
| @@ -1315,7 +1365,8 @@ static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port * | |||
| 1315 | spin_lock_irqsave(&bp->lock, flags); | 1365 | spin_lock_irqsave(&bp->lock, flags); |
| 1316 | sx_out(bp, CD186x_CAR, port_No(port)); | 1366 | sx_out(bp, CD186x_CAR, port_No(port)); |
| 1317 | 1367 | ||
| 1318 | if (!(tty = port->port.tty) || C_HUPCL(tty)) { | 1368 | tty = port->port.tty; |
| 1369 | if (tty == NULL || C_HUPCL(tty)) { | ||
| 1319 | /* Drop DTR */ | 1370 | /* Drop DTR */ |
| 1320 | sx_out(bp, CD186x_MSVDTR, 0); | 1371 | sx_out(bp, CD186x_MSVDTR, 0); |
| 1321 | } | 1372 | } |
| @@ -1338,8 +1389,8 @@ static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port * | |||
| 1338 | } | 1389 | } |
| 1339 | 1390 | ||
| 1340 | 1391 | ||
| 1341 | static int block_til_ready(struct tty_struct *tty, struct file * filp, | 1392 | static int block_til_ready(struct tty_struct *tty, struct file *filp, |
| 1342 | struct specialix_port *port) | 1393 | struct specialix_port *port) |
| 1343 | { | 1394 | { |
| 1344 | DECLARE_WAITQUEUE(wait, current); | 1395 | DECLARE_WAITQUEUE(wait, current); |
| 1345 | struct specialix_board *bp = port_Board(port); | 1396 | struct specialix_board *bp = port_Board(port); |
| @@ -1389,23 +1440,22 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
| 1389 | retval = 0; | 1440 | retval = 0; |
| 1390 | add_wait_queue(&port->port.open_wait, &wait); | 1441 | add_wait_queue(&port->port.open_wait, &wait); |
| 1391 | spin_lock_irqsave(&port->lock, flags); | 1442 | spin_lock_irqsave(&port->lock, flags); |
| 1392 | if (!tty_hung_up_p(filp)) { | 1443 | if (!tty_hung_up_p(filp)) |
| 1393 | port->port.count--; | 1444 | port->port.count--; |
| 1394 | } | ||
| 1395 | spin_unlock_irqrestore(&port->lock, flags); | 1445 | spin_unlock_irqrestore(&port->lock, flags); |
| 1396 | port->port.blocked_open++; | 1446 | port->port.blocked_open++; |
| 1397 | while (1) { | 1447 | while (1) { |
| 1398 | spin_lock_irqsave(&bp->lock, flags); | 1448 | spin_lock_irqsave(&bp->lock, flags); |
| 1399 | sx_out(bp, CD186x_CAR, port_No(port)); | 1449 | sx_out(bp, CD186x_CAR, port_No(port)); |
| 1400 | CD = sx_in(bp, CD186x_MSVR) & MSVR_CD; | 1450 | CD = sx_in(bp, CD186x_MSVR) & MSVR_CD; |
| 1401 | if (SX_CRTSCTS (tty)) { | 1451 | if (SX_CRTSCTS(tty)) { |
| 1402 | /* Activate RTS */ | 1452 | /* Activate RTS */ |
| 1403 | port->MSVR |= MSVR_DTR; /* WTF? */ | 1453 | port->MSVR |= MSVR_DTR; /* WTF? */ |
| 1404 | sx_out (bp, CD186x_MSVR, port->MSVR); | 1454 | sx_out(bp, CD186x_MSVR, port->MSVR); |
| 1405 | } else { | 1455 | } else { |
| 1406 | /* Activate DTR */ | 1456 | /* Activate DTR */ |
| 1407 | port->MSVR |= MSVR_DTR; | 1457 | port->MSVR |= MSVR_DTR; |
| 1408 | sx_out (bp, CD186x_MSVR, port->MSVR); | 1458 | sx_out(bp, CD186x_MSVR, port->MSVR); |
| 1409 | } | 1459 | } |
| 1410 | spin_unlock_irqrestore(&bp->lock, flags); | 1460 | spin_unlock_irqrestore(&bp->lock, flags); |
| 1411 | set_current_state(TASK_INTERRUPTIBLE); | 1461 | set_current_state(TASK_INTERRUPTIBLE); |
| @@ -1430,9 +1480,8 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
| 1430 | set_current_state(TASK_RUNNING); | 1480 | set_current_state(TASK_RUNNING); |
| 1431 | remove_wait_queue(&port->port.open_wait, &wait); | 1481 | remove_wait_queue(&port->port.open_wait, &wait); |
| 1432 | spin_lock_irqsave(&port->lock, flags); | 1482 | spin_lock_irqsave(&port->lock, flags); |
| 1433 | if (!tty_hung_up_p(filp)) { | 1483 | if (!tty_hung_up_p(filp)) |
| 1434 | port->port.count++; | 1484 | port->port.count++; |
| 1435 | } | ||
| 1436 | port->port.blocked_open--; | 1485 | port->port.blocked_open--; |
| 1437 | spin_unlock_irqrestore(&port->lock, flags); | 1486 | spin_unlock_irqrestore(&port->lock, flags); |
| 1438 | if (retval) { | 1487 | if (retval) { |
| @@ -1446,12 +1495,12 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
| 1446 | } | 1495 | } |
| 1447 | 1496 | ||
| 1448 | 1497 | ||
| 1449 | static int sx_open(struct tty_struct * tty, struct file * filp) | 1498 | static int sx_open(struct tty_struct *tty, struct file *filp) |
| 1450 | { | 1499 | { |
| 1451 | int board; | 1500 | int board; |
| 1452 | int error; | 1501 | int error; |
| 1453 | struct specialix_port * port; | 1502 | struct specialix_port *port; |
| 1454 | struct specialix_board * bp; | 1503 | struct specialix_board *bp; |
| 1455 | int i; | 1504 | int i; |
| 1456 | unsigned long flags; | 1505 | unsigned long flags; |
| 1457 | 1506 | ||
| @@ -1468,17 +1517,19 @@ static int sx_open(struct tty_struct * tty, struct file * filp) | |||
| 1468 | port = sx_port + board * SX_NPORT + SX_PORT(tty->index); | 1517 | port = sx_port + board * SX_NPORT + SX_PORT(tty->index); |
| 1469 | port->overrun = 0; | 1518 | port->overrun = 0; |
| 1470 | for (i = 0; i < 10; i++) | 1519 | for (i = 0; i < 10; i++) |
| 1471 | port->hits[i]=0; | 1520 | port->hits[i] = 0; |
| 1472 | 1521 | ||
| 1473 | dprintk (SX_DEBUG_OPEN, "Board = %d, bp = %p, port = %p, portno = %d.\n", | 1522 | dprintk(SX_DEBUG_OPEN, |
| 1474 | board, bp, port, SX_PORT(tty->index)); | 1523 | "Board = %d, bp = %p, port = %p, portno = %d.\n", |
| 1524 | board, bp, port, SX_PORT(tty->index)); | ||
| 1475 | 1525 | ||
| 1476 | if (sx_paranoia_check(port, tty->name, "sx_open")) { | 1526 | if (sx_paranoia_check(port, tty->name, "sx_open")) { |
| 1477 | func_enter(); | 1527 | func_enter(); |
| 1478 | return -ENODEV; | 1528 | return -ENODEV; |
| 1479 | } | 1529 | } |
| 1480 | 1530 | ||
| 1481 | if ((error = sx_setup_board(bp))) { | 1531 | error = sx_setup_board(bp); |
| 1532 | if (error) { | ||
| 1482 | func_exit(); | 1533 | func_exit(); |
| 1483 | return error; | 1534 | return error; |
| 1484 | } | 1535 | } |
| @@ -1490,12 +1541,14 @@ static int sx_open(struct tty_struct * tty, struct file * filp) | |||
| 1490 | port->port.tty = tty; | 1541 | port->port.tty = tty; |
| 1491 | spin_unlock_irqrestore(&bp->lock, flags); | 1542 | spin_unlock_irqrestore(&bp->lock, flags); |
| 1492 | 1543 | ||
| 1493 | if ((error = sx_setup_port(bp, port))) { | 1544 | error = sx_setup_port(bp, port); |
| 1545 | if (error) { | ||
| 1494 | func_enter(); | 1546 | func_enter(); |
| 1495 | return error; | 1547 | return error; |
| 1496 | } | 1548 | } |
| 1497 | 1549 | ||
| 1498 | if ((error = block_til_ready(tty, filp, port))) { | 1550 | error = block_til_ready(tty, filp, port); |
| 1551 | if (error) { | ||
| 1499 | func_enter(); | 1552 | func_enter(); |
| 1500 | return error; | 1553 | return error; |
| 1501 | } | 1554 | } |
| @@ -1508,7 +1561,7 @@ static void sx_flush_buffer(struct tty_struct *tty) | |||
| 1508 | { | 1561 | { |
| 1509 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 1562 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
| 1510 | unsigned long flags; | 1563 | unsigned long flags; |
| 1511 | struct specialix_board * bp; | 1564 | struct specialix_board *bp; |
| 1512 | 1565 | ||
| 1513 | func_enter(); | 1566 | func_enter(); |
| 1514 | 1567 | ||
| @@ -1526,9 +1579,9 @@ static void sx_flush_buffer(struct tty_struct *tty) | |||
| 1526 | func_exit(); | 1579 | func_exit(); |
| 1527 | } | 1580 | } |
| 1528 | 1581 | ||
| 1529 | static void sx_close(struct tty_struct * tty, struct file * filp) | 1582 | static void sx_close(struct tty_struct *tty, struct file *filp) |
| 1530 | { | 1583 | { |
| 1531 | struct specialix_port *port = (struct specialix_port *) tty->driver_data; | 1584 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
| 1532 | struct specialix_board *bp; | 1585 | struct specialix_board *bp; |
| 1533 | unsigned long flags; | 1586 | unsigned long flags; |
| 1534 | unsigned long timeout; | 1587 | unsigned long timeout; |
| @@ -1570,17 +1623,16 @@ static void sx_close(struct tty_struct * tty, struct file * filp) | |||
| 1570 | */ | 1623 | */ |
| 1571 | tty->closing = 1; | 1624 | tty->closing = 1; |
| 1572 | spin_unlock_irqrestore(&port->lock, flags); | 1625 | spin_unlock_irqrestore(&port->lock, flags); |
| 1573 | dprintk (SX_DEBUG_OPEN, "Closing\n"); | 1626 | dprintk(SX_DEBUG_OPEN, "Closing\n"); |
| 1574 | if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) { | 1627 | if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) |
| 1575 | tty_wait_until_sent(tty, port->port.closing_wait); | 1628 | tty_wait_until_sent(tty, port->port.closing_wait); |
| 1576 | } | ||
| 1577 | /* | 1629 | /* |
| 1578 | * At this point we stop accepting input. To do this, we | 1630 | * At this point we stop accepting input. To do this, we |
| 1579 | * disable the receive line status interrupts, and tell the | 1631 | * disable the receive line status interrupts, and tell the |
| 1580 | * interrupt driver to stop checking the data ready bit in the | 1632 | * interrupt driver to stop checking the data ready bit in the |
| 1581 | * line status register. | 1633 | * line status register. |
| 1582 | */ | 1634 | */ |
| 1583 | dprintk (SX_DEBUG_OPEN, "Closed\n"); | 1635 | dprintk(SX_DEBUG_OPEN, "Closed\n"); |
| 1584 | port->IER &= ~IER_RXD; | 1636 | port->IER &= ~IER_RXD; |
| 1585 | if (port->port.flags & ASYNC_INITIALIZED) { | 1637 | if (port->port.flags & ASYNC_INITIALIZED) { |
| 1586 | port->IER &= ~IER_TXRDY; | 1638 | port->IER &= ~IER_TXRDY; |
| @@ -1595,11 +1647,11 @@ static void sx_close(struct tty_struct * tty, struct file * filp) | |||
| 1595 | * important if there is a transmit FIFO! | 1647 | * important if there is a transmit FIFO! |
| 1596 | */ | 1648 | */ |
| 1597 | timeout = jiffies+HZ; | 1649 | timeout = jiffies+HZ; |
| 1598 | while(port->IER & IER_TXEMPTY) { | 1650 | while (port->IER & IER_TXEMPTY) { |
| 1599 | set_current_state (TASK_INTERRUPTIBLE); | 1651 | set_current_state(TASK_INTERRUPTIBLE); |
| 1600 | msleep_interruptible(jiffies_to_msecs(port->timeout)); | 1652 | msleep_interruptible(jiffies_to_msecs(port->timeout)); |
| 1601 | if (time_after(jiffies, timeout)) { | 1653 | if (time_after(jiffies, timeout)) { |
| 1602 | printk (KERN_INFO "Timeout waiting for close\n"); | 1654 | printk(KERN_INFO "Timeout waiting for close\n"); |
| 1603 | break; | 1655 | break; |
| 1604 | } | 1656 | } |
| 1605 | } | 1657 | } |
| @@ -1607,13 +1659,15 @@ static void sx_close(struct tty_struct * tty, struct file * filp) | |||
| 1607 | } | 1659 | } |
| 1608 | 1660 | ||
| 1609 | if (--bp->count < 0) { | 1661 | if (--bp->count < 0) { |
| 1610 | printk(KERN_ERR "sx%d: sx_shutdown_port: bad board count: %d port: %d\n", | 1662 | printk(KERN_ERR |
| 1611 | board_No(bp), bp->count, tty->index); | 1663 | "sx%d: sx_shutdown_port: bad board count: %d port: %d\n", |
| 1664 | board_No(bp), bp->count, tty->index); | ||
| 1612 | bp->count = 0; | 1665 | bp->count = 0; |
| 1613 | } | 1666 | } |
| 1614 | if (--port->port.count < 0) { | 1667 | if (--port->port.count < 0) { |
| 1615 | printk(KERN_ERR "sx%d: sx_close: bad port count for tty%d: %d\n", | 1668 | printk(KERN_ERR |
| 1616 | board_No(bp), port_No(port), port->port.count); | 1669 | "sx%d: sx_close: bad port count for tty%d: %d\n", |
| 1670 | board_No(bp), port_No(port), port->port.count); | ||
| 1617 | port->port.count = 0; | 1671 | port->port.count = 0; |
| 1618 | } | 1672 | } |
| 1619 | 1673 | ||
| @@ -1625,9 +1679,9 @@ static void sx_close(struct tty_struct * tty, struct file * filp) | |||
| 1625 | port->port.tty = NULL; | 1679 | port->port.tty = NULL; |
| 1626 | spin_unlock_irqrestore(&port->lock, flags); | 1680 | spin_unlock_irqrestore(&port->lock, flags); |
| 1627 | if (port->port.blocked_open) { | 1681 | if (port->port.blocked_open) { |
| 1628 | if (port->port.close_delay) { | 1682 | if (port->port.close_delay) |
| 1629 | msleep_interruptible(jiffies_to_msecs(port->port.close_delay)); | 1683 | msleep_interruptible( |
| 1630 | } | 1684 | jiffies_to_msecs(port->port.close_delay)); |
| 1631 | wake_up_interruptible(&port->port.open_wait); | 1685 | wake_up_interruptible(&port->port.open_wait); |
| 1632 | } | 1686 | } |
| 1633 | port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | 1687 | port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); |
| @@ -1637,8 +1691,8 @@ static void sx_close(struct tty_struct * tty, struct file * filp) | |||
| 1637 | } | 1691 | } |
| 1638 | 1692 | ||
| 1639 | 1693 | ||
| 1640 | static int sx_write(struct tty_struct * tty, | 1694 | static int sx_write(struct tty_struct *tty, |
| 1641 | const unsigned char *buf, int count) | 1695 | const unsigned char *buf, int count) |
| 1642 | { | 1696 | { |
| 1643 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 1697 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
| 1644 | struct specialix_board *bp; | 1698 | struct specialix_board *bp; |
| @@ -1690,11 +1744,11 @@ static int sx_write(struct tty_struct * tty, | |||
| 1690 | } | 1744 | } |
| 1691 | 1745 | ||
| 1692 | 1746 | ||
| 1693 | static int sx_put_char(struct tty_struct * tty, unsigned char ch) | 1747 | static int sx_put_char(struct tty_struct *tty, unsigned char ch) |
| 1694 | { | 1748 | { |
| 1695 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 1749 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
| 1696 | unsigned long flags; | 1750 | unsigned long flags; |
| 1697 | struct specialix_board * bp; | 1751 | struct specialix_board *bp; |
| 1698 | 1752 | ||
| 1699 | func_enter(); | 1753 | func_enter(); |
| 1700 | 1754 | ||
| @@ -1702,7 +1756,7 @@ static int sx_put_char(struct tty_struct * tty, unsigned char ch) | |||
| 1702 | func_exit(); | 1756 | func_exit(); |
| 1703 | return 0; | 1757 | return 0; |
| 1704 | } | 1758 | } |
| 1705 | dprintk (SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf); | 1759 | dprintk(SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf); |
| 1706 | if (!port->xmit_buf) { | 1760 | if (!port->xmit_buf) { |
| 1707 | func_exit(); | 1761 | func_exit(); |
| 1708 | return 0; | 1762 | return 0; |
| @@ -1710,14 +1764,15 @@ static int sx_put_char(struct tty_struct * tty, unsigned char ch) | |||
| 1710 | bp = port_Board(port); | 1764 | bp = port_Board(port); |
| 1711 | spin_lock_irqsave(&port->lock, flags); | 1765 | spin_lock_irqsave(&port->lock, flags); |
| 1712 | 1766 | ||
| 1713 | dprintk (SX_DEBUG_TX, "xmit_cnt: %d xmit_buf: %p\n", port->xmit_cnt, port->xmit_buf); | 1767 | dprintk(SX_DEBUG_TX, "xmit_cnt: %d xmit_buf: %p\n", |
| 1714 | if ((port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) || (!port->xmit_buf)) { | 1768 | port->xmit_cnt, port->xmit_buf); |
| 1769 | if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1 || !port->xmit_buf) { | ||
| 1715 | spin_unlock_irqrestore(&port->lock, flags); | 1770 | spin_unlock_irqrestore(&port->lock, flags); |
| 1716 | dprintk (SX_DEBUG_TX, "Exit size\n"); | 1771 | dprintk(SX_DEBUG_TX, "Exit size\n"); |
| 1717 | func_exit(); | 1772 | func_exit(); |
| 1718 | return 0; | 1773 | return 0; |
| 1719 | } | 1774 | } |
| 1720 | dprintk (SX_DEBUG_TX, "Handle xmit: %p %p\n", port, port->xmit_buf); | 1775 | dprintk(SX_DEBUG_TX, "Handle xmit: %p %p\n", port, port->xmit_buf); |
| 1721 | port->xmit_buf[port->xmit_head++] = ch; | 1776 | port->xmit_buf[port->xmit_head++] = ch; |
| 1722 | port->xmit_head &= SERIAL_XMIT_SIZE - 1; | 1777 | port->xmit_head &= SERIAL_XMIT_SIZE - 1; |
| 1723 | port->xmit_cnt++; | 1778 | port->xmit_cnt++; |
| @@ -1728,11 +1783,11 @@ static int sx_put_char(struct tty_struct * tty, unsigned char ch) | |||
| 1728 | } | 1783 | } |
| 1729 | 1784 | ||
| 1730 | 1785 | ||
| 1731 | static void sx_flush_chars(struct tty_struct * tty) | 1786 | static void sx_flush_chars(struct tty_struct *tty) |
| 1732 | { | 1787 | { |
| 1733 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 1788 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
| 1734 | unsigned long flags; | 1789 | unsigned long flags; |
| 1735 | struct specialix_board * bp = port_Board(port); | 1790 | struct specialix_board *bp = port_Board(port); |
| 1736 | 1791 | ||
| 1737 | func_enter(); | 1792 | func_enter(); |
| 1738 | 1793 | ||
| @@ -1755,7 +1810,7 @@ static void sx_flush_chars(struct tty_struct * tty) | |||
| 1755 | } | 1810 | } |
| 1756 | 1811 | ||
| 1757 | 1812 | ||
| 1758 | static int sx_write_room(struct tty_struct * tty) | 1813 | static int sx_write_room(struct tty_struct *tty) |
| 1759 | { | 1814 | { |
| 1760 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 1815 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
| 1761 | int ret; | 1816 | int ret; |
| @@ -1790,12 +1845,10 @@ static int sx_chars_in_buffer(struct tty_struct *tty) | |||
| 1790 | return port->xmit_cnt; | 1845 | return port->xmit_cnt; |
| 1791 | } | 1846 | } |
| 1792 | 1847 | ||
| 1793 | |||
| 1794 | |||
| 1795 | static int sx_tiocmget(struct tty_struct *tty, struct file *file) | 1848 | static int sx_tiocmget(struct tty_struct *tty, struct file *file) |
| 1796 | { | 1849 | { |
| 1797 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 1850 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
| 1798 | struct specialix_board * bp; | 1851 | struct specialix_board *bp; |
| 1799 | unsigned char status; | 1852 | unsigned char status; |
| 1800 | unsigned int result; | 1853 | unsigned int result; |
| 1801 | unsigned long flags; | 1854 | unsigned long flags; |
| @@ -1808,25 +1861,25 @@ static int sx_tiocmget(struct tty_struct *tty, struct file *file) | |||
| 1808 | } | 1861 | } |
| 1809 | 1862 | ||
| 1810 | bp = port_Board(port); | 1863 | bp = port_Board(port); |
| 1811 | spin_lock_irqsave (&bp->lock, flags); | 1864 | spin_lock_irqsave(&bp->lock, flags); |
| 1812 | sx_out(bp, CD186x_CAR, port_No(port)); | 1865 | sx_out(bp, CD186x_CAR, port_No(port)); |
| 1813 | status = sx_in(bp, CD186x_MSVR); | 1866 | status = sx_in(bp, CD186x_MSVR); |
| 1814 | spin_unlock_irqrestore(&bp->lock, flags); | 1867 | spin_unlock_irqrestore(&bp->lock, flags); |
| 1815 | dprintk (SX_DEBUG_INIT, "Got msvr[%d] = %02x, car = %d.\n", | 1868 | dprintk(SX_DEBUG_INIT, "Got msvr[%d] = %02x, car = %d.\n", |
| 1816 | port_No(port), status, sx_in (bp, CD186x_CAR)); | 1869 | port_No(port), status, sx_in(bp, CD186x_CAR)); |
| 1817 | dprintk (SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port); | 1870 | dprintk(SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port); |
| 1818 | if (SX_CRTSCTS(port->port.tty)) { | 1871 | if (SX_CRTSCTS(port->port.tty)) { |
| 1819 | result = /* (status & MSVR_RTS) ? */ TIOCM_DTR /* : 0) */ | 1872 | result = /* (status & MSVR_RTS) ? */ TIOCM_DTR /* : 0) */ |
| 1820 | | ((status & MSVR_DTR) ? TIOCM_RTS : 0) | 1873 | | ((status & MSVR_DTR) ? TIOCM_RTS : 0) |
| 1821 | | ((status & MSVR_CD) ? TIOCM_CAR : 0) | 1874 | | ((status & MSVR_CD) ? TIOCM_CAR : 0) |
| 1822 | |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */ | 1875 | |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */ |
| 1823 | | ((status & MSVR_CTS) ? TIOCM_CTS : 0); | 1876 | | ((status & MSVR_CTS) ? TIOCM_CTS : 0); |
| 1824 | } else { | 1877 | } else { |
| 1825 | result = /* (status & MSVR_RTS) ? */ TIOCM_RTS /* : 0) */ | 1878 | result = /* (status & MSVR_RTS) ? */ TIOCM_RTS /* : 0) */ |
| 1826 | | ((status & MSVR_DTR) ? TIOCM_DTR : 0) | 1879 | | ((status & MSVR_DTR) ? TIOCM_DTR : 0) |
| 1827 | | ((status & MSVR_CD) ? TIOCM_CAR : 0) | 1880 | | ((status & MSVR_CD) ? TIOCM_CAR : 0) |
| 1828 | |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */ | 1881 | |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */ |
| 1829 | | ((status & MSVR_CTS) ? TIOCM_CTS : 0); | 1882 | | ((status & MSVR_CTS) ? TIOCM_CTS : 0); |
| 1830 | } | 1883 | } |
| 1831 | 1884 | ||
| 1832 | func_exit(); | 1885 | func_exit(); |
| @@ -1886,14 +1939,15 @@ static int sx_tiocmset(struct tty_struct *tty, struct file *file, | |||
| 1886 | } | 1939 | } |
| 1887 | 1940 | ||
| 1888 | 1941 | ||
| 1889 | static inline void sx_send_break(struct specialix_port * port, unsigned long length) | 1942 | static inline void sx_send_break(struct specialix_port *port, |
| 1943 | unsigned long length) | ||
| 1890 | { | 1944 | { |
| 1891 | struct specialix_board *bp = port_Board(port); | 1945 | struct specialix_board *bp = port_Board(port); |
| 1892 | unsigned long flags; | 1946 | unsigned long flags; |
| 1893 | 1947 | ||
| 1894 | func_enter(); | 1948 | func_enter(); |
| 1895 | 1949 | ||
| 1896 | spin_lock_irqsave (&port->lock, flags); | 1950 | spin_lock_irqsave(&port->lock, flags); |
| 1897 | port->break_length = SPECIALIX_TPS / HZ * length; | 1951 | port->break_length = SPECIALIX_TPS / HZ * length; |
| 1898 | port->COR2 |= COR2_ETC; | 1952 | port->COR2 |= COR2_ETC; |
| 1899 | port->IER |= IER_TXRDY; | 1953 | port->IER |= IER_TXRDY; |
| @@ -1902,7 +1956,7 @@ static inline void sx_send_break(struct specialix_port * port, unsigned long len | |||
| 1902 | sx_out(bp, CD186x_COR2, port->COR2); | 1956 | sx_out(bp, CD186x_COR2, port->COR2); |
| 1903 | sx_out(bp, CD186x_IER, port->IER); | 1957 | sx_out(bp, CD186x_IER, port->IER); |
| 1904 | spin_unlock_irqrestore(&bp->lock, flags); | 1958 | spin_unlock_irqrestore(&bp->lock, flags); |
| 1905 | spin_unlock_irqrestore (&port->lock, flags); | 1959 | spin_unlock_irqrestore(&port->lock, flags); |
| 1906 | sx_wait_CCR(bp); | 1960 | sx_wait_CCR(bp); |
| 1907 | spin_lock_irqsave(&bp->lock, flags); | 1961 | spin_lock_irqsave(&bp->lock, flags); |
| 1908 | sx_out(bp, CD186x_CCR, CCR_CORCHG2); | 1962 | sx_out(bp, CD186x_CCR, CCR_CORCHG2); |
| @@ -1913,8 +1967,8 @@ static inline void sx_send_break(struct specialix_port * port, unsigned long len | |||
| 1913 | } | 1967 | } |
| 1914 | 1968 | ||
| 1915 | 1969 | ||
| 1916 | static inline int sx_set_serial_info(struct specialix_port * port, | 1970 | static inline int sx_set_serial_info(struct specialix_port *port, |
| 1917 | struct serial_struct __user * newinfo) | 1971 | struct serial_struct __user *newinfo) |
| 1918 | { | 1972 | { |
| 1919 | struct serial_struct tmp; | 1973 | struct serial_struct tmp; |
| 1920 | struct specialix_board *bp = port_Board(port); | 1974 | struct specialix_board *bp = port_Board(port); |
| @@ -1943,25 +1997,25 @@ static inline int sx_set_serial_info(struct specialix_port * port, | |||
| 1943 | return -EPERM; | 1997 | return -EPERM; |
| 1944 | } | 1998 | } |
| 1945 | port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | | 1999 | port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | |
| 1946 | (tmp.flags & ASYNC_USR_MASK)); | 2000 | (tmp.flags & ASYNC_USR_MASK)); |
| 1947 | port->custom_divisor = tmp.custom_divisor; | 2001 | port->custom_divisor = tmp.custom_divisor; |
| 1948 | } else { | 2002 | } else { |
| 1949 | port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) | | 2003 | port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) | |
| 1950 | (tmp.flags & ASYNC_FLAGS)); | 2004 | (tmp.flags & ASYNC_FLAGS)); |
| 1951 | port->port.close_delay = tmp.close_delay; | 2005 | port->port.close_delay = tmp.close_delay; |
| 1952 | port->port.closing_wait = tmp.closing_wait; | 2006 | port->port.closing_wait = tmp.closing_wait; |
| 1953 | port->custom_divisor = tmp.custom_divisor; | 2007 | port->custom_divisor = tmp.custom_divisor; |
| 1954 | } | 2008 | } |
| 1955 | if (change_speed) { | 2009 | if (change_speed) |
| 1956 | sx_change_speed(bp, port); | 2010 | sx_change_speed(bp, port); |
| 1957 | } | 2011 | |
| 1958 | func_exit(); | 2012 | func_exit(); |
| 1959 | unlock_kernel(); | 2013 | unlock_kernel(); |
| 1960 | return 0; | 2014 | return 0; |
| 1961 | } | 2015 | } |
| 1962 | 2016 | ||
| 1963 | 2017 | ||
| 1964 | static inline int sx_get_serial_info(struct specialix_port * port, | 2018 | static inline int sx_get_serial_info(struct specialix_port *port, |
| 1965 | struct serial_struct __user *retinfo) | 2019 | struct serial_struct __user *retinfo) |
| 1966 | { | 2020 | { |
| 1967 | struct serial_struct tmp; | 2021 | struct serial_struct tmp; |
| @@ -1992,8 +2046,8 @@ static inline int sx_get_serial_info(struct specialix_port * port, | |||
| 1992 | } | 2046 | } |
| 1993 | 2047 | ||
| 1994 | 2048 | ||
| 1995 | static int sx_ioctl(struct tty_struct * tty, struct file * filp, | 2049 | static int sx_ioctl(struct tty_struct *tty, struct file *filp, |
| 1996 | unsigned int cmd, unsigned long arg) | 2050 | unsigned int cmd, unsigned long arg) |
| 1997 | { | 2051 | { |
| 1998 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 2052 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
| 1999 | int retval; | 2053 | int retval; |
| @@ -2007,7 +2061,7 @@ static int sx_ioctl(struct tty_struct * tty, struct file * filp, | |||
| 2007 | } | 2061 | } |
| 2008 | 2062 | ||
| 2009 | switch (cmd) { | 2063 | switch (cmd) { |
| 2010 | case TCSBRK: /* SVID version: non-zero arg --> no break */ | 2064 | case TCSBRK: /* SVID version: non-zero arg --> no break */ |
| 2011 | retval = tty_check_change(tty); | 2065 | retval = tty_check_change(tty); |
| 2012 | if (retval) { | 2066 | if (retval) { |
| 2013 | func_exit(); | 2067 | func_exit(); |
| @@ -2017,7 +2071,7 @@ static int sx_ioctl(struct tty_struct * tty, struct file * filp, | |||
| 2017 | if (!arg) | 2071 | if (!arg) |
| 2018 | sx_send_break(port, HZ/4); /* 1/4 second */ | 2072 | sx_send_break(port, HZ/4); /* 1/4 second */ |
| 2019 | return 0; | 2073 | return 0; |
| 2020 | case TCSBRKP: /* support for POSIX tcsendbreak() */ | 2074 | case TCSBRKP: /* support for POSIX tcsendbreak() */ |
| 2021 | retval = tty_check_change(tty); | 2075 | retval = tty_check_change(tty); |
| 2022 | if (retval) { | 2076 | if (retval) { |
| 2023 | func_exit(); | 2077 | func_exit(); |
| @@ -2027,13 +2081,13 @@ static int sx_ioctl(struct tty_struct * tty, struct file * filp, | |||
| 2027 | sx_send_break(port, arg ? arg*(HZ/10) : HZ/4); | 2081 | sx_send_break(port, arg ? arg*(HZ/10) : HZ/4); |
| 2028 | func_exit(); | 2082 | func_exit(); |
| 2029 | return 0; | 2083 | return 0; |
| 2030 | case TIOCGSERIAL: | 2084 | case TIOCGSERIAL: |
| 2031 | func_exit(); | 2085 | func_exit(); |
| 2032 | return sx_get_serial_info(port, argp); | 2086 | return sx_get_serial_info(port, argp); |
| 2033 | case TIOCSSERIAL: | 2087 | case TIOCSSERIAL: |
| 2034 | func_exit(); | 2088 | func_exit(); |
| 2035 | return sx_set_serial_info(port, argp); | 2089 | return sx_set_serial_info(port, argp); |
| 2036 | default: | 2090 | default: |
| 2037 | func_exit(); | 2091 | func_exit(); |
| 2038 | return -ENOIOCTLCMD; | 2092 | return -ENOIOCTLCMD; |
| 2039 | } | 2093 | } |
| @@ -2042,7 +2096,7 @@ static int sx_ioctl(struct tty_struct * tty, struct file * filp, | |||
| 2042 | } | 2096 | } |
| 2043 | 2097 | ||
| 2044 | 2098 | ||
| 2045 | static void sx_throttle(struct tty_struct * tty) | 2099 | static void sx_throttle(struct tty_struct *tty) |
| 2046 | { | 2100 | { |
| 2047 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 2101 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
| 2048 | struct specialix_board *bp; | 2102 | struct specialix_board *bp; |
| @@ -2058,15 +2112,16 @@ static void sx_throttle(struct tty_struct * tty) | |||
| 2058 | bp = port_Board(port); | 2112 | bp = port_Board(port); |
| 2059 | 2113 | ||
| 2060 | /* Use DTR instead of RTS ! */ | 2114 | /* Use DTR instead of RTS ! */ |
| 2061 | if (SX_CRTSCTS (tty)) | 2115 | if (SX_CRTSCTS(tty)) |
| 2062 | port->MSVR &= ~MSVR_DTR; | 2116 | port->MSVR &= ~MSVR_DTR; |
| 2063 | else { | 2117 | else { |
| 2064 | /* Auch!!! I think the system shouldn't call this then. */ | 2118 | /* Auch!!! I think the system shouldn't call this then. */ |
| 2065 | /* Or maybe we're supposed (allowed?) to do our side of hw | 2119 | /* Or maybe we're supposed (allowed?) to do our side of hw |
| 2066 | handshake anyway, even when hardware handshake is off. | 2120 | handshake anyway, even when hardware handshake is off. |
| 2067 | When you see this in your logs, please report.... */ | 2121 | When you see this in your logs, please report.... */ |
| 2068 | printk (KERN_ERR "sx%d: Need to throttle, but can't (hardware hs is off)\n", | 2122 | printk(KERN_ERR |
| 2069 | port_No (port)); | 2123 | "sx%d: Need to throttle, but can't (hardware hs is off)\n", |
| 2124 | port_No(port)); | ||
| 2070 | } | 2125 | } |
| 2071 | spin_lock_irqsave(&bp->lock, flags); | 2126 | spin_lock_irqsave(&bp->lock, flags); |
| 2072 | sx_out(bp, CD186x_CAR, port_No(port)); | 2127 | sx_out(bp, CD186x_CAR, port_No(port)); |
| @@ -2086,7 +2141,7 @@ static void sx_throttle(struct tty_struct * tty) | |||
| 2086 | } | 2141 | } |
| 2087 | 2142 | ||
| 2088 | 2143 | ||
| 2089 | static void sx_unthrottle(struct tty_struct * tty) | 2144 | static void sx_unthrottle(struct tty_struct *tty) |
| 2090 | { | 2145 | { |
| 2091 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 2146 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
| 2092 | struct specialix_board *bp; | 2147 | struct specialix_board *bp; |
| @@ -2103,9 +2158,9 @@ static void sx_unthrottle(struct tty_struct * tty) | |||
| 2103 | 2158 | ||
| 2104 | spin_lock_irqsave(&port->lock, flags); | 2159 | spin_lock_irqsave(&port->lock, flags); |
| 2105 | /* XXXX Use DTR INSTEAD???? */ | 2160 | /* XXXX Use DTR INSTEAD???? */ |
| 2106 | if (SX_CRTSCTS(tty)) { | 2161 | if (SX_CRTSCTS(tty)) |
| 2107 | port->MSVR |= MSVR_DTR; | 2162 | port->MSVR |= MSVR_DTR; |
| 2108 | } /* Else clause: see remark in "sx_throttle"... */ | 2163 | /* Else clause: see remark in "sx_throttle"... */ |
| 2109 | spin_lock_irqsave(&bp->lock, flags); | 2164 | spin_lock_irqsave(&bp->lock, flags); |
| 2110 | sx_out(bp, CD186x_CAR, port_No(port)); | 2165 | sx_out(bp, CD186x_CAR, port_No(port)); |
| 2111 | spin_unlock_irqrestore(&bp->lock, flags); | 2166 | spin_unlock_irqrestore(&bp->lock, flags); |
| @@ -2127,7 +2182,7 @@ static void sx_unthrottle(struct tty_struct * tty) | |||
| 2127 | } | 2182 | } |
| 2128 | 2183 | ||
| 2129 | 2184 | ||
| 2130 | static void sx_stop(struct tty_struct * tty) | 2185 | static void sx_stop(struct tty_struct *tty) |
| 2131 | { | 2186 | { |
| 2132 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 2187 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
| 2133 | struct specialix_board *bp; | 2188 | struct specialix_board *bp; |
| @@ -2154,7 +2209,7 @@ static void sx_stop(struct tty_struct * tty) | |||
| 2154 | } | 2209 | } |
| 2155 | 2210 | ||
| 2156 | 2211 | ||
| 2157 | static void sx_start(struct tty_struct * tty) | 2212 | static void sx_start(struct tty_struct *tty) |
| 2158 | { | 2213 | { |
| 2159 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 2214 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
| 2160 | struct specialix_board *bp; | 2215 | struct specialix_board *bp; |
| @@ -2182,7 +2237,7 @@ static void sx_start(struct tty_struct * tty) | |||
| 2182 | func_exit(); | 2237 | func_exit(); |
| 2183 | } | 2238 | } |
| 2184 | 2239 | ||
| 2185 | static void sx_hangup(struct tty_struct * tty) | 2240 | static void sx_hangup(struct tty_struct *tty) |
| 2186 | { | 2241 | { |
| 2187 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 2242 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
| 2188 | struct specialix_board *bp; | 2243 | struct specialix_board *bp; |
| @@ -2201,8 +2256,9 @@ static void sx_hangup(struct tty_struct * tty) | |||
| 2201 | spin_lock_irqsave(&port->lock, flags); | 2256 | spin_lock_irqsave(&port->lock, flags); |
| 2202 | bp->count -= port->port.count; | 2257 | bp->count -= port->port.count; |
| 2203 | if (bp->count < 0) { | 2258 | if (bp->count < 0) { |
| 2204 | printk(KERN_ERR "sx%d: sx_hangup: bad board count: %d port: %d\n", | 2259 | printk(KERN_ERR |
| 2205 | board_No(bp), bp->count, tty->index); | 2260 | "sx%d: sx_hangup: bad board count: %d port: %d\n", |
| 2261 | board_No(bp), bp->count, tty->index); | ||
| 2206 | bp->count = 0; | 2262 | bp->count = 0; |
| 2207 | } | 2263 | } |
| 2208 | port->port.count = 0; | 2264 | port->port.count = 0; |
| @@ -2215,11 +2271,12 @@ static void sx_hangup(struct tty_struct * tty) | |||
| 2215 | } | 2271 | } |
| 2216 | 2272 | ||
| 2217 | 2273 | ||
| 2218 | static void sx_set_termios(struct tty_struct * tty, struct ktermios * old_termios) | 2274 | static void sx_set_termios(struct tty_struct *tty, |
| 2275 | struct ktermios *old_termios) | ||
| 2219 | { | 2276 | { |
| 2220 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 2277 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
| 2221 | unsigned long flags; | 2278 | unsigned long flags; |
| 2222 | struct specialix_board * bp; | 2279 | struct specialix_board *bp; |
| 2223 | 2280 | ||
| 2224 | if (sx_paranoia_check(port, tty->name, "sx_set_termios")) | 2281 | if (sx_paranoia_check(port, tty->name, "sx_set_termios")) |
| 2225 | return; | 2282 | return; |
| @@ -2283,10 +2340,12 @@ static int sx_init_drivers(void) | |||
| 2283 | specialix_driver->flags = TTY_DRIVER_REAL_RAW; | 2340 | specialix_driver->flags = TTY_DRIVER_REAL_RAW; |
| 2284 | tty_set_operations(specialix_driver, &sx_ops); | 2341 | tty_set_operations(specialix_driver, &sx_ops); |
| 2285 | 2342 | ||
| 2286 | if ((error = tty_register_driver(specialix_driver))) { | 2343 | error = tty_register_driver(specialix_driver); |
| 2344 | if (error) { | ||
| 2287 | put_tty_driver(specialix_driver); | 2345 | put_tty_driver(specialix_driver); |
| 2288 | printk(KERN_ERR "sx: Couldn't register specialix IO8+ driver, error = %d\n", | 2346 | printk(KERN_ERR |
| 2289 | error); | 2347 | "sx: Couldn't register specialix IO8+ driver, error = %d\n", |
| 2348 | error); | ||
| 2290 | func_exit(); | 2349 | func_exit(); |
| 2291 | return 1; | 2350 | return 1; |
| 2292 | } | 2351 | } |
| @@ -2323,9 +2382,9 @@ static int __init specialix_init(void) | |||
| 2323 | printk(KERN_INFO "sx: Specialix IO8+ driver v" VERSION ", (c) R.E.Wolff 1997/1998.\n"); | 2382 | printk(KERN_INFO "sx: Specialix IO8+ driver v" VERSION ", (c) R.E.Wolff 1997/1998.\n"); |
| 2324 | printk(KERN_INFO "sx: derived from work (c) D.Gorodchanin 1994-1996.\n"); | 2383 | printk(KERN_INFO "sx: derived from work (c) D.Gorodchanin 1994-1996.\n"); |
| 2325 | #ifdef CONFIG_SPECIALIX_RTSCTS | 2384 | #ifdef CONFIG_SPECIALIX_RTSCTS |
| 2326 | printk (KERN_INFO "sx: DTR/RTS pin is always RTS.\n"); | 2385 | printk(KERN_INFO "sx: DTR/RTS pin is always RTS.\n"); |
| 2327 | #else | 2386 | #else |
| 2328 | printk (KERN_INFO "sx: DTR/RTS pin is RTS when CRTSCTS is on.\n"); | 2387 | printk(KERN_INFO "sx: DTR/RTS pin is RTS when CRTSCTS is on.\n"); |
| 2329 | #endif | 2388 | #endif |
| 2330 | 2389 | ||
| 2331 | for (i = 0; i < SX_NBOARD; i++) | 2390 | for (i = 0; i < SX_NBOARD; i++) |
| @@ -2344,27 +2403,27 @@ static int __init specialix_init(void) | |||
| 2344 | { | 2403 | { |
| 2345 | struct pci_dev *pdev = NULL; | 2404 | struct pci_dev *pdev = NULL; |
| 2346 | 2405 | ||
| 2347 | i=0; | 2406 | i = 0; |
| 2348 | while (i < SX_NBOARD) { | 2407 | while (i < SX_NBOARD) { |
| 2349 | if (sx_board[i].flags & SX_BOARD_PRESENT) { | 2408 | if (sx_board[i].flags & SX_BOARD_PRESENT) { |
| 2350 | i++; | 2409 | i++; |
| 2351 | continue; | 2410 | continue; |
| 2352 | } | 2411 | } |
| 2353 | pdev = pci_get_device (PCI_VENDOR_ID_SPECIALIX, | 2412 | pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX, |
| 2354 | PCI_DEVICE_ID_SPECIALIX_IO8, | 2413 | PCI_DEVICE_ID_SPECIALIX_IO8, pdev); |
| 2355 | pdev); | 2414 | if (!pdev) |
| 2356 | if (!pdev) break; | 2415 | break; |
| 2357 | 2416 | ||
| 2358 | if (pci_enable_device(pdev)) | 2417 | if (pci_enable_device(pdev)) |
| 2359 | continue; | 2418 | continue; |
| 2360 | 2419 | ||
| 2361 | sx_board[i].irq = pdev->irq; | 2420 | sx_board[i].irq = pdev->irq; |
| 2362 | 2421 | ||
| 2363 | sx_board[i].base = pci_resource_start (pdev, 2); | 2422 | sx_board[i].base = pci_resource_start(pdev, 2); |
| 2364 | 2423 | ||
| 2365 | sx_board[i].flags |= SX_BOARD_IS_PCI; | 2424 | sx_board[i].flags |= SX_BOARD_IS_PCI; |
| 2366 | if (!sx_probe(&sx_board[i])) | 2425 | if (!sx_probe(&sx_board[i])) |
| 2367 | found ++; | 2426 | found++; |
| 2368 | } | 2427 | } |
| 2369 | /* May exit pci_get sequence early with lots of boards */ | 2428 | /* May exit pci_get sequence early with lots of boards */ |
| 2370 | if (pdev != NULL) | 2429 | if (pdev != NULL) |
| @@ -2411,10 +2470,10 @@ static int __init specialix_init_module(void) | |||
| 2411 | func_enter(); | 2470 | func_enter(); |
| 2412 | 2471 | ||
| 2413 | if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) { | 2472 | if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) { |
| 2414 | for(i = 0; i < SX_NBOARD; i++) { | 2473 | for (i = 0; i < SX_NBOARD; i++) { |
| 2415 | sx_board[i].base = iobase[i]; | 2474 | sx_board[i].base = iobase[i]; |
| 2416 | sx_board[i].irq = irq[i]; | 2475 | sx_board[i].irq = irq[i]; |
| 2417 | sx_board[i].count= 0; | 2476 | sx_board[i].count = 0; |
| 2418 | } | 2477 | } |
| 2419 | } | 2478 | } |
| 2420 | 2479 | ||
