diff options
| -rw-r--r-- | Documentation/m68k/kernel-options.txt | 7 | ||||
| -rw-r--r-- | Documentation/networking/net-modules.txt | 6 | ||||
| -rw-r--r-- | drivers/block/Kconfig | 11 | ||||
| -rw-r--r-- | drivers/block/Makefile | 1 | ||||
| -rw-r--r-- | drivers/block/acsi_slm.c | 1032 | ||||
| -rw-r--r-- | drivers/net/Kconfig | 16 | ||||
| -rw-r--r-- | drivers/net/Makefile | 2 | ||||
| -rw-r--r-- | drivers/net/Space.c | 8 | ||||
| -rw-r--r-- | drivers/net/atari_bionet.c | 675 | ||||
| -rw-r--r-- | drivers/net/atari_pamsnet.c | 878 | ||||
| -rw-r--r-- | include/asm-m68k/atari_SLM.h | 28 | ||||
| -rw-r--r-- | include/asm-m68k/atari_acsi.h | 37 |
12 files changed, 0 insertions, 2701 deletions
diff --git a/Documentation/m68k/kernel-options.txt b/Documentation/m68k/kernel-options.txt index 1c41db21d3c1..59108cebe163 100644 --- a/Documentation/m68k/kernel-options.txt +++ b/Documentation/m68k/kernel-options.txt | |||
| @@ -82,13 +82,6 @@ Valid names are: | |||
| 82 | /dev/fd : -> 0x0200 (floppy disk) | 82 | /dev/fd : -> 0x0200 (floppy disk) |
| 83 | /dev/xda: -> 0x0c00 (first XT disk, unused in Linux/m68k) | 83 | /dev/xda: -> 0x0c00 (first XT disk, unused in Linux/m68k) |
| 84 | /dev/xdb: -> 0x0c40 (second XT disk, unused in Linux/m68k) | 84 | /dev/xdb: -> 0x0c40 (second XT disk, unused in Linux/m68k) |
| 85 | /dev/ada: -> 0x1c00 (first ACSI device) | ||
| 86 | /dev/adb: -> 0x1c10 (second ACSI device) | ||
| 87 | /dev/adc: -> 0x1c20 (third ACSI device) | ||
| 88 | /dev/add: -> 0x1c30 (forth ACSI device) | ||
| 89 | |||
| 90 | The last four names are available only if the kernel has been compiled | ||
| 91 | with Atari and ACSI support. | ||
| 92 | 85 | ||
| 93 | The name must be followed by a decimal number, that stands for the | 86 | The name must be followed by a decimal number, that stands for the |
| 94 | partition number. Internally, the value of the number is just | 87 | partition number. Internally, the value of the number is just |
diff --git a/Documentation/networking/net-modules.txt b/Documentation/networking/net-modules.txt index 0b27863f155c..98c4392dd0fd 100644 --- a/Documentation/networking/net-modules.txt +++ b/Documentation/networking/net-modules.txt | |||
| @@ -146,12 +146,6 @@ at1700.c: | |||
| 146 | irq = 0 | 146 | irq = 0 |
| 147 | (Probes ports: 0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300) | 147 | (Probes ports: 0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300) |
| 148 | 148 | ||
| 149 | atari_bionet.c: | ||
| 150 | Supports full autoprobing. (m68k/Atari) | ||
| 151 | |||
| 152 | atari_pamsnet.c: | ||
| 153 | Supports full autoprobing. (m68k/Atari) | ||
| 154 | |||
| 155 | atarilance.c: | 149 | atarilance.c: |
| 156 | Supports full autoprobing. (m68k/Atari) | 150 | Supports full autoprobing. (m68k/Atari) |
| 157 | 151 | ||
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 6e23af1ecbdb..95d6838c4ff3 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig | |||
| @@ -59,17 +59,6 @@ config AMIGA_Z2RAM | |||
| 59 | To compile this driver as a module, choose M here: the | 59 | To compile this driver as a module, choose M here: the |
| 60 | module will be called z2ram. | 60 | module will be called z2ram. |
| 61 | 61 | ||
| 62 | config ATARI_SLM | ||
| 63 | tristate "Atari SLM laser printer support" | ||
| 64 | depends on ATARI | ||
| 65 | help | ||
| 66 | If you have an Atari SLM laser printer, say Y to include support for | ||
| 67 | it in the kernel. Otherwise, say N. This driver is also available as | ||
| 68 | a module ( = code which can be inserted in and removed from the | ||
| 69 | running kernel whenever you want). The module will be called | ||
| 70 | acsi_slm. Be warned: the driver needs much ST-RAM and can cause | ||
| 71 | problems due to that fact! | ||
| 72 | |||
| 73 | config BLK_DEV_XD | 62 | config BLK_DEV_XD |
| 74 | tristate "XT hard disk support" | 63 | tristate "XT hard disk support" |
| 75 | depends on ISA && ISA_DMA_API | 64 | depends on ISA && ISA_DMA_API |
diff --git a/drivers/block/Makefile b/drivers/block/Makefile index e5f98acc5d52..bba3119b28c4 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile | |||
| @@ -9,7 +9,6 @@ obj-$(CONFIG_MAC_FLOPPY) += swim3.o | |||
| 9 | obj-$(CONFIG_BLK_DEV_FD) += floppy.o | 9 | obj-$(CONFIG_BLK_DEV_FD) += floppy.o |
| 10 | obj-$(CONFIG_AMIGA_FLOPPY) += amiflop.o | 10 | obj-$(CONFIG_AMIGA_FLOPPY) += amiflop.o |
| 11 | obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o | 11 | obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o |
| 12 | obj-$(CONFIG_ATARI_SLM) += acsi_slm.o | ||
| 13 | obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o | 12 | obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o |
| 14 | obj-$(CONFIG_BLK_DEV_RAM) += rd.o | 13 | obj-$(CONFIG_BLK_DEV_RAM) += rd.o |
| 15 | obj-$(CONFIG_BLK_DEV_LOOP) += loop.o | 14 | obj-$(CONFIG_BLK_DEV_LOOP) += loop.o |
diff --git a/drivers/block/acsi_slm.c b/drivers/block/acsi_slm.c deleted file mode 100644 index 1d9d9b4f48cc..000000000000 --- a/drivers/block/acsi_slm.c +++ /dev/null | |||
| @@ -1,1032 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * acsi_slm.c -- Device driver for the Atari SLM laser printer | ||
| 3 | * | ||
| 4 | * Copyright 1995 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> | ||
| 5 | * | ||
| 6 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 7 | * License. See the file COPYING in the main directory of this archive for | ||
| 8 | * more details. | ||
| 9 | * | ||
| 10 | */ | ||
| 11 | |||
| 12 | /* | ||
| 13 | |||
| 14 | Notes: | ||
| 15 | |||
| 16 | The major number for SLM printers is 28 (like ACSI), but as a character | ||
| 17 | device, not block device. The minor number is the number of the printer (if | ||
| 18 | you have more than one SLM; currently max. 2 (#define-constant) SLMs are | ||
| 19 | supported). The device can be opened for reading and writing. If reading it, | ||
| 20 | you get some status infos (MODE SENSE data). Writing mode is used for the data | ||
| 21 | to be printed. Some ioctls allow to get the printer status and to tune printer | ||
| 22 | modes and some internal variables. | ||
| 23 | |||
| 24 | A special problem of the SLM driver is the timing and thus the buffering of | ||
| 25 | the print data. The problem is that all the data for one page must be present | ||
| 26 | in memory when printing starts, else --when swapping occurs-- the timing could | ||
| 27 | not be guaranteed. There are several ways to assure this: | ||
| 28 | |||
| 29 | 1) Reserve a buffer of 1196k (maximum page size) statically by | ||
| 30 | atari_stram_alloc(). The data are collected there until they're complete, | ||
| 31 | and then printing starts. Since the buffer is reserved, no further | ||
| 32 | considerations about memory and swapping are needed. So this is the | ||
| 33 | simplest method, but it needs a lot of memory for just the SLM. | ||
| 34 | |||
| 35 | An striking advantage of this method is (supposed the SLM_CONT_CNT_REPROG | ||
| 36 | method works, see there), that there are no timing problems with the DMA | ||
| 37 | anymore. | ||
| 38 | |||
| 39 | 2) The other method would be to reserve the buffer dynamically each time | ||
| 40 | printing is required. I could think of looking at mem_map where the | ||
| 41 | largest unallocted ST-RAM area is, taking the area, and then extending it | ||
| 42 | by swapping out the neighbored pages, until the needed size is reached. | ||
| 43 | This requires some mm hacking, but seems possible. The only obstacle could | ||
| 44 | be pages that cannot be swapped out (reserved pages)... | ||
| 45 | |||
| 46 | 3) Another possibility would be to leave the real data in user space and to | ||
| 47 | work with two dribble buffers of about 32k in the driver: While the one | ||
| 48 | buffer is DMAed to the SLM, the other can be filled with new data. But | ||
| 49 | to keep the timing, that requires that the user data remain in memory and | ||
| 50 | are not swapped out. Requires mm hacking, too, but maybe not so bad as | ||
| 51 | method 2). | ||
| 52 | |||
| 53 | */ | ||
| 54 | |||
| 55 | #include <linux/module.h> | ||
| 56 | |||
| 57 | #include <linux/errno.h> | ||
| 58 | #include <linux/sched.h> | ||
| 59 | #include <linux/timer.h> | ||
| 60 | #include <linux/fs.h> | ||
| 61 | #include <linux/major.h> | ||
| 62 | #include <linux/kernel.h> | ||
| 63 | #include <linux/delay.h> | ||
| 64 | #include <linux/interrupt.h> | ||
| 65 | #include <linux/time.h> | ||
| 66 | #include <linux/mm.h> | ||
| 67 | #include <linux/slab.h> | ||
| 68 | |||
| 69 | #include <asm/pgtable.h> | ||
| 70 | #include <asm/system.h> | ||
| 71 | #include <asm/uaccess.h> | ||
| 72 | #include <asm/atarihw.h> | ||
| 73 | #include <asm/atariints.h> | ||
| 74 | #include <asm/atari_acsi.h> | ||
| 75 | #include <asm/atari_stdma.h> | ||
| 76 | #include <asm/atari_stram.h> | ||
| 77 | #include <asm/atari_SLM.h> | ||
| 78 | |||
| 79 | |||
| 80 | #undef DEBUG | ||
| 81 | |||
| 82 | /* Define this if the page data are continuous in physical memory. That | ||
| 83 | * requires less reprogramming of the ST-DMA */ | ||
| 84 | #define SLM_CONTINUOUS_DMA | ||
| 85 | |||
| 86 | /* Use continuous reprogramming of the ST-DMA counter register. This is | ||
| 87 | * --strictly speaking-- not allowed, Atari recommends not to look at the | ||
| 88 | * counter register while a DMA is going on. But I don't know if that applies | ||
| 89 | * only for reading the register, or also writing to it. Writing only works | ||
| 90 | * fine for me... The advantage is that the timing becomes absolutely | ||
| 91 | * uncritical: Just update each, say 200ms, the counter reg to its maximum, | ||
| 92 | * and the DMA will work until the status byte interrupt occurs. | ||
| 93 | */ | ||
| 94 | #define SLM_CONT_CNT_REPROG | ||
| 95 | |||
| 96 | #define CMDSET_TARG_LUN(cmd,targ,lun) \ | ||
| 97 | do { \ | ||
| 98 | cmd[0] = (cmd[0] & ~0xe0) | (targ)<<5; \ | ||
| 99 | cmd[1] = (cmd[1] & ~0xe0) | (lun)<<5; \ | ||
| 100 | } while(0) | ||
| 101 | |||
| 102 | #define START_TIMER(to) mod_timer(&slm_timer, jiffies + (to)) | ||
| 103 | #define STOP_TIMER() del_timer(&slm_timer) | ||
| 104 | |||
| 105 | |||
| 106 | static char slmreqsense_cmd[6] = { 0x03, 0, 0, 0, 0, 0 }; | ||
| 107 | static char slmprint_cmd[6] = { 0x0a, 0, 0, 0, 0, 0 }; | ||
| 108 | static char slminquiry_cmd[6] = { 0x12, 0, 0, 0, 0, 0x80 }; | ||
| 109 | static char slmmsense_cmd[6] = { 0x1a, 0, 0, 0, 255, 0 }; | ||
| 110 | #if 0 | ||
| 111 | static char slmmselect_cmd[6] = { 0x15, 0, 0, 0, 0, 0 }; | ||
| 112 | #endif | ||
| 113 | |||
| 114 | |||
| 115 | #define MAX_SLM 2 | ||
| 116 | |||
| 117 | static struct slm { | ||
| 118 | unsigned target; /* target number */ | ||
| 119 | unsigned lun; /* LUN in target controller */ | ||
| 120 | atomic_t wr_ok; /* set to 0 if output part busy */ | ||
| 121 | atomic_t rd_ok; /* set to 0 if status part busy */ | ||
| 122 | } slm_info[MAX_SLM]; | ||
| 123 | |||
| 124 | int N_SLM_Printers = 0; | ||
| 125 | |||
| 126 | /* printer buffer */ | ||
| 127 | static unsigned char *SLMBuffer; /* start of buffer */ | ||
| 128 | static unsigned char *BufferP; /* current position in buffer */ | ||
| 129 | static int BufferSize; /* length of buffer for page size */ | ||
| 130 | |||
| 131 | typedef enum { IDLE, FILLING, PRINTING } SLMSTATE; | ||
| 132 | static SLMSTATE SLMState; | ||
| 133 | static int SLMBufOwner; /* SLM# currently using the buffer */ | ||
| 134 | |||
| 135 | /* DMA variables */ | ||
| 136 | #ifndef SLM_CONT_CNT_REPROG | ||
| 137 | static unsigned long SLMCurAddr; /* current base addr of DMA chunk */ | ||
| 138 | static unsigned long SLMEndAddr; /* expected end addr */ | ||
| 139 | static unsigned long SLMSliceSize; /* size of one DMA chunk */ | ||
| 140 | #endif | ||
| 141 | static int SLMError; | ||
| 142 | |||
| 143 | /* wait queues */ | ||
| 144 | static DECLARE_WAIT_QUEUE_HEAD(slm_wait); /* waiting for buffer */ | ||
| 145 | static DECLARE_WAIT_QUEUE_HEAD(print_wait); /* waiting for printing finished */ | ||
| 146 | |||
| 147 | /* status codes */ | ||
| 148 | #define SLMSTAT_OK 0x00 | ||
| 149 | #define SLMSTAT_ORNERY 0x02 | ||
| 150 | #define SLMSTAT_TONER 0x03 | ||
| 151 | #define SLMSTAT_WARMUP 0x04 | ||
| 152 | #define SLMSTAT_PAPER 0x05 | ||
| 153 | #define SLMSTAT_DRUM 0x06 | ||
| 154 | #define SLMSTAT_INJAM 0x07 | ||
| 155 | #define SLMSTAT_THRJAM 0x08 | ||
| 156 | #define SLMSTAT_OUTJAM 0x09 | ||
| 157 | #define SLMSTAT_COVER 0x0a | ||
| 158 | #define SLMSTAT_FUSER 0x0b | ||
| 159 | #define SLMSTAT_IMAGER 0x0c | ||
| 160 | #define SLMSTAT_MOTOR 0x0d | ||
| 161 | #define SLMSTAT_VIDEO 0x0e | ||
| 162 | #define SLMSTAT_SYSTO 0x10 | ||
| 163 | #define SLMSTAT_OPCODE 0x12 | ||
| 164 | #define SLMSTAT_DEVNUM 0x15 | ||
| 165 | #define SLMSTAT_PARAM 0x1a | ||
| 166 | #define SLMSTAT_ACSITO 0x1b /* driver defined */ | ||
| 167 | #define SLMSTAT_NOTALL 0x1c /* driver defined */ | ||
| 168 | |||
| 169 | static char *SLMErrors[] = { | ||
| 170 | /* 0x00 */ "OK and ready", | ||
| 171 | /* 0x01 */ NULL, | ||
| 172 | /* 0x02 */ "ornery printer", | ||
| 173 | /* 0x03 */ "toner empty", | ||
| 174 | /* 0x04 */ "warming up", | ||
| 175 | /* 0x05 */ "paper empty", | ||
| 176 | /* 0x06 */ "drum empty", | ||
| 177 | /* 0x07 */ "input jam", | ||
| 178 | /* 0x08 */ "through jam", | ||
| 179 | /* 0x09 */ "output jam", | ||
| 180 | /* 0x0a */ "cover open", | ||
| 181 | /* 0x0b */ "fuser malfunction", | ||
| 182 | /* 0x0c */ "imager malfunction", | ||
| 183 | /* 0x0d */ "motor malfunction", | ||
| 184 | /* 0x0e */ "video malfunction", | ||
| 185 | /* 0x0f */ NULL, | ||
| 186 | /* 0x10 */ "printer system timeout", | ||
| 187 | /* 0x11 */ NULL, | ||
| 188 | /* 0x12 */ "invalid operation code", | ||
| 189 | /* 0x13 */ NULL, | ||
| 190 | /* 0x14 */ NULL, | ||
| 191 | /* 0x15 */ "invalid device number", | ||
| 192 | /* 0x16 */ NULL, | ||
| 193 | /* 0x17 */ NULL, | ||
| 194 | /* 0x18 */ NULL, | ||
| 195 | /* 0x19 */ NULL, | ||
| 196 | /* 0x1a */ "invalid parameter list", | ||
| 197 | /* 0x1b */ "ACSI timeout", | ||
| 198 | /* 0x1c */ "not all printed" | ||
| 199 | }; | ||
| 200 | |||
| 201 | #define N_ERRORS (sizeof(SLMErrors)/sizeof(*SLMErrors)) | ||
| 202 | |||
| 203 | /* real (driver caused) error? */ | ||
| 204 | #define IS_REAL_ERROR(x) (x > 0x10) | ||
| 205 | |||
| 206 | |||
| 207 | static struct { | ||
| 208 | char *name; | ||
| 209 | int w, h; | ||
| 210 | } StdPageSize[] = { | ||
| 211 | { "Letter", 2400, 3180 }, | ||
| 212 | { "Legal", 2400, 4080 }, | ||
| 213 | { "A4", 2336, 3386 }, | ||
| 214 | { "B5", 2016, 2914 } | ||
| 215 | }; | ||
| 216 | |||
| 217 | #define N_STD_SIZES (sizeof(StdPageSize)/sizeof(*StdPageSize)) | ||
| 218 | |||
| 219 | #define SLM_BUFFER_SIZE (2336*3386/8) /* A4 for now */ | ||
| 220 | #define SLM_DMA_AMOUNT 255 /* #sectors to program the DMA for */ | ||
| 221 | |||
| 222 | #ifdef SLM_CONTINUOUS_DMA | ||
| 223 | # define SLM_DMA_INT_OFFSET 0 /* DMA goes until seccnt 0, no offs */ | ||
| 224 | # define SLM_DMA_END_OFFSET 32 /* 32 Byte ST-DMA FIFO */ | ||
| 225 | # define SLM_SLICE_SIZE(w) (255*512) | ||
| 226 | #else | ||
| 227 | # define SLM_DMA_INT_OFFSET 32 /* 32 Byte ST-DMA FIFO */ | ||
| 228 | # define SLM_DMA_END_OFFSET 32 /* 32 Byte ST-DMA FIFO */ | ||
| 229 | # define SLM_SLICE_SIZE(w) ((254*512)/(w/8)*(w/8)) | ||
| 230 | #endif | ||
| 231 | |||
| 232 | /* calculate the number of jiffies to wait for 'n' bytes */ | ||
| 233 | #ifdef SLM_CONT_CNT_REPROG | ||
| 234 | #define DMA_TIME_FOR(n) 50 | ||
| 235 | #define DMA_STARTUP_TIME 0 | ||
| 236 | #else | ||
| 237 | #define DMA_TIME_FOR(n) (n/1400-1) | ||
| 238 | #define DMA_STARTUP_TIME 650 | ||
| 239 | #endif | ||
| 240 | |||
| 241 | /***************************** Prototypes *****************************/ | ||
| 242 | |||
| 243 | static char *slm_errstr( int stat ); | ||
| 244 | static int slm_getstats( char *buffer, int device ); | ||
| 245 | static ssize_t slm_read( struct file* file, char *buf, size_t count, loff_t | ||
| 246 | *ppos ); | ||
| 247 | static void start_print( int device ); | ||
| 248 | static irqreturn_t slm_interrupt(int irc, void *data); | ||
| 249 | static void slm_test_ready( unsigned long dummy ); | ||
| 250 | static void set_dma_addr( unsigned long paddr ); | ||
| 251 | static unsigned long get_dma_addr( void ); | ||
| 252 | static ssize_t slm_write( struct file *file, const char *buf, size_t count, | ||
| 253 | loff_t *ppos ); | ||
| 254 | static int slm_ioctl( struct inode *inode, struct file *file, unsigned int | ||
| 255 | cmd, unsigned long arg ); | ||
| 256 | static int slm_open( struct inode *inode, struct file *file ); | ||
| 257 | static int slm_release( struct inode *inode, struct file *file ); | ||
| 258 | static int slm_req_sense( int device ); | ||
| 259 | static int slm_mode_sense( int device, char *buffer, int abs_flag ); | ||
| 260 | #if 0 | ||
| 261 | static int slm_mode_select( int device, char *buffer, int len, int | ||
| 262 | default_flag ); | ||
| 263 | #endif | ||
| 264 | static int slm_get_pagesize( int device, int *w, int *h ); | ||
| 265 | |||
| 266 | /************************* End of Prototypes **************************/ | ||
| 267 | |||
| 268 | |||
| 269 | static DEFINE_TIMER(slm_timer, slm_test_ready, 0, 0); | ||
| 270 | |||
| 271 | static const struct file_operations slm_fops = { | ||
| 272 | .owner = THIS_MODULE, | ||
| 273 | .read = slm_read, | ||
| 274 | .write = slm_write, | ||
| 275 | .ioctl = slm_ioctl, | ||
| 276 | .open = slm_open, | ||
| 277 | .release = slm_release, | ||
| 278 | }; | ||
| 279 | |||
| 280 | |||
| 281 | /* ---------------------------------------------------------------------- */ | ||
| 282 | /* Status Functions */ | ||
| 283 | |||
| 284 | |||
| 285 | static char *slm_errstr( int stat ) | ||
| 286 | |||
| 287 | { char *p; | ||
| 288 | static char str[22]; | ||
| 289 | |||
| 290 | stat &= 0x1f; | ||
| 291 | if (stat >= 0 && stat < N_ERRORS && (p = SLMErrors[stat])) | ||
| 292 | return( p ); | ||
| 293 | sprintf( str, "unknown status 0x%02x", stat ); | ||
| 294 | return( str ); | ||
| 295 | } | ||
| 296 | |||
| 297 | |||
| 298 | static int slm_getstats( char *buffer, int device ) | ||
| 299 | |||
| 300 | { int len = 0, stat, i, w, h; | ||
| 301 | unsigned char buf[256]; | ||
| 302 | |||
| 303 | stat = slm_mode_sense( device, buf, 0 ); | ||
| 304 | if (IS_REAL_ERROR(stat)) | ||
| 305 | return( -EIO ); | ||
| 306 | |||
| 307 | #define SHORTDATA(i) ((buf[i] << 8) | buf[i+1]) | ||
| 308 | #define BOOLDATA(i,mask) ((buf[i] & mask) ? "on" : "off") | ||
| 309 | |||
| 310 | w = SHORTDATA( 3 ); | ||
| 311 | h = SHORTDATA( 1 ); | ||
| 312 | |||
| 313 | len += sprintf( buffer+len, "Status\t\t%s\n", | ||
| 314 | slm_errstr( stat ) ); | ||
| 315 | len += sprintf( buffer+len, "Page Size\t%dx%d", | ||
| 316 | w, h ); | ||
| 317 | |||
| 318 | for( i = 0; i < N_STD_SIZES; ++i ) { | ||
| 319 | if (w == StdPageSize[i].w && h == StdPageSize[i].h) | ||
| 320 | break; | ||
| 321 | } | ||
| 322 | if (i < N_STD_SIZES) | ||
| 323 | len += sprintf( buffer+len, " (%s)", StdPageSize[i].name ); | ||
| 324 | buffer[len++] = '\n'; | ||
| 325 | |||
| 326 | len += sprintf( buffer+len, "Top/Left Margin\t%d/%d\n", | ||
| 327 | SHORTDATA( 5 ), SHORTDATA( 7 ) ); | ||
| 328 | len += sprintf( buffer+len, "Manual Feed\t%s\n", | ||
| 329 | BOOLDATA( 9, 0x01 ) ); | ||
| 330 | len += sprintf( buffer+len, "Input Select\t%d\n", | ||
| 331 | (buf[9] >> 1) & 7 ); | ||
| 332 | len += sprintf( buffer+len, "Auto Select\t%s\n", | ||
| 333 | BOOLDATA( 9, 0x10 ) ); | ||
| 334 | len += sprintf( buffer+len, "Prefeed Paper\t%s\n", | ||
| 335 | BOOLDATA( 9, 0x20 ) ); | ||
| 336 | len += sprintf( buffer+len, "Thick Pixels\t%s\n", | ||
| 337 | BOOLDATA( 9, 0x40 ) ); | ||
| 338 | len += sprintf( buffer+len, "H/V Resol.\t%d/%d dpi\n", | ||
| 339 | SHORTDATA( 12 ), SHORTDATA( 10 ) ); | ||
| 340 | len += sprintf( buffer+len, "System Timeout\t%d\n", | ||
| 341 | buf[14] ); | ||
| 342 | len += sprintf( buffer+len, "Scan Time\t%d\n", | ||
| 343 | SHORTDATA( 15 ) ); | ||
| 344 | len += sprintf( buffer+len, "Page Count\t%d\n", | ||
| 345 | SHORTDATA( 17 ) ); | ||
| 346 | len += sprintf( buffer+len, "In/Out Cap.\t%d/%d\n", | ||
| 347 | SHORTDATA( 19 ), SHORTDATA( 21 ) ); | ||
| 348 | len += sprintf( buffer+len, "Stagger Output\t%s\n", | ||
| 349 | BOOLDATA( 23, 0x01 ) ); | ||
| 350 | len += sprintf( buffer+len, "Output Select\t%d\n", | ||
| 351 | (buf[23] >> 1) & 7 ); | ||
| 352 | len += sprintf( buffer+len, "Duplex Print\t%s\n", | ||
| 353 | BOOLDATA( 23, 0x10 ) ); | ||
| 354 | len += sprintf( buffer+len, "Color Sep.\t%s\n", | ||
| 355 | BOOLDATA( 23, 0x20 ) ); | ||
| 356 | |||
| 357 | return( len ); | ||
| 358 | } | ||
| 359 | |||
| 360 | |||
| 361 | static ssize_t slm_read( struct file *file, char *buf, size_t count, | ||
| 362 | loff_t *ppos ) | ||
| 363 | |||
| 364 | { | ||
| 365 | struct inode *node = file->f_path.dentry->d_inode; | ||
| 366 | unsigned long page; | ||
| 367 | int length; | ||
| 368 | int end; | ||
| 369 | |||
| 370 | if (!(page = __get_free_page( GFP_KERNEL ))) | ||
| 371 | return( -ENOMEM ); | ||
| 372 | |||
| 373 | length = slm_getstats( (char *)page, iminor(node) ); | ||
| 374 | if (length < 0) { | ||
| 375 | count = length; | ||
| 376 | goto out; | ||
| 377 | } | ||
| 378 | if (file->f_pos >= length) { | ||
| 379 | count = 0; | ||
| 380 | goto out; | ||
| 381 | } | ||
| 382 | if (count + file->f_pos > length) | ||
| 383 | count = length - file->f_pos; | ||
| 384 | end = count + file->f_pos; | ||
| 385 | if (copy_to_user(buf, (char *)page + file->f_pos, count)) { | ||
| 386 | count = -EFAULT; | ||
| 387 | goto out; | ||
| 388 | } | ||
| 389 | file->f_pos = end; | ||
| 390 | out: free_page( page ); | ||
| 391 | return( count ); | ||
| 392 | } | ||
| 393 | |||
| 394 | |||
| 395 | /* ---------------------------------------------------------------------- */ | ||
| 396 | /* Printing */ | ||
| 397 | |||
| 398 | |||
| 399 | static void start_print( int device ) | ||
| 400 | |||
| 401 | { struct slm *sip = &slm_info[device]; | ||
| 402 | unsigned char *cmd; | ||
| 403 | unsigned long paddr; | ||
| 404 | int i; | ||
| 405 | |||
| 406 | stdma_lock( slm_interrupt, NULL ); | ||
| 407 | |||
| 408 | CMDSET_TARG_LUN( slmprint_cmd, sip->target, sip->lun ); | ||
| 409 | cmd = slmprint_cmd; | ||
| 410 | paddr = virt_to_phys( SLMBuffer ); | ||
| 411 | dma_cache_maintenance( paddr, virt_to_phys(BufferP)-paddr, 1 ); | ||
| 412 | DISABLE_IRQ(); | ||
| 413 | |||
| 414 | /* Low on A1 */ | ||
| 415 | dma_wd.dma_mode_status = 0x88; | ||
| 416 | MFPDELAY(); | ||
| 417 | |||
| 418 | /* send the command bytes except the last */ | ||
| 419 | for( i = 0; i < 5; ++i ) { | ||
| 420 | DMA_LONG_WRITE( *cmd++, 0x8a ); | ||
| 421 | udelay(20); | ||
| 422 | if (!acsi_wait_for_IRQ( HZ/2 )) { | ||
| 423 | SLMError = 1; | ||
| 424 | return; /* timeout */ | ||
| 425 | } | ||
| 426 | } | ||
| 427 | /* last command byte */ | ||
| 428 | DMA_LONG_WRITE( *cmd++, 0x82 ); | ||
| 429 | MFPDELAY(); | ||
| 430 | /* set DMA address */ | ||
| 431 | set_dma_addr( paddr ); | ||
| 432 | /* program DMA for write and select sector counter reg */ | ||
| 433 | dma_wd.dma_mode_status = 0x192; | ||
| 434 | MFPDELAY(); | ||
| 435 | /* program for 255*512 bytes and start DMA */ | ||
| 436 | DMA_LONG_WRITE( SLM_DMA_AMOUNT, 0x112 ); | ||
| 437 | |||
| 438 | #ifndef SLM_CONT_CNT_REPROG | ||
| 439 | SLMCurAddr = paddr; | ||
| 440 | SLMEndAddr = paddr + SLMSliceSize + SLM_DMA_INT_OFFSET; | ||
| 441 | #endif | ||
| 442 | START_TIMER( DMA_STARTUP_TIME + DMA_TIME_FOR( SLMSliceSize )); | ||
| 443 | #if !defined(SLM_CONT_CNT_REPROG) && defined(DEBUG) | ||
| 444 | printk( "SLM: CurAddr=%#lx EndAddr=%#lx timer=%ld\n", | ||
| 445 | SLMCurAddr, SLMEndAddr, DMA_TIME_FOR( SLMSliceSize ) ); | ||
| 446 | #endif | ||
| 447 | |||
| 448 | ENABLE_IRQ(); | ||
| 449 | } | ||
| 450 | |||
| 451 | |||
| 452 | /* Only called when an error happened or at the end of a page */ | ||
| 453 | |||
| 454 | static irqreturn_t slm_interrupt(int irc, void *data) | ||
| 455 | |||
| 456 | { unsigned long addr; | ||
| 457 | int stat; | ||
| 458 | |||
| 459 | STOP_TIMER(); | ||
| 460 | addr = get_dma_addr(); | ||
| 461 | stat = acsi_getstatus(); | ||
| 462 | SLMError = (stat < 0) ? SLMSTAT_ACSITO : | ||
| 463 | (addr < virt_to_phys(BufferP)) ? SLMSTAT_NOTALL : | ||
| 464 | stat; | ||
| 465 | |||
| 466 | dma_wd.dma_mode_status = 0x80; | ||
| 467 | MFPDELAY(); | ||
| 468 | #ifdef DEBUG | ||
| 469 | printk( "SLM: interrupt, addr=%#lx, error=%d\n", addr, SLMError ); | ||
| 470 | #endif | ||
| 471 | |||
| 472 | wake_up( &print_wait ); | ||
| 473 | stdma_release(); | ||
| 474 | ENABLE_IRQ(); | ||
| 475 | return IRQ_HANDLED; | ||
| 476 | } | ||
| 477 | |||
| 478 | |||
| 479 | static void slm_test_ready( unsigned long dummy ) | ||
| 480 | |||
| 481 | { | ||
| 482 | #ifdef SLM_CONT_CNT_REPROG | ||
| 483 | /* program for 255*512 bytes again */ | ||
| 484 | dma_wd.fdc_acces_seccount = SLM_DMA_AMOUNT; | ||
| 485 | START_TIMER( DMA_TIME_FOR(0) ); | ||
| 486 | #ifdef DEBUG | ||
| 487 | printk( "SLM: reprogramming timer for %d jiffies, addr=%#lx\n", | ||
| 488 | DMA_TIME_FOR(0), get_dma_addr() ); | ||
| 489 | #endif | ||
| 490 | |||
| 491 | #else /* !SLM_CONT_CNT_REPROG */ | ||
| 492 | |||
| 493 | unsigned long flags, addr; | ||
| 494 | int d, ti; | ||
| 495 | #ifdef DEBUG | ||
| 496 | struct timeval start_tm, end_tm; | ||
| 497 | int did_wait = 0; | ||
| 498 | #endif | ||
| 499 | |||
| 500 | local_irq_save(flags); | ||
| 501 | |||
| 502 | addr = get_dma_addr(); | ||
| 503 | if ((d = SLMEndAddr - addr) > 0) { | ||
| 504 | local_irq_restore(flags); | ||
| 505 | |||
| 506 | /* slice not yet finished, decide whether to start another timer or to | ||
| 507 | * busy-wait */ | ||
| 508 | ti = DMA_TIME_FOR( d ); | ||
| 509 | if (ti > 0) { | ||
| 510 | #ifdef DEBUG | ||
| 511 | printk( "SLM: reprogramming timer for %d jiffies, rest %d bytes\n", | ||
| 512 | ti, d ); | ||
| 513 | #endif | ||
| 514 | START_TIMER( ti ); | ||
| 515 | return; | ||
| 516 | } | ||
| 517 | /* wait for desired end address to be reached */ | ||
| 518 | #ifdef DEBUG | ||
| 519 | do_gettimeofday( &start_tm ); | ||
| 520 | did_wait = 1; | ||
| 521 | #endif | ||
| 522 | local_irq_disable(); | ||
| 523 | while( get_dma_addr() < SLMEndAddr ) | ||
| 524 | barrier(); | ||
| 525 | } | ||
| 526 | |||
| 527 | /* slice finished, start next one */ | ||
| 528 | SLMCurAddr += SLMSliceSize; | ||
| 529 | |||
| 530 | #ifdef SLM_CONTINUOUS_DMA | ||
| 531 | /* program for 255*512 bytes again */ | ||
| 532 | dma_wd.fdc_acces_seccount = SLM_DMA_AMOUNT; | ||
| 533 | #else | ||
| 534 | /* set DMA address; | ||
| 535 | * add 2 bytes for the ones in the SLM controller FIFO! */ | ||
| 536 | set_dma_addr( SLMCurAddr + 2 ); | ||
| 537 | /* toggle DMA to write and select sector counter reg */ | ||
| 538 | dma_wd.dma_mode_status = 0x92; | ||
| 539 | MFPDELAY(); | ||
| 540 | dma_wd.dma_mode_status = 0x192; | ||
| 541 | MFPDELAY(); | ||
| 542 | /* program for 255*512 bytes and start DMA */ | ||
| 543 | DMA_LONG_WRITE( SLM_DMA_AMOUNT, 0x112 ); | ||
| 544 | #endif | ||
| 545 | |||
| 546 | local_irq_restore(flags); | ||
| 547 | |||
| 548 | #ifdef DEBUG | ||
| 549 | if (did_wait) { | ||
| 550 | int ms; | ||
| 551 | do_gettimeofday( &end_tm ); | ||
| 552 | ms = (end_tm.tv_sec*1000000+end_tm.tv_usec) - | ||
| 553 | (start_tm.tv_sec*1000000+start_tm.tv_usec); | ||
| 554 | printk( "SLM: did %ld.%ld ms busy waiting for %d bytes\n", | ||
| 555 | ms/1000, ms%1000, d ); | ||
| 556 | } | ||
| 557 | else | ||
| 558 | printk( "SLM: didn't wait (!)\n" ); | ||
| 559 | #endif | ||
| 560 | |||
| 561 | if ((unsigned char *)PTOV( SLMCurAddr + SLMSliceSize ) >= BufferP) { | ||
| 562 | /* will be last slice, no timer necessary */ | ||
| 563 | #ifdef DEBUG | ||
| 564 | printk( "SLM: CurAddr=%#lx EndAddr=%#lx last slice -> no timer\n", | ||
| 565 | SLMCurAddr, SLMEndAddr ); | ||
| 566 | #endif | ||
| 567 | } | ||
| 568 | else { | ||
| 569 | /* not last slice */ | ||
| 570 | SLMEndAddr = SLMCurAddr + SLMSliceSize + SLM_DMA_INT_OFFSET; | ||
| 571 | START_TIMER( DMA_TIME_FOR( SLMSliceSize )); | ||
| 572 | #ifdef DEBUG | ||
| 573 | printk( "SLM: CurAddr=%#lx EndAddr=%#lx timer=%ld\n", | ||
| 574 | SLMCurAddr, SLMEndAddr, DMA_TIME_FOR( SLMSliceSize ) ); | ||
| 575 | #endif | ||
| 576 | } | ||
| 577 | #endif /* SLM_CONT_CNT_REPROG */ | ||
| 578 | } | ||
| 579 | |||
| 580 | |||
| 581 | static void set_dma_addr( unsigned long paddr ) | ||
| 582 | |||
| 583 | { unsigned long flags; | ||
| 584 | |||
| 585 | local_irq_save(flags); | ||
| 586 | dma_wd.dma_lo = (unsigned char)paddr; | ||
| 587 | paddr >>= 8; | ||
| 588 | MFPDELAY(); | ||
| 589 | dma_wd.dma_md = (unsigned char)paddr; | ||
| 590 | paddr >>= 8; | ||
| 591 | MFPDELAY(); | ||
| 592 | if (ATARIHW_PRESENT( EXTD_DMA )) | ||
| 593 | st_dma_ext_dmahi = (unsigned short)paddr; | ||
| 594 | else | ||
| 595 | dma_wd.dma_hi = (unsigned char)paddr; | ||
| 596 | MFPDELAY(); | ||
| 597 | local_irq_restore(flags); | ||
| 598 | } | ||
| 599 | |||
| 600 | |||
| 601 | static unsigned long get_dma_addr( void ) | ||
| 602 | |||
| 603 | { unsigned long addr; | ||
| 604 | |||
| 605 | addr = dma_wd.dma_lo & 0xff; | ||
| 606 | MFPDELAY(); | ||
| 607 | addr |= (dma_wd.dma_md & 0xff) << 8; | ||
| 608 | MFPDELAY(); | ||
| 609 | addr |= (dma_wd.dma_hi & 0xff) << 16; | ||
| 610 | MFPDELAY(); | ||
| 611 | |||
| 612 | return( addr ); | ||
| 613 | } | ||
| 614 | |||
| 615 | |||
| 616 | static ssize_t slm_write( struct file *file, const char *buf, size_t count, | ||
| 617 | loff_t *ppos ) | ||
| 618 | |||
| 619 | { | ||
| 620 | struct inode *node = file->f_path.dentry->d_inode; | ||
| 621 | int device = iminor(node); | ||
| 622 | int n, filled, w, h; | ||
| 623 | |||
| 624 | while( SLMState == PRINTING || | ||
| 625 | (SLMState == FILLING && SLMBufOwner != device) ) { | ||
| 626 | interruptible_sleep_on( &slm_wait ); | ||
| 627 | if (signal_pending(current)) | ||
| 628 | return( -ERESTARTSYS ); | ||
| 629 | } | ||
| 630 | if (SLMState == IDLE) { | ||
| 631 | /* first data of page: get current page size */ | ||
| 632 | if (slm_get_pagesize( device, &w, &h )) | ||
| 633 | return( -EIO ); | ||
| 634 | BufferSize = w*h/8; | ||
| 635 | if (BufferSize > SLM_BUFFER_SIZE) | ||
| 636 | return( -ENOMEM ); | ||
| 637 | |||
| 638 | SLMState = FILLING; | ||
| 639 | SLMBufOwner = device; | ||
| 640 | } | ||
| 641 | |||
| 642 | n = count; | ||
| 643 | filled = BufferP - SLMBuffer; | ||
| 644 | if (filled + n > BufferSize) | ||
| 645 | n = BufferSize - filled; | ||
| 646 | |||
| 647 | if (copy_from_user(BufferP, buf, n)) | ||
| 648 | return -EFAULT; | ||
| 649 | BufferP += n; | ||
| 650 | filled += n; | ||
| 651 | |||
| 652 | if (filled == BufferSize) { | ||
| 653 | /* Check the paper size again! The user may have switched it in the | ||
| 654 | * time between starting the data and finishing them. Would end up in | ||
| 655 | * a trashy page... */ | ||
| 656 | if (slm_get_pagesize( device, &w, &h )) | ||
| 657 | return( -EIO ); | ||
| 658 | if (BufferSize != w*h/8) { | ||
| 659 | printk( KERN_NOTICE "slm%d: page size changed while printing\n", | ||
| 660 | device ); | ||
| 661 | return( -EAGAIN ); | ||
| 662 | } | ||
| 663 | |||
| 664 | SLMState = PRINTING; | ||
| 665 | /* choose a slice size that is a multiple of the line size */ | ||
| 666 | #ifndef SLM_CONT_CNT_REPROG | ||
| 667 | SLMSliceSize = SLM_SLICE_SIZE(w); | ||
| 668 | #endif | ||
| 669 | |||
| 670 | start_print( device ); | ||
| 671 | sleep_on( &print_wait ); | ||
| 672 | if (SLMError && IS_REAL_ERROR(SLMError)) { | ||
| 673 | printk( KERN_ERR "slm%d: %s\n", device, slm_errstr(SLMError) ); | ||
| 674 | n = -EIO; | ||
| 675 | } | ||
| 676 | |||
| 677 | SLMState = IDLE; | ||
| 678 | BufferP = SLMBuffer; | ||
| 679 | wake_up_interruptible( &slm_wait ); | ||
| 680 | } | ||
| 681 | |||
| 682 | return( n ); | ||
| 683 | } | ||
| 684 | |||
| 685 | |||
| 686 | /* ---------------------------------------------------------------------- */ | ||
| 687 | /* ioctl Functions */ | ||
| 688 | |||
| 689 | |||
| 690 | static int slm_ioctl( struct inode *inode, struct file *file, | ||
| 691 | unsigned int cmd, unsigned long arg ) | ||
| 692 | |||
| 693 | { int device = iminor(inode), err; | ||
| 694 | |||
| 695 | /* I can think of setting: | ||
| 696 | * - manual feed | ||
| 697 | * - paper format | ||
| 698 | * - copy count | ||
| 699 | * - ... | ||
| 700 | * but haven't implemented that yet :-) | ||
| 701 | * BTW, has anybody better docs about the MODE SENSE/MODE SELECT data? | ||
| 702 | */ | ||
| 703 | switch( cmd ) { | ||
| 704 | |||
| 705 | case SLMIORESET: /* reset buffer, i.e. empty the buffer */ | ||
| 706 | if (!(file->f_mode & 2)) | ||
| 707 | return( -EINVAL ); | ||
| 708 | if (SLMState == PRINTING) | ||
| 709 | return( -EBUSY ); | ||
| 710 | SLMState = IDLE; | ||
| 711 | BufferP = SLMBuffer; | ||
| 712 | wake_up_interruptible( &slm_wait ); | ||
| 713 | return( 0 ); | ||
| 714 | |||
| 715 | case SLMIOGSTAT: { /* get status */ | ||
| 716 | int stat; | ||
| 717 | char *str; | ||
| 718 | |||
| 719 | stat = slm_req_sense( device ); | ||
| 720 | if (arg) { | ||
| 721 | str = slm_errstr( stat ); | ||
| 722 | if (put_user(stat, | ||
| 723 | (long *)&((struct SLM_status *)arg)->stat)) | ||
| 724 | return -EFAULT; | ||
| 725 | if (copy_to_user( ((struct SLM_status *)arg)->str, str, | ||
| 726 | strlen(str) + 1)) | ||
| 727 | return -EFAULT; | ||
| 728 | } | ||
| 729 | return( stat ); | ||
| 730 | } | ||
| 731 | |||
| 732 | case SLMIOGPSIZE: { /* get paper size */ | ||
| 733 | int w, h; | ||
| 734 | |||
| 735 | if ((err = slm_get_pagesize( device, &w, &h ))) return( err ); | ||
| 736 | |||
| 737 | if (put_user(w, (long *)&((struct SLM_paper_size *)arg)->width)) | ||
| 738 | return -EFAULT; | ||
| 739 | if (put_user(h, (long *)&((struct SLM_paper_size *)arg)->height)) | ||
| 740 | return -EFAULT; | ||
| 741 | return( 0 ); | ||
| 742 | } | ||
| 743 | |||
| 744 | case SLMIOGMFEED: /* get manual feed */ | ||
| 745 | return( -EINVAL ); | ||
| 746 | |||
| 747 | case SLMIOSPSIZE: /* set paper size */ | ||
| 748 | return( -EINVAL ); | ||
| 749 | |||
| 750 | case SLMIOSMFEED: /* set manual feed */ | ||
| 751 | return( -EINVAL ); | ||
| 752 | |||
| 753 | } | ||
| 754 | return( -EINVAL ); | ||
| 755 | } | ||
| 756 | |||
| 757 | |||
| 758 | /* ---------------------------------------------------------------------- */ | ||
| 759 | /* Opening and Closing */ | ||
| 760 | |||
| 761 | |||
| 762 | static int slm_open( struct inode *inode, struct file *file ) | ||
| 763 | |||
| 764 | { int device; | ||
| 765 | struct slm *sip; | ||
| 766 | |||
| 767 | device = iminor(inode); | ||
| 768 | if (device >= N_SLM_Printers) | ||
| 769 | return( -ENXIO ); | ||
| 770 | sip = &slm_info[device]; | ||
| 771 | |||
| 772 | if (file->f_mode & 2) { | ||
| 773 | /* open for writing is exclusive */ | ||
| 774 | if ( !atomic_dec_and_test(&sip->wr_ok) ) { | ||
| 775 | atomic_inc(&sip->wr_ok); | ||
| 776 | return( -EBUSY ); | ||
| 777 | } | ||
| 778 | } | ||
| 779 | if (file->f_mode & 1) { | ||
| 780 | /* open for reading is exclusive */ | ||
| 781 | if ( !atomic_dec_and_test(&sip->rd_ok) ) { | ||
| 782 | atomic_inc(&sip->rd_ok); | ||
| 783 | return( -EBUSY ); | ||
| 784 | } | ||
| 785 | } | ||
| 786 | |||
| 787 | return( 0 ); | ||
| 788 | } | ||
| 789 | |||
| 790 | |||
| 791 | static int slm_release( struct inode *inode, struct file *file ) | ||
| 792 | |||
| 793 | { int device; | ||
| 794 | struct slm *sip; | ||
| 795 | |||
| 796 | device = iminor(inode); | ||
| 797 | sip = &slm_info[device]; | ||
| 798 | |||
| 799 | if (file->f_mode & 2) | ||
| 800 | atomic_inc( &sip->wr_ok ); | ||
| 801 | if (file->f_mode & 1) | ||
| 802 | atomic_inc( &sip->rd_ok ); | ||
| 803 | |||
| 804 | return( 0 ); | ||
| 805 | } | ||
| 806 | |||
| 807 | |||
| 808 | /* ---------------------------------------------------------------------- */ | ||
| 809 | /* ACSI Primitives for the SLM */ | ||
| 810 | |||
| 811 | |||
| 812 | static int slm_req_sense( int device ) | ||
| 813 | |||
| 814 | { int stat, rv; | ||
| 815 | struct slm *sip = &slm_info[device]; | ||
| 816 | |||
| 817 | stdma_lock( NULL, NULL ); | ||
| 818 | |||
| 819 | CMDSET_TARG_LUN( slmreqsense_cmd, sip->target, sip->lun ); | ||
| 820 | if (!acsicmd_nodma( slmreqsense_cmd, 0 ) || | ||
| 821 | (stat = acsi_getstatus()) < 0) | ||
| 822 | rv = SLMSTAT_ACSITO; | ||
| 823 | else | ||
| 824 | rv = stat & 0x1f; | ||
| 825 | |||
| 826 | ENABLE_IRQ(); | ||
| 827 | stdma_release(); | ||
| 828 | return( rv ); | ||
| 829 | } | ||
| 830 | |||
| 831 | |||
| 832 | static int slm_mode_sense( int device, char *buffer, int abs_flag ) | ||
| 833 | |||
| 834 | { unsigned char stat, len; | ||
| 835 | int rv = 0; | ||
| 836 | struct slm *sip = &slm_info[device]; | ||
| 837 | |||
| 838 | stdma_lock( NULL, NULL ); | ||
| 839 | |||
| 840 | CMDSET_TARG_LUN( slmmsense_cmd, sip->target, sip->lun ); | ||
| 841 | slmmsense_cmd[5] = abs_flag ? 0x80 : 0; | ||
| 842 | if (!acsicmd_nodma( slmmsense_cmd, 0 )) { | ||
| 843 | rv = SLMSTAT_ACSITO; | ||
| 844 | goto the_end; | ||
| 845 | } | ||
| 846 | |||
| 847 | if (!acsi_extstatus( &stat, 1 )) { | ||
| 848 | acsi_end_extstatus(); | ||
| 849 | rv = SLMSTAT_ACSITO; | ||
| 850 | goto the_end; | ||
| 851 | } | ||
| 852 | |||
| 853 | if (!acsi_extstatus( &len, 1 )) { | ||
| 854 | acsi_end_extstatus(); | ||
| 855 | rv = SLMSTAT_ACSITO; | ||
| 856 | goto the_end; | ||
| 857 | } | ||
| 858 | buffer[0] = len; | ||
| 859 | if (!acsi_extstatus( buffer+1, len )) { | ||
| 860 | acsi_end_extstatus(); | ||
| 861 | rv = SLMSTAT_ACSITO; | ||
| 862 | goto the_end; | ||
| 863 | } | ||
| 864 | |||
| 865 | acsi_end_extstatus(); | ||
| 866 | rv = stat & 0x1f; | ||
| 867 | |||
| 868 | the_end: | ||
| 869 | ENABLE_IRQ(); | ||
| 870 | stdma_release(); | ||
| 871 | return( rv ); | ||
| 872 | } | ||
| 873 | |||
| 874 | |||
| 875 | #if 0 | ||
| 876 | /* currently unused */ | ||
| 877 | static int slm_mode_select( int device, char *buffer, int len, | ||
| 878 | int default_flag ) | ||
| 879 | |||
| 880 | { int stat, rv; | ||
| 881 | struct slm *sip = &slm_info[device]; | ||
| 882 | |||
| 883 | stdma_lock( NULL, NULL ); | ||
| 884 | |||
| 885 | CMDSET_TARG_LUN( slmmselect_cmd, sip->target, sip->lun ); | ||
| 886 | slmmselect_cmd[5] = default_flag ? 0x80 : 0; | ||
| 887 | if (!acsicmd_nodma( slmmselect_cmd, 0 )) { | ||
| 888 | rv = SLMSTAT_ACSITO; | ||
| 889 | goto the_end; | ||
| 890 | } | ||
| 891 | |||
| 892 | if (!default_flag) { | ||
| 893 | unsigned char c = len; | ||
| 894 | if (!acsi_extcmd( &c, 1 )) { | ||
| 895 | rv = SLMSTAT_ACSITO; | ||
| 896 | goto the_end; | ||
| 897 | } | ||
| 898 | if (!acsi_extcmd( buffer, len )) { | ||
| 899 | rv = SLMSTAT_ACSITO; | ||
| 900 | goto the_end; | ||
| 901 | } | ||
| 902 | } | ||
| 903 | |||
| 904 | stat = acsi_getstatus(); | ||
| 905 | rv = (stat < 0 ? SLMSTAT_ACSITO : stat); | ||
| 906 | |||
| 907 | the_end: | ||
| 908 | ENABLE_IRQ(); | ||
| 909 | stdma_release(); | ||
| 910 | return( rv ); | ||
| 911 | } | ||
| 912 | #endif | ||
| 913 | |||
| 914 | |||
| 915 | static int slm_get_pagesize( int device, int *w, int *h ) | ||
| 916 | |||
| 917 | { char buf[256]; | ||
| 918 | int stat; | ||
| 919 | |||
| 920 | stat = slm_mode_sense( device, buf, 0 ); | ||
| 921 | ENABLE_IRQ(); | ||
| 922 | stdma_release(); | ||
| 923 | |||
| 924 | if (stat != SLMSTAT_OK) | ||
| 925 | return( -EIO ); | ||
| 926 | |||
| 927 | *w = (buf[3] << 8) | buf[4]; | ||
| 928 | *h = (buf[1] << 8) | buf[2]; | ||
| 929 | return( 0 ); | ||
| 930 | } | ||
| 931 | |||
| 932 | |||
| 933 | /* ---------------------------------------------------------------------- */ | ||
| 934 | /* Initialization */ | ||
| 935 | |||
| 936 | |||
| 937 | int attach_slm( int target, int lun ) | ||
| 938 | |||
| 939 | { static int did_register; | ||
| 940 | int len; | ||
| 941 | |||
| 942 | if (N_SLM_Printers >= MAX_SLM) { | ||
| 943 | printk( KERN_WARNING "Too much SLMs\n" ); | ||
| 944 | return( 0 ); | ||
| 945 | } | ||
| 946 | |||
| 947 | /* do an INQUIRY */ | ||
| 948 | udelay(100); | ||
| 949 | CMDSET_TARG_LUN( slminquiry_cmd, target, lun ); | ||
| 950 | if (!acsicmd_nodma( slminquiry_cmd, 0 )) { | ||
| 951 | inq_timeout: | ||
| 952 | printk( KERN_ERR "SLM inquiry command timed out.\n" ); | ||
| 953 | inq_fail: | ||
| 954 | acsi_end_extstatus(); | ||
| 955 | return( 0 ); | ||
| 956 | } | ||
| 957 | /* read status and header of return data */ | ||
| 958 | if (!acsi_extstatus( SLMBuffer, 6 )) | ||
| 959 | goto inq_timeout; | ||
| 960 | |||
| 961 | if (SLMBuffer[1] != 2) { /* device type == printer? */ | ||
| 962 | printk( KERN_ERR "SLM inquiry returned device type != printer\n" ); | ||
| 963 | goto inq_fail; | ||
| 964 | } | ||
| 965 | len = SLMBuffer[5]; | ||
| 966 | |||
| 967 | /* read id string */ | ||
| 968 | if (!acsi_extstatus( SLMBuffer, len )) | ||
| 969 | goto inq_timeout; | ||
| 970 | acsi_end_extstatus(); | ||
| 971 | SLMBuffer[len] = 0; | ||
| 972 | |||
| 973 | if (!did_register) { | ||
| 974 | did_register = 1; | ||
| 975 | } | ||
| 976 | |||
| 977 | slm_info[N_SLM_Printers].target = target; | ||
| 978 | slm_info[N_SLM_Printers].lun = lun; | ||
| 979 | atomic_set(&slm_info[N_SLM_Printers].wr_ok, 1 ); | ||
| 980 | atomic_set(&slm_info[N_SLM_Printers].rd_ok, 1 ); | ||
| 981 | |||
| 982 | printk( KERN_INFO " Printer: %s\n", SLMBuffer ); | ||
| 983 | printk( KERN_INFO "Detected slm%d at id %d lun %d\n", | ||
| 984 | N_SLM_Printers, target, lun ); | ||
| 985 | N_SLM_Printers++; | ||
| 986 | return( 1 ); | ||
| 987 | } | ||
| 988 | |||
| 989 | int slm_init( void ) | ||
| 990 | |||
| 991 | { | ||
| 992 | int i; | ||
| 993 | if (register_chrdev( ACSI_MAJOR, "slm", &slm_fops )) { | ||
| 994 | printk( KERN_ERR "Unable to get major %d for ACSI SLM\n", ACSI_MAJOR ); | ||
| 995 | return -EBUSY; | ||
| 996 | } | ||
| 997 | |||
| 998 | if (!(SLMBuffer = atari_stram_alloc( SLM_BUFFER_SIZE, "SLM" ))) { | ||
| 999 | printk( KERN_ERR "Unable to get SLM ST-Ram buffer.\n" ); | ||
| 1000 | unregister_chrdev( ACSI_MAJOR, "slm" ); | ||
| 1001 | return -ENOMEM; | ||
| 1002 | } | ||
| 1003 | BufferP = SLMBuffer; | ||
| 1004 | SLMState = IDLE; | ||
| 1005 | |||
| 1006 | return 0; | ||
| 1007 | } | ||
| 1008 | |||
| 1009 | #ifdef MODULE | ||
| 1010 | |||
| 1011 | /* from acsi.c */ | ||
| 1012 | void acsi_attach_SLMs( int (*attach_func)( int, int ) ); | ||
| 1013 | |||
| 1014 | int init_module(void) | ||
| 1015 | { | ||
| 1016 | int err; | ||
| 1017 | |||
| 1018 | if ((err = slm_init())) | ||
| 1019 | return( err ); | ||
| 1020 | /* This calls attach_slm() for every target/lun where acsi.c detected a | ||
| 1021 | * printer */ | ||
| 1022 | acsi_attach_SLMs( attach_slm ); | ||
| 1023 | return( 0 ); | ||
| 1024 | } | ||
| 1025 | |||
| 1026 | void cleanup_module(void) | ||
| 1027 | { | ||
| 1028 | if (unregister_chrdev( ACSI_MAJOR, "slm" ) != 0) | ||
| 1029 | printk( KERN_ERR "acsi_slm: cleanup_module failed\n"); | ||
| 1030 | atari_stram_free( SLMBuffer ); | ||
| 1031 | } | ||
| 1032 | #endif | ||
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index d17d64eb7065..71e7ef2cc99c 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
| @@ -405,22 +405,6 @@ config ATARILANCE | |||
| 405 | on the AMD Lance chipset: RieblCard (with or without battery), or | 405 | on the AMD Lance chipset: RieblCard (with or without battery), or |
| 406 | PAMCard VME (also the version by Rhotron, with different addresses). | 406 | PAMCard VME (also the version by Rhotron, with different addresses). |
| 407 | 407 | ||
| 408 | config ATARI_BIONET | ||
| 409 | tristate "BioNet-100 support" | ||
| 410 | depends on ATARI && ATARI_ACSI && BROKEN | ||
| 411 | help | ||
| 412 | Say Y to include support for BioData's BioNet-100 Ethernet adapter | ||
| 413 | for the ACSI port. The driver works (has to work...) with a polled | ||
| 414 | I/O scheme, so it's rather slow :-( | ||
| 415 | |||
| 416 | config ATARI_PAMSNET | ||
| 417 | tristate "PAMsNet support" | ||
| 418 | depends on ATARI && ATARI_ACSI && BROKEN | ||
| 419 | help | ||
| 420 | Say Y to include support for the PAMsNet Ethernet adapter for the | ||
| 421 | ACSI port ("ACSI node"). The driver works (has to work...) with a | ||
| 422 | polled I/O scheme, so it's rather slow :-( | ||
| 423 | |||
| 424 | config SUN3LANCE | 408 | config SUN3LANCE |
| 425 | tristate "Sun3/Sun3x on-board LANCE support" | 409 | tristate "Sun3/Sun3x on-board LANCE support" |
| 426 | depends on SUN3 || SUN3X | 410 | depends on SUN3 || SUN3X |
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index c26b8674213c..a21b98ea16ad 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile | |||
| @@ -180,8 +180,6 @@ obj-$(CONFIG_MIPS_SIM_NET) += mipsnet.o | |||
| 180 | obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o | 180 | obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o |
| 181 | obj-$(CONFIG_DECLANCE) += declance.o | 181 | obj-$(CONFIG_DECLANCE) += declance.o |
| 182 | obj-$(CONFIG_ATARILANCE) += atarilance.o | 182 | obj-$(CONFIG_ATARILANCE) += atarilance.o |
| 183 | obj-$(CONFIG_ATARI_BIONET) += atari_bionet.o | ||
| 184 | obj-$(CONFIG_ATARI_PAMSNET) += atari_pamsnet.o | ||
| 185 | obj-$(CONFIG_A2065) += a2065.o | 183 | obj-$(CONFIG_A2065) += a2065.o |
| 186 | obj-$(CONFIG_HYDRA) += hydra.o | 184 | obj-$(CONFIG_HYDRA) += hydra.o |
| 187 | obj-$(CONFIG_ARIADNE) += ariadne.o | 185 | obj-$(CONFIG_ARIADNE) += ariadne.o |
diff --git a/drivers/net/Space.c b/drivers/net/Space.c index 1c3e293fbaf7..3b79c6cf21a3 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c | |||
| @@ -75,8 +75,6 @@ extern struct net_device *atarilance_probe(int unit); | |||
| 75 | extern struct net_device *sun3lance_probe(int unit); | 75 | extern struct net_device *sun3lance_probe(int unit); |
| 76 | extern struct net_device *sun3_82586_probe(int unit); | 76 | extern struct net_device *sun3_82586_probe(int unit); |
| 77 | extern struct net_device *apne_probe(int unit); | 77 | extern struct net_device *apne_probe(int unit); |
| 78 | extern struct net_device *bionet_probe(int unit); | ||
| 79 | extern struct net_device *pamsnet_probe(int unit); | ||
| 80 | extern struct net_device *cs89x0_probe(int unit); | 78 | extern struct net_device *cs89x0_probe(int unit); |
| 81 | extern struct net_device *hplance_probe(int unit); | 79 | extern struct net_device *hplance_probe(int unit); |
| 82 | extern struct net_device *bagetlance_probe(int unit); | 80 | extern struct net_device *bagetlance_probe(int unit); |
| @@ -264,12 +262,6 @@ static struct devprobe2 m68k_probes[] __initdata = { | |||
| 264 | #ifdef CONFIG_APNE /* A1200 PCMCIA NE2000 */ | 262 | #ifdef CONFIG_APNE /* A1200 PCMCIA NE2000 */ |
| 265 | {apne_probe, 0}, | 263 | {apne_probe, 0}, |
| 266 | #endif | 264 | #endif |
| 267 | #ifdef CONFIG_ATARI_BIONET /* Atari Bionet Ethernet board */ | ||
| 268 | {bionet_probe, 0}, | ||
| 269 | #endif | ||
| 270 | #ifdef CONFIG_ATARI_PAMSNET /* Atari PAMsNet Ethernet board */ | ||
| 271 | {pamsnet_probe, 0}, | ||
| 272 | #endif | ||
| 273 | #ifdef CONFIG_MVME147_NET /* MVME147 internal Ethernet */ | 265 | #ifdef CONFIG_MVME147_NET /* MVME147 internal Ethernet */ |
| 274 | {mvme147lance_probe, 0}, | 266 | {mvme147lance_probe, 0}, |
| 275 | #endif | 267 | #endif |
diff --git a/drivers/net/atari_bionet.c b/drivers/net/atari_bionet.c deleted file mode 100644 index 3d87bd2b4194..000000000000 --- a/drivers/net/atari_bionet.c +++ /dev/null | |||
| @@ -1,675 +0,0 @@ | |||
| 1 | /* bionet.c BioNet-100 device driver for linux68k. | ||
| 2 | * | ||
| 3 | * Version: @(#)bionet.c 1.0 02/06/96 | ||
| 4 | * | ||
| 5 | * Author: Hartmut Laue <laue@ifk-mp.uni-kiel.de> | ||
| 6 | * and Torsten Narjes <narjes@ifk-mp.uni-kiel.de> | ||
| 7 | * | ||
| 8 | * Little adaptions for integration into pl7 by Roman Hodek | ||
| 9 | * | ||
| 10 | * Some changes in bionet_poll_rx by Karl-Heinz Lohner | ||
| 11 | * | ||
| 12 | What is it ? | ||
| 13 | ------------ | ||
| 14 | This driver controls the BIONET-100 LAN-Adapter which connects | ||
| 15 | an ATARI ST/TT via the ACSI-port to an Ethernet-based network. | ||
| 16 | |||
| 17 | This version can be compiled as a loadable module (See the | ||
| 18 | compile command at the bottom of this file). | ||
| 19 | At load time, you can optionally set the debugging level and the | ||
| 20 | fastest response time on the command line of 'insmod'. | ||
| 21 | |||
| 22 | 'bionet_debug' | ||
| 23 | controls the amount of diagnostic messages: | ||
| 24 | 0 : no messages | ||
| 25 | >0 : see code for meaning of printed messages | ||
| 26 | |||
| 27 | 'bionet_min_poll_time' (always >=1) | ||
| 28 | gives the time (in jiffies) between polls. Low values | ||
| 29 | increase the system load (beware!) | ||
| 30 | |||
| 31 | When loaded, a net device with the name 'bio0' becomes available, | ||
| 32 | which can be controlled with the usual 'ifconfig' command. | ||
| 33 | |||
| 34 | It is possible to compile this driver into the kernel like other | ||
| 35 | (net) drivers. For this purpose, some source files (e.g. config-files | ||
| 36 | makefiles, Space.c) must be changed accordingly. (You may refer to | ||
| 37 | other drivers how to do it.) In this case, the device will be detected | ||
| 38 | at boot time and (probably) appear as 'eth0'. | ||
| 39 | |||
| 40 | This code is based on several sources: | ||
| 41 | - The driver code for a parallel port ethernet adapter by | ||
| 42 | Donald Becker (see file 'atp.c' from the PC linux distribution) | ||
| 43 | - The ACSI code by Roman Hodek for the ATARI-ACSI harddisk support | ||
| 44 | and DMA handling. | ||
| 45 | - Very limited information about moving packets in and out of the | ||
| 46 | BIONET-adapter from the TCP package for TOS by BioData GmbH. | ||
| 47 | |||
| 48 | Theory of Operation | ||
| 49 | ------------------- | ||
| 50 | Because the ATARI DMA port is usually shared between several | ||
| 51 | devices (eg. harddisk, floppy) we cannot block the ACSI bus | ||
| 52 | while waiting for interrupts. Therefore we use a polling mechanism | ||
| 53 | to fetch packets from the adapter. For the same reason, we send | ||
| 54 | packets without checking that the previous packet has been sent to | ||
| 55 | the LAN. We rely on the higher levels of the networking code to detect | ||
| 56 | missing packets and resend them. | ||
| 57 | |||
| 58 | Before we access the ATARI DMA controller, we check if another | ||
| 59 | process is using the DMA. If not, we lock the DMA, perform one or | ||
| 60 | more packet transfers and unlock the DMA before returning. | ||
| 61 | We do not use 'stdma_lock' unconditionally because it is unclear | ||
| 62 | if the networking code can be set to sleep, which will happen if | ||
| 63 | another (possibly slow) device is using the DMA controller. | ||
| 64 | |||
| 65 | The polling is done via timer interrupts which periodically | ||
| 66 | 'simulate' an interrupt from the Ethernet adapter. The time (in jiffies) | ||
| 67 | between polls varies depending on an estimate of the net activity. | ||
| 68 | The allowed range is given by the variable 'bionet_min_poll_time' | ||
| 69 | for the lower (fastest) limit and the constant 'MAX_POLL_TIME' | ||
| 70 | for the higher (slowest) limit. | ||
| 71 | |||
| 72 | Whenever a packet arrives, we switch to fastest response by setting | ||
| 73 | the polling time to its lowest limit. If the following poll fails, | ||
| 74 | because no packets have arrived, we increase the time for the next | ||
| 75 | poll. When the net activity is low, the polling time effectively | ||
| 76 | stays at its maximum value, resulting in the lowest load for the | ||
| 77 | machine. | ||
| 78 | */ | ||
| 79 | |||
| 80 | #define MAX_POLL_TIME 10 | ||
| 81 | |||
| 82 | static char version[] = | ||
| 83 | "bionet.c:v1.0 06-feb-96 (c) Hartmut Laue.\n"; | ||
| 84 | |||
| 85 | #include <linux/module.h> | ||
| 86 | |||
| 87 | #include <linux/errno.h> | ||
| 88 | #include <linux/kernel.h> | ||
| 89 | #include <linux/jiffies.h> | ||
| 90 | #include <linux/types.h> | ||
| 91 | #include <linux/fcntl.h> | ||
| 92 | #include <linux/interrupt.h> | ||
| 93 | #include <linux/ioport.h> | ||
| 94 | #include <linux/in.h> | ||
| 95 | #include <linux/slab.h> | ||
| 96 | #include <linux/string.h> | ||
| 97 | #include <linux/delay.h> | ||
| 98 | #include <linux/timer.h> | ||
| 99 | #include <linux/init.h> | ||
| 100 | #include <linux/bitops.h> | ||
| 101 | |||
| 102 | #include <linux/netdevice.h> | ||
| 103 | #include <linux/etherdevice.h> | ||
| 104 | #include <linux/skbuff.h> | ||
| 105 | |||
| 106 | #include <asm/setup.h> | ||
| 107 | #include <asm/pgtable.h> | ||
| 108 | #include <asm/system.h> | ||
| 109 | #include <asm/io.h> | ||
| 110 | #include <asm/dma.h> | ||
| 111 | #include <asm/atarihw.h> | ||
| 112 | #include <asm/atariints.h> | ||
| 113 | #include <asm/atari_acsi.h> | ||
| 114 | #include <asm/atari_stdma.h> | ||
| 115 | |||
| 116 | |||
| 117 | /* use 0 for production, 1 for verification, >2 for debug | ||
| 118 | */ | ||
| 119 | #ifndef NET_DEBUG | ||
| 120 | #define NET_DEBUG 0 | ||
| 121 | #endif | ||
| 122 | /* | ||
| 123 | * Global variable 'bionet_debug'. Can be set at load time by 'insmod' | ||
| 124 | */ | ||
| 125 | unsigned int bionet_debug = NET_DEBUG; | ||
| 126 | module_param(bionet_debug, int, 0); | ||
| 127 | MODULE_PARM_DESC(bionet_debug, "bionet debug level (0-2)"); | ||
| 128 | MODULE_LICENSE("GPL"); | ||
| 129 | |||
| 130 | static unsigned int bionet_min_poll_time = 2; | ||
| 131 | |||
| 132 | |||
| 133 | /* Information that need to be kept for each board. | ||
| 134 | */ | ||
| 135 | struct net_local { | ||
| 136 | struct net_device_stats stats; | ||
| 137 | long open_time; /* for debugging */ | ||
| 138 | int poll_time; /* polling time varies with net load */ | ||
| 139 | }; | ||
| 140 | |||
| 141 | static struct nic_pkt_s { /* packet format */ | ||
| 142 | unsigned char status; | ||
| 143 | unsigned char dummy; | ||
| 144 | unsigned char l_lo, l_hi; | ||
| 145 | unsigned char buffer[3000]; | ||
| 146 | } *nic_packet; | ||
| 147 | unsigned char *phys_nic_packet; | ||
| 148 | |||
| 149 | /* Index to functions, as function prototypes. | ||
| 150 | */ | ||
| 151 | static int bionet_open(struct net_device *dev); | ||
| 152 | static int bionet_send_packet(struct sk_buff *skb, struct net_device *dev); | ||
| 153 | static void bionet_poll_rx(struct net_device *); | ||
| 154 | static int bionet_close(struct net_device *dev); | ||
| 155 | static struct net_device_stats *net_get_stats(struct net_device *dev); | ||
| 156 | static void bionet_tick(unsigned long); | ||
| 157 | |||
| 158 | static DEFINE_TIMER(bionet_timer, bionet_tick, 0, 0); | ||
| 159 | |||
| 160 | #define STRAM_ADDR(a) (((a) & 0xff000000) == 0) | ||
| 161 | |||
| 162 | /* The following routines access the ethernet board connected to the | ||
| 163 | * ACSI port via the st_dma chip. | ||
| 164 | */ | ||
| 165 | #define NODE_ADR 0x60 | ||
| 166 | |||
| 167 | #define C_READ 8 | ||
| 168 | #define C_WRITE 0x0a | ||
| 169 | #define C_GETEA 0x0f | ||
| 170 | #define C_SETCR 0x0e | ||
| 171 | |||
| 172 | static int | ||
| 173 | sendcmd(unsigned int a0, unsigned int mod, unsigned int cmd) { | ||
| 174 | unsigned int c; | ||
| 175 | |||
| 176 | dma_wd.dma_mode_status = (mod | ((a0) ? 2 : 0) | 0x88); | ||
| 177 | dma_wd.fdc_acces_seccount = cmd; | ||
| 178 | dma_wd.dma_mode_status = (mod | 0x8a); | ||
| 179 | |||
| 180 | if( !acsi_wait_for_IRQ(HZ/2) ) /* wait for cmd ack */ | ||
| 181 | return -1; /* timeout */ | ||
| 182 | |||
| 183 | c = dma_wd.fdc_acces_seccount; | ||
| 184 | return (c & 0xff); | ||
| 185 | } | ||
| 186 | |||
| 187 | |||
| 188 | static void | ||
| 189 | set_status(int cr) { | ||
| 190 | sendcmd(0,0x100,NODE_ADR | C_SETCR); /* CMD: SET CR */ | ||
| 191 | sendcmd(1,0x100,cr); | ||
| 192 | |||
| 193 | dma_wd.dma_mode_status = 0x80; | ||
| 194 | } | ||
| 195 | |||
| 196 | static int | ||
| 197 | get_status(unsigned char *adr) { | ||
| 198 | int i,c; | ||
| 199 | |||
| 200 | DISABLE_IRQ(); | ||
| 201 | c = sendcmd(0,0x00,NODE_ADR | C_GETEA); /* CMD: GET ETH ADR*/ | ||
| 202 | if( c < 0 ) goto gsend; | ||
| 203 | |||
| 204 | /* now read status bytes */ | ||
| 205 | |||
| 206 | for (i=0; i<6; i++) { | ||
| 207 | dma_wd.fdc_acces_seccount = 0; /* request next byte */ | ||
| 208 | |||
| 209 | if( !acsi_wait_for_IRQ(HZ/2) ) { /* wait for cmd ack */ | ||
| 210 | c = -1; | ||
| 211 | goto gsend; /* timeout */ | ||
| 212 | } | ||
| 213 | c = dma_wd.fdc_acces_seccount; | ||
| 214 | *adr++ = (unsigned char)c; | ||
| 215 | } | ||
| 216 | c = 1; | ||
| 217 | gsend: | ||
| 218 | dma_wd.dma_mode_status = 0x80; | ||
| 219 | return c; | ||
| 220 | } | ||
| 221 | |||
| 222 | static irqreturn_t | ||
| 223 | bionet_intr(int irq, void *data) { | ||
| 224 | return IRQ_HANDLED; | ||
| 225 | } | ||
| 226 | |||
| 227 | |||
| 228 | static int | ||
| 229 | get_frame(unsigned long paddr, int odd) { | ||
| 230 | int c; | ||
| 231 | unsigned long flags; | ||
| 232 | |||
| 233 | DISABLE_IRQ(); | ||
| 234 | local_irq_save(flags); | ||
| 235 | |||
| 236 | dma_wd.dma_mode_status = 0x9a; | ||
| 237 | dma_wd.dma_mode_status = 0x19a; | ||
| 238 | dma_wd.dma_mode_status = 0x9a; | ||
| 239 | dma_wd.fdc_acces_seccount = 0x04; /* sector count (was 5) */ | ||
| 240 | dma_wd.dma_lo = (unsigned char)paddr; | ||
| 241 | paddr >>= 8; | ||
| 242 | dma_wd.dma_md = (unsigned char)paddr; | ||
| 243 | paddr >>= 8; | ||
| 244 | dma_wd.dma_hi = (unsigned char)paddr; | ||
| 245 | local_irq_restore(flags); | ||
| 246 | |||
| 247 | c = sendcmd(0,0x00,NODE_ADR | C_READ); /* CMD: READ */ | ||
| 248 | if( c < 128 ) goto rend; | ||
| 249 | |||
| 250 | /* now read block */ | ||
| 251 | |||
| 252 | c = sendcmd(1,0x00,odd); /* odd flag for address shift */ | ||
| 253 | dma_wd.dma_mode_status = 0x0a; | ||
| 254 | |||
| 255 | if( !acsi_wait_for_IRQ(100) ) { /* wait for DMA to complete */ | ||
| 256 | c = -1; | ||
| 257 | goto rend; | ||
| 258 | } | ||
| 259 | dma_wd.dma_mode_status = 0x8a; | ||
| 260 | dma_wd.dma_mode_status = 0x18a; | ||
| 261 | dma_wd.dma_mode_status = 0x8a; | ||
| 262 | c = dma_wd.fdc_acces_seccount; | ||
| 263 | |||
| 264 | dma_wd.dma_mode_status = 0x88; | ||
| 265 | c = dma_wd.fdc_acces_seccount; | ||
| 266 | c = 1; | ||
| 267 | |||
| 268 | rend: | ||
| 269 | dma_wd.dma_mode_status = 0x80; | ||
| 270 | udelay(40); | ||
| 271 | acsi_wait_for_noIRQ(20); | ||
| 272 | return c; | ||
| 273 | } | ||
| 274 | |||
| 275 | |||
| 276 | static int | ||
| 277 | hardware_send_packet(unsigned long paddr, int cnt) { | ||
| 278 | unsigned int c; | ||
| 279 | unsigned long flags; | ||
| 280 | |||
| 281 | DISABLE_IRQ(); | ||
| 282 | local_irq_save(flags); | ||
| 283 | |||
| 284 | dma_wd.dma_mode_status = 0x19a; | ||
| 285 | dma_wd.dma_mode_status = 0x9a; | ||
| 286 | dma_wd.dma_mode_status = 0x19a; | ||
| 287 | dma_wd.dma_lo = (unsigned char)paddr; | ||
| 288 | paddr >>= 8; | ||
| 289 | dma_wd.dma_md = (unsigned char)paddr; | ||
| 290 | paddr >>= 8; | ||
| 291 | dma_wd.dma_hi = (unsigned char)paddr; | ||
| 292 | |||
| 293 | dma_wd.fdc_acces_seccount = 0x4; /* sector count */ | ||
| 294 | local_irq_restore(flags); | ||
| 295 | |||
| 296 | c = sendcmd(0,0x100,NODE_ADR | C_WRITE); /* CMD: WRITE */ | ||
| 297 | c = sendcmd(1,0x100,cnt&0xff); | ||
| 298 | c = sendcmd(1,0x100,cnt>>8); | ||
| 299 | |||
| 300 | /* now write block */ | ||
| 301 | |||
| 302 | dma_wd.dma_mode_status = 0x10a; /* DMA enable */ | ||
| 303 | if( !acsi_wait_for_IRQ(100) ) /* wait for DMA to complete */ | ||
| 304 | goto end; | ||
| 305 | |||
| 306 | dma_wd.dma_mode_status = 0x19a; /* DMA disable ! */ | ||
| 307 | c = dma_wd.fdc_acces_seccount; | ||
| 308 | |||
| 309 | end: | ||
| 310 | c = sendcmd(1,0x100,0); | ||
| 311 | c = sendcmd(1,0x100,0); | ||
| 312 | |||
| 313 | dma_wd.dma_mode_status = 0x180; | ||
| 314 | udelay(40); | ||
| 315 | acsi_wait_for_noIRQ(20); | ||
| 316 | return( c & 0x02); | ||
| 317 | } | ||
| 318 | |||
| 319 | |||
| 320 | /* Check for a network adaptor of this type, and return '0' if one exists. | ||
| 321 | */ | ||
| 322 | struct net_device * __init bionet_probe(int unit) | ||
| 323 | { | ||
| 324 | struct net_device *dev; | ||
| 325 | unsigned char station_addr[6]; | ||
| 326 | static unsigned version_printed; | ||
| 327 | static int no_more_found; /* avoid "Probing for..." printed 4 times */ | ||
| 328 | int i; | ||
| 329 | int err; | ||
| 330 | |||
| 331 | if (!MACH_IS_ATARI || no_more_found) | ||
| 332 | return ERR_PTR(-ENODEV); | ||
| 333 | |||
| 334 | dev = alloc_etherdev(sizeof(struct net_local)); | ||
| 335 | if (!dev) | ||
| 336 | return ERR_PTR(-ENOMEM); | ||
| 337 | if (unit >= 0) { | ||
| 338 | sprintf(dev->name, "eth%d", unit); | ||
| 339 | netdev_boot_setup_check(dev); | ||
| 340 | } | ||
| 341 | SET_MODULE_OWNER(dev); | ||
| 342 | |||
| 343 | printk("Probing for BioNet 100 Adapter...\n"); | ||
| 344 | |||
| 345 | stdma_lock(bionet_intr, NULL); | ||
| 346 | i = get_status(station_addr); /* Read the station address PROM. */ | ||
| 347 | ENABLE_IRQ(); | ||
| 348 | stdma_release(); | ||
| 349 | |||
| 350 | /* Check the first three octets of the S.A. for the manufactor's code. | ||
| 351 | */ | ||
| 352 | |||
| 353 | if( i < 0 | ||
| 354 | || station_addr[0] != 'B' | ||
| 355 | || station_addr[1] != 'I' | ||
| 356 | || station_addr[2] != 'O' ) { | ||
| 357 | no_more_found = 1; | ||
| 358 | printk( "No BioNet 100 found.\n" ); | ||
| 359 | free_netdev(dev); | ||
| 360 | return ERR_PTR(-ENODEV); | ||
| 361 | } | ||
| 362 | |||
| 363 | if (bionet_debug > 0 && version_printed++ == 0) | ||
| 364 | printk(version); | ||
| 365 | |||
| 366 | printk("%s: %s found, eth-addr: %02x-%02x-%02x:%02x-%02x-%02x.\n", | ||
| 367 | dev->name, "BioNet 100", | ||
| 368 | station_addr[0], station_addr[1], station_addr[2], | ||
| 369 | station_addr[3], station_addr[4], station_addr[5]); | ||
| 370 | |||
| 371 | /* Initialize the device structure. */ | ||
| 372 | |||
| 373 | nic_packet = (struct nic_pkt_s *)acsi_buffer; | ||
| 374 | phys_nic_packet = (unsigned char *)phys_acsi_buffer; | ||
| 375 | if (bionet_debug > 0) { | ||
| 376 | printk("nic_packet at 0x%p, phys at 0x%p\n", | ||
| 377 | nic_packet, phys_nic_packet ); | ||
| 378 | } | ||
| 379 | |||
| 380 | dev->open = bionet_open; | ||
| 381 | dev->stop = bionet_close; | ||
| 382 | dev->hard_start_xmit = bionet_send_packet; | ||
| 383 | dev->get_stats = net_get_stats; | ||
| 384 | |||
| 385 | /* Fill in the fields of the device structure with ethernet-generic | ||
| 386 | * values. This should be in a common file instead of per-driver. | ||
| 387 | */ | ||
| 388 | |||
| 389 | for (i = 0; i < ETH_ALEN; i++) { | ||
| 390 | #if 0 | ||
| 391 | dev->broadcast[i] = 0xff; | ||
| 392 | #endif | ||
| 393 | dev->dev_addr[i] = station_addr[i]; | ||
| 394 | } | ||
| 395 | err = register_netdev(dev); | ||
| 396 | if (!err) | ||
| 397 | return dev; | ||
| 398 | free_netdev(dev); | ||
| 399 | return ERR_PTR(err); | ||
| 400 | } | ||
| 401 | |||
| 402 | /* Open/initialize the board. This is called (in the current kernel) | ||
| 403 | sometime after booting when the 'ifconfig' program is run. | ||
| 404 | |||
| 405 | This routine should set everything up anew at each open, even | ||
| 406 | registers that "should" only need to be set once at boot, so that | ||
| 407 | there is non-reboot way to recover if something goes wrong. | ||
| 408 | */ | ||
| 409 | static int | ||
| 410 | bionet_open(struct net_device *dev) { | ||
| 411 | struct net_local *lp = netdev_priv(dev); | ||
| 412 | |||
| 413 | if (bionet_debug > 0) | ||
| 414 | printk("bionet_open\n"); | ||
| 415 | stdma_lock(bionet_intr, NULL); | ||
| 416 | |||
| 417 | /* Reset the hardware here. | ||
| 418 | */ | ||
| 419 | set_status(4); | ||
| 420 | lp->open_time = 0; /*jiffies*/ | ||
| 421 | lp->poll_time = MAX_POLL_TIME; | ||
| 422 | |||
| 423 | dev->tbusy = 0; | ||
| 424 | dev->interrupt = 0; | ||
| 425 | dev->start = 1; | ||
| 426 | |||
| 427 | stdma_release(); | ||
| 428 | bionet_timer.data = (long)dev; | ||
| 429 | bionet_timer.expires = jiffies + lp->poll_time; | ||
| 430 | add_timer(&bionet_timer); | ||
| 431 | return 0; | ||
| 432 | } | ||
| 433 | |||
| 434 | static int | ||
| 435 | bionet_send_packet(struct sk_buff *skb, struct net_device *dev) { | ||
| 436 | struct net_local *lp = netdev_priv(dev); | ||
| 437 | unsigned long flags; | ||
| 438 | |||
| 439 | /* Block a timer-based transmit from overlapping. This could better be | ||
| 440 | * done with atomic_swap(1, dev->tbusy), but set_bit() works as well. | ||
| 441 | */ | ||
| 442 | local_irq_save(flags); | ||
| 443 | |||
| 444 | if (stdma_islocked()) { | ||
| 445 | local_irq_restore(flags); | ||
| 446 | lp->stats.tx_errors++; | ||
| 447 | } | ||
| 448 | else { | ||
| 449 | int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; | ||
| 450 | unsigned long buf = virt_to_phys(skb->data); | ||
| 451 | int stat; | ||
| 452 | |||
| 453 | stdma_lock(bionet_intr, NULL); | ||
| 454 | local_irq_restore(flags); | ||
| 455 | if( !STRAM_ADDR(buf+length-1) ) { | ||
| 456 | skb_copy_from_linear_data(skb, nic_packet->buffer, | ||
| 457 | length); | ||
| 458 | buf = (unsigned long)&((struct nic_pkt_s *)phys_nic_packet)->buffer; | ||
| 459 | } | ||
| 460 | |||
| 461 | if (bionet_debug >1) { | ||
| 462 | u_char *data = nic_packet->buffer, *p; | ||
| 463 | int i; | ||
| 464 | |||
| 465 | printk( "%s: TX pkt type 0x%4x from ", dev->name, | ||
| 466 | ((u_short *)data)[6]); | ||
| 467 | |||
| 468 | for( p = &data[6], i = 0; i < 6; i++ ) | ||
| 469 | printk("%02x%s", *p++,i != 5 ? ":" : "" ); | ||
| 470 | printk(" to "); | ||
| 471 | |||
| 472 | for( p = data, i = 0; i < 6; i++ ) | ||
| 473 | printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" ); | ||
| 474 | |||
| 475 | printk( "%s: ", dev->name ); | ||
| 476 | printk(" data %02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x" | ||
| 477 | " %02x%02x%02x%02x len %d\n", | ||
| 478 | data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19], | ||
| 479 | data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27], | ||
| 480 | data[28], data[29], data[30], data[31], data[32], data[33], | ||
| 481 | length ); | ||
| 482 | } | ||
| 483 | dma_cache_maintenance(buf, length, 1); | ||
| 484 | |||
| 485 | stat = hardware_send_packet(buf, length); | ||
| 486 | ENABLE_IRQ(); | ||
| 487 | stdma_release(); | ||
| 488 | |||
| 489 | dev->trans_start = jiffies; | ||
| 490 | dev->tbusy = 0; | ||
| 491 | lp->stats.tx_packets++; | ||
| 492 | lp->stats.tx_bytes+=length; | ||
| 493 | } | ||
| 494 | dev_kfree_skb(skb); | ||
| 495 | |||
| 496 | return 0; | ||
| 497 | } | ||
| 498 | |||
| 499 | /* We have a good packet(s), get it/them out of the buffers. | ||
| 500 | */ | ||
| 501 | static void | ||
| 502 | bionet_poll_rx(struct net_device *dev) { | ||
| 503 | struct net_local *lp = netdev_priv(dev); | ||
| 504 | int boguscount = 10; | ||
| 505 | int pkt_len, status; | ||
| 506 | unsigned long flags; | ||
| 507 | |||
| 508 | local_irq_save(flags); | ||
| 509 | /* ++roman: Take care at locking the ST-DMA... This must be done with ints | ||
| 510 | * off, since otherwise an int could slip in between the question and the | ||
| 511 | * locking itself, and then we'd go to sleep... And locking itself is | ||
| 512 | * necessary to keep the floppy_change timer from working with ST-DMA | ||
| 513 | * registers. */ | ||
| 514 | if (stdma_islocked()) { | ||
| 515 | local_irq_restore(flags); | ||
| 516 | return; | ||
| 517 | } | ||
| 518 | stdma_lock(bionet_intr, NULL); | ||
| 519 | DISABLE_IRQ(); | ||
| 520 | local_irq_restore(flags); | ||
| 521 | |||
| 522 | if( lp->poll_time < MAX_POLL_TIME ) lp->poll_time++; | ||
| 523 | |||
| 524 | while(boguscount--) { | ||
| 525 | status = get_frame((unsigned long)phys_nic_packet, 0); | ||
| 526 | |||
| 527 | if( status == 0 ) break; | ||
| 528 | |||
| 529 | /* Good packet... */ | ||
| 530 | |||
| 531 | dma_cache_maintenance((unsigned long)phys_nic_packet, 1520, 0); | ||
| 532 | |||
| 533 | pkt_len = (nic_packet->l_hi << 8) | nic_packet->l_lo; | ||
| 534 | |||
| 535 | lp->poll_time = bionet_min_poll_time; /* fast poll */ | ||
| 536 | if( pkt_len >= 60 && pkt_len <= 1520 ) { | ||
| 537 | /* ^^^^ war 1514 KHL */ | ||
| 538 | /* Malloc up new buffer. | ||
| 539 | */ | ||
| 540 | struct sk_buff *skb = dev_alloc_skb( pkt_len + 2 ); | ||
| 541 | if (skb == NULL) { | ||
| 542 | printk("%s: Memory squeeze, dropping packet.\n", | ||
| 543 | dev->name); | ||
| 544 | lp->stats.rx_dropped++; | ||
| 545 | break; | ||
| 546 | } | ||
| 547 | |||
| 548 | skb_reserve( skb, 2 ); /* 16 Byte align */ | ||
| 549 | skb_put( skb, pkt_len ); /* make room */ | ||
| 550 | |||
| 551 | /* 'skb->data' points to the start of sk_buff data area. | ||
| 552 | */ | ||
| 553 | skb_copy_to_linear_data(skb, nic_packet->buffer, | ||
| 554 | pkt_len); | ||
| 555 | skb->protocol = eth_type_trans( skb, dev ); | ||
| 556 | netif_rx(skb); | ||
| 557 | dev->last_rx = jiffies; | ||
| 558 | lp->stats.rx_packets++; | ||
| 559 | lp->stats.rx_bytes+=pkt_len; | ||
| 560 | |||
| 561 | /* If any worth-while packets have been received, dev_rint() | ||
| 562 | has done a mark_bh(INET_BH) for us and will work on them | ||
| 563 | when we get to the bottom-half routine. | ||
| 564 | */ | ||
| 565 | |||
| 566 | if (bionet_debug >1) { | ||
| 567 | u_char *data = nic_packet->buffer, *p; | ||
| 568 | int i; | ||
| 569 | |||
| 570 | printk( "%s: RX pkt type 0x%4x from ", dev->name, | ||
| 571 | ((u_short *)data)[6]); | ||
| 572 | |||
| 573 | |||
| 574 | for( p = &data[6], i = 0; i < 6; i++ ) | ||
| 575 | printk("%02x%s", *p++,i != 5 ? ":" : "" ); | ||
| 576 | printk(" to "); | ||
| 577 | for( p = data, i = 0; i < 6; i++ ) | ||
| 578 | printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" ); | ||
| 579 | |||
| 580 | printk( "%s: ", dev->name ); | ||
| 581 | printk(" data %02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x" | ||
| 582 | " %02x%02x%02x%02x len %d\n", | ||
| 583 | data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19], | ||
| 584 | data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27], | ||
| 585 | data[28], data[29], data[30], data[31], data[32], data[33], | ||
| 586 | pkt_len ); | ||
| 587 | } | ||
| 588 | } | ||
| 589 | else { | ||
| 590 | printk(" Packet has wrong length: %04d bytes\n", pkt_len); | ||
| 591 | lp->stats.rx_errors++; | ||
| 592 | } | ||
| 593 | } | ||
| 594 | stdma_release(); | ||
| 595 | ENABLE_IRQ(); | ||
| 596 | return; | ||
| 597 | } | ||
| 598 | |||
| 599 | /* bionet_tick: called by bionet_timer. Reads packets from the adapter, | ||
| 600 | * passes them to the higher layers and restarts the timer. | ||
| 601 | */ | ||
| 602 | static void | ||
| 603 | bionet_tick(unsigned long data) { | ||
| 604 | struct net_device *dev = (struct net_device *)data; | ||
| 605 | struct net_local *lp = netdev_priv(dev); | ||
| 606 | |||
| 607 | if( bionet_debug > 0 && (lp->open_time++ & 7) == 8 ) | ||
| 608 | printk("bionet_tick: %ld\n", lp->open_time); | ||
| 609 | |||
| 610 | if( !stdma_islocked() ) bionet_poll_rx(dev); | ||
| 611 | |||
| 612 | bionet_timer.expires = jiffies + lp->poll_time; | ||
| 613 | add_timer(&bionet_timer); | ||
| 614 | } | ||
| 615 | |||
| 616 | /* The inverse routine to bionet_open(). | ||
| 617 | */ | ||
| 618 | static int | ||
| 619 | bionet_close(struct net_device *dev) { | ||
| 620 | struct net_local *lp = netdev_priv(dev); | ||
| 621 | |||
| 622 | if (bionet_debug > 0) | ||
| 623 | printk("bionet_close, open_time=%ld\n", lp->open_time); | ||
| 624 | del_timer(&bionet_timer); | ||
| 625 | stdma_lock(bionet_intr, NULL); | ||
| 626 | |||
| 627 | set_status(0); | ||
| 628 | lp->open_time = 0; | ||
| 629 | |||
| 630 | dev->tbusy = 1; | ||
| 631 | dev->start = 0; | ||
| 632 | |||
| 633 | stdma_release(); | ||
| 634 | return 0; | ||
| 635 | } | ||
| 636 | |||
| 637 | /* Get the current statistics. | ||
| 638 | This may be called with the card open or closed. | ||
| 639 | */ | ||
| 640 | static struct net_device_stats *net_get_stats(struct net_device *dev) | ||
| 641 | { | ||
| 642 | struct net_local *lp = netdev_priv(dev); | ||
| 643 | return &lp->stats; | ||
| 644 | } | ||
| 645 | |||
| 646 | |||
| 647 | #ifdef MODULE | ||
| 648 | |||
| 649 | static struct net_device *bio_dev; | ||
| 650 | |||
| 651 | int init_module(void) | ||
| 652 | { | ||
| 653 | bio_dev = bionet_probe(-1); | ||
| 654 | if (IS_ERR(bio_dev)) | ||
| 655 | return PTR_ERR(bio_dev); | ||
| 656 | return 0; | ||
| 657 | } | ||
| 658 | |||
| 659 | void cleanup_module(void) | ||
| 660 | { | ||
| 661 | unregister_netdev(bio_dev); | ||
| 662 | free_netdev(bio_dev); | ||
| 663 | } | ||
| 664 | |||
| 665 | #endif /* MODULE */ | ||
| 666 | |||
| 667 | /* Local variables: | ||
| 668 | * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include | ||
| 669 | -b m68k-linuxaout -Wall -Wstrict-prototypes -O2 | ||
| 670 | -fomit-frame-pointer -pipe -DMODULE -I../../net/inet -c bionet.c" | ||
| 671 | * version-control: t | ||
| 672 | * kept-new-versions: 5 | ||
| 673 | * tab-width: 8 | ||
| 674 | * End: | ||
| 675 | */ | ||
diff --git a/drivers/net/atari_pamsnet.c b/drivers/net/atari_pamsnet.c deleted file mode 100644 index f7356374a2e7..000000000000 --- a/drivers/net/atari_pamsnet.c +++ /dev/null | |||
| @@ -1,878 +0,0 @@ | |||
| 1 | /* atari_pamsnet.c PAMsNet device driver for linux68k. | ||
| 2 | * | ||
| 3 | * Version: @(#)PAMsNet.c 0.2ß 03/31/96 | ||
| 4 | * | ||
| 5 | * Author: Torsten Lang <Torsten.Lang@ap.physik.uni-giessen.de> | ||
| 6 | * <Torsten.Lang@jung.de> | ||
| 7 | * | ||
| 8 | * This driver is based on my driver PAMSDMA.c for MiNT-Net and | ||
| 9 | * on the driver bionet.c written by | ||
| 10 | * Hartmut Laue <laue@ifk-mp.uni-kiel.de> | ||
| 11 | * and Torsten Narjes <narjes@ifk-mp.uni-kiel.de> | ||
| 12 | * | ||
| 13 | * Little adaptions for integration into pl7 by Roman Hodek | ||
| 14 | * | ||
| 15 | What is it ? | ||
| 16 | ------------ | ||
| 17 | This driver controls the PAMsNet LAN-Adapter which connects | ||
| 18 | an ATARI ST/TT via the ACSI-port to an Ethernet-based network. | ||
| 19 | |||
| 20 | This version can be compiled as a loadable module (See the | ||
| 21 | compile command at the bottom of this file). | ||
| 22 | At load time, you can optionally set the debugging level and the | ||
| 23 | fastest response time on the command line of 'insmod'. | ||
| 24 | |||
| 25 | 'pamsnet_debug' | ||
| 26 | controls the amount of diagnostic messages: | ||
| 27 | 0 : no messages | ||
| 28 | >0 : see code for meaning of printed messages | ||
| 29 | |||
| 30 | 'pamsnet_min_poll_time' (always >=1) | ||
| 31 | gives the time (in jiffies) between polls. Low values | ||
| 32 | increase the system load (beware!) | ||
| 33 | |||
| 34 | When loaded, a net device with the name 'eth?' becomes available, | ||
| 35 | which can be controlled with the usual 'ifconfig' command. | ||
| 36 | |||
| 37 | It is possible to compile this driver into the kernel like other | ||
| 38 | (net) drivers. For this purpose, some source files (e.g. config-files | ||
| 39 | makefiles, Space.c) must be changed accordingly. (You may refer to | ||
| 40 | other drivers how to do it.) In this case, the device will be detected | ||
| 41 | at boot time and (probably) appear as 'eth0'. | ||
| 42 | |||
| 43 | Theory of Operation | ||
| 44 | ------------------- | ||
| 45 | Because the ATARI DMA port is usually shared between several | ||
| 46 | devices (eg. harddisk, floppy) we cannot block the ACSI bus | ||
| 47 | while waiting for interrupts. Therefore we use a polling mechanism | ||
| 48 | to fetch packets from the adapter. For the same reason, we send | ||
| 49 | packets without checking that the previous packet has been sent to | ||
| 50 | the LAN. We rely on the higher levels of the networking code to detect | ||
| 51 | missing packets and resend them. | ||
| 52 | |||
| 53 | Before we access the ATARI DMA controller, we check if another | ||
| 54 | process is using the DMA. If not, we lock the DMA, perform one or | ||
| 55 | more packet transfers and unlock the DMA before returning. | ||
| 56 | We do not use 'stdma_lock' unconditionally because it is unclear | ||
| 57 | if the networking code can be set to sleep, which will happen if | ||
| 58 | another (possibly slow) device is using the DMA controller. | ||
| 59 | |||
| 60 | The polling is done via timer interrupts which periodically | ||
| 61 | 'simulate' an interrupt from the Ethernet adapter. The time (in jiffies) | ||
| 62 | between polls varies depending on an estimate of the net activity. | ||
| 63 | The allowed range is given by the variable 'bionet_min_poll_time' | ||
| 64 | for the lower (fastest) limit and the constant 'MAX_POLL_TIME' | ||
| 65 | for the higher (slowest) limit. | ||
| 66 | |||
| 67 | Whenever a packet arrives, we switch to fastest response by setting | ||
| 68 | the polling time to its lowest limit. If the following poll fails, | ||
| 69 | because no packets have arrived, we increase the time for the next | ||
| 70 | poll. When the net activity is low, the polling time effectively | ||
| 71 | stays at its maximum value, resulting in the lowest load for the | ||
| 72 | machine. | ||
| 73 | */ | ||
| 74 | |||
| 75 | #define MAX_POLL_TIME 10 | ||
| 76 | |||
| 77 | static char *version = | ||
| 78 | "pamsnet.c:v0.2beta 30-mar-96 (c) Torsten Lang.\n"; | ||
| 79 | |||
| 80 | #include <linux/module.h> | ||
| 81 | |||
| 82 | #include <linux/kernel.h> | ||
| 83 | #include <linux/jiffies.h> | ||
| 84 | #include <linux/types.h> | ||
| 85 | #include <linux/fcntl.h> | ||
| 86 | #include <linux/interrupt.h> | ||
| 87 | #include <linux/ioport.h> | ||
| 88 | #include <linux/in.h> | ||
| 89 | #include <linux/slab.h> | ||
| 90 | #include <linux/string.h> | ||
| 91 | #include <linux/bitops.h> | ||
| 92 | #include <asm/system.h> | ||
| 93 | #include <asm/pgtable.h> | ||
| 94 | #include <asm/io.h> | ||
| 95 | #include <asm/dma.h> | ||
| 96 | #include <linux/errno.h> | ||
| 97 | #include <asm/atarihw.h> | ||
| 98 | #include <asm/atariints.h> | ||
| 99 | #include <asm/atari_stdma.h> | ||
| 100 | #include <asm/atari_acsi.h> | ||
| 101 | |||
| 102 | #include <linux/delay.h> | ||
| 103 | #include <linux/timer.h> | ||
| 104 | #include <linux/init.h> | ||
| 105 | |||
| 106 | #include <linux/netdevice.h> | ||
| 107 | #include <linux/etherdevice.h> | ||
| 108 | #include <linux/skbuff.h> | ||
| 109 | |||
| 110 | #undef READ | ||
| 111 | #undef WRITE | ||
| 112 | |||
| 113 | /* use 0 for production, 1 for verification, >2 for debug | ||
| 114 | */ | ||
| 115 | #ifndef NET_DEBUG | ||
| 116 | #define NET_DEBUG 0 | ||
| 117 | #endif | ||
| 118 | /* | ||
| 119 | * Global variable 'pamsnet_debug'. Can be set at load time by 'insmod' | ||
| 120 | */ | ||
| 121 | unsigned int pamsnet_debug = NET_DEBUG; | ||
| 122 | module_param(pamsnet_debug, int, 0); | ||
| 123 | MODULE_PARM_DESC(pamsnet_debug, "pamsnet debug enable (0-1)"); | ||
| 124 | MODULE_LICENSE("GPL"); | ||
| 125 | |||
| 126 | static unsigned int pamsnet_min_poll_time = 2; | ||
| 127 | |||
| 128 | |||
| 129 | /* Information that need to be kept for each board. | ||
| 130 | */ | ||
| 131 | struct net_local { | ||
| 132 | struct net_device_stats stats; | ||
| 133 | long open_time; /* for debugging */ | ||
| 134 | int poll_time; /* polling time varies with net load */ | ||
| 135 | }; | ||
| 136 | |||
| 137 | static struct nic_pkt_s { /* packet format */ | ||
| 138 | unsigned char buffer[2048]; | ||
| 139 | } *nic_packet = 0; | ||
| 140 | unsigned char *phys_nic_packet; | ||
| 141 | |||
| 142 | typedef unsigned char HADDR[6]; /* 6-byte hardware address of lance */ | ||
| 143 | |||
| 144 | /* Index to functions, as function prototypes. | ||
| 145 | */ | ||
| 146 | static void start (int target); | ||
| 147 | static int stop (int target); | ||
| 148 | static int testpkt (int target); | ||
| 149 | static int sendpkt (int target, unsigned char *buffer, int length); | ||
| 150 | static int receivepkt (int target, unsigned char *buffer); | ||
| 151 | static int inquiry (int target, unsigned char *buffer); | ||
| 152 | static HADDR *read_hw_addr(int target, unsigned char *buffer); | ||
| 153 | static void setup_dma (void *address, unsigned rw_flag, int num_blocks); | ||
| 154 | static int send_first (int target, unsigned char byte); | ||
| 155 | static int send_1_5 (int lun, unsigned char *command, int dma); | ||
| 156 | static int get_status (void); | ||
| 157 | static int calc_received (void *start_address); | ||
| 158 | |||
| 159 | static int pamsnet_open(struct net_device *dev); | ||
| 160 | static int pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev); | ||
| 161 | static void pamsnet_poll_rx(struct net_device *); | ||
| 162 | static int pamsnet_close(struct net_device *dev); | ||
| 163 | static struct net_device_stats *net_get_stats(struct net_device *dev); | ||
| 164 | static void pamsnet_tick(unsigned long); | ||
| 165 | |||
| 166 | static irqreturn_t pamsnet_intr(int irq, void *data); | ||
| 167 | |||
| 168 | static DEFINE_TIMER(pamsnet_timer, pamsnet_tick, 0, 0); | ||
| 169 | |||
| 170 | #define STRAM_ADDR(a) (((a) & 0xff000000) == 0) | ||
| 171 | |||
| 172 | typedef struct | ||
| 173 | { | ||
| 174 | unsigned char reserved1[0x38]; | ||
| 175 | HADDR hwaddr; | ||
| 176 | unsigned char reserved2[0x1c2]; | ||
| 177 | } DMAHWADDR; | ||
| 178 | |||
| 179 | /* | ||
| 180 | * Definitions of commands understood by the PAMs DMA adaptor. | ||
| 181 | * | ||
| 182 | * In general the DMA adaptor uses LUN 0, 5, 6 and 7 on one ID changeable | ||
| 183 | * by the PAM's Net software. | ||
| 184 | * | ||
| 185 | * LUN 0 works as a harddisk. You can boot the PAM's Net driver there. | ||
| 186 | * LUN 5 works as a harddisk and lets you access the RAM and some I/O HW | ||
| 187 | * area. In sector 0, bytes 0x38-0x3d you find the ethernet HW address | ||
| 188 | * of the adaptor. | ||
| 189 | * LUN 6 works as a harddisk and lets you access the firmware ROM. | ||
| 190 | * LUN 7 lets you send and receive packets. | ||
| 191 | * | ||
| 192 | * Some commands like the INQUIRY command work identical on all used LUNs. | ||
| 193 | * | ||
| 194 | * UNKNOWN1 seems to read some data. | ||
| 195 | * Command length is 6 bytes. | ||
| 196 | * UNKNOWN2 seems to read some data (command byte 1 must be !=0). The | ||
| 197 | * following bytes seem to be something like an allocation length. | ||
| 198 | * Command length is 6 bytes. | ||
| 199 | * READPKT reads a packet received by the DMA adaptor. | ||
| 200 | * Command length is 6 bytes. | ||
| 201 | * WRITEPKT sends a packet transferred by the following DMA phase. The length | ||
| 202 | * of the packet is transferred in command bytes 3 and 4. | ||
| 203 | * The adaptor automatically replaces the src hw address in an ethernet | ||
| 204 | * packet by its own hw address. | ||
| 205 | * Command length is 6 bytes. | ||
| 206 | * INQUIRY has the same function as the INQUIRY command supported by harddisks | ||
| 207 | * and other SCSI devices. It lets you detect which device you found | ||
| 208 | * at a given address. | ||
| 209 | * Command length is 6 bytes. | ||
| 210 | * START initializes the DMA adaptor. After this command it is able to send | ||
| 211 | * and receive packets. There is no status byte returned! | ||
| 212 | * Command length is 1 byte. | ||
| 213 | * NUMPKTS gives back the number of received packets waiting in the queue in | ||
| 214 | * the status byte. | ||
| 215 | * Command length is 1 byte. | ||
| 216 | * UNKNOWN3 | ||
| 217 | * UNKNOWN4 Function of these three commands is unknown. | ||
| 218 | * UNKNOWN5 The command length of these three commands is 1 byte. | ||
| 219 | * DESELECT immediately deselects the DMA adaptor. May important with interrupt | ||
| 220 | * driven operation. | ||
| 221 | * Command length is 1 byte. | ||
| 222 | * STOP resets the DMA adaptor. After this command packets can no longer | ||
| 223 | * be received or transferred. | ||
| 224 | * Command length is 6 byte. | ||
| 225 | */ | ||
| 226 | |||
| 227 | enum {UNKNOWN1=3, READPKT=8, UNKNOWN2, WRITEPKT=10, INQUIRY=18, START, | ||
| 228 | NUMPKTS=22, UNKNOWN3, UNKNOWN4, UNKNOWN5, DESELECT, STOP}; | ||
| 229 | |||
| 230 | #define READSECTOR READPKT | ||
| 231 | #define WRITESECTOR WRITEPKT | ||
| 232 | |||
| 233 | u_char *inquire8="MV PAM's NET/GK"; | ||
| 234 | |||
| 235 | #define DMALOW dma_wd.dma_lo | ||
| 236 | #define DMAMID dma_wd.dma_md | ||
| 237 | #define DMAHIGH dma_wd.dma_hi | ||
| 238 | #define DACCESS dma_wd.fdc_acces_seccount | ||
| 239 | |||
| 240 | #define MFP_GPIP mfp.par_dt_reg | ||
| 241 | |||
| 242 | /* Some useful functions */ | ||
| 243 | |||
| 244 | #define INT (!(MFP_GPIP & 0x20)) | ||
| 245 | #define DELAY ({MFP_GPIP; MFP_GPIP; MFP_GPIP;}) | ||
| 246 | #define WRITEMODE(value) \ | ||
| 247 | ({ u_short dummy = value; \ | ||
| 248 | __asm__ volatile("movew %0, 0xFFFF8606" : : "d"(dummy)); \ | ||
| 249 | DELAY; \ | ||
| 250 | }) | ||
| 251 | #define WRITEBOTH(value1, value2) \ | ||
| 252 | ({ u_long dummy = (u_long)(value1)<<16 | (u_short)(value2); \ | ||
| 253 | __asm__ volatile("movel %0, 0xFFFF8604" : : "d"(dummy)); \ | ||
| 254 | DELAY; \ | ||
| 255 | }) | ||
| 256 | |||
| 257 | /* Definitions for DMODE */ | ||
| 258 | |||
| 259 | #define READ 0x000 | ||
| 260 | #define WRITE 0x100 | ||
| 261 | |||
| 262 | #define DMA_FDC 0x080 | ||
| 263 | #define DMA_ACSI 0x000 | ||
| 264 | |||
| 265 | #define DMA_DISABLE 0x040 | ||
| 266 | |||
| 267 | #define SEC_COUNT 0x010 | ||
| 268 | #define DMA_WINDOW 0x000 | ||
| 269 | |||
| 270 | #define REG_ACSI 0x008 | ||
| 271 | #define REG_FDC 0x000 | ||
| 272 | |||
| 273 | #define A1 0x002 | ||
| 274 | |||
| 275 | /* Timeout constants */ | ||
| 276 | |||
| 277 | #define TIMEOUTCMD HZ/2 /* ca. 500ms */ | ||
| 278 | #define TIMEOUTDMA HZ /* ca. 1s */ | ||
| 279 | #define COMMAND_DELAY 500 /* ca. 0.5ms */ | ||
| 280 | |||
| 281 | unsigned rw; | ||
| 282 | int lance_target = -1; | ||
| 283 | int if_up = 0; | ||
| 284 | |||
| 285 | /* The following routines access the ethernet board connected to the | ||
| 286 | * ACSI port via the st_dma chip. | ||
| 287 | */ | ||
| 288 | |||
| 289 | /* The following lowlevel routines work on physical addresses only and assume | ||
| 290 | * that eventually needed buffers are | ||
| 291 | * - completely located in ST RAM | ||
| 292 | * - are contigous in the physical address space | ||
| 293 | */ | ||
| 294 | |||
| 295 | /* Setup the DMA counter */ | ||
| 296 | |||
| 297 | static void | ||
| 298 | setup_dma (void *address, unsigned rw_flag, int num_blocks) | ||
| 299 | { | ||
| 300 | WRITEMODE((unsigned) rw_flag | DMA_FDC | SEC_COUNT | REG_ACSI | | ||
| 301 | A1); | ||
| 302 | WRITEMODE((unsigned)(rw_flag ^ WRITE) | DMA_FDC | SEC_COUNT | REG_ACSI | | ||
| 303 | A1); | ||
| 304 | WRITEMODE((unsigned) rw_flag | DMA_FDC | SEC_COUNT | REG_ACSI | | ||
| 305 | A1); | ||
| 306 | DMALOW = (unsigned char)((unsigned long)address & 0xFF); | ||
| 307 | DMAMID = (unsigned char)(((unsigned long)address >> 8) & 0xFF); | ||
| 308 | DMAHIGH = (unsigned char)(((unsigned long)address >> 16) & 0xFF); | ||
| 309 | WRITEBOTH((unsigned)num_blocks & 0xFF, | ||
| 310 | rw_flag | DMA_FDC | DMA_WINDOW | REG_ACSI | A1); | ||
| 311 | rw = rw_flag; | ||
| 312 | } | ||
| 313 | |||
| 314 | /* Send the first byte of an command block */ | ||
| 315 | |||
| 316 | static int | ||
| 317 | send_first (int target, unsigned char byte) | ||
| 318 | { | ||
| 319 | rw = READ; | ||
| 320 | acsi_delay_end(COMMAND_DELAY); | ||
| 321 | /* | ||
| 322 | * wake up ACSI | ||
| 323 | */ | ||
| 324 | WRITEMODE(DMA_FDC | DMA_WINDOW | REG_ACSI); | ||
| 325 | /* | ||
| 326 | * write command byte | ||
| 327 | */ | ||
| 328 | WRITEBOTH((target << 5) | (byte & 0x1F), DMA_FDC | | ||
| 329 | DMA_WINDOW | REG_ACSI | A1); | ||
| 330 | return (!acsi_wait_for_IRQ(TIMEOUTCMD)); | ||
| 331 | } | ||
| 332 | |||
| 333 | /* Send the rest of an command block */ | ||
| 334 | |||
| 335 | static int | ||
| 336 | send_1_5 (int lun, unsigned char *command, int dma) | ||
| 337 | { | ||
| 338 | int i, j; | ||
| 339 | |||
| 340 | for (i=0; i<5; i++) { | ||
| 341 | WRITEBOTH((!i ? (((lun & 0x7) << 5) | (command[i] & 0x1F)) | ||
| 342 | : command[i]), | ||
| 343 | rw | REG_ACSI | DMA_WINDOW | | ||
| 344 | ((i < 4) ? DMA_FDC | ||
| 345 | : (dma ? DMA_ACSI | ||
| 346 | : DMA_FDC)) | A1); | ||
| 347 | if (i < 4 && (j = !acsi_wait_for_IRQ(TIMEOUTCMD))) | ||
| 348 | return (j); | ||
| 349 | } | ||
| 350 | return (0); | ||
| 351 | } | ||
| 352 | |||
| 353 | /* Read a status byte */ | ||
| 354 | |||
| 355 | static int | ||
| 356 | get_status (void) | ||
| 357 | { | ||
| 358 | WRITEMODE(DMA_FDC | DMA_WINDOW | REG_ACSI | A1); | ||
| 359 | acsi_delay_start(); | ||
| 360 | return ((int)(DACCESS & 0xFF)); | ||
| 361 | } | ||
| 362 | |||
| 363 | /* Calculate the number of received bytes */ | ||
| 364 | |||
| 365 | static int | ||
| 366 | calc_received (void *start_address) | ||
| 367 | { | ||
| 368 | return (int)( | ||
| 369 | (((unsigned long)DMAHIGH << 16) | ((unsigned)DMAMID << 8) | DMALOW) | ||
| 370 | - (unsigned long)start_address); | ||
| 371 | } | ||
| 372 | |||
| 373 | /* The following midlevel routines still work on physical addresses ... */ | ||
| 374 | |||
| 375 | /* start() starts the PAM's DMA adaptor */ | ||
| 376 | |||
| 377 | static void | ||
| 378 | start (int target) | ||
| 379 | { | ||
| 380 | send_first(target, START); | ||
| 381 | } | ||
| 382 | |||
| 383 | /* stop() stops the PAM's DMA adaptor and returns a value of zero in case of success */ | ||
| 384 | |||
| 385 | static int | ||
| 386 | stop (int target) | ||
| 387 | { | ||
| 388 | int ret = -1; | ||
| 389 | unsigned char cmd_buffer[5]; | ||
| 390 | |||
| 391 | if (send_first(target, STOP)) | ||
| 392 | goto bad; | ||
| 393 | cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] = | ||
| 394 | cmd_buffer[3] = cmd_buffer[4] = 0; | ||
| 395 | if (send_1_5(7, cmd_buffer, 0) || | ||
| 396 | !acsi_wait_for_IRQ(TIMEOUTDMA) || | ||
| 397 | get_status()) | ||
| 398 | goto bad; | ||
| 399 | ret = 0; | ||
| 400 | bad: | ||
| 401 | return (ret); | ||
| 402 | } | ||
| 403 | |||
| 404 | /* testpkt() returns the number of received packets waiting in the queue */ | ||
| 405 | |||
| 406 | static int | ||
| 407 | testpkt(int target) | ||
| 408 | { | ||
| 409 | int ret = -1; | ||
| 410 | |||
| 411 | if (send_first(target, NUMPKTS)) | ||
| 412 | goto bad; | ||
| 413 | ret = get_status(); | ||
| 414 | bad: | ||
| 415 | return (ret); | ||
| 416 | } | ||
| 417 | |||
| 418 | /* inquiry() returns 0 when PAM's DMA found, -1 when timeout, -2 otherwise */ | ||
| 419 | /* Please note: The buffer is for internal use only but must be defined! */ | ||
| 420 | |||
| 421 | static int | ||
| 422 | inquiry (int target, unsigned char *buffer) | ||
| 423 | { | ||
| 424 | int ret = -1; | ||
| 425 | unsigned char *vbuffer = phys_to_virt((unsigned long)buffer); | ||
| 426 | unsigned char cmd_buffer[5]; | ||
| 427 | |||
| 428 | if (send_first(target, INQUIRY)) | ||
| 429 | goto bad; | ||
| 430 | setup_dma(buffer, READ, 1); | ||
| 431 | vbuffer[8] = vbuffer[27] = 0; /* Avoid confusion with previous read data */ | ||
| 432 | cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] = cmd_buffer[4] = 0; | ||
| 433 | cmd_buffer[3] = 48; | ||
| 434 | if (send_1_5(5, cmd_buffer, 1) || | ||
| 435 | !acsi_wait_for_IRQ(TIMEOUTDMA) || | ||
| 436 | get_status() || | ||
| 437 | (calc_received(buffer) < 32)) | ||
| 438 | goto bad; | ||
| 439 | dma_cache_maintenance((unsigned long)(buffer+8), 20, 0); | ||
| 440 | if (memcmp(inquire8, vbuffer+8, 20)) | ||
| 441 | goto bad; | ||
| 442 | ret = 0; | ||
| 443 | bad: | ||
| 444 | if (!!NET_DEBUG) { | ||
| 445 | vbuffer[8+20]=0; | ||
| 446 | printk("inquiry of target %d: %s\n", target, vbuffer+8); | ||
| 447 | } | ||
| 448 | return (ret); | ||
| 449 | } | ||
| 450 | |||
| 451 | /* | ||
| 452 | * read_hw_addr() reads the sector containing the hwaddr and returns | ||
| 453 | * a pointer to it (virtual address!) or 0 in case of an error | ||
| 454 | */ | ||
| 455 | |||
| 456 | static HADDR | ||
| 457 | *read_hw_addr(int target, unsigned char *buffer) | ||
| 458 | { | ||
| 459 | HADDR *ret = 0; | ||
| 460 | unsigned char cmd_buffer[5]; | ||
| 461 | |||
| 462 | if (send_first(target, READSECTOR)) | ||
| 463 | goto bad; | ||
| 464 | setup_dma(buffer, READ, 1); | ||
| 465 | cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] = cmd_buffer[4] = 0; | ||
| 466 | cmd_buffer[3] = 1; | ||
| 467 | if (send_1_5(5, cmd_buffer, 1) || | ||
| 468 | !acsi_wait_for_IRQ(TIMEOUTDMA) || | ||
| 469 | get_status()) | ||
| 470 | goto bad; | ||
| 471 | ret = phys_to_virt((unsigned long)&(((DMAHWADDR *)buffer)->hwaddr)); | ||
| 472 | dma_cache_maintenance((unsigned long)buffer, 512, 0); | ||
| 473 | bad: | ||
| 474 | return (ret); | ||
| 475 | } | ||
| 476 | |||
| 477 | static irqreturn_t | ||
| 478 | pamsnet_intr(int irq, void *data) | ||
| 479 | { | ||
| 480 | return IRQ_HANDLED; | ||
| 481 | } | ||
| 482 | |||
| 483 | /* receivepkt() loads a packet to a given buffer and returns its length */ | ||
| 484 | |||
| 485 | static int | ||
| 486 | receivepkt (int target, unsigned char *buffer) | ||
| 487 | { | ||
| 488 | int ret = -1; | ||
| 489 | unsigned char cmd_buffer[5]; | ||
| 490 | |||
| 491 | if (send_first(target, READPKT)) | ||
| 492 | goto bad; | ||
| 493 | setup_dma(buffer, READ, 3); | ||
| 494 | cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] = cmd_buffer[4] = 0; | ||
| 495 | cmd_buffer[3] = 3; | ||
| 496 | if (send_1_5(7, cmd_buffer, 1) || | ||
| 497 | !acsi_wait_for_IRQ(TIMEOUTDMA) || | ||
| 498 | get_status()) | ||
| 499 | goto bad; | ||
| 500 | ret = calc_received(buffer); | ||
| 501 | bad: | ||
| 502 | return (ret); | ||
| 503 | } | ||
| 504 | |||
| 505 | /* sendpkt() sends a packet and returns a value of zero when the packet was sent | ||
| 506 | successfully */ | ||
| 507 | |||
| 508 | static int | ||
| 509 | sendpkt (int target, unsigned char *buffer, int length) | ||
| 510 | { | ||
| 511 | int ret = -1; | ||
| 512 | unsigned char cmd_buffer[5]; | ||
| 513 | |||
| 514 | if (send_first(target, WRITEPKT)) | ||
| 515 | goto bad; | ||
| 516 | setup_dma(buffer, WRITE, 3); | ||
| 517 | cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[4] = 0; | ||
| 518 | cmd_buffer[2] = length >> 8; | ||
| 519 | cmd_buffer[3] = length & 0xFF; | ||
| 520 | if (send_1_5(7, cmd_buffer, 1) || | ||
| 521 | !acsi_wait_for_IRQ(TIMEOUTDMA) || | ||
| 522 | get_status()) | ||
| 523 | goto bad; | ||
| 524 | ret = 0; | ||
| 525 | bad: | ||
| 526 | return (ret); | ||
| 527 | } | ||
| 528 | |||
| 529 | /* The following higher level routines work on virtual addresses and convert them to | ||
| 530 | * physical addresses when passed to the lowlevel routines. It's up to the higher level | ||
| 531 | * routines to copy data from Alternate RAM to ST RAM if neccesary! | ||
| 532 | */ | ||
| 533 | |||
| 534 | /* Check for a network adaptor of this type, and return '0' if one exists. | ||
| 535 | */ | ||
| 536 | |||
| 537 | struct net_device * __init pamsnet_probe (int unit) | ||
| 538 | { | ||
| 539 | struct net_device *dev; | ||
| 540 | int i; | ||
| 541 | HADDR *hwaddr; | ||
| 542 | int err; | ||
| 543 | |||
| 544 | unsigned char station_addr[6]; | ||
| 545 | static unsigned version_printed; | ||
| 546 | /* avoid "Probing for..." printed 4 times - the driver is supporting only one adapter now! */ | ||
| 547 | static int no_more_found; | ||
| 548 | |||
| 549 | if (no_more_found) | ||
| 550 | return ERR_PTR(-ENODEV); | ||
| 551 | no_more_found = 1; | ||
| 552 | |||
| 553 | dev = alloc_etherdev(sizeof(struct net_local)); | ||
| 554 | if (!dev) | ||
| 555 | return ERR_PTR(-ENOMEM); | ||
| 556 | if (unit >= 0) { | ||
| 557 | sprintf(dev->name, "eth%d", unit); | ||
| 558 | netdev_boot_setup_check(dev); | ||
| 559 | } | ||
| 560 | SET_MODULE_OWNER(dev); | ||
| 561 | |||
| 562 | printk("Probing for PAM's Net/GK Adapter...\n"); | ||
| 563 | |||
| 564 | /* Allocate the DMA buffer here since we need it for probing! */ | ||
| 565 | |||
| 566 | nic_packet = (struct nic_pkt_s *)acsi_buffer; | ||
| 567 | phys_nic_packet = (unsigned char *)phys_acsi_buffer; | ||
| 568 | if (pamsnet_debug > 0) { | ||
| 569 | printk("nic_packet at 0x%p, phys at 0x%p\n", | ||
| 570 | nic_packet, phys_nic_packet ); | ||
| 571 | } | ||
| 572 | |||
| 573 | stdma_lock(pamsnet_intr, NULL); | ||
| 574 | DISABLE_IRQ(); | ||
| 575 | |||
| 576 | for (i=0; i<8; i++) { | ||
| 577 | /* Do two inquiries to cover cases with strange equipment on previous ID */ | ||
| 578 | /* blocking the ACSI bus (like the SLMC804 laser printer controller... */ | ||
| 579 | inquiry(i, phys_nic_packet); | ||
| 580 | if (!inquiry(i, phys_nic_packet)) { | ||
| 581 | lance_target = i; | ||
| 582 | break; | ||
| 583 | } | ||
| 584 | } | ||
| 585 | |||
| 586 | if (!!NET_DEBUG) | ||
| 587 | printk("ID: %d\n",i); | ||
| 588 | |||
| 589 | if (lance_target >= 0) { | ||
| 590 | if (!(hwaddr = read_hw_addr(lance_target, phys_nic_packet))) | ||
| 591 | lance_target = -1; | ||
| 592 | else | ||
| 593 | memcpy (station_addr, hwaddr, ETH_ALEN); | ||
| 594 | } | ||
| 595 | |||
| 596 | ENABLE_IRQ(); | ||
| 597 | stdma_release(); | ||
| 598 | |||
| 599 | if (lance_target < 0) { | ||
| 600 | printk("No PAM's Net/GK found.\n"); | ||
| 601 | free_netdev(dev); | ||
| 602 | return ERR_PTR(-ENODEV); | ||
| 603 | } | ||
| 604 | |||
| 605 | if (pamsnet_debug > 0 && version_printed++ == 0) | ||
| 606 | printk(version); | ||
| 607 | |||
| 608 | printk("%s: %s found on target %01d, eth-addr: %02x:%02x:%02x:%02x:%02x:%02x.\n", | ||
| 609 | dev->name, "PAM's Net/GK", lance_target, | ||
| 610 | station_addr[0], station_addr[1], station_addr[2], | ||
| 611 | station_addr[3], station_addr[4], station_addr[5]); | ||
| 612 | |||
| 613 | /* Initialize the device structure. */ | ||
| 614 | dev->open = pamsnet_open; | ||
| 615 | dev->stop = pamsnet_close; | ||
| 616 | dev->hard_start_xmit = pamsnet_send_packet; | ||
| 617 | dev->get_stats = net_get_stats; | ||
| 618 | |||
| 619 | /* Fill in the fields of the device structure with ethernet-generic | ||
| 620 | * values. This should be in a common file instead of per-driver. | ||
| 621 | */ | ||
| 622 | |||
| 623 | for (i = 0; i < ETH_ALEN; i++) { | ||
| 624 | #if 0 | ||
| 625 | dev->broadcast[i] = 0xff; | ||
| 626 | #endif | ||
| 627 | dev->dev_addr[i] = station_addr[i]; | ||
| 628 | } | ||
| 629 | err = register_netdev(dev); | ||
| 630 | if (!err) | ||
| 631 | return dev; | ||
| 632 | |||
| 633 | free_netdev(dev); | ||
| 634 | return ERR_PTR(err); | ||
| 635 | } | ||
| 636 | |||
| 637 | /* Open/initialize the board. This is called (in the current kernel) | ||
| 638 | sometime after booting when the 'ifconfig' program is run. | ||
| 639 | |||
| 640 | This routine should set everything up anew at each open, even | ||
| 641 | registers that "should" only need to be set once at boot, so that | ||
| 642 | there is non-reboot way to recover if something goes wrong. | ||
| 643 | */ | ||
| 644 | static int | ||
| 645 | pamsnet_open(struct net_device *dev) | ||
| 646 | { | ||
| 647 | struct net_local *lp = netdev_priv(dev); | ||
| 648 | |||
| 649 | if (pamsnet_debug > 0) | ||
| 650 | printk("pamsnet_open\n"); | ||
| 651 | stdma_lock(pamsnet_intr, NULL); | ||
| 652 | DISABLE_IRQ(); | ||
| 653 | |||
| 654 | /* Reset the hardware here. | ||
| 655 | */ | ||
| 656 | if (!if_up) | ||
| 657 | start(lance_target); | ||
| 658 | if_up = 1; | ||
| 659 | lp->open_time = 0; /*jiffies*/ | ||
| 660 | lp->poll_time = MAX_POLL_TIME; | ||
| 661 | |||
| 662 | dev->tbusy = 0; | ||
| 663 | dev->interrupt = 0; | ||
| 664 | dev->start = 1; | ||
| 665 | |||
| 666 | ENABLE_IRQ(); | ||
| 667 | stdma_release(); | ||
| 668 | pamsnet_timer.data = (long)dev; | ||
| 669 | pamsnet_timer.expires = jiffies + lp->poll_time; | ||
| 670 | add_timer(&pamsnet_timer); | ||
| 671 | return 0; | ||
| 672 | } | ||
| 673 | |||
| 674 | static int | ||
| 675 | pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev) | ||
| 676 | { | ||
| 677 | struct net_local *lp = netdev_priv(dev); | ||
| 678 | unsigned long flags; | ||
| 679 | |||
| 680 | /* Block a timer-based transmit from overlapping. This could better be | ||
| 681 | * done with atomic_swap(1, dev->tbusy), but set_bit() works as well. | ||
| 682 | */ | ||
| 683 | local_irq_save(flags); | ||
| 684 | |||
| 685 | if (stdma_islocked()) { | ||
| 686 | local_irq_restore(flags); | ||
| 687 | lp->stats.tx_errors++; | ||
| 688 | } | ||
| 689 | else { | ||
| 690 | int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; | ||
| 691 | unsigned long buf = virt_to_phys(skb->data); | ||
| 692 | int stat; | ||
| 693 | |||
| 694 | stdma_lock(pamsnet_intr, NULL); | ||
| 695 | DISABLE_IRQ(); | ||
| 696 | |||
| 697 | local_irq_restore(flags); | ||
| 698 | if( !STRAM_ADDR(buf+length-1) ) { | ||
| 699 | skb_copy_from_linear_data(skb, nic_packet->buffer, | ||
| 700 | length); | ||
| 701 | buf = (unsigned long)phys_nic_packet; | ||
| 702 | } | ||
| 703 | |||
| 704 | dma_cache_maintenance(buf, length, 1); | ||
| 705 | |||
| 706 | stat = sendpkt(lance_target, (unsigned char *)buf, length); | ||
| 707 | ENABLE_IRQ(); | ||
| 708 | stdma_release(); | ||
| 709 | |||
| 710 | dev->trans_start = jiffies; | ||
| 711 | dev->tbusy = 0; | ||
| 712 | lp->stats.tx_packets++; | ||
| 713 | lp->stats.tx_bytes+=length; | ||
| 714 | } | ||
| 715 | dev_kfree_skb(skb); | ||
| 716 | |||
| 717 | return 0; | ||
| 718 | } | ||
| 719 | |||
| 720 | /* We have a good packet(s), get it/them out of the buffers. | ||
| 721 | */ | ||
| 722 | static void | ||
| 723 | pamsnet_poll_rx(struct net_device *dev) | ||
| 724 | { | ||
| 725 | struct net_local *lp = netdev_priv(dev); | ||
| 726 | int boguscount; | ||
| 727 | int pkt_len; | ||
| 728 | struct sk_buff *skb; | ||
| 729 | unsigned long flags; | ||
| 730 | |||
| 731 | local_irq_save(flags); | ||
| 732 | /* ++roman: Take care at locking the ST-DMA... This must be done with ints | ||
| 733 | * off, since otherwise an int could slip in between the question and the | ||
| 734 | * locking itself, and then we'd go to sleep... And locking itself is | ||
| 735 | * necessary to keep the floppy_change timer from working with ST-DMA | ||
| 736 | * registers. */ | ||
| 737 | if (stdma_islocked()) { | ||
| 738 | local_irq_restore(flags); | ||
| 739 | return; | ||
| 740 | } | ||
| 741 | stdma_lock(pamsnet_intr, NULL); | ||
| 742 | DISABLE_IRQ(); | ||
| 743 | local_irq_restore(flags); | ||
| 744 | |||
| 745 | boguscount = testpkt(lance_target); | ||
| 746 | if( lp->poll_time < MAX_POLL_TIME ) lp->poll_time++; | ||
| 747 | |||
| 748 | while(boguscount--) { | ||
| 749 | pkt_len = receivepkt(lance_target, phys_nic_packet); | ||
| 750 | |||
| 751 | if( pkt_len < 60 ) break; | ||
| 752 | |||
| 753 | /* Good packet... */ | ||
| 754 | |||
| 755 | dma_cache_maintenance((unsigned long)phys_nic_packet, pkt_len, 0); | ||
| 756 | |||
| 757 | lp->poll_time = pamsnet_min_poll_time; /* fast poll */ | ||
| 758 | if( pkt_len >= 60 && pkt_len <= 2048 ) { | ||
| 759 | if (pkt_len > 1514) | ||
| 760 | pkt_len = 1514; | ||
| 761 | |||
| 762 | /* Malloc up new buffer. | ||
| 763 | */ | ||
| 764 | skb = alloc_skb(pkt_len, GFP_ATOMIC); | ||
| 765 | if (skb == NULL) { | ||
| 766 | printk("%s: Memory squeeze, dropping packet.\n", | ||
| 767 | dev->name); | ||
| 768 | lp->stats.rx_dropped++; | ||
| 769 | break; | ||
| 770 | } | ||
| 771 | skb->len = pkt_len; | ||
| 772 | skb->dev = dev; | ||
| 773 | |||
| 774 | /* 'skb->data' points to the start of sk_buff data area. | ||
| 775 | */ | ||
| 776 | skb_copy_to_linear_data(skb, nic_packet->buffer, | ||
| 777 | pkt_len); | ||
| 778 | netif_rx(skb); | ||
| 779 | dev->last_rx = jiffies; | ||
| 780 | lp->stats.rx_packets++; | ||
| 781 | lp->stats.rx_bytes+=pkt_len; | ||
| 782 | } | ||
| 783 | } | ||
| 784 | |||
| 785 | /* If any worth-while packets have been received, dev_rint() | ||
| 786 | has done a mark_bh(INET_BH) for us and will work on them | ||
| 787 | when we get to the bottom-half routine. | ||
| 788 | */ | ||
| 789 | |||
| 790 | ENABLE_IRQ(); | ||
| 791 | stdma_release(); | ||
| 792 | return; | ||
| 793 | } | ||
| 794 | |||
| 795 | /* pamsnet_tick: called by pamsnet_timer. Reads packets from the adapter, | ||
| 796 | * passes them to the higher layers and restarts the timer. | ||
| 797 | */ | ||
| 798 | static void | ||
| 799 | pamsnet_tick(unsigned long data) | ||
| 800 | { | ||
| 801 | struct net_device *dev = (struct net_device *)data; | ||
| 802 | struct net_local *lp = netdev_priv(dev); | ||
| 803 | |||
| 804 | if( pamsnet_debug > 0 && (lp->open_time++ & 7) == 8 ) | ||
| 805 | printk("pamsnet_tick: %ld\n", lp->open_time); | ||
| 806 | |||
| 807 | pamsnet_poll_rx(dev); | ||
| 808 | |||
| 809 | pamsnet_timer.expires = jiffies + lp->poll_time; | ||
| 810 | add_timer(&pamsnet_timer); | ||
| 811 | } | ||
| 812 | |||
| 813 | /* The inverse routine to pamsnet_open(). | ||
| 814 | */ | ||
| 815 | static int | ||
| 816 | pamsnet_close(struct net_device *dev) | ||
| 817 | { | ||
| 818 | struct net_local *lp = netdev_priv(dev); | ||
| 819 | |||
| 820 | if (pamsnet_debug > 0) | ||
| 821 | printk("pamsnet_close, open_time=%ld\n", lp->open_time); | ||
| 822 | del_timer(&pamsnet_timer); | ||
| 823 | stdma_lock(pamsnet_intr, NULL); | ||
| 824 | DISABLE_IRQ(); | ||
| 825 | |||
| 826 | if (if_up) | ||
| 827 | stop(lance_target); | ||
| 828 | if_up = 0; | ||
| 829 | |||
| 830 | lp->open_time = 0; | ||
| 831 | |||
| 832 | dev->tbusy = 1; | ||
| 833 | dev->start = 0; | ||
| 834 | |||
| 835 | ENABLE_IRQ(); | ||
| 836 | stdma_release(); | ||
| 837 | return 0; | ||
| 838 | } | ||
| 839 | |||
| 840 | /* Get the current statistics. | ||
| 841 | This may be called with the card open or closed. | ||
| 842 | */ | ||
| 843 | static struct net_device_stats *net_get_stats(struct net_device *dev) | ||
| 844 | { | ||
| 845 | struct net_local *lp = netdev_priv(dev); | ||
| 846 | return &lp->stats; | ||
| 847 | } | ||
| 848 | |||
| 849 | |||
| 850 | #ifdef MODULE | ||
| 851 | |||
| 852 | static struct net_device *pam_dev; | ||
| 853 | |||
| 854 | int init_module(void) | ||
| 855 | { | ||
| 856 | pam_dev = pamsnet_probe(-1); | ||
| 857 | if (IS_ERR(pam_dev)) | ||
| 858 | return PTR_ERR(pam_dev); | ||
| 859 | return 0; | ||
| 860 | } | ||
| 861 | |||
| 862 | void cleanup_module(void) | ||
| 863 | { | ||
| 864 | unregister_netdev(pam_dev); | ||
| 865 | free_netdev(pam_dev); | ||
| 866 | } | ||
| 867 | |||
| 868 | #endif /* MODULE */ | ||
| 869 | |||
| 870 | /* Local variables: | ||
| 871 | * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include | ||
| 872 | -b m68k-linuxaout -Wall -Wstrict-prototypes -O2 | ||
| 873 | -fomit-frame-pointer -pipe -DMODULE -I../../net/inet -c atari_pamsnet.c" | ||
| 874 | * version-control: t | ||
| 875 | * kept-new-versions: 5 | ||
| 876 | * tab-width: 8 | ||
| 877 | * End: | ||
| 878 | */ | ||
diff --git a/include/asm-m68k/atari_SLM.h b/include/asm-m68k/atari_SLM.h deleted file mode 100644 index 42f4fcdd8bc7..000000000000 --- a/include/asm-m68k/atari_SLM.h +++ /dev/null | |||
| @@ -1,28 +0,0 @@ | |||
| 1 | |||
| 2 | #ifndef _ATARI_SLM_H | ||
| 3 | #define _ATARI_SLM_H | ||
| 4 | |||
| 5 | /* Atari SLM laser printer specific ioctls */ | ||
| 6 | |||
| 7 | #define SLMIOGSTAT 0xa100 | ||
| 8 | #define SLMIOGPSIZE 0xa101 | ||
| 9 | #define SLMIOGMFEED 0xa102 | ||
| 10 | |||
| 11 | #define SLMIORESET 0xa140 | ||
| 12 | |||
| 13 | #define SLMIOSPSIZE 0xa181 | ||
| 14 | #define SLMIOSMFEED 0xa182 | ||
| 15 | |||
| 16 | /* Status returning structure (SLMIOGSTAT) */ | ||
| 17 | struct SLM_status { | ||
| 18 | int stat; /* numeric status code */ | ||
| 19 | char str[40]; /* status string */ | ||
| 20 | }; | ||
| 21 | |||
| 22 | /* Paper size structure (SLMIO[GS]PSIZE) */ | ||
| 23 | struct SLM_paper_size { | ||
| 24 | int width; | ||
| 25 | int height; | ||
| 26 | }; | ||
| 27 | |||
| 28 | #endif /* _ATARI_SLM_H */ | ||
diff --git a/include/asm-m68k/atari_acsi.h b/include/asm-m68k/atari_acsi.h deleted file mode 100644 index 10fea68f191a..000000000000 --- a/include/asm-m68k/atari_acsi.h +++ /dev/null | |||
| @@ -1,37 +0,0 @@ | |||
| 1 | #ifndef _ASM_ATARI_ACSI_H | ||
| 2 | #define _ASM_ATARI_ACSI_H | ||
| 3 | |||
| 4 | /* Functions exported by drivers/block/acsi.c */ | ||
| 5 | |||
| 6 | void acsi_delay_start( void ); | ||
| 7 | void acsi_delay_end( long usec ); | ||
| 8 | int acsi_wait_for_IRQ( unsigned timeout ); | ||
| 9 | int acsi_wait_for_noIRQ( unsigned timeout ); | ||
| 10 | int acsicmd_nodma( const char *cmd, int enable); | ||
| 11 | int acsi_getstatus( void ); | ||
| 12 | int acsi_extstatus( char *buffer, int cnt ); | ||
| 13 | void acsi_end_extstatus( void ); | ||
| 14 | int acsi_extcmd( unsigned char *buffer, int cnt ); | ||
| 15 | |||
| 16 | /* The ACSI buffer is guarantueed to reside in ST-RAM and may be used by other | ||
| 17 | * drivers that work on the ACSI bus, too. It's data are valid only as long as | ||
| 18 | * the ST-DMA is locked. */ | ||
| 19 | extern char *acsi_buffer; | ||
| 20 | extern unsigned long phys_acsi_buffer; | ||
| 21 | |||
| 22 | /* Utility macros */ | ||
| 23 | |||
| 24 | /* Send one data byte over the bus and set mode for next operation | ||
| 25 | * with one move.l -- Atari recommends this... | ||
| 26 | */ | ||
| 27 | |||
| 28 | #define DMA_LONG_WRITE(data,mode) \ | ||
| 29 | do { \ | ||
| 30 | *((unsigned long *)&dma_wd.fdc_acces_seccount) = \ | ||
| 31 | ((data)<<16) | (mode); \ | ||
| 32 | } while(0) | ||
| 33 | |||
| 34 | #define ENABLE_IRQ() atari_turnon_irq( IRQ_MFP_ACSI ) | ||
| 35 | #define DISABLE_IRQ() atari_turnoff_irq( IRQ_MFP_ACSI ) | ||
| 36 | |||
| 37 | #endif /* _ASM_ATARI_ACSI_H */ | ||
