diff -cr --new-file ../linux/drivers/block/Makefile linux/drivers/block/Makefile *** ../linux/drivers/block/Makefile Fri Jul 8 10:36:03 1994 --- linux/drivers/block/Makefile Wed Aug 24 16:17:40 1994 *************** *** 21,28 **** # In the future, some of these should be built conditionally. # ! OBJS := ll_rw_blk.o floppy.o ramdisk.o genhd.o ! SRCS := ll_rw_blk.c floppy.c ramdisk.c genhd.c ifdef CONFIG_CDU31A OBJS := $(OBJS) cdu31a.o --- 21,28 ---- # In the future, some of these should be built conditionally. # ! OBJS := ll_rw_blk.o ramdisk.o floppy.o genhd.o ! SRCS := ll_rw_blk.c ramdisk.c floppy.c genhd.c ifdef CONFIG_CDU31A OBJS := $(OBJS) cdu31a.o *************** *** 64,74 **** --- 64,80 ---- SRCS := $(SRCS) xd.c endif + ifdef CONFIG_BLK_DEV_PS2 + OBJS := $(OBJS) ps2esdi.o + SRCS := $(SRCS) ps2esdi.c + endif + all: block.a block.a: $(OBJS) rm -f block.a $(AR) rcs block.a $(OBJS) + ranlib block.a sync dep: diff -cr --new-file ../linux/drivers/block/blk.h linux/drivers/block/blk.h *** ../linux/drivers/block/blk.h Wed Aug 24 15:51:07 1994 --- linux/drivers/block/blk.h Wed Aug 24 15:37:29 1994 *************** *** 223,228 **** --- 223,236 ---- #define DEVICE_ON(device) #define DEVICE_OFF(device) + #elif (MAJOR_NR == PS2ESDI_MAJOR) + + #define DEVICE_NAME "PS2ESDI" + #define DEVICE_REQUEST do_ps2esdi_request + #define DEVICE_NR(device) (MINOR(device) >> 6) + #define DEVICE_ON(device) + #define DEVICE_OFF(device) + #endif #if (MAJOR_NR != SCSI_TAPE_MAJOR) diff -cr --new-file ../linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c *** ../linux/drivers/block/ll_rw_blk.c Wed Aug 10 18:25:58 1994 --- linux/drivers/block/ll_rw_blk.c Wed Aug 24 16:56:11 1994 *************** *** 496,501 **** --- 496,505 ---- #ifdef CONFIG_SBPCD mem_start = sbpcd_init(mem_start, mem_end); #endif CONFIG_SBPCD + #ifdef CONFIG_BLK_DEV_PS2 + mem_start = ps2esdi_init(mem_start, mem_end); + #endif CONFIG_BLK_DEV_PS2 + if (ramdisk_size) mem_start += rd_init(mem_start, ramdisk_size*1024); return mem_start; diff -cr --new-file ../linux/drivers/block/ps2esdi.c linux/drivers/block/ps2esdi.c *** ../linux/drivers/block/ps2esdi.c Thu Jan 1 01:00:00 1970 --- linux/drivers/block/ps2esdi.c Wed Aug 24 16:18:41 1994 *************** *** 0 **** --- 1,993 ---- + /* ps2esdi driver based on assembler code by Arindam Banerji, + written by Peter De Schrijver */ + /* Reassuring note to IBM : This driver was NOT developed by vice-versa + engineering the PS/2's BIOS */ + /* Dedicated to Wannes, Tofke, Ykke, Godot, Killroy and all those other lovely + fish out there... */ + /* This code was written during the long and boring WINA elections 1994 */ + /* Thanks to Arindam Banerij for giving me the source of his driver */ + /* This code may be freely distributed and modified in any way, as long as these + notes remain intact */ + + /* Revised: 05/07/94 by Arindam Banerji (axb@cse.nd.edu) */ + /* Revised: 09/08/94 by Peter De Schrijver (stud11@cc4.kuleuven.ac.be) + Thanks to Arindam Banerij for sending me the docs of the adapter */ + + /* TODO : + + Timeouts + + Get disk parameters + + DMA above 16MB + + reset after read/write error + */ + #include + #ifdef CONFIG_BLK_DEV_PS2 + + #include + #include + #include + #include + #include + #include + + #include + #include + #include + #include + + #define MAJOR_NR 31 + #define PS2ESDI_IRQ 14 + #define MAX_HD 2 + #define MAX_RETRIES 5 + #define MAX_16BIT 65536 + #define ESDI_TIMEOUT 0xf000 + #define ESDI_STAT_TIMEOUT 4 + + #define TYPE_0_CMD_BLK_LENGTH 2 + #define TYPE_1_CMD_BLK_LENGTH 4 + + #include "blk.h" + + static void reset_ctrl(void); + + u_long ps2esdi_init(u_long mem_start, u_long mem_end); + + static void ps2esdi_geninit(void); + + static void do_ps2esdi_request(void); + + static void ps2esdi_readwrite(int cmd,u_char drive, u_int block,u_int count); + + static void ps2esdi_fill_cmd_block(u_short *cmd_blk,u_short cmd, + u_short cyl,u_short head,u_short sector,u_short length,u_char drive); + + static int ps2esdi_out_cmd_blk(u_short *cmd_blk); + + static void ps2esdi_prep_dma(char *buffer,u_short length,u_char dma_xmode); + + static void ps2esdi_interrupt_handler(int unused); + static void (*current_int_handler)(u_int)=NULL; + static void ps2esdi_normal_interrupt_handler(u_int); + static void ps2esdi_initial_reset_int_handler(u_int); + static void ps2esdi_geometry_int_handler(u_int); + + static void ps2esdi_continue_request(void); + + static int ps2esdi_open(struct inode *inode,struct file *file); + + static void ps2esdi_release (struct inode *inode, struct file *file); + + static int ps2esdi_ioctl (struct inode *inode,struct file *file, + u_int cmd,u_long arg); + + static int ps2esdi_reread_partitions(int dev); + + static int ps2esdi_read_status_words(int num_words,int max_words,u_short *buffer); + + static void dump_cmd_complete_status(u_int int_ret_code); + + static void ps2esdi_get_device_cfg(void); + + u_int dma_arb_level; /* DMA arbitration level */ + + static struct wait_queue *ps2esdi_int = NULL, *ps2esdi_wait_open=NULL; + int no_int_yet; + static int access_count[MAX_HD]={0,}; + static char ps2esdi_valid[MAX_HD]={0,}; + static int ps2esdi_sizes[MAX_HD<<6]={0,}; + static int ps2esdi_blocksizes[MAX_HD<<6]={0,}; + static int ps2esdi_drives=0; + static struct hd_struct ps2esdi[MAX_HD<<6]; + static u_short io_base; + + struct ps2esdi_i_struct { + unsigned int head,sect,cyl,wpcom,lzone,ctl; + }; + struct ps2esdi_i_struct ps2esdi_info[] = { {0,0,0,0,0,0},{0,0,0,0,0,0} }; + + static struct file_operations ps2esdi_fops = { + NULL, /* lseek - default */ + block_read, /* read - general block-dev read */ + block_write, /* write - general block-dev write */ + NULL, /* readdir - bad */ + NULL, /* select */ + ps2esdi_ioctl, /* ioctl */ + NULL, /* mmap */ + ps2esdi_open, /* open */ + ps2esdi_release, /* release */ + block_fsync /* fsync */ + }; + + static struct gendisk ps2esdi_gendisk = { + MAJOR_NR, /* Major number */ + "ps2esdi", /* Major name */ + 6, /* Bits to shift to get real from partition */ + 1 << 6, /* Number of partitions per real */ + MAX_HD, /* maximum number of real */ + ps2esdi_geninit, /* init function */ + ps2esdi, /* hd struct */ + ps2esdi_sizes, /* block sizes */ + 0, /* number */ + (void *) ps2esdi_info, /* internal */ + NULL /* next */ + }; + + /* initialization routine called by ll_rw_blk.c */ + u_long ps2esdi_init(u_long mem_start, u_long mem_end) + { + + /* register the device - pass the name, major number and operations + vector . */ + if(register_blkdev(MAJOR_NR,"ps2esdi",&ps2esdi_fops)) { + printk("%s: Unable to get major number %d\n",DEVICE_NAME,MAJOR_NR); + return mem_start; + } + + /* set up some global information - indicating device specific info */ + blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; + read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read ahead */ + + /* some minor housekeeping - setup the global gendisk structure */ + ps2esdi_gendisk.next = gendisk_head; + gendisk_head = &ps2esdi_gendisk; + + return mem_start; + } /* ps2esdi_init */ + + /* handles boot time command line parameters */ + void ed_setup(char *str, int *ints) + { + int hdind = 0; + + /* handles 3 parameters only - corresponding to + 1. Number of cylinders + 2. Number of heads + 3. Sectors/track + */ + + if (ints[0] != 3) + return; + + /* print out the information - seen at boot time */ + printk("%s: ints[0]=%d ints[1]=%d ints[2]=%d ints[3]=%d\n", + DEVICE_NAME,ints[0],ints[1],ints[2],ints[3]); + + /* set the index into device specific information table */ + if (ps2esdi_info[0].head != 0) + hdind=1; + + /* set up all the device information */ + ps2esdi_info[hdind].head = ints[2]; + ps2esdi_info[hdind].sect = ints[3]; + ps2esdi_info[hdind].cyl = ints[1]; + ps2esdi_info[hdind].wpcom = 0; + ps2esdi_info[hdind].lzone = ints[1]; + ps2esdi_info[hdind].ctl = (ints[2] > 8 ? 8 : 0); + ps2esdi_drives = hdind+1; /* increment index for the next time */ + } /* ed_setup */ + + /* ps2 esdi specific initialization - called thru the gendisk chain */ + static void ps2esdi_geninit(void) + { + /* + + The first part contains the initialization code + for the ESDI disk subsystem. All we really do + is search for the POS registers of the controller + to do some simple setup operations. First, we + must ensure that the controller is installed, + enabled, and configured as PRIMARY. Then we must + determine the DMA arbitration level being used by + the controller so we can handle data transfer + operations properly. If all of this works, then + we will set the INIT_FLAG to a non-zero value. + */ + + int i; + u_int id; + u_char status; + + /* Search for the cadr which contains the ESDI adapter */ + for(i=0;i>2) & 0xf; + + printk("%s: DMA arbitration level : %d\n",DEVICE_NAME,dma_arb_level); + + LITE_ON; + current_int_handler=ps2esdi_initial_reset_int_handler; + reset_ctrl(); + sleep_on(&ps2esdi_int); + LITE_OFF; + + + ps2esdi_get_device_cfg(); + + current_int_handler=ps2esdi_normal_interrupt_handler; + + /* finally this part sets up some global data structures etc. */ + + ps2esdi_gendisk.nr_real = ps2esdi_drives; + + for(i=0;idev),CURRENT->cmd,CURRENT->sector, + CURRENT->nr_sectors,CURRENT->buffer); + #endif + + /* standard macro that ensures that requests are really on the + list + sanity checks. */ + INIT_REQUEST; + + if((u_int)CURRENT->buffer+CURRENT->nr_sectors*512 > 16*MB) { + printk("%s: DMA above 16MB not supported\n",DEVICE_NAME); + end_request(FAIL); + if(CURRENT) + do_ps2esdi_request(); + return; + } /* check for above 16Mb dmas */ + + if((CURRENT_DEV < ps2esdi_drives) && + (CURRENT->sector + CURRENT->nr_sectors <= + ps2esdi[MINOR(CURRENT->dev)].nr_sects)) + { + #if 0 + printk("%s:got request. device : %d minor : %d command : %d sector : %ld count : %ld\n", + DEVICE_NAME,CURRENT_DEV,MINOR(CURRENT->dev),CURRENT->cmd,CURRENT->sector, + CURRENT->nr_sectors); + #endif + + + block=CURRENT->sector + ps2esdi[MINOR(CURRENT->dev)].start_sect; + + #if 0 + printk("%s: blocknumber : %d\n",DEVICE_NAME,block); + #endif + count=CURRENT->nr_sectors; + switch(CURRENT->cmd) { + case READ: + ps2esdi_readwrite(READ,CURRENT_DEV,block,count); + return; + break; + case WRITE: + ps2esdi_readwrite(WRITE,CURRENT_DEV,block,count); + return; + break; + default: + printk("%s: Unknown command\n",DEVICE_NAME); + end_request(FAIL); + if(CURRENT) + do_ps2esdi_request(); + break; + } /* handle different commands */ + } /* is request is valid */ + else { + printk("Grrr. error. ps2esdi_drives: %d, %lu %lu\n",ps2esdi_drives, + CURRENT->sector, ps2esdi[MINOR(CURRENT->dev)].nr_sects); + end_request(FAIL); + if(CURRENT) + do_ps2esdi_request(); + } + + } /* main strategy routine */ + + /* resets the ESDI adapter */ + static void reset_ctrl(void) + { + + u_long expire; + + /* read the ESDI status port - if the controller is not busy, + simply do a soft reset (fast) - otherwise we'll have to do a + hard (slow) reset. */ + if(!(inb(ESDI_STATUS) & STATUS_BUSY)) { + printk("%s: soft reset...\n",DEVICE_NAME); + outb_p(CTRL_SOFT_RESET,ESDI_ATTN); + } /* soft reset */ + else { + printk("%s: hard reset...\n",DEVICE_NAME); + outb_p(CTRL_HARD_RESET,ESDI_CONTROL); + expire=jiffies + 10; + while(jiffies < expire) + ; + outb_p(0,ESDI_CONTROL); + } /* hard reset */ + + /* enable interrupts on the controller */ + outb_p(CTRL_ENABLE_INTR,ESDI_CONTROL); + + } /* reset the controller */ + + /* called by the strategy routine to handle read and write requests */ + static void ps2esdi_readwrite(int cmd,u_char drive, u_int block, u_int count) + { + + u_short track,head,cylinder,sector; + u_short cmd_blk[TYPE_1_CMD_BLK_LENGTH]; + + /* do some relevant arithmatic */ + CURRENT->current_nr_sectors= + (count < (2*MAX_16BIT/SECT_SIZE)) ? count : (2*MAX_16BIT/SECT_SIZE); + track=block / ps2esdi_info[drive].sect; + head=track % ps2esdi_info[drive].head; + cylinder=track / ps2esdi_info[drive].head; + sector=block % ps2esdi_info[drive].sect; + + #if 0 + printk("%s: cyl=%d head=%d sect=%d\n",DEVICE_NAME,cylinder,head,sector); + #endif + /* call the routine that actually fills out a command block */ + ps2esdi_fill_cmd_block(cmd_blk, + (cmd==READ) ? CMD_READ : CMD_WRITE,cylinder,head,sector, + CURRENT->current_nr_sectors,drive); + + /* send the command block to the controller */ + if(ps2esdi_out_cmd_blk(cmd_blk)) { + printk("%s: Controller failed\n",DEVICE_NAME); + if((++CURRENT->errors)> 5; + + } /* fill out the command block */ + + /* write a command block to the controller */ + static int ps2esdi_out_cmd_blk(u_short *cmd_blk) + { + + int i,j; + u_char status; + + /* enable interrupts */ + outb(CTRL_ENABLE_INTR,ESDI_CONTROL); + + /* do not write to the controller, if it is busy */ + for(i=jiffies+ESDI_STAT_TIMEOUT;(i>jiffies) && (inb(ESDI_STATUS) & + STATUS_BUSY);); + + #if 0 + printk("%s: i(1)=%d\n",DEVICE_NAME,i); + #endif + + /* if device is still busy - then just time out */ + if(inb(ESDI_STATUS) & STATUS_BUSY) { + printk("%s: ps2esdi_out_cmd timed out (1)\n",DEVICE_NAME); + return ERROR; + } /* timeout ??? */ + + /* Set up the attention register in the controller */ + outb(((*cmd_blk) & 0xE0) | 1,ESDI_ATTN); + + #if 0 + printk("%s: sending %d words to controller\n",DEVICE_NAME,(((*cmd_blk)>>14)+1)<<1); + #endif + + /* one by one send each word out */ + for(i=(((*cmd_blk)>>14)+1)<<1;i;i--) + { + status=inb(ESDI_STATUS); + for(j=jiffies+ESDI_STAT_TIMEOUT;(j>jiffies) && (status & STATUS_BUSY) && + (status & STATUS_CMD_INF);status=inb(ESDI_STATUS)); + if((status & (STATUS_BUSY | STATUS_CMD_INF))==STATUS_BUSY) { + #if 0 + printk("%s: sending %04X\n",DEVICE_NAME,*cmd_blk); + #endif + outw(*cmd_blk++,ESDI_CMD_INT); + } + else { + printk("%s: ps2esdi_out_cmd timed out while sending command (status=%02X)\n", + DEVICE_NAME,status); + return ERROR; + } + } /* send all words out */ + return OK; + } /* send out the commands */ + + /* prepare for dma - do all the necessary setup */ + static void ps2esdi_prep_dma(char *buffer,u_short length,u_char dma_xmode) + { + + u_int tc; + + #if 0 + printk("ps2esdi: b_wait: %p\n",CURRENT->bh->b_wait); + #endif + cli(); + + outb(dma_arb_level | DMA_MASK_CHAN,PORT_DMA_FN); + + outb(dma_arb_level | DMA_WRITE_ADDR,PORT_DMA_FN); + outb((u_int) buffer & (u_int) 0xff,PORT_DMA_EX); + outb(((u_int) buffer >> 8) & (u_int) 0xff,PORT_DMA_EX); + outb(((u_int) buffer >> 16) & (u_int) 0xff,PORT_DMA_EX); + + outb(dma_arb_level | DMA_WRITE_TC,PORT_DMA_FN); + tc=(length*SECT_SIZE/2)-1; + outb(tc & 0xff,PORT_DMA_EX); + outb((tc>>8) & 0xff,PORT_DMA_EX); + + outb(dma_arb_level | DMA_WRITE_MODE,PORT_DMA_FN); + outb(dma_xmode,PORT_DMA_EX); + + outb(dma_arb_level | DMA_UNMASK_CHAN,PORT_DMA_FN); + + sti(); + + } /* prepare for dma */ + + static void ps2esdi_interrupt_handler(int unused) { + + u_int int_ret_code; + + if(inb(ESDI_STATUS) & STATUS_INTR) { + int_ret_code=inb(ESDI_INTRPT); + if(current_int_handler) { + /* Disable adapter interrupts till processing is finished */ + outb(CTRL_DISABLE_INTR,ESDI_CONTROL); + current_int_handler(int_ret_code); + } + else + printk("%s: help ! No interrupt handler.\n",DEVICE_NAME); + } + else { + printk("%s: Spurious interrupt ?\n",DEVICE_NAME); + } + } + + static void ps2esdi_initial_reset_int_handler(u_int int_ret_code) { + + switch(int_ret_code & 0xf) { + case INT_RESET: + printk("%s: initial reset completed.\n",DEVICE_NAME); + outb((int_ret_code & 0xe0) | ATT_EOI,ESDI_ATTN); + break; + case INT_ATTN_ERROR: + printk("%s: Attention error. interrupt status : %02X\n",DEVICE_NAME, + int_ret_code); + break; + default: + printk("%s: initial reset handler received interrupt: %02X\n",DEVICE_NAME, + int_ret_code); + outb((int_ret_code & 0xe0) | ATT_EOI,ESDI_ATTN); + break; + } + outb(CTRL_ENABLE_INTR,ESDI_CONTROL); + wake_up(&ps2esdi_int); + } + static void ps2esdi_geometry_int_handler(u_int int_ret_code) { + + u_int status; + int i; + + switch(int_ret_code & 0xf) { + case INT_CMD_COMPLETE: + for(i=ESDI_TIMEOUT;i & !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL);i--); + if(!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { + printk("%s: timeout reading status word\n",DEVICE_NAME); + outb((int_ret_code & 0xe0) | ATT_EOI,ESDI_ATTN); + break; + } + status=inw(ESDI_STT_INT); + if((status & 0x1F)==CMD_GET_DEV_CONFIG) { + #define REPLY_WORDS 5 /* we already read word 0 */ + u_short reply[REPLY_WORDS]; + + if(ps2esdi_read_status_words((status>>8)-1,REPLY_WORDS,reply)) { + printk("%s: Device Configuration Status for drive %u\n", + DEVICE_NAME,int_ret_code>>5); + printk("%s: Spares/cyls: %u, ",DEVICE_NAME,reply[0]>>8); + printk("Config bits: %s%s%s%s%s\n", + (reply[0] & CONFIG_IS) ? "Invalid Secondary, " : "", + ((reply[0] & CONFIG_ZD) && !(reply[0] & CONFIG_IS)) + ? "Zero Defect, " : "Defects Present, ", + (reply[0] & CONFIG_SF) ? "Skewed Format, " : "", + (reply[0] & CONFIG_FR) ? "Removable, " : "Non-Removable, ", + (reply[0] & CONFIG_RT) ? "No Retries" : "Retries"); + printk("%s: Number of RBA's: %lu\n",DEVICE_NAME,reply[1]| + ((unsigned long)reply[2]<<16)); + printk("%s: Number of cylinders: %u, Sectors/Track: %u, Heads: %u\n", + DEVICE_NAME,reply[3],reply[4]>>8,reply[4] & 0xff); + if(!ps2esdi_info[int_ret_code>>5].head) { + ps2esdi_info[int_ret_code>>5].head=reply[4] & 0Xff; + ps2esdi_info[int_ret_code>>5].sect=reply[4]>>8; + ps2esdi_info[int_ret_code>>5].cyl=reply[3]; + ps2esdi_info[int_ret_code>>5].wpcom=0; + ps2esdi_info[int_ret_code>>5].lzone=reply[3]; + ps2esdi_drives++; + } + } + else + printk("%s: failed while getting device config\n",DEVICE_NAME); + #undef REPLY_WORDS + } + else + printk("%s: command %02X unknown by geometry handler\n",DEVICE_NAME, + status &0x1f); + + outb((int_ret_code & 0xe0) | ATT_EOI,ESDI_ATTN); + break; + + case INT_ATTN_ERROR: + printk("%s: Attention error. interrupt status : %02X\n",DEVICE_NAME, + int_ret_code); + printk("%s: Device not available\n",DEVICE_NAME); + break; + case INT_CMD_ECC: + case INT_CMD_RETRY: + case INT_CMD_ECC_RETRY: + case INT_CMD_WARNING: + case INT_CMD_ABORT: + case INT_CMD_FAILED: + case INT_DMA_ERR: + case INT_CMD_BLK_ERR: + printk("%s :Whaa. Error occurred...\n",DEVICE_NAME); + dump_cmd_complete_status(int_ret_code); + outb((int_ret_code & 0xe0) | ATT_EOI,ESDI_ATTN); + break; + default: + printk("%s: Unknown interrupt reason: %02X\n",DEVICE_NAME, + int_ret_code & 0xf); + outb((int_ret_code & 0xe0) | ATT_EOI,ESDI_ATTN); + break; + } + + wake_up(&ps2esdi_int); + no_int_yet=FALSE; + outb(CTRL_ENABLE_INTR,ESDI_CONTROL); + + } + + static void ps2esdi_normal_interrupt_handler(u_int int_ret_code) + { + + u_int status; + int i; + + switch(int_ret_code & 0x0f) { + case INT_TRANSFER_REQ: + ps2esdi_prep_dma(CURRENT->buffer,CURRENT->current_nr_sectors, + (CURRENT->cmd==READ) ? DMA_READ_16 : DMA_WRITE_16); + outb(CTRL_ENABLE_DMA | CTRL_ENABLE_INTR,ESDI_CONTROL); + break; + + case INT_ATTN_ERROR: + printk("%s: Attention error. interrupt status : %02X\n",DEVICE_NAME, + int_ret_code); + outb(CTRL_ENABLE_INTR,ESDI_CONTROL); + break; + + case INT_CMD_COMPLETE: + for(i=ESDI_TIMEOUT;i & !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL);i--); + if(!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { + printk("%s: timeout reading status word\n",DEVICE_NAME); + outb((int_ret_code & 0xe0) | ATT_EOI,ESDI_ATTN); + outb(CTRL_ENABLE_INTR,ESDI_CONTROL); + if((++CURRENT->errors) < MAX_RETRIES) + do_ps2esdi_request(); + else { + end_request(FAIL); + if(CURRENT) + do_ps2esdi_request(); + } + break; + } + status=inw(ESDI_STT_INT); + switch(status & 0x1F) { + case (CMD_READ & 0xff): + case (CMD_WRITE & 0xff): + LITE_OFF; + outb((int_ret_code & 0xe0) | ATT_EOI,ESDI_ATTN); + outb(CTRL_ENABLE_INTR,ESDI_CONTROL); + #if 0 + printk("ps2esdi: cmd_complete b_wait: %p\n",CURRENT->bh->b_wait); + #endif + ps2esdi_continue_request(); + break; + default: + printk("%s: interrupt for unknown command %02X\n",DEVICE_NAME, + status & 0x1f); + outb((int_ret_code & 0xe0) | ATT_EOI,ESDI_ATTN); + outb(CTRL_ENABLE_INTR,ESDI_CONTROL); + break; + } + break; + case INT_CMD_ECC: + case INT_CMD_RETRY: + case INT_CMD_ECC_RETRY: + LITE_OFF; + dump_cmd_complete_status(int_ret_code); + outb((int_ret_code & 0xe0) | ATT_EOI,ESDI_ATTN); + outb(CTRL_ENABLE_INTR,ESDI_CONTROL); + ps2esdi_continue_request(); + break; + case INT_CMD_WARNING: + case INT_CMD_ABORT: + case INT_CMD_FAILED: + case INT_DMA_ERR: + LITE_OFF; + dump_cmd_complete_status(int_ret_code); + outb((int_ret_code & 0xe0) | ATT_EOI,ESDI_ATTN); + outb(CTRL_ENABLE_INTR,ESDI_CONTROL); + if((++CURRENT->errors) < MAX_RETRIES) + do_ps2esdi_request(); + else { + end_request(FAIL); + if(CURRENT) + do_ps2esdi_request(); + } + break; + + case INT_CMD_BLK_ERR: + dump_cmd_complete_status(int_ret_code); + outb((int_ret_code & 0xe0) | ATT_EOI,ESDI_ATTN); + outb(CTRL_ENABLE_INTR,ESDI_CONTROL); + end_request(FAIL); + if(CURRENT) + do_ps2esdi_request(); + break; + + case INT_CMD_FORMAT: + printk("%s: huh ? Who issued this format command ?\n",DEVICE_NAME); + outb((int_ret_code & 0xe0) | ATT_EOI,ESDI_ATTN); + outb(CTRL_ENABLE_INTR,ESDI_CONTROL); + break; + + case INT_RESET: + printk("%s: reset completed.\n",DEVICE_NAME); + outb((int_ret_code & 0xe0) | ATT_EOI,ESDI_ATTN); + outb(CTRL_ENABLE_INTR,ESDI_CONTROL); + break; + + default: + printk("%s: Unknown interrupt reason: %02X\n",DEVICE_NAME, + int_ret_code & 0xf); + outb((int_ret_code & 0xe0) | ATT_EOI,ESDI_ATTN); + outb(CTRL_ENABLE_INTR,ESDI_CONTROL); + break; + } + + } /* handle interrupts */ + + static void ps2esdi_continue_request(void) { + + if(CURRENT->nr_sectors-=CURRENT->current_nr_sectors) { + CURRENT->buffer+=CURRENT->current_nr_sectors*SECT_SIZE; + CURRENT->sector+=CURRENT->current_nr_sectors; + do_ps2esdi_request(); + } + else { + end_request(SUCCES); + if(CURRENT) + do_ps2esdi_request(); + } + } + + static int ps2esdi_read_status_words(int num_words,int max_words,u_short *buffer) { + + int i; + + for(;max_words && num_words;max_words--,num_words--,buffer++) { + for(i=ESDI_TIMEOUT;i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL);i--); + if(!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { + printk("%s: timeout reading status word\n",DEVICE_NAME); + return FAIL; + } + *buffer=inw(ESDI_STT_INT); + } + return SUCCES; + } + + static void dump_cmd_complete_status(u_int int_ret_code) { + + #define WAIT_FOR_STATUS \ + for(i=ESDI_TIMEOUT;i && !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL);i--); \ + if(!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { \ + printk("%s: timeout reading status word\n",DEVICE_NAME); \ + return; \ + } + + int i,word_count; + u_short stat_word; + u_long rba; + + printk("%s: Device: %u, interrupt ID: %02X\n",DEVICE_NAME,int_ret_code>>5, + int_ret_code & 0xf); + + WAIT_FOR_STATUS; + stat_word=inw(ESDI_STT_INT); + word_count=(stat_word>>8)-1; + printk("%s: %u status words, command: %02X\n",DEVICE_NAME,word_count, + stat_word & 0xff); + + if(word_count--) { + WAIT_FOR_STATUS; + stat_word=inw(ESDI_STT_INT); + printk("%s: command status code: %02X, command error code: %02X\n", + DEVICE_NAME,stat_word>>8, stat_word & 0xff); + } + + if(word_count--) { + WAIT_FOR_STATUS; + stat_word=inw(ESDI_STT_INT); + printk("%s: device error code: %s%s%s%s%s,%02X\n",DEVICE_NAME, + (stat_word & 0x1000) ? "Ready, " : "Not Ready, ", + (stat_word & 0x0800) ? "Selected, " : "Not Selected, ", + (stat_word & 0x0400) ? "Write Fault, " : "", + (stat_word & 0x0200) ? "Track 0, " : "", + (stat_word & 0x0100) ? "Seek or command complete, " : "", + stat_word>>8); + } + + if(word_count--) { + WAIT_FOR_STATUS; + stat_word=inw(ESDI_STT_INT); + printk("%s: Blocks to do: %u", DEVICE_NAME,stat_word); + } + + if(word_count-=2) { + WAIT_FOR_STATUS; + rba=inw(ESDI_STT_INT); + WAIT_FOR_STATUS; + rba|=inw(ESDI_STT_INT)<<16; + printk(", Last Cyl: %u Head: %u Sector: %u\n",(u_short)((rba & 0x1ff80000) >> 11), + (u_short)((rba & 0x7E0) >> 5), (u_short)(rba & 0x1f)); + } + else + printk("\n"); + + if(word_count--) { + WAIT_FOR_STATUS; + stat_word=inw(ESDI_STT_INT); + printk("%s: Blocks required ECC: %u", DEVICE_NAME,stat_word); + } + printk("\n"); + + #undef WAIT_FOR_STATUS + + } + + + + static int ps2esdi_open(struct inode *inode,struct file *file) { + + int dev = DEVICE_NR(MINOR(inode->i_rdev)); + + #if 0 + printk("%s: dev= %d\n",DEVICE_NAME,dev); + #endif + + if (dev < ps2esdi_drives) { + while (!ps2esdi_valid[dev]) + sleep_on(&ps2esdi_wait_open); + + access_count[dev]++; + + return (0); + } + else + return (-ENODEV); + } + + static void ps2esdi_release (struct inode *inode, struct file *file) { + + int dev = DEVICE_NR(MINOR(inode->i_rdev)); + + if (dev < ps2esdi_drives) { + sync_dev(dev); + access_count[dev]--; + } + } + + static int ps2esdi_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg) { + + struct ps2esdi_geometry *geometry = (struct ps2esdi_geometry *) arg; + int dev = DEVICE_NR(MINOR(inode->i_rdev)),err; + + if (inode && (dev < ps2esdi_drives)) + switch (cmd) { + case HDIO_GETGEO: + if (arg) { + if ((err = verify_area(VERIFY_WRITE,geometry,sizeof(*geometry)))) + return (err); + put_fs_byte(ps2esdi_info[dev].head,(char *) &geometry->heads); + put_fs_byte(ps2esdi_info[dev].sect,(char *) &geometry->sectors); + put_fs_word(ps2esdi_info[dev].cyl,(short *) &geometry->cylinders); + put_fs_long(ps2esdi[MINOR(inode->i_rdev)].start_sect,(long *) &geometry->start); + + return (0); + } + break; + case BLKRASET: + if(!suser()) return -EACCES; + if(!inode->i_rdev) return -EINVAL; + if(arg > 0xff) return -EINVAL; + read_ahead[MAJOR(inode->i_rdev)] = arg; + return 0; + case BLKGETSIZE: + if (arg) { + if ((err = verify_area(VERIFY_WRITE,(long *) arg,sizeof(long)))) + return (err); + put_fs_long(ps2esdi[MINOR(inode->i_rdev)].nr_sects,(long *) arg); + + return (0); + } + break; + case BLKFLSBUF: + if(!suser()) return -EACCES; + if(!inode->i_rdev) return -EINVAL; + fsync_dev(inode->i_rdev); + invalidate_buffers(inode->i_rdev); + return 0; + + case BLKRRPART: + return (ps2esdi_reread_partitions(inode->i_rdev)); + RO_IOCTLS(inode->i_rdev,arg); + } + return (-EINVAL); + } + + static int ps2esdi_reread_partitions(int dev) { + + int target = DEVICE_NR(MINOR(dev)),start = target << ps2esdi_gendisk.minor_shift,partition; + + cli(); ps2esdi_valid[target] = (access_count[target] != 1); sti(); + if (ps2esdi_valid[target]) + return (-EBUSY); + + for (partition = ps2esdi_gendisk.max_p - 1; partition >= 0; partition--) { + sync_dev(MAJOR_NR << 8 | start | partition); + invalidate_inodes(MAJOR_NR << 8 | start | partition); + invalidate_buffers(MAJOR_NR << 8 | start | partition); + ps2esdi_gendisk.part[start + partition].start_sect = 0; + ps2esdi_gendisk.part[start + partition].nr_sects = 0; + }; + + ps2esdi_gendisk.part[start].nr_sects = ps2esdi_info[target].head * ps2esdi_info[target].cyl * ps2esdi_info[target].sect; + resetup_one_dev(&ps2esdi_gendisk,target); + + ps2esdi_valid[target] = 1; + wake_up(&ps2esdi_wait_open); + + return (0); + } + #endif diff -cr --new-file ../linux/drivers/net/Makefile linux/drivers/net/Makefile *** ../linux/drivers/net/Makefile Wed Aug 10 20:40:42 1994 --- linux/drivers/net/Makefile Wed Aug 24 15:36:59 1994 *************** *** 24,29 **** --- 24,31 ---- net_init.o: ../../include/linux/autoconf.h + NETDRV_OBJS := $(NETDRV_OBJS) ibmtr.o + ifdef CONFIG_SK_G16 NETDRV_OBJS := $(NETDRV_OBJS) sk_g16.o endif diff -cr --new-file ../linux/drivers/net/Space.c linux/drivers/net/Space.c *** ../linux/drivers/net/Space.c Wed Aug 24 15:50:03 1994 --- linux/drivers/net/Space.c Wed Aug 24 15:36:55 1994 *************** *** 185,191 **** static struct device plip1_dev = { "plip1", 0, 0, 0, 0, 0x378, 7, 0, 0, 0, &plip2_dev, plip_init, }; static struct device plip0_dev = { ! "plip0", 0, 0, 0, 0, 0x3BC, 5, 0, 0, 0, &plip1_dev, plip_init, }; # undef NEXT_DEV # define NEXT_DEV (&plip0_dev) #endif /* PLIP */ --- 185,191 ---- static struct device plip1_dev = { "plip1", 0, 0, 0, 0, 0x378, 7, 0, 0, 0, &plip2_dev, plip_init, }; static struct device plip0_dev = { ! "plip0", 0, 0, 0, 0, 0x3BC, 7, 0, 0, 0, &plip1_dev, plip_init, }; # undef NEXT_DEV # define NEXT_DEV (&plip0_dev) #endif /* PLIP */ *************** *** 303,307 **** --- 303,324 ---- # define NEXT_DEV (&loopback_dev) #endif + /* #ifdef IBMTR */ + extern int tok_probe(struct device *dev); + static struct device ibmtr_dev = { + "tr0", /* Software Loopback interface */ + 0x0, /* recv memory end */ + 0x0, /* recv memory start */ + 0x0, /* memory end */ + 0x0, /* memory start */ + 0xa20, /* base I/O address */ + 0, /* IRQ */ + 0, 0, 0, /* flags */ + NEXT_DEV, /* next device */ + tok_probe /* loopback_init should set up the rest */ + }; + # undef NEXT_DEV + # define NEXT_DEV (&ibmtr_dev) + /* #endif */ struct device *dev_base = NEXT_DEV; diff -cr --new-file ../linux/drivers/net/ibmtr.c linux/drivers/net/ibmtr.c *** ../linux/drivers/net/ibmtr.c Thu Jan 1 01:00:00 1970 --- linux/drivers/net/ibmtr.c Wed Aug 24 15:37:15 1994 *************** *** 0 **** --- 1,870 ---- + /* ibmtr.c: A shared-memory IBM Token Ring II 16/4 driver for linux */ + /* + Written 1993 by Mark Swanson and Peter De Schrijver. + This software may be used and distributed according to the terms + of the GNU Public License, incorporated herein by reference. + + This device driver should work with Any IBM Token Ring Card that does + not use DMA. + + The Author may be reached at ag010@freenet.carleton.ca. The + response will not be swift due to the limited number of + phone lines and the difficulty of logging on to the freenet. + + I used Donald Becker's (becker@super.org) device driver work + as a base for most of my initial work. + */ + + /* + Changes by Peter De Schrijver (stud11@cc4.kuleuven.ac.be) : + + + changed name to ibmtr.c in anticipation of other tr boards. + + changed reset code and adapter open code. + + added SAP open code. + + a first attempt to write interrupt, transmit and receive routines. + */ + + #define NO_AUTODETECT 1 + #undef ENABLE_PAGING + + static char *version = "ibmtr.c:v1.1.36 8/7/94 Peter De Schrijver and Mark Swanson\n"; + + static char pcchannelid[]={0x05, 0x00, 0x04, 0x09, + 0x04, 0x03, 0x04, 0x0f, + 0x03, 0x06, 0x03, 0x01, + 0x03, 0x01, 0x03, 0x00, + 0x03, 0x09, 0x03, 0x09, + 0x03, 0x00, 0x02, 0x00}; + static char mcchannelid[]={0x04, 0x0d, 0x04, 0x01, + 0x05, 0x02, 0x05, 0x03, + 0x03, 0x06, 0x03, 0x03, + 0x05, 0x08, 0x03, 0x04, + 0x03, 0x05, 0x03, 0x01, + 0x03, 0x08, 0x02, 0x00}; + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include "ibmtr.h" + + #define DPRINTK(x) printk("%s: ",dev->name),printk x + + struct tok_info ti; + static struct wait_queue *wait_for_tok_int=NULL; + static int reset_completed=0; + extern void *irq2dev_map[16]; + + void (*do_tok_int)(struct device *dev)=NULL; + + int tok_probe(struct device *dev); + unsigned char get_sram_size(struct tok_info *adapt_info); + /* int tok_probe1(int ioaddr, struct device *dev); */ + + static void tok_init_card(unsigned long dev_addr); + static void tok_interrupt(int reg_ptr); + + static void initial_tok_int(struct device *dev); + static void regular_tok_int(struct device *dev); + + static void open_sap(unsigned char type,struct device *dev); + void tok_open_adapter(unsigned long dev_addr); + static void tr_rx(struct device *dev); + static void tr_tx(struct device *dev); + + static int tok_open(struct device *dev); + static int tok_close(struct device *dev); + static int tok_send_packet(struct sk_buff *skb, struct device *dev); + static struct enet_statistics * tok_get_stats(struct device *dev); + + static struct timer_list tr_timer={NULL,NULL,0,0L,tok_open_adapter}; + + int tok_probe(struct device *dev) + { + short ioaddr = dev->base_addr; + unsigned char segment=0, intr=0, irq=0, i=0, j=0, cardpresent=NOTOK,temp=0; + + if (ioaddr <0) return ENXIO; + /* if (ioaddr >0) return ! tokprobe1(ioaddr, dev); WHY!!!???????? */ + + if ( check_region(MMIOStartLocP,4) ) { + DPRINTK(("Could not check_region MMIO.\n")); + return ENODEV; /* Must be done before I muck with I/O addresses */ + } + segment = inb(MMIOStartLocP); /* Returns segment address of the start of the MMIO */ + ti.mmio=(char *) (((segment & 0xfc) << 11) + 0x80000); /* fix it up, since we don't care about segments */ + DPRINTK(("mmio segment : %p\n",ti.mmio)); + intr = segment & 0x03; + #ifdef 0 + for (i=0;i<=46;i+=2) DPRINTK(("%d, %p ",* (char *)(i+CHANNEL_ID + ti.mmio), (char *) (i+CHANNEL_ID+ti.mmio))); + #endif + j=0; + for (i=0; i<=46; i=i+2) { + if ( * (char *)( i + CHANNEL_ID + ti.mmio) != pcchannelid[j]) { + cardpresent=NOTOK; + goto next; + } + cardpresent=ISA; + ++j; + } + + next: + if (cardpresent != ISA) { + for (i=0,j=0; i<=46; i=i+2,j++) { + DPRINTK(("%p: %01X\\ ",i + CHANNEL_ID + ti.mmio,*(char *)(i+CHANNEL_ID+ti.mmio))); + if ( * (char *)( i + CHANNEL_ID + ti.mmio) != mcchannelid[j]) { + DPRINTK(("Warning: Did not pass channel identification..\n")); + + #if !defined(NO_AUTODETECT) + return ENODEV; + #endif + } + } + cardpresent=MCA; + } + + DPRINTK((version)); /* As we have passed card identification, let the world know we're here! */ + + /* Now, allocate some of the pl0 buffers for this driver.. */ + snarf_region(MMIOStartLocP,4); + /* dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL); */ + + switch (cardpresent) { + case ISA: + if (intr==0) irq=9; /* irq2 really is irq9 */ + if (intr==1) irq=3; + if (intr==2) irq=6; + if (intr==3) irq=7; + ti.global_int_enable=GLOBAL_INT_ENABLE+((irq==9) ? 2 : irq); + ti.sram=NULL; + DPRINTK(("ti.global_int_enable: %04X\n",ti.global_int_enable)); + break; + case MCA: + if (intr==0) irq=9; + if (intr==1) irq=3; + if (intr==2) irq=10; + if (intr==3) irq=11; + ti.global_int_enable=0; + ti.sram=(unsigned char *)((inb(ADAPTRESETRELP) & 0xfe) << 12); + } + if (request_irq (dev->irq = irq, &tok_interrupt,0,"IBM TR") != 0) { + DPRINTK(("Could not grab irq %d. Halting Token Ring driver.\n",irq)); + return ENODEV; + } + irq2dev_map[irq]=dev; + + DPRINTK(("ti.mmio=%p, ",ti.mmio)); + printk("irq=%d, ",irq); + printk("segment=%02X.\n",segment); + + DPRINTK(("hw address: ")); + /* Get hw address of token ring card */ + j=0; + for (i=0; i<0x18; i=i+2) { + temp = *(char *)((ulong)AIP + (ulong)i + ti.mmio) & 0x0f; /* Tech ref states must do this */ + printk("%02X ",ti.hw_address[j]=temp); + if(j&1) + dev->dev_addr[(j/2)]=ti.hw_address[j]+(ti.hw_address[j-1]<<4); + ++j; + } + printk("\n"); + /* get Adapter type */ + ti.adapter_type = *(char *)(ti.mmio + AIPADAPTYPE); /* 'F' = Adapter/A */ + + /* get Data Rate */ + ti.data_rate = *(char *)(ti.mmio + AIPDATARATE); /* F=4Mb, E=16Mb, D=4Mb & 16Mb ?? */ + + /* Does card support Early Token Release? */ + ti.token_release = *(char *)(ti.mmio + AIPEARLYTOKEN); /* F=no, E=4Mb, D=16Mb, C=4&16Mb */ + + /* How much shared RAM is on adapter ? */ + ti.avail_shared_ram = get_sram_size(&ti); + + /* We need to set or do a bunch of work here based on previous results.. */ + /* Support paging? If so, what sizes? */ + ti.shared_ram_paging = *(char *)(ti.mmio + AIPSHRAMPAGE); /* F=no, E=16k, D=32k, C=16 & 32k, */ + + /* Available DHB 4Mb size */ + ti.dhb_size4mb = *(char *) (ti.mmio + AIP4MBDHB); /* F=2048, E=4096, D=4464 */ + + /* Available DHB 16Mb size */ + ti.dhb_size16mb = *(char *)(ti.mmio + AIP16MBDHB); /* F=2048, E=4096, D=8192, C=16384, B=17960 */ + + DPRINTK(("atype=%x, drate=%x, trel=%x, asram=%dK, srp=%x, 4mb hdb=%x, 16mb hdb=%x\n",ti.adapter_type, \ + ti.data_rate, ti.token_release, ti.avail_shared_ram/2, ti.shared_ram_paging, ti.dhb_size4mb, + ti.dhb_size16mb)); + + ti.used_shared_ram=1<<(((*(unsigned char *)(ti.mmio+ ACA_OFFSET + ACA_RW + RRR_ODD))>>2)+4); + DPRINTK(("shared ram page size: %d\n",ti.used_shared_ram)); + ti.page_size=0; + #ifdef ENABLE_PAGING + switch(ti.shared_ram_paging) { + case 0xf: break; + case 0xe: ti.page_size=(ti.used_shared_ram==32) ? 0xc0 : 0; + ti.used_shared_ram=ti.avail_shared_ram; + break; + case 0xd: ti.page_size=(ti.used_shared_ram==64) ? 0x80 : 0; + ti.used_shared_ram=ti.avail_shared_ram; + break; + case 0xc: ti.page_size=(ti.used_shared_ram==32) ? 0xc0 : 0; + ti.page_size=(ti.used_shared_ram==64) ? 0x80 : 0; + ti.used_shared_ram=ti.avail_shared_ram; + break; + default: DPRINTK(("Unknown shared ram paging info %01X\n",ti.shared_ram_paging)); + break; + } + if(ti.page_size) + DPRINTK(("Shared RAM paging enabled. Page size : %uK\n",((ti.page_size^ 0xff)+1)>>2)); + #endif + + DPRINTK(("Using %dK shared RAM\n",ti.used_shared_ram/2)); + + dev->open=tok_open; + dev->stop=tok_close; + dev->hard_start_xmit=tok_send_packet; + dev->get_stats = NULL; /* tok_get_stats; */ + dev->set_multicast_list = NULL; + tr_setup(dev); + tok_init_card((unsigned long)dev); + + return 0; /* Return 0 if we have found a Token Ring card. Obviously, we have. */ + } + + unsigned char get_sram_size(struct tok_info *adapt_info) { + + unsigned char avail_sram_code; + static unsigned char size_code[]={ 0,16,32,64,127,128 }; + + avail_sram_code=0xf-*(adapt_info->mmio + AIPAVAILSHRAM); + if(avail_sram_code) + return size_code[avail_sram_code]; + else + return 1<<(((*(unsigned char *)(ti.mmio+ ACA_OFFSET + ACA_RW + RRR_ODD))>>2)+4); + } + + static int tok_open(struct device *dev) { + + if(reset_completed) { + dev->tbusy=0; + dev->interrupt=0; + dev->start=1; + return 0; + } + + return -EAGAIN; + + } + + static int tok_close(struct device *dev) { + + struct srb_close_adapter *close_adapter=(struct srb_close_adapter *)ti.srb; + + close_adapter->command=DIR_CLOSE_ADAPTER; + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_SET + ISRA_ODD)=CMD_IN_SRB; + + sleep_on(&wait_for_tok_int); + + if(close_adapter->ret_code) + DPRINTK(("close adapter failed: %02X\n",close_adapter->ret_code)); + + return 0; + } + static void tok_interrupt (int reg_ptr) + { + + int irq = -(((struct pt_regs *)reg_ptr)->orig_eax+2); + struct device *dev = (struct device *)(irq2dev_map[irq]); + #if 0 + DPRINTK(("Int from tok_driver, dev : %p\n",dev)); + #endif + + if(do_tok_int) + do_tok_int(dev); + else + DPRINTK(("Unexpected interrupt from tr adapter\n")); + + } + + static void initial_tok_int(struct device *dev) { + + int i; + unsigned char *encoded_addr; + + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_RESET + ISRP_EVEN)=(~INT_ENABLE); + + /* Reset interrupt for ISA boards */ + if(ti.global_int_enable) + outb(0,ti.global_int_enable); + + do_tok_int=regular_tok_int; + + DPRINTK(("Initial tok int received\n")); + + if(!ti.sram) { + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_RW + RRR_EVEN)=0xD0 ; /* set RRR even to D000 for shared ram address */ + ti.sram=(char *)0xd0000; + } + ti.init_srb=ti.sram+ntohs(*(unsigned short *)(ti.mmio+ ACA_OFFSET + WRBR_EVEN)); + SET_PAGE(ntohs(*(unsigned short *)(ti.mmio+ ACA_OFFSET + WRBR_EVEN))); + + DPRINTK(("init_srb:")); + for(i=0;i<17;i++) + printk("%02X ",*(ti.init_srb+i)); + printk("\n"); + + DPRINTK(("srb_init_response->encoded_address: %04X\n",((struct srb_init_response *)ti.init_srb)->encoded_address)); + DPRINTK(("ntohs(srb_init_response->encoded_address): %04X\n",ntohs(((struct srb_init_response *)ti.init_srb)->encoded_address))); + encoded_addr=(unsigned char *)(ti.sram + ntohs(((struct srb_init_response *)ti.init_srb)->encoded_address)); + + DPRINTK(("encoded addr (%p): ",encoded_addr)); + + for(i=0;idev_addr[i]=encoded_addr[i],(i==TR_ALEN-1) ? "" : ":" ); + printk("\n"); + + DPRINTK(("ti.sram: %p, ti.init_srb: %p\n",ti.sram,ti.init_srb)); + + tok_open_adapter((unsigned long)dev); + + } + + static void tok_init_card(unsigned long dev_addr) + { + + int i; + struct device *dev=(struct device *)dev_addr; + + do_tok_int=initial_tok_int; /* Special processing for first interrupt after reset */ + + /* Reset adapter */ + + reset_completed=0; + dev->tbusy=1; /* nothing can be done before reset and open completed */ + + #ifdef ENABLE_PAGING + if(ti.page_size) { + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_RW + SRPR_EVEN)=SRPR_ENABLE_PAGING; + } + #endif + + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_RESET + ISRP_EVEN)=~(INT_ENABLE); + DPRINTK(("resetting card\n")); + outb(ADAPTRESETP,0); + for(i=jiffies+5;i<=jiffies;); /* wait 50ms */ + outb(ADAPTRESETRELP,0); + DPRINTK(("card reset\n")); + + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN)=INT_ENABLE; + + DPRINTK(("Tok_init_card executed.\n")); + + } + + static void open_sap(unsigned char type,struct device *dev) { + + struct dlc_open_sap *open_sap=(struct dlc_open_sap *)ti.srb; + + SET_PAGE(ti.srb); + memset(open_sap,0,sizeof(struct dlc_open_sap)); + + open_sap->command=DLC_OPEN_SAP; + open_sap->max_i_field=htons(MAX_I_FIELD); + open_sap->sap_options=SAP_OPEN_IND_SAP | SAP_OPEN_PRIORITY; + open_sap->station_count=SAP_OPEN_STATION_CNT; + open_sap->sap_value=type; + + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_SET + ISRA_ODD)=CMD_IN_SRB; + + } + + void tok_open_adapter(unsigned long dev_addr) { + + struct device *dev=(struct device *)dev_addr; + struct dir_open_adapter *open_adapter; + + DPRINTK(("now opening the board...\n")); + + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_RESET + ISRP_ODD)=~(SRB_RESP_INT); + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_RESET + ISRA_ODD)=~(CMD_IN_SRB); + + open_adapter=(struct dir_open_adapter *)(ti.init_srb); + memset(open_adapter,0,sizeof(struct dir_open_adapter)); + + open_adapter->command=DIR_OPEN_ADAPTER; + open_adapter->open_options=htons(OPEN_PASS_BCON_MAC); + open_adapter->num_rcv_buf=htons(NUM_RCV_BUF); + open_adapter->rcv_buf_len=htons(RCV_BUF_LEN); + open_adapter->dhb_length=htons(DHB_LENGTH); + open_adapter->num_dhb=NUM_DHB; + open_adapter->dlc_max_sap=DLC_MAX_SAP; + open_adapter->dlc_max_sta=DLC_MAX_STA; + + ti.srb=ti.init_srb; /* We use this one in the interrupt handler */ + + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN)=INT_ENABLE; + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_SET + ISRA_ODD)=CMD_IN_SRB; + + } + + static void regular_tok_int(struct device *dev) { + + unsigned char status; + + dev->interrupt=1; + + /* Disable interrupts till processing is finished */ + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_RESET + ISRP_EVEN)=(~INT_ENABLE); + + /* Reset interrupt for ISA boards */ + if(ti.global_int_enable) + outb(0,ti.global_int_enable); + + status=*(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_RW + ISRP_ODD); + + if(status & ADAP_CHK_INT) { + int i; + unsigned char *check_reason=ti.mmio + ntohs(*(unsigned short *)(ti.mmio + ACA_OFFSET + ACA_RW +WWCR_EVEN)); + + DPRINTK(("adapter check interrupt\n")); + + DPRINTK(("8 reason bytes follow: ")); + for(i=0;i< 8;i++,check_reason++) + DPRINTK(("%02X ",*check_reason)); + DPRINTK(("\n")); + + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_RESET + ISRP_ODD)=(~ADAP_CHK_INT); + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN)=INT_ENABLE; + dev->interrupt=0; + } + + else if((*(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_RW + ISRP_EVEN)) & (TCR_INT + ERR_INT + ACCESS_INT)) { + + printk("adapter error: ISRP_EVEN : %02x\n", + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_RW + ISRP_EVEN)); + + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_RESET + ISRP_EVEN)=~(TCR_INT + ERR_INT + ACCESS_INT); + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN)=INT_ENABLE; + dev->interrupt=0; + } + + else if(status & (SRB_RESP_INT + ASB_FREE_INT + ARB_CMD_INT + SSB_RESP_INT)) { + + if(status & SRB_RESP_INT) { + switch(*ti.srb) { + case XMIT_DIR_FRAME: { + struct srb_xmit *xmit=(struct srb_xmit *)(ti.srb); + if(xmit->ret_code!=0xff) { + DPRINTK(("error on xmit_dir_frame request: %02X\n",xmit->ret_code)); + if(ti.current_skb) { + dev_kfree_skb(ti.current_skb, FREE_WRITE); + ti.current_skb=NULL; + } + dev->tbusy=0; + } + } + break; + + case XMIT_UI_FRAME: { + struct srb_xmit *xmit=(struct srb_xmit *)(ti.srb); + if(xmit->ret_code!=0xff) { + DPRINTK(("error on xmit_ui_frame request: %02X\n",xmit->ret_code)); + if(ti.current_skb) { + dev_kfree_skb(ti.current_skb, FREE_WRITE); + ti.current_skb=NULL; + } + dev->tbusy=0; + } + } + break; + + case DIR_OPEN_ADAPTER: { + struct srb_open_response *open_response=(struct srb_open_response *)(ti.init_srb); + + DPRINTK(("board opened...\n")); + ti.srb=ti.sram+ntohs(open_response->srb_addr); + ti.ssb=ti.sram+ntohs(open_response->ssb_addr); + ti.arb=ti.sram+ntohs(open_response->arb_addr); + ti.asb=ti.sram+ntohs(open_response->asb_addr); + ti.current_skb=NULL; + + + if(open_response->ret_code) { + DPRINTK(("open failed: ret_code = %02X, retrying\n",open_response->ret_code)); + tr_timer.expires=TR_RETRY_INTERVAL; + tr_timer.data=(unsigned long)dev; + tr_timer.next=tr_timer.prev=NULL; + add_timer(&tr_timer); + } + else { + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_RESET + ISRP_ODD)=~(SRB_RESP_INT); + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_RESET + ISRA_ODD)=~(CMD_IN_SRB); + open_sap(EXTENDED_SAP,dev); + /* YdW probably hates me */ + goto skip_reset; + } + } + break; + + case DIR_CLOSE_ADAPTER: + wake_up(&wait_for_tok_int); + break; + case DLC_OPEN_SAP: { + struct dlc_open_sap *open_sap=(struct dlc_open_sap *)ti.srb; + if(open_sap->ret_code) { + DPRINTK(("open_sap failed: ret_code = %02X,retrying\n",open_sap->ret_code)); + tr_timer.expires=TR_RETRY_INTERVAL; + tr_timer.data=(unsigned long)dev; + tr_timer.next=tr_timer.prev=NULL; + add_timer(&tr_timer); + } + else { + ti.exsap_station_id=open_sap->station_id; + reset_completed=1; /* TR adapter is now available */ + } + } + break; + + case DIR_INTERRUPT: + case DIR_MOD_OPEN_PARAMS: + case DIR_SET_GRP_ADDR: + case DIR_SET_FUNC_ADDR: + case DLC_CLOSE_SAP: { + struct srb_interrupt *intr=(struct srb_interrupt *)(ti.srb); + if(intr->ret_code) + DPRINTK(("error on %02X: %02X\n",intr->command,intr->ret_code)); + } + break; + + case DIR_READ_LOG: { + struct srb_read_log *read_log=(struct srb_read_log *)(ti.srb); + if(read_log->ret_code) + DPRINTK(("error on dir_read_log: %02X\n",read_log->ret_code)); + else { + DPRINTK(("Line errors %02X, Internal errors %02X, Burst errors %02X\n", + read_log->line_errors,read_log->internal_errors,read_log->burst_errors)); + DPRINTK(("A/C errors %02X, Abort delimiters %02X, Lost frames %02X\n", + read_log->A_C_errors,read_log->abort_delimiters,read_log->lost_frames)); + DPRINTK(("Receive congestion count %02X, Frame copied errors %02X, Frequency errors %02X\n", + read_log->recv_congest_count,read_log->frame_copied_errors,read_log->frequency_errors)); + DPRINTK(("Token errors %02X\n",read_log->token_errors)); + } + dev->tbusy=0; + } + break; + + default: + DPRINTK(("Unknown command %02X encountered\n",*(ti.srb))); + } + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_RESET + ISRA_ODD)=~(CMD_IN_SRB); + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_RESET + ISRP_ODD)=~(SRB_RESP_INT); + skip_reset: + } + + if(status & ASB_FREE_INT) { + switch(*ti.asb) { + case REC_DATA: + case XMIT_UI_FRAME: + case XMIT_DIR_FRAME: + if(*(ti.asb+2)!=0xff) + DPRINTK(("ASB error %02X in cmd %02X\n", *(ti.asb+2),*(ti.asb))); + break; + default: + DPRINTK(("unknown command in asb %02X\n",*ti.asb)); + } + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_RESET + ISRP_ODD)=~(ASB_FREE_INT); + } + + if(status & ARB_CMD_INT) { + switch(*ti.arb) { + case DLC_STATUS: { + struct arb_dlc_status *dlc_status=(struct arb_dlc_status *)(ti.arb); + DPRINTK(("DLC_STATUS new status: %02X on station %02X\n",ntohs(dlc_status->status),ntohs(dlc_status->station_id))); + } + break; + + case REC_DATA: + tr_rx(dev); + break; + + case RING_STAT_CHANGE: { + struct arb_ring_stat_change *ring_stat_change=(struct arb_ring_stat_change *)(ti.arb); + unsigned short ring_status=ntohs(ring_stat_change->ring_status); + + if(ring_status & (SIGNAL_LOSS + LOBE_FAULT)) { + DPRINTK(("Signal loss/Lobe fault\n")); + DPRINTK(("We try to reopen the adapter.\n")); + tr_timer.expires=TR_RETRY_INTERVAL; + tr_timer.data=(unsigned long)dev; + tr_timer.next=tr_timer.prev=NULL; + add_timer(&tr_timer); + } + else DPRINTK(("New ring status: %02X\n",ring_status)); + + if(ring_status & LOG_OVERFLOW) { + *(ti.srb)=DIR_READ_LOG; + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN)=INT_ENABLE; + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_SET + ISRA_ODD)=CMD_IN_SRB; + dev->tbusy=1; /* really srb busy... */ + } + } + break; + + case XMIT_DATA_REQ: + tr_tx(dev); + break; + + default: + DPRINTK(("Unknown command %02X in arb\n",*(ti.arb))); + break; + } + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_RESET + ISRP_ODD)=~(ARB_CMD_INT); + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_SET + ISRA_ODD)=ARB_FREE; + } + + if(status & SSB_RESP_INT) { + switch(*ti.ssb) { + case XMIT_DIR_FRAME: + case XMIT_UI_FRAME: + if(*(ti.ssb+2)) + DPRINTK(("xmit ret_code: %02X xmit error code: %02X\n",*(ti.ssb+2),*(ti.ssb+6))); + else + ti.tr_stats.tx_packets++; + break; + + case XMIT_XID_CMD: + DPRINTK(("xmit xid ret_code: %02X\n",*(ti.ssb+2))); + + default: + DPRINTK(("Unknown command %02X in ssb\n",*(ti.ssb))); + } + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_RESET + ISRP_ODD)=~(SSB_RESP_INT); + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_SET + ISRA_ODD)=SSB_FREE; + } + } + + dev->interrupt=0; + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN)=INT_ENABLE; + + return; + } + + static void tr_tx(struct device *dev) { + + struct asb_xmit_resp *xmit_resp=(struct asb_xmit_resp *)ti.asb; + struct arb_xmit_req *xmit_req=(struct arb_xmit_req *)ti.arb; + struct srb_xmit *xmit=(struct srb_xmit *)ti.srb; + unsigned int rif_len; + unsigned char *dhb; + + #if 0 + DPRINTK(("transmitting...\n")); + #endif + + if(xmit_resp->ret_code!=0xff) + DPRINTK(("ASB not free !!!\n")); + + dhb=ti.sram+ntohs(xmit_req->dhb_address); + + xmit_resp->command=xmit->command; + xmit_resp->station_id=xmit_req->station_id; + xmit_resp->rsap_value=EXTENDED_SAP; + xmit_resp->cmd_corr=xmit_req->cmd_corr; + xmit_resp->ret_code=0; + + if((xmit->command==XMIT_XID_CMD) && (xmit->command==XMIT_TEST_CMD)) { + xmit_resp->frame_length=htons(0x11); + xmit_resp->hdr_length=0x0e; + dhb[0]=AC; + dhb[1]=LLC_FRAME; + memset(dhb+2,0xff,TR_ALEN); + memset(dhb+8,0,TR_ALEN); + } + + memcpy(dhb,ti.current_skb->data,sizeof(struct trh_hdr)); + dhb+=sizeof(struct trh_hdr); + if(!(((struct trh_hdr *)(&ti.current_skb->data))->saddr[0] & 0x80)) { + dhb-=18; + xmit_resp->hdr_length=sizeof(struct trh_hdr)-18; + xmit_resp->frame_length=htons(ti.current_skb->len-18); + #if 0 + DPRINTK(("hdr_length: %d, frame length: %ld\n",sizeof(struct trh_hdr)-18, + ti.current_skb->len-18)); + #endif + } + else { + rif_len=(ntohs(((struct trh_hdr *)(&ti.current_skb->data))->rcf) & TR_RCF_LEN_MASK)>>8; + #if 0 + DPRINTK(("rcf: %02X rif_len: %d\n",((struct trh_hdr *)&ti.current_skb->data)->rcf,rif_len)); + DPRINTK(("hdr_length: %d, frame length: %ld\n",sizeof(struct trh_hdr)-18+rif_len, + ti.current_skb->len-18+rif_len)); + #endif + xmit_resp->hdr_length=sizeof(struct trh_hdr)-18+rif_len; + xmit_resp->frame_length=htons(ti.current_skb->len-18+rif_len); + dhb+=rif_len-18; + } + + memcpy(dhb,ti.current_skb->data+sizeof(struct trh_hdr),ti.current_skb->len-sizeof(struct trh_hdr)); + + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_SET + ISRA_ODD)=RESP_IN_ASB; + dev->tbusy=0; + dev_kfree_skb(ti.current_skb,FREE_WRITE); + ti.current_skb=NULL; + mark_bh(NET_BH); + } + + static void tr_rx(struct device *dev) { + + struct arb_rec_req *rec_req=(struct arb_rec_req *)ti.arb; + struct asb_rec *rec_resp=(struct asb_rec *)ti.asb; + struct rec_buf *rbuffer; + struct trllc *llc; + unsigned char *data; + unsigned int rbuffer_len,lan_hdr_len; + struct sk_buff *skb; + + rbuffer=(struct rec_buf *)(ti.sram+ntohs(rec_req->rec_buf_addr)); + + if(rec_resp->ret_code!=0xff) + DPRINTK(("ASB not free !!!\n")); + + rec_resp->command=REC_DATA; + rec_resp->station_id=rec_req->station_id; + rec_resp->rec_buf_addr=rec_req->rec_buf_addr; + + lan_hdr_len=rec_req->lan_hdr_len; + + llc=(struct trllc *)((unsigned char *)rbuffer+offsetof(struct rec_buf,data)+lan_hdr_len); + + #if 0 + DPRINTK(("offsetof data: %02X lan_hdr_len: %02X\n",offsetof(struct rec_buf,data),lan_hdr_len)); + DPRINTK(("llc: %p rec_buf_addr: %04X ti.sram: %p\n",llc,ntohs(rec_req->rec_buf_addr),ti.sram)); + DPRINTK(("dsap: %02X, ssap: %02X, llc: %02X, protid: %02X%02X%02X, ethertype: %04X\n", + llc->dsap,llc->ssap,llc->llc,llc->protid[0],llc->protid[1],llc->protid[2],llc->ethertype)); + #endif + + if(llc->llc!=UI_CMD) { + + DPRINTK(("non-UI frame arrived. dropped. llc= %02X\n",llc->llc)); + rec_resp->ret_code=DATA_LOST; + ti.tr_stats.rx_dropped++; + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_SET + ISRA_ODD)=RESP_IN_ASB; + return; + } + + #if 0 + if((llc->dsap!=0xaa) || (llc->ssap!=0xaa)) { + + struct trh_hdr *trhdr=(struct trh_hdr *)((unsigned char *)rbuffer+offsetof(struct rec_buf,data)); + + DPRINTK(("Probably non-IP frame received.\n")); + DPRINTK(("ssap: %02X dsap: %02X saddr: %02X:%02X:%02X:%02X:%02X:%02X daddr: %02X:%02X:%02X:%02X:%02X:%02X\n", + llc->ssap,llc->dsap,trhdr->saddr[0],trhdr->saddr[1],trhdr->saddr[2],trhdr->saddr[3],trhdr->saddr[4],trhdr->saddr[5], + trhdr->daddr[0],trhdr->daddr[1],trhdr->daddr[2],trhdr->daddr[3],trhdr->daddr[4],trhdr->daddr[5])); + } + #endif + + + if(!(skb=alloc_skb(ntohs(rec_req->frame_len)-lan_hdr_len+sizeof(struct trh_hdr), GFP_ATOMIC))) { + DPRINTK(("out of memory. frame dropped.\n")); + ti.tr_stats.rx_dropped++; + rec_resp->ret_code=DATA_LOST; + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_SET + ISRA_ODD)=RESP_IN_ASB; + return; + } + + skb->len=ntohs(rec_req->frame_len)-lan_hdr_len+sizeof(struct trh_hdr); + skb->dev=dev; + + #if 0 + DPRINTK(("Now copying data...\n")); + #endif + + + data=skb->data; + memcpy(data,&(rbuffer->data),lan_hdr_len); + + + if(lan_hdr_lenbuf_len)-lan_hdr_len; + #if 0 + DPRINTK(("rbuffer_len: %d, data: %p\n",rbuffer_len,data)); + #endif + memcpy(data,(unsigned char *)(&(rbuffer->data))+lan_hdr_len,rbuffer_len); + data+=rbuffer_len; + + + if(rbuffer->buf_ptr) + for(rbuffer=(struct rec_buf *)(ti.sram+ntohs(rbuffer->buf_ptr)-2); + memcpy(data,&(rbuffer->data),rbuffer_len=ntohs(rbuffer->buf_len)),rbuffer->buf_ptr; + data+=rbuffer_len,rbuffer=(struct rec_buf *)(ti.sram+ntohs(rbuffer->buf_ptr)-2)) + #if 0 + DPRINTK(("buf_ptr: %d,data =%p\n",ntohs(rbuffer->buf_ptr),data)); + #endif + + rec_resp->ret_code=0; + + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_SET + ISRA_ODD)=RESP_IN_ASB; + + ti.tr_stats.rx_packets++; + + netif_rx(skb); + + return; + } + + static int tok_send_packet(struct sk_buff *skb, struct device *dev) { + + + #if 0 + DPRINTK(("tada: sending packet...\n")); + #endif + + if (dev->tbusy) { + int ticks_waited=jiffies - dev->trans_start; + if(ticks_waited<5) + return 1; + DPRINTK(("Arrg. Transmitter busy for more than 50 msec. Donald resets adapter, but resetting\n \ + the IBM tokenring adapter takes a long time. It might not even help when the\n \ + ring is very busy, so we just wait a little longer and hope for the best.\n")); + dev->trans_start+=5; /* we fake the transmission start time... */ + } + + /* Donald does this, so we do too. */ + + if(skb==NULL) { + dev_tint(dev); + return 0; + } + + if(set_bit(0,(void *)&dev->tbusy)!=0) + DPRINTK(("Transmitter access conflict\n")); + else { + struct srb_xmit *xmit=(struct srb_xmit *)ti.srb; + + ti.current_skb=skb; /* save skb. We will need it when the adapter + asks for the data */ + xmit->command=XMIT_UI_FRAME; + xmit->station_id=ti.exsap_station_id; + *(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_SET + ISRA_ODD)=CMD_IN_SRB; + dev->trans_start=jiffies; + } + + return 0; + } diff -cr --new-file ../linux/drivers/net/ibmtr.h linux/drivers/net/ibmtr.h *** ../linux/drivers/net/ibmtr.h Thu Jan 1 01:00:00 1970 --- linux/drivers/net/ibmtr.h Wed Aug 24 15:37:15 1994 *************** *** 0 **** --- 1,401 ---- + /* Definitions for an IBM Token Ring card. */ + /* This file is distributed under the GNU GPL */ + + #define TR_RETRY_INTERVAL 500 + #define ISA 1 + #define MCA 2 + #define NOTOK 0 + #define TOKDEBUG 1 + + #define CHANNEL_ID 0X1F30 + #define AIP 0X1F00 + #define AIPCHKSUM1 0X1F60 + #define AIPCHKSUM2 0X1FF0 + #define AIPADAPTYPE 0X1FA0 + #define AIPDATARATE 0X1FA2 + #define AIPEARLYTOKEN 0X1FA4 + #define AIPAVAILSHRAM 0X1FA6 + #define AIPSHRAMPAGE 0X1FA8 + #define AIP4MBDHB 0X1FAA + #define AIP16MBDHB 0X1FAC + + /* Note, 0xA20 == 0x220 since motherboard decodes 10 bits. I left everything + the way my documentation had it, ie: 0x0A20. */ + #define ADAPTINTCNTRL 0x02f0 /* Adapter interrupt control */ + #define ADAPTRESETP 0x0a21 /* Control Adapter reset (primary) */ + #define ADAPTRESETA 0x0a25 /* Control Adapter reset (alternate) */ + #define ADAPTRESETRELP 0x0a22 /* Release Adapter from reset (primary) */ + #define ADAPTRESETRELA 0x0a26 /* Release Adapter from reset (alternate) */ + + #define MMIOStartLocP 0x0a20 /* Primary adapter's starting MMIO area */ + #define MMIOStartLocA 0x0a24 /* Alternate adapter's starting MMIO area */ + + #define GLOBAL_INT_ENABLE 0x02f0 + + /* MMIO bits 0-4 select register */ + #define RRR_EVEN 0x00 /* Shared RAM relocation registers - even and odd */ + /* Used to set the starting address of shared RAM */ + /* Bits 1 through 7 of this register map to bits 13 through 19 of the shared RAM address.*/ + /* ie: 0x02 sets RAM address to ...ato! issy su wazzoo !! GODZILLA!!! */ + #define RRR_ODD 0x01 + /* Bits 2 and 3 of this register can be read to determine shared RAM size */ + /* 00 for 8k, 01 for 16k, 10 for 32k, 11 for 64k */ + #define WRBR_EVEN 0x02 /* Write region base registers - even and odd */ + #define WRBR_ODD 0x03 + #define WWCR_EVEN 0x04 /* Write window close registers - even and odd */ + #define WWCR_ODD 0x05 + #define WWOR_EVEN 0x06 /* Write window open registers - even and odd */ + #define WWOR_ODD 0x07 + + /* Interrupt status registers - PC system - even and odd */ + #define ISRP_EVEN 0x08 + + #define TCR_INT 0x10 /* Bit 4 - Timer interrupt. The TVR_EVEN timer has + expired. */ + #define ERR_INT 0x08 /* Bit 3 - Error interrupt. The adapter has had an + internal error. */ + #define ACCESS_INT 0x04 /* Bit 2 - Access interrupt. You have attempted to + write to an invalid area of shared RAM or an invalid + register within the MMIO. */ + /* In addition, the following bits within ISRP_EVEN can be turned on or off by you */ + /* to control the interrupt processing: */ + #define INT_IRQ 0x80 /* Bit 7 - If 0 the adapter will issue a CHCK, if 1 and + IRQ. This should normally be set (by you) to 1. */ + #define INT_ENABLE 0x40 /* Bit 6 - Interrupt enable. If 0, no interrupts will + occur. If 1, interrupts will occur normally. + Normally set to 1. */ + /* Bit 0 - Primary or alternate adapter. Set to zero if this adapter is the primary adapter,*/ + /* 1 if this adapter is the alternate adapter. */ + + + #define ISRP_ODD 0x09 + + #define ADAP_CHK_INT 0x40 /* Bit 6 - Adapter check. the adapter has + encountered a serious problem and has closed + itself. Whoa. */ + #define SRB_RESP_INT 0x20 /* Bit 5 - SRB response. The adapter has accepted + an SRB request and set the return code withing + the SRB. */ + #define ASB_FREE_INT 0x10 /* Bit 4 - ASB free. The adapter has read the ASB + and this area can be safely reused. This interrupt + is only used if your application has set the ASB + free request bit in ISRA_ODD or if an error was + detected in your response. */ + #define ARB_CMD_INT 0x08 /* Bit 3 - ARB command. The adapter has given you a + command for action. The command is located in the + ARB area of shared memory. */ + #define SSB_RESP_INT 0x04 /* Bit 2 - SSB response. The adapter has posted a + response to your SRB (the response is located in + the SSB area of shared memory). */ + /* Bit 1 - Bridge frame forward complete. */ + + + + #define ISRA_EVEN 0x0A /* Interrupt status registers - adapter - even and odd */ + /* Bit 7 - Internal parity error (on adapter's internal bus) */ + /* Bit 6 - Timer interrupt pending */ + /* Bit 5 - Access interrupt (attempt by adapter to access illegal address) */ + /* Bit 4 - Adapter microcode problem (microcode dead-man timer expired) */ + /* Bit 3 - Adapter processor check status */ + /* Bit 2 - Reserved */ + /* Bit 1 - Adapter hardware interrupt mask (prevents internal interrupts) */ + /* Bit 0 - Adapter software interrupt mask (prevents internal software interrupts) */ + + #define ISRA_ODD 0x0B + #define CMD_IN_SRB 0x20 /* Bit 5 - Indicates that you have placed a new + command in the SRB and are ready for the adapter to + process the command. */ + #define RESP_IN_ASB 0x10 /* Bit 4 - Indicates that you have placed a response + (an ASB) in the shared RAM which is available for + the adapter's use. */ + /* Bit 3 - Indicates that you are ready to ut an SRB in the shared RAM, but that a previous */ + /* command is still pending. The adapter will then interrupt you when the previous */ + /* command is completed */ + /* Bit 2 - Indicates that you are ready to put an ASB in the shared RAM, but that a previous */ + /* ASB is still pending. The adapter will then interrupt you when the previous ASB */ + /* is copied. */ + #define ARB_FREE 0x2 + #define SSB_FREE 0x1 + + #define TCR_EVEN 0x0C /* Timer control registers - even and odd */ + #define TCR_ODD 0x0D + #define TVR_EVEN 0x0E /* Timer value registers - even and odd */ + #define TVR_ODD 0x0F + #define SRPR_EVEN 0x10 /* Shared RAM paging registers - even and odd */ + #define SRPR_ENABLE_PAGING 0xc0 + #define SRPR_ODD 0x11 /* Not used. */ + #define TOKREAD 0x60 + #define TOKOR 0x40 + #define TOKAND 0x20 + #define TOKWRITE 0x00 + + /* MMIO bits 5-6 select operation */ + /* 00 is used to write to a register */ + /* 01 is used to bitwise AND a byte with a register */ + /* 10 is used to bitwise OR a byte with a register */ + /* 11 is used to read from a register */ + + /* MMIO bits 7-8 select area of interest.. see below */ + /* 00 selects attachment control area. */ + /* 01 is reserved. */ + /* 10 selects adapter identification area A containing the adapter encoded address. */ + /* 11 selects the adapter identification area B containing test patterns. */ + + #define PCCHANNELID 5049434F3631313039393020 + #define MCCHANNELID 4D4152533633583435313820 + + #define ACA_OFFSET 0x1e00 + #define ACA_SET 0x40 + #define ACA_RESET 0x20 + #define ACA_RW 0x00 + + #ifdef ENABLE_PAGING + #define SET_PAGE(x) (*(unsigned char *)(ti.mmio + ACA_OFFSET + ACA_RW + SRPR_EVEN)\ + = (x>>8)&ti.page_size) + #else + #define SET_PAGE(x) + #endif + + struct tok_info { + unsigned char irq; + unsigned char *mmio; + unsigned char hw_address[32]; + unsigned char adapter_type; + unsigned char data_rate; + unsigned char token_release; + unsigned char avail_shared_ram; + unsigned char shared_ram_paging; + unsigned char dhb_size4mb; + unsigned char dhb_size16mb; + /* Additions by Peter De Schrijver */ + unsigned char page_size; + unsigned char used_shared_ram; + unsigned char *sram; /* Shared memory base address */ + unsigned char *init_srb; /* Initial System Request Block address */ + unsigned char *srb; /* System Request Block address */ + unsigned char *ssb; /* System Status Block address */ + unsigned char *arb; /* Adapter Request Block address */ + unsigned char *asb; /* Adapter Status Block address */ + unsigned short exsap_station_id; + unsigned short global_int_enable; + struct sk_buff *current_skb; + struct tr_statistics tr_stats; + }; + + struct srb_init_response { + unsigned char command; + unsigned char init_status; + unsigned char reserved[4]; + unsigned short bring_up_code; + unsigned short encoded_address; + unsigned short level_address; + unsigned short adapter_address; + unsigned short parms_address; + unsigned short mac_address; + }; + + #define DIR_OPEN_ADAPTER 0x03 + + struct dir_open_adapter { + unsigned char command; + char reserved[7]; + unsigned short open_options; + unsigned char node_address[6]; + unsigned char group_address[4]; + unsigned char funct_address[4]; + unsigned short num_rcv_buf; + unsigned short rcv_buf_len; + unsigned short dhb_length; + unsigned char num_dhb; + char reserved2; + unsigned char dlc_max_sap; + unsigned char dlc_max_sta; + unsigned char dlc_max_gsap; + unsigned char dlc_max_gmem; + unsigned char dlc_t1_tick_1; + unsigned char dlc_t2_tick_1; + unsigned char dlc_ti_tick_1; + unsigned char dlc_t1_tick_2; + unsigned char dlc_t2_tick_2; + unsigned char dlc_ti_tick_2; + unsigned char product_id[18]; + }; + + struct srb_open_response { + unsigned char command; + unsigned char reserved1; + unsigned char ret_code; + unsigned char reserved2[3]; + unsigned short error_code; + unsigned short asb_addr; + unsigned short srb_addr; + unsigned short arb_addr; + unsigned short ssb_addr; + }; + + /* DIR_OPEN_ADAPTER options */ + + #define OPEN_PASS_BCON_MAC 0x0100 + #define NUM_RCV_BUF 16 + #define RCV_BUF_LEN 136 + #define DHB_LENGTH 2048 + #define NUM_DHB 2 + #define DLC_MAX_SAP 2 + #define DLC_MAX_STA 1 + + #define DLC_OPEN_SAP 0x15 + + struct dlc_open_sap { + unsigned char command; + unsigned char reserved1; + unsigned char ret_code; + unsigned char reserved2; + unsigned short station_id; + unsigned char timer_t1; + unsigned char timer_t2; + unsigned char timer_ti; + unsigned char maxout; + unsigned char maxin; + unsigned char maxout_incr; + unsigned char max_retry_count; + unsigned char gsap_max_mem; + unsigned short max_i_field; + unsigned char sap_value; + unsigned char sap_options; + unsigned char station_count; + unsigned char sap_gsap_mem; + unsigned char gsap[0]; + }; + + /* DLC_OPEN_SAP options */ + + #define MAX_I_FIELD 0x0088 + #define SAP_OPEN_IND_SAP 0x04 + #define SAP_OPEN_PRIORITY 0x20 + #define SAP_OPEN_STATION_CNT 0x1 + + #define XMIT_DIR_FRAME 0x0a + #define XMIT_UI_FRAME 0x0d + #define XMIT_XID_CMD 0x0e + #define XMIT_TEST_CMD 0x11 + + struct srb_xmit { + unsigned char command; + unsigned char cmd_corr; + unsigned char ret_code; + unsigned char reserved1; + unsigned short station_id; + }; + + #define DIR_INTERRUPT 0x00 + struct srb_interrupt { + unsigned char command; + unsigned char cmd_corr; + unsigned char ret_code; + }; + + #define DIR_READ_LOG 0x08 + struct srb_read_log { + unsigned char command; + unsigned char reserved1; + unsigned char ret_code; + unsigned char reserved2; + unsigned char line_errors; + unsigned char internal_errors; + unsigned char burst_errors; + unsigned char A_C_errors; + unsigned char abort_delimiters; + unsigned char reserved3; + unsigned char lost_frames; + unsigned char recv_congest_count; + unsigned char frame_copied_errors; + unsigned char frequency_errors; + unsigned char token_errors; + }; + + struct asb_xmit_resp { + unsigned char command; + unsigned char cmd_corr; + unsigned char ret_code; + unsigned char reserved; + unsigned short station_id; + unsigned short frame_length; + unsigned char hdr_length; + unsigned char rsap_value; + }; + + #define XMIT_DATA_REQ 0x82 + struct arb_xmit_req { + unsigned char command; + unsigned char cmd_corr; + unsigned char reserved1[2]; + unsigned short station_id; + unsigned short dhb_address; + }; + + #define REC_DATA 0x81 + struct arb_rec_req { + unsigned char command; + unsigned char reserved1[3]; + unsigned short station_id; + unsigned short rec_buf_addr; + unsigned char lan_hdr_len; + unsigned char dlc_hdr_len; + unsigned short frame_len; + unsigned char msg_type; + }; + + #define DATA_LOST 0x20 + struct asb_rec { + unsigned char command; + unsigned char reserved1; + unsigned char ret_code; + unsigned char reserved2; + unsigned short station_id; + unsigned short rec_buf_addr; + }; + + struct rec_buf { + unsigned char reserved1[2]; + unsigned short buf_ptr; + unsigned char reserved2; + unsigned short buf_len; + unsigned char data[0]; + }; + + #define DLC_STATUS 0x83 + struct arb_dlc_status { + unsigned char command; + unsigned char reserved1[3]; + unsigned short station_id; + unsigned short status; + unsigned char frmr_data[5]; + unsigned char access_prio; + unsigned char rem_addr[TR_ALEN]; + unsigned char rsap_value; + }; + + #define RING_STAT_CHANGE 0x84 + struct arb_ring_stat_change { + unsigned char command; + unsigned char reserved1[5]; + unsigned short ring_status; + }; + + #define DIR_CLOSE_ADAPTER 0x04 + struct srb_close_adapter { + unsigned char command; + unsigned char reserved1; + unsigned char ret_code; + }; + + #define DIR_MOD_OPEN_PARAMS 0x01 + #define DIR_SET_GRP_ADDR 0x06 + #define DIR_SET_FUNC_ADDR 0x07 + #define DLC_CLOSE_SAP 0x16 + + + #define SIGNAL_LOSS 0x8000 + #define LOBE_FAULT 0x0800 + #define LOG_OVERFLOW 0x0080 + diff -cr --new-file ../linux/drivers/net/net_init.c linux/drivers/net/net_init.c *** ../linux/drivers/net/net_init.c Wed Aug 24 15:50:04 1994 --- linux/drivers/net/net_init.c Wed Aug 24 15:37:23 1994 *************** *** 30,35 **** --- 30,36 ---- #include #include #include + #include /* The network devices currently exist only in the socket namespace, so these entries are unused. The only ones that make sense are *************** *** 173,178 **** --- 174,207 ---- dev->pa_alen = sizeof(unsigned long); } + void tr_setup(struct device *dev) + { + int i; + /* Fill in the fields of the device structure with ethernet-generic values. + This should be in a common file instead of per-driver. */ + for (i = 0; i < DEV_NUMBUFFS; i++) + skb_queue_head_init(&dev->buffs[i]); + + dev->hard_header = tr_header; + dev->rebuild_header = tr_rebuild_header; + dev->type_trans = tr_type_trans; + + dev->type = ARPHRD_IEEE802; + dev->hard_header_len = TR_HLEN; + dev->mtu = 2000; /* bug in fragmenter...*/ + dev->addr_len = TR_ALEN; + for (i = 0; i < TR_ALEN; i++) { + dev->broadcast[i]=0xff; + } + + /* New-style flags. */ + dev->flags = IFF_BROADCAST; + dev->family = AF_INET; + dev->pa_addr = 0; + dev->pa_brdaddr = 0; + dev->pa_mask = 0; + dev->pa_alen = sizeof(unsigned long); + } int ether_config(struct device *dev, struct ifmap *map) { if (map->mem_start != (u_long)(-1)) diff -cr --new-file ../linux/include/linux/if_tr.h linux/include/linux/if_tr.h *** ../linux/include/linux/if_tr.h Thu Jan 1 01:00:00 1970 --- linux/include/linux/if_tr.h Wed Aug 24 15:41:37 1994 *************** *** 0 **** --- 1,100 ---- + /* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * Global definitions for the Token-Ring IEEE 802.5 interface. + * + * Version: @(#)if_tr.h 0.0 07/11/94 + * + * Author: Fred N. van Kempen, + * Donald Becker, + * Peter De Schrijver, + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + #ifndef _LINUX_IF_TR_H + #define _LINUX_IF_TR_H + + + /* IEEE 802.5 Token-Ring magic constants. The frame sizes omit the preamble + and FCS/CRC (frame check sequence). */ + #define TR_ALEN 6 /* Octets in one ethernet addr */ + #define TR_HLEN (sizeof(struct trh_hdr)+sizeof(struct trllc)) + #define AC 0x10 + #define LLC_FRAME 0x40 + #if 0 + #define ETH_HLEN 14 /* Total octets in header. */ + #define ETH_ZLEN 60 /* Min. octets in frame sans FCS */ + #define ETH_DATA_LEN 1500 /* Max. octets in payload */ + #define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS */ + #endif + + + /* These are some defined Ethernet Protocol ID's. */ + #define ETH_P_IP 0x0800 /* Internet Protocol packet */ + #define ETH_P_ARP 0x0806 /* Address Resolution packet */ + #define ETH_P_RARP 0x8035 /* Reverse Addr Res packet */ + + /* LLC and SNAP constants */ + #define EXTENDED_SAP 0xAA + #define UI_CMD 0x03 + + /* This is an Token-Ring frame header. */ + struct trh_hdr { + unsigned char ac; /* access control field */ + unsigned char fc; /* frame control field */ + unsigned char daddr[TR_ALEN]; /* destination address */ + unsigned char saddr[TR_ALEN]; /* source address */ + unsigned short rcf; /* route control field */ + unsigned short rseg[8];/* routing registers */ + }; + + /* This is an Token-Ring LLC structure */ + struct trllc { + unsigned char dsap; /* destination SAP */ + unsigned char ssap; /* source SAP */ + unsigned char llc; /* LLC control field */ + unsigned char protid[3]; /* protocol id */ + unsigned short ethertype; /* ether type field */ + }; + + + /* Token-Ring statistics collection data. */ + struct tr_statistics{ + int rx_packets; /* total packets received */ + int tx_packets; /* total packets transmitted */ + int rx_errors; /* bad packets received */ + int tx_errors; /* packet transmit problems */ + int rx_dropped; /* no space in linux buffers */ + int tx_dropped; /* no space available in linux */ + int multicast; /* multicast packets received */ + + /* detailed Token-Ring errors. See IBM Token-Ring Network Architecture + for more info */ + + int line_errors; + int internal_errors; + int burst_errors; + int A_C_errors; + int abort_delimiters; + int lost_frames; + int recv_congest_count; + int frame_copied_errors; + int frequency_errors; + int token_errors; + + }; + + /* source routing stuff */ + + #define TR_RII 0x80 + #define TR_RCF_DIR_BIT 0x80 + #define TR_RCF_LEN_MASK 0x1f00 + #define TR_RCF_BROADCAST 0x8000 + #define TR_RCF_FRAME2K 0x20 + + #endif /* _LINUX_IF_TR_H */ diff -cr --new-file ../linux/include/linux/major.h linux/include/linux/major.h *** ../linux/include/linux/major.h Fri Jul 8 10:36:04 1994 --- linux/include/linux/major.h Wed Aug 24 15:41:28 1994 *************** *** 77,82 **** --- 77,83 ---- #define MATSUSHITA_CDROM3_MAJOR 27 #define MATSUSHITA_CDROM4_MAJOR 28 #define QIC117_TAPE_MAJOR 27 + #define PS2ESDI_MAJOR 31 /* * Tests for SCSI devices. diff -cr --new-file ../linux/include/linux/mktime.h linux/include/linux/mktime.h *** ../linux/include/linux/mktime.h Thu Jan 1 01:00:00 1970 --- linux/include/linux/mktime.h Wed Aug 24 15:41:02 1994 *************** *** 0 **** --- 1,13 ---- + #ifndef _LINUX_MKTIME_H + #define _LINUX_MKTIME_H + + struct mktime { + int sec; + int min; + int hour; + int day; + int mon; + int year; + }; + + #endif diff -cr --new-file ../linux/include/linux/netdevice.h linux/include/linux/netdevice.h *** ../linux/include/linux/netdevice.h Wed Aug 10 18:26:43 1994 --- linux/include/linux/netdevice.h Wed Aug 24 15:41:25 1994 *************** *** 196,201 **** --- 196,202 ---- /* These functions live elsewhere (drivers/net/net_init.c, but related) */ extern void ether_setup(struct device *dev); + extern void tr_setup(struct device *dev); extern int ether_config(struct device *dev, struct ifmap *map); /* Support for loadable net-drivers */ extern int register_netdev(struct device *dev); diff -cr --new-file ../linux/include/linux/ps2esdi.h linux/include/linux/ps2esdi.h *** ../linux/include/linux/ps2esdi.h Thu Jan 1 01:00:00 1970 --- linux/include/linux/ps2esdi.h Wed Aug 24 15:41:05 1994 *************** *** 0 **** --- 1,102 ---- + #define NRML_ESDI_ID 0xddff + #define INTG_ESDI_ID 0xdf9f + + #define PRIMARY_IO_BASE 0x3510 + #define ALT_IO_BASE 0x3518 + + #define ESDI_CMD_INT (io_base+0) + #define ESDI_STT_INT (io_base+0) + #define ESDI_CONTROL (io_base+2) + #define ESDI_STATUS (io_base+2) + #define ESDI_ATTN (io_base+3) + #define ESDI_INTRPT (io_base+3) + + #define STATUS_ENABLED 0x01 + #define STATUS_ALTERNATE 0x02 + #define STATUS_BUSY 0x10 + #define STATUS_STAT_AVAIL 0x08 + #define STATUS_INTR 0x01 + #define STATUS_RESET_FAIL 0xea + #define STATUS_CMD_INF 0x04 + + #define CTRL_SOFT_RESET 0xe4 + #define CTRL_HARD_RESET 0x80 + #define CTRL_EOI 0xe2 + #define CTRL_ENABLE_DMA 0x02 + #define CTRL_ENABLE_INTR 0x01 + #define CTRL_DISABLE_INTR 0x00 + + #define ATT_EOI 0x02 + + /* bits of word 0 of configuration status block. more info see p.38 of tech ref */ + #define CONFIG_IS 0x10 /* Invalid Secondary */ + #define CONFIG_ZD 0x08 /* Zero Defect */ + #define CONFIG_SF 0x04 /* Skewed Format */ + #define CONFIG_FR 0x02 /* Removable */ + #define CONFIG_RT 0x01 /* Retries */ + + #define PORT_SYS_A 0x92 + #define PORT_DMA_FN 0x18 + #define PORT_DMA_EX 0x1a + + #define ON (unsigned char)0x40 + #define OFF (unsigned char)~ON + #define LITE_ON outb(inb(PORT_SYS_A) | ON,PORT_SYS_A) + #define LITE_OFF outb((inb(PORT_SYS_A) & OFF),PORT_SYS_A) + + #define NUMBER_OF_SLOTS 8 + #define PORT_POS_SEL 0x096 + #define PORT_POS_REG_0 0x100 + #define PORT_POS_REG_1 0x101 + #define PORT_POS_REG_2 0x102 + + #define FAIL 0 + #define SUCCES 1 + + #define SELECT_BIT 0x08 + + #define INT_CMD_COMPLETE 0x01 + #define INT_CMD_ECC 0x03 + #define INT_CMD_RETRY 0x05 + #define INT_CMD_FORMAT 0x06 + #define INT_CMD_ECC_RETRY 0x07 + #define INT_CMD_WARNING 0x08 + #define INT_CMD_ABORT 0x09 + #define INT_RESET 0x0A + #define INT_TRANSFER_REQ 0x0B + #define INT_CMD_FAILED 0x0C + #define INT_DMA_ERR 0x0D + #define INT_CMD_BLK_ERR 0x0E + #define INT_ATTN_ERROR 0x0F + + #define DMA_MASK_CHAN 0x90 + #define DMA_UNMASK_CHAN 0xA0 + #define DMA_WRITE_ADDR 0x20 + #define DMA_WRITE_TC 0x40 + #define DMA_WRITE_MODE 0x70 + + #define CMD_GET_DEV_CONFIG 0x09 + #define CMD_READ 0x4601 + #define CMD_WRITE 0x4602 + #define DMA_READ_16 0x4C + #define DMA_WRITE_16 0x44 + + + #define MB 1024*1024 + #define SECT_SIZE 512 + + #define ERROR 1 + #define OK 0 + + #define HDIO_GETGEO 0x0301 + + #define FALSE 0 + #define TRUE !FALSE + + struct ps2esdi_geometry { + unsigned char heads; + unsigned char sectors; + unsigned short cylinders; + unsigned long start; + }; + diff -cr --new-file ../linux/include/linux/tcp.h linux/include/linux/tcp.h *** ../linux/include/linux/tcp.h Sat May 7 13:12:57 1994 --- linux/include/linux/tcp.h Wed Aug 24 15:41:08 1994 *************** *** 18,24 **** #define _LINUX_TCP_H ! #define HEADER_SIZE 64 /* maximum header size */ struct tcphdr { --- 18,24 ---- #define _LINUX_TCP_H ! #define HEADER_SIZE 128 /* maximum header size */ struct tcphdr { diff -cr --new-file ../linux/include/linux/trdevice.h linux/include/linux/trdevice.h *** ../linux/include/linux/trdevice.h Thu Jan 1 01:00:00 1970 --- linux/include/linux/trdevice.h Wed Aug 24 15:41:23 1994 *************** *** 0 **** --- 1,41 ---- + /* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. NET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * Definitions for the Ethernet handlers. + * + * Version: @(#)eth.h 1.0.4 05/13/93 + * + * Authors: Ross Biro, + * Fred N. van Kempen, + * + * Relocated to include/linux where it belongs by Alan Cox + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * WARNING: This move may well be temporary. This file will get merged with others RSN. + * + */ + #ifndef _LINUX_TRDEVICE_H + #define _LINUX_TRDEVICE_H + + + #include + + #ifdef __KERNEL__ + extern int tr_header(unsigned char *buff, struct device *dev, + unsigned short type, void *daddr, + void *saddr, unsigned len, + struct sk_buff *skb); + extern int tr_rebuild_header(void *buff, struct device *dev, + unsigned long raddr, struct sk_buff *skb); + extern unsigned short tr_type_trans(struct sk_buff *skb, struct device *dev); + + #endif + + #endif /* _LINUX_TRDEVICE_H */ diff -cr --new-file ../linux/init/main.c linux/init/main.c *** ../linux/init/main.c Fri Aug 12 07:49:08 1994 --- linux/init/main.c Wed Aug 24 15:36:39 1994 *************** *** 95,100 **** --- 95,101 ---- extern void aha152x_setup(char *str, int *ints); extern void scsi_luns_setup(char *str, int *ints); extern void sound_setup(char *str, int *ints); + extern void ed_setup(char *str, int *ints); #ifdef CONFIG_SBPCD extern void sbpcd_setup(char *str, int *ints); #endif CONFIG_SBPCD *************** *** 189,194 **** --- 190,198 ---- #ifdef CONFIG_CHR_DEV_ST { "st=", st_setup }, #endif + #ifdef CONFIG_BLK_DEV_ED + { "ed=", ed_setup }, + #endif #ifdef CONFIG_BUSMOUSE { "bmouse=", bmouse_setup }, #endif *************** *** 220,225 **** --- 224,230 ---- #ifdef CONFIG_SBPCD { "sbpcd=", sbpcd_setup }, #endif CONFIG_SBPCD + { "ed=", ed_setup }, { 0, 0 } }; *************** *** 552,557 **** --- 557,563 ---- #endif (void) open("/dev/tty1",O_RDWR,0); + printf("aha...\n"); (void) dup(0); (void) dup(0); diff -cr --new-file ../linux/kernel/sched.c linux/kernel/sched.c *** ../linux/kernel/sched.c Wed Aug 24 15:50:52 1994 --- linux/kernel/sched.c Wed Aug 24 15:41:51 1994 *************** *** 597,602 **** --- 597,606 ---- unsigned long mask; struct timer_struct *tp; + #ifdef CONFIG_BLK_DEV_PS2 + unsigned char x; + #endif + long ltemp; /* Advance the phase, once it gets to one microsecond, then *************** *** 692,697 **** --- 696,707 ---- mark_bh(TIMER_BH); } cli(); + #ifdef CONFIG_BLK_DEV_PS2 + x=inb_p(0x61); + outb_p(x|0x80,0x61); + outb_p(x&0x7F,0x61); + outb(0x20,0x20); + #endif itimer_ticks++; if (itimer_ticks > itimer_next) need_resched = 1; diff -cr --new-file ../linux/net/inet/Makefile linux/net/inet/Makefile *** ../linux/net/inet/Makefile Wed Aug 10 20:38:27 1994 --- linux/net/inet/Makefile Wed Aug 24 15:42:11 1994 *************** *** 15,21 **** $(CC) $(CFLAGS) -S $< ! OBJS := sock.o eth.o dev.o skbuff.o datagram.o ifdef CONFIG_INET --- 15,21 ---- $(CC) $(CFLAGS) -S $< ! OBJS := sock.o eth.o tr.o dev.o skbuff.o datagram.o ifdef CONFIG_INET diff -cr --new-file ../linux/net/inet/arp.c linux/net/inet/arp.c *** ../linux/net/inet/arp.c Wed Aug 24 15:50:55 1994 --- linux/net/inet/arp.c Wed Aug 24 15:42:22 1994 *************** *** 573,578 **** --- 573,586 ---- } break; + case ARPHRD_IEEE802: + if(arp->ar_pro != htons(ETH_P_IP)) + { + kfree_skb(skb, FREE_READ); + return 0; + } + break; + default: printk("ARP: dev->type mangled!\n"); kfree_skb(skb, FREE_READ); diff -cr --new-file ../linux/net/inet/tr.c linux/net/inet/tr.c *** ../linux/net/inet/tr.c Thu Jan 1 01:00:00 1970 --- linux/net/inet/tr.c Wed Aug 24 15:42:24 1994 *************** *** 0 **** --- 1,261 ---- + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include "arp.h" + + static void tr_source_route(struct trh_hdr *trh,struct device *dev); + static void tr_add_rif_info(struct trh_hdr *trh); + static void rif_check_expire(unsigned long dummy); + + typedef struct rif_cache_s *rif_cache; + + struct rif_cache_s { + unsigned char addr[TR_ALEN]; + unsigned short rcf; + unsigned short rseg[8]; + rif_cache next; + unsigned long last_used; + }; + + #define RIF_TABLE_SIZE 16 + rif_cache rif_table[RIF_TABLE_SIZE]={ NULL, }; + + #define RIF_TIMEOUT 60*10*HZ + #define RIF_CHECK_INTERVAL 60*HZ + static struct timer_list rif_timer={ NULL,NULL,RIF_CHECK_INTERVAL,0L,rif_check_expire }; + + int tr_header(unsigned char *buff, struct device *dev, unsigned short type, + void *daddr, void *saddr, unsigned len, struct sk_buff *skb) { + + struct trh_hdr *trh=(struct trh_hdr *)buff; + struct trllc *trllc=(struct trllc *)(buff+sizeof(struct trh_hdr)); + + trh->ac=AC; + trh->fc=LLC_FRAME; + + if(saddr) + memcpy(trh->saddr,saddr,dev->addr_len); + else + memset(trh->saddr,0,dev->addr_len); /* Adapter fills in address */ + + trllc->dsap=trllc->ssap=EXTENDED_SAP; + trllc->llc=UI_CMD; + + trllc->protid[0]=trllc->protid[1]=trllc->protid[2]=0x00; + trllc->ethertype=htons(type); + + if(daddr) { + memcpy(trh->daddr,daddr,dev->addr_len); + tr_source_route(trh,dev); + return(dev->hard_header_len); + } + return -dev->hard_header_len; + + } + + int tr_rebuild_header(void *buff, struct device *dev, unsigned long dest, + struct sk_buff *skb) { + + struct trh_hdr *trh=(struct trh_hdr *)buff; + struct trllc *trllc=(struct trllc *)(buff+sizeof(struct trh_hdr)); + + if(trllc->ethertype != htons(ETH_P_IP)) { + printk("tr_rebuild_header: Don't know how to resolve type %04X addresses ?\n",(unsigned int)htons( trllc->ethertype)); + return 0; + } + + if(arp_find(trh->daddr, dest, dev, dev->pa_addr, skb)) { + tr_source_route(trh,dev); + return 1; + } + else return 0; + + } + + unsigned short tr_type_trans(struct sk_buff *skb, struct device *dev) { + + struct trh_hdr *trh=(struct trh_hdr *)skb->data; + struct trllc *trllc=(struct trllc *)(skb->data+sizeof(struct trh_hdr)); + + if(trh->saddr[0] & TR_RII) + tr_add_rif_info(trh); + + if(*trh->daddr & 1) { + if(!memcmp(trh->daddr,dev->broadcast,TR_ALEN)) + skb->pkt_type=PACKET_BROADCAST; + else + skb->pkt_type=PACKET_MULTICAST; + } + + if(dev->flags & IFF_PROMISC) { + if(memcmp(trh->daddr, dev->dev_addr, TR_ALEN)) + skb->pkt_type=PACKET_OTHERHOST; + } + + return trllc->ethertype; + } + + /* We try to do source routing... */ + + static void tr_source_route(struct trh_hdr *trh,struct device *dev) { + + int i; + unsigned int hash; + rif_cache entry; + + + /* broadcasts are always all-routes, even though RFC 1042 says that IP + broadcasts should be single-route. */ + if(!memcmp(&(trh->daddr[0]),&(dev->broadcast[0]),TR_ALEN)) { + trh->rcf=htons((((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK) + | TR_RCF_FRAME2K | TR_RCF_BROADCAST); + trh->saddr[0]|=TR_RII; + } + else { + for(i=0,hash=0;idaddr[i++]); + hash&=RIF_TABLE_SIZE-1; + for(entry=rif_table[hash];entry && memcmp(&(entry->addr[0]),&(trh->daddr[0]),TR_ALEN);entry=entry->next); + + if(entry) { + #if 0 + printk("source routing for %02X %02X %02X %02X %02X %02X\n",trh->daddr[0], + trh->daddr[1],trh->daddr[2],trh->daddr[3],trh->daddr[4],trh->daddr[5]); + #endif + trh->rcf=entry->rcf; + memcpy(&trh->rseg[0],&entry->rseg[0],8*sizeof(unsigned short)); + trh->rcf^=htons(TR_RCF_DIR_BIT); + trh->saddr[0]|=TR_RII; + entry->last_used=jiffies; + } + else { + trh->rcf=htons((((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK) + | TR_RCF_FRAME2K | TR_RCF_BROADCAST); + trh->saddr[0]|=TR_RII; + } + } + + } + + static void tr_add_rif_info(struct trh_hdr *trh) { + + int i; + unsigned int hash; + rif_cache entry; + + + trh->saddr[0]&=0x7f; + for(i=0,hash=0;isaddr[i++]); + hash&=RIF_TABLE_SIZE-1; + #if 0 + printk("hash: %d\n",hash); + #endif + for(entry=rif_table[hash];entry && memcmp(&(entry->addr[0]),&(trh->saddr[0]),TR_ALEN);entry=entry->next); + + if(entry==NULL) { + #if 0 + printk("adding rif_entry: addr:%02X:%02X:%02X:%02X:%02X:%02X rcf:%04X\n", + trh->daddr[0],trh->saddr[1],trh->saddr[2],trh->saddr[3],trh->saddr[4],trh->saddr[5], + trh->rcf); + #endif + entry=kmalloc(sizeof(struct rif_cache_s),GFP_ATOMIC); + if(!entry) { + printk("tr.c: Couldn't malloc rif cache entry !\n"); + return; + } + entry->rcf=trh->rcf; + memcpy(&(entry->rseg[0]),&(trh->rseg[0]),8*sizeof(unsigned short)); + memcpy(&(entry->addr[0]),&(trh->saddr[0]),TR_ALEN); + entry->next=rif_table[hash]; + entry->last_used=jiffies; + rif_table[hash]=entry; + } + + } + + static void rif_check_expire(unsigned long dummy) { + + int i; + unsigned long now=jiffies,flags; + + save_flags(flags); + cli(); + + for(i=0; i < RIF_TABLE_SIZE;i++) { + + rif_cache entry, *pentry=rif_table+i; + + while((entry=*pentry)) + if((now-entry->last_used) > RIF_TIMEOUT) { + *pentry=entry->next; + kfree_s(entry,sizeof(struct rif_cache_s)); + } + else + pentry=&entry->next; + } + restore_flags(flags); + + del_timer(&rif_timer); + rif_timer.expires=RIF_CHECK_INTERVAL; + add_timer(&rif_timer); + + } + + int rif_get_info(char *buffer,char **start, off_t offset, int length) { + + int len=0; + off_t begin=0; + off_t pos=0; + int size,i; + + rif_cache entry; + + size=sprintf(buffer,"TR address rcf routing segments TTL\n\n"); + pos+=size; + len+=size; + + for(i=0;i < RIF_TABLE_SIZE;i++) { + for(entry=rif_table[i];entry;entry=entry->next) { + size=sprintf(buffer+len,"%02X:%02X:%02X:%02X:%02X:%02X %04X %04X %04X %04X %04X %04X %04X %04X %04X %lu\n", + entry->addr[0],entry->addr[1],entry->addr[2],entry->addr[3],entry->addr[4],entry->addr[5], + entry->rcf,entry->rseg[0],entry->rseg[1],entry->rseg[2],entry->rseg[3], + entry->rseg[4],entry->rseg[5],entry->rseg[6],entry->rseg[7],jiffies-entry->last_used); + len+=size; + pos=begin+len; + + if(posoffset+length) + break; + } + if(pos>offset+length) + break; + } + + *start=buffer+(offset-begin); /* Start of wanted data */ + len-=(offset-begin); /* Start slop */ + if(len>length) + len=length; /* Ending slop */ + return len; + } + + void rif_init(void) { + + add_timer(&rif_timer); + + } +