Skip site navigation (1)Skip section navigation (2)
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>