Date: Sat, 12 Apr 1997 07:06:19 +0200 (CEST) From: Luigi Rizzo <luigi@prova.iet.unipi.it> To: FreeBSD-gnats-submit@freebsd.org Subject: kern/3268: update for asc driver Message-ID: <199704120506.HAA00441@prova.iet.unipi.it> Resent-Message-ID: <199704122010.NAA19294@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 3268 >Category: kern >Synopsis: fix and feature add for asc driver >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Class: change-request >Submitter-Id: current-users >Arrival-Date: Sat Apr 12 13:10:03 PDT 1997 >Last-Modified: >Originator: Luigi Rizzo >Organization: DEIT >Release: FreeBSD 2.2.1-RELEASE i386 >Environment: system with Mustek hand scanners >Description: the asc driver as of 2.2.1-R causes my system to panic with a double fault right before giving control to /etc/rc. Although the reason is unknown, the driver is highly out of date, so I am submitting some patches to add support for color hand scanners as well. >How-To-Repeat: kernel with asc driver compiled in >Fix: The following patch fixes the panic and adds support for color hand scanners as well. Tested under 2.2.1-R --- /usr/src/sys221R/i386/isa/asc.c Mon Dec 30 22:18:32 1996 +++ asc.c Sat Apr 12 06:44:32 1997 @@ -2,10 +2,10 @@ * * Current version supports: * - * - Trust AmiScan BW (GI1904 chipset) + * - AmiScan (Mustek) Color and BW hand scanners (GI1904 chipset) * * Copyright (c) 1995 Gunther Schadow. All rights reserved. - * Copyright (c) 1995 Luigi Rizzo. All rights reserved. + * Copyright (c) 1995,1996,1997 Luigi Rizzo. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -106,7 +106,7 @@ #define DBUG_MASK 0x20 #define FRMT_MASK 0x18 /* output format */ #define FRMT_RAW 0x00 /* output bits as read from scanner */ -#define FRMT_GRAY 0x10 /* output graymap (not implemented yet) */ +#define FRMT_GRAY 0x1 /* output gray mode for color scanner */ #define FRMT_PBM 0x08 /* output pbm format */ #define FRMT_PGM 0x18 @@ -114,6 +114,7 @@ *** THE GEMOMETRY TABLE ***/ +#define GREY_LINE 826 /* 825, or 826 , or 550 ??? */ static const struct asc_geom { int dpi; /* dots per inch */ int dpl; /* dots per line */ @@ -128,6 +129,8 @@ { 300, 1240, 155, ASC_RES_300}, { 200, 832, 104, ASC_RES_200}, { 100, 416, 52, ASC_RES_100}, + { 200, 3*GREY_LINE, 3*GREY_LINE, 0 /* returned by color scanner */}, + { 200, GREY_LINE, GREY_LINE, 0 /* color scanner, grey mode */}, { INVALID, 416, 52, INVALID } /* terminator */ }; @@ -144,12 +147,14 @@ }; struct asc_unit { + long thedev; /* XXX */ int base; /* base address */ int dma_num; /* dma number */ char dma_byte; /* mask of byte for setting DMA value */ char int_byte; /* mask of byte for setting int value */ char cfg_byte; /* mirror of byte written to config reg (ASC_CFG). */ char cmd_byte; /* mirror of byte written to cmd port (ASC_CMD)*/ + char portf_byte; int flags; #define ATTACHED 0x01 #define OPEN 0x02 @@ -186,9 +191,11 @@ *** experiments. MAXPHYS is obviously too much, while DEV_BSIZE and *** PAGE_SIZE are really too small. There must be something wrong *** with isa_dmastart/isa_dmarangecheck HELP!!! + *** + *** Note, must be DEFAULT_BLEN * samples_per_line <= MAX_BUFSIZE ***/ -#define MAX_BUFSIZE 0x3000 -#define DEFAULT_BLEN 20 +#define MAX_BUFSIZE 0xb000 /* XXX was 0x3000 */ +#define DEFAULT_BLEN 16 /*** *** THE PER-DRIVER RECORD FOR ISA.C @@ -259,6 +266,12 @@ lprintf("asc.get_resolution: %d dpi\n",geomtab[i].dpi); scu->geometry = i; } + scu->portf_byte=0; /* default */ + if (geomtab[scu->geometry].g_res==0 && !(scu->thedev&FRMT_GRAY)) { + /* color scanner seems to require this */ + scu->portf_byte=2; + /* scu->geometry++; */ + } scu->linesize = geomtab[scu->geometry].bpl; scu->height = geomtab[scu->geometry].dpl; /* default... */ } @@ -302,6 +315,22 @@ static void dma_restart(struct asc_unit *scu) { + unsigned char al=scu->cmd_byte; + + if (geomtab[scu->geometry].g_res==0) {/* color */ + isa_dmastart(B_READ, scu->sbuf.base+scu->sbuf.wptr, + scu->linesize + 90 /* XXX */ , scu->dma_num); + /* + * looks like we have to set and then clear this + * bit to enable the scanner to send interrupts + */ + outb( ASC_CMD, al |= 4 ); /* seems to disable interrupts */ +#if 0 + outb( ASC_CMD, al |= 8 ); /* ??? seems useless */ +#endif + outb( ASC_CMD, al &= 0xfb ); + scu->cmd_byte = al; + } else { /* normal */ isa_dmastart(B_READ, scu->sbuf.base+scu->sbuf.wptr, scu->linesize, scu->dma_num); /*** this is done in sub_20, after dmastart ? ***/ @@ -313,6 +342,7 @@ #else outb( ASC_CMD, ASC_OPERATE); #endif + } scu->flags |= DMA_ACTIVE; } @@ -365,14 +395,34 @@ return PROBE_FAIL; } +/* + * NOTE NOTE NOTE + * the new AmiScan Color board uses int 10,11,12 instead of 3,5,10 + * respectively. This means that the driver must act accordingly. + * Unfortunately there is no easy way of telling which board one has, + * other than trying to get an interrupt and noticing that it is + * missing. use "option ASC_NEW_BOARD" if you have a new board. + * + */ + +#if ASC_NEW_BOARD +#define ASC_IRQ_A 10 +#define ASC_IRQ_B 11 +#define ASC_IRQ_C 12 +#else +#define ASC_IRQ_A 3 +#define ASC_IRQ_B 5 +#define ASC_IRQ_C 10 +#endif + switch(ffs(isdp->id_irq) - 1) { - case 3: + case ASC_IRQ_A : scu->int_byte = ASC_CNF_IRQ3; break; - case 5: + case ASC_IRQ_B : scu->int_byte = ASC_CNF_IRQ5; break; - case 10: + case ASC_IRQ_C : scu->int_byte = ASC_CNF_IRQ10; break; #if 0 @@ -383,7 +433,7 @@ #endif default: lprintf("asc%d.probe: unsupported INT %d (only 3, 5, 10)\n", - unit, isdp->id_irq); + unit, ffs(isdp->id_irq) - 1 ); return PROBE_FAIL; } scu->dma_num = isdp->id_drq; @@ -420,7 +470,7 @@ struct asc_unit *scu = unittab + unit; scu->flags |= FLAG_DEBUG; - printf("asc%d: [GI1904/Trust Ami-Scan Grey, type S2]\n", unit); + printf("asc%d: [GI1904/Trust Ami-Scan Grey/Color]\n", unit); /* * Initialize buffer structure. @@ -552,7 +602,7 @@ scu = unittab + unit; if ( !( scu->flags & ATTACHED ) ) { - lprintf("asc%d.open: unit was not attached successfully 0x04x\n", + lprintf("asc%d.open: unit was not attached successfully 0x%04x\n", unit, scu->flags); return ENXIO; } @@ -600,8 +650,12 @@ scu->cfg_byte= scu->cmd_byte=0; /* init scanner */ outb(ASC_CMD, scu->cmd_byte); /*** this was done in sub_16, set scan len... ***/ - outb(ASC_BOH, 0 ); + outb(ASC_BOH, scu->portf_byte ); + if (geomtab[scu->geometry].g_res==0) { /* color */ + scu->cmd_byte = 0x00 ; + } else { scu->cmd_byte = 0x90 ; + } outb(ASC_CMD, scu->cmd_byte); outb(ASC_LEN_L, scu->linesize & 0xff /* len_low */); outb(ASC_LEN_H, (scu->linesize >>8) & 0xff /* len_high */); @@ -673,9 +727,11 @@ scu->sbuf.rptr=scu->sbuf.size-l; bcopy(scu->sbuf.base, scu->sbuf.base+scu->sbuf.rptr,l); scu->sbuf.count = l; + if (geomtab[scu->geometry].g_res!=0) { /* BW scanner */ for(p = scu->sbuf.base + scu->sbuf.rptr; l; p++, l--) *p = ~*p; } +} /************************************************************************** *** *** ascread @@ -739,10 +795,11 @@ if ( (scu->flags & PBM_MODE) ) nbytes = min( nbytes, scu->bcount ); lprintf("asc%d.read: transferring 0x%x bytes\n", unit, nbytes); - + if (geomtab[scu->geometry].g_res!=0) { /* BW scanner */ lprintf("asc%d.read: invert buffer\n",unit); for(p = scu->sbuf.base + scu->sbuf.rptr, res=nbytes; res; p++, res--) *p = ~*p; + } res = uiomove(scu->sbuf.base + scu->sbuf.rptr, nbytes, uio); if ( res != SUCCESS ) { lprintf("asc%d.read: uiomove failed %d", unit, res); @@ -779,7 +836,7 @@ unit, minor(dev)); if ( unit >= NASC || !( scu->flags & ATTACHED ) ) { - lprintf("asc%d.ioctl: unit was not attached successfully %0x04x\n", + lprintf("asc%d.ioctl: unit was not attached successfully 0x%04x\n", unit, scu->flags); return ENXIO; } >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199704120506.HAA00441>