1 /* udc.c 1.2 86/01/21 */ 2 3 #include "../machine/mtpr.h" 4 5 #include "param.h" 6 #include "inode.h" 7 #include "fs.h" 8 9 #include "../tahoevba/vbaparam.h" 10 #include "../tahoestand/udc.h" 11 12 #include "saio.h" 13 14 #ifdef NOIO 15 #define MEMDISK 0x80000 /* Memory mapped disk at 1/2 Mega */ 16 #endif 17 18 /* Some I/O addresses used to generate pulses for scopes */ 19 #define OUT1 0xffffb034 20 #define OUT2 0xffffb018 21 #define OUT3 0xffffb020 22 #define OUT4 0xffffb004 23 #define OUT5 0xffffb024 24 #define OUT6 0xffffb00c 25 #define OUT7 0xffffb02c 26 27 #define IN1 0xffffb030 28 #define IN2 0xffffb03c 29 #define IN3 0xffffb004 30 #define IN4 0xffffb00c 31 #define IN5 0xffffb02c 32 33 #undef scope_in 34 #undef scope_out 35 #define scope_out(x) movob(OUT/**/x,0) 36 #define scope_in(x) dummy = *(char *)(IN/**/x) 37 38 /* 39 * Universal disk controller driver for the Motorola M68000/IPC. 40 * Stand-alone version (no interrupts, etc.) 41 */ 42 43 44 static struct UDPAC udpkt = { 45 2, 0, 21, 0, 0, 0, 0, SECTSIZ, {0, 0}, 0, 0, 3 46 } ; 47 48 long udstd[] = { /* May be used some day to boot from any of 49 * several UDC controllers */ 50 0xf0000 51 }; 52 53 /***************************************************** 54 /* 55 /*The next layout of major/minor number assignments are for the UDC 56 /*devices. 57 /* 58 /* 1 59 /* 5 8 7 4 3 2 0 60 /* +----------------+-----+-+-+-----+ 61 /* | Major device # | |D|R| FLS | 62 /* +----------------+-----+-+-+-----+ 63 /* | | |_____ File system # ( 0-7 ) 64 /* | |_________ Fixed (0) or removable(1) media 65 /* |___________ Drive # (0-1) 66 /* 67 /* For the floppy drives, the major / minor assignment will be 68 /* 1 69 /* 5 8 7 4 3 2 0 70 /* +----------------+-----+---+-----+ 71 /* | 4 | | D | FLS | 72 /* +----------------+-----+---+-----+ 73 /* | |_____ File system # ( 0-7 ) 74 /* |____________ Drive # (0-3) 75 /* 76 /****************************************************/ 77 78 #define UDCUNIT(x) ((minor(x) & 0x18) >> 3) 79 80 udstrategy(io, func) 81 register struct iob *io; 82 long func; /* Known to be 'read' */ 83 { 84 85 register unit = io->i_unit; 86 register bn = io->i_bn; 87 register char *cntaddr ; 88 register char *addr ; 89 register timeout , retries , i; 90 #ifdef NOIO 91 register int *memory = (int *)(bn*1024 + MEMDISK); 92 #endif 93 94 cntaddr = (char *)(udstd[0] + VBIOBASE); /* Booting from cntrlr 0 */ 95 /* 96 * prepare a command packet for the controller. 97 */ 98 retries = 3; 99 loop: 100 #ifndef NOIO 101 #ifndef SIMIO 102 if (cntaddr[OB1]) { 103 printf("UDC controller not ready, %x=%x\n",OB1+cntaddr, 104 cntaddr[OB1] & 0xff); 105 return(0); 106 } 107 #endif 108 #endif 109 udpkt._pkid = 0xAA ; 110 udpkt._pkdev = UDCUNIT(unit); 111 if (io->i_ino.i_dev == 3) udpkt._pkdev += 4; /* Floppy */ 112 udpkt._pkmem[0] = (((long)io->i_ma) >> 16) & 0xffff; 113 udpkt._pkmem[1] = ((long)io->i_ma) & 0xffff; 114 if (func == READ) { 115 udpkt._pkcmd = UDREAD ; 116 udpkt._pkfnc = UDWTRY ; 117 } else { 118 udpkt._pkcmd = UDWRITE ; 119 udpkt._pkfnc = UDWSECT ; 120 } 121 udpkt._psecno = bn * (DEV_BSIZE/SECTSIZ); 122 udpkt._pkcnt = (io->i_cc + SECTSIZ-1)/SECTSIZ ; 123 if (movep21(&udpkt,cntaddr+0x105,sizeof(udpkt) )) { 124 #ifndef NOIO 125 #ifndef SIMIO 126 cntaddr[OB1] = (char)0x80 ; /* signal packet transmitted */ 127 cntaddr[IB2] = (char)0 ; /* clear ACK/NAK field */ 128 cntaddr[INT] = (char)0x0 ; /* interrupt the controller */ 129 scope_out(1); 130 #else 131 dskio(&udpkt); 132 #endif 133 #endif 134 } 135 else { 136 printf ("Wrong command packet arrived at UDC\n"); 137 printf ("Original UDC\n"); 138 for (i = 0; i < sizeof(udpkt); i++ ) 139 printf(" %0x\t%0x\n", ((char *)&udpkt)[i*2] & 0xff, 140 cntaddr[0x105+i*2] & 0xff); 141 } 142 /* 143 * 144 * Wait until done (no interrupts now). 145 * 146 */ 147 wait: 148 #ifndef SIMIO 149 #ifndef NOIO 150 timeout = 100; 151 while (cntaddr[IB2] != (char)0x06 && cntaddr[IB2] != (char)0x15) { 152 /************** 153 DELAY(10000); 154 timeout--; 155 if (timeout <= 0) { 156 printf("UDC controller timeout\n"); 157 return(0); 158 } 159 *****************/ 160 } 161 scope_out(2); 162 if (cntaddr[IB2] == (char)0x15) { 163 if (retries-- < 0) { 164 printf("Too many NAK from UDC - give up\n"); 165 return(0); 166 } else goto loop; 167 } 168 169 while (cntaddr[IB1] != (char)DEVRDY) 170 /* DELAY (10000); /* Wait for his response */; 171 scope_out(3); 172 173 174 /* Ignore unsolicited status messages */ 175 if (cntaddr[PKID] != (char)udpkt._pkid && cntaddr[PKSTT] == (char)0x80) 176 { 177 cntaddr[IB1] = (char)0; 178 cntaddr[OB2] = (char)6; 179 cntaddr[INT] = (char)0x80; 180 goto loop; 181 } 182 if (cntaddr[PKID] != (char)udpkt._pkid || 183 cntaddr[PKDEV] != (char)udpkt._pkdev || 184 cntaddr[PKLEN] != (char)19 || 185 cntaddr[PKCMD] != (char)udpkt._pkcmd || 186 cntaddr[PKSTT] != (char)0x70 || /* Command completion */ 187 cntaddr[STAT1] != (char)0 || 188 cntaddr[STAT2] != (char)0 ) { 189 printf ("Strange status from UDC:\n"); 190 printf("Packet id=%x,unit=%x,original command=%x,status type=%x,status=%x\n", 191 cntaddr[PKID] & 0xff, 192 cntaddr[PKDEV] & 0xff, 193 cntaddr[PKCMD] & 0xff, 194 cntaddr[PKSTT] & 0xff, 195 (cntaddr[STAT1]*256+cntaddr[STAT2]) & 0xffff); 196 if (cntaddr[PKLEN] > 9) { 197 printf("More response info : "); 198 for (i=1; i<=cntaddr[PKLEN]-9; i++) 199 printf("%x ", cntaddr[STAT2+2*i] & 0xff); 200 printf("\n"); 201 } 202 cntaddr[IB1] = (char)0; 203 cntaddr[OB2] = (char)6; 204 cntaddr[INT] = (char)0x80; 205 return(0); 206 } else { 207 cntaddr[IB1] = (char)0; 208 cntaddr[OB2] = (char)6; 209 cntaddr[INT] = (char)0x80; 210 scope_out(4); 211 mtpr(PADC, 0); /* So data will come in right */ 212 return(io->i_cc); 213 } 214 #else 215 for (i=0; i<io->i_cc/4; i++) 216 ((int *)io->i_buf)[i] = *memory++; 217 return(io->i_cc); 218 #endif 219 #else 220 while (udpkt._pkfnc != 0x7f) ; /* wait for completion */ 221 return(io->i_cc); 222 #endif 223 224 } 225 226 /* 227 * Transfer a 21 bytes packet to the controller. 228 * the message is written to odd addresses, starting from 229 * the given address. 230 * For reliability, read it back and see if it's the same. If not, 231 * return an error code. 232 */ 233 movep21(src, dest,cnt) 234 235 char *src, *dest; 236 int cnt; 237 { 238 #ifndef NOIO 239 #ifndef SIMIO 240 register char *running_src, *running_dest; 241 register long running_cnt; 242 243 running_src = src; 244 running_dest = dest; 245 running_cnt = cnt; 246 247 for (; running_cnt>0; running_cnt--) { 248 *running_dest++ = *running_src++; 249 running_dest++; 250 } 251 running_src = src; 252 running_dest = dest; 253 running_cnt = cnt; 254 for (; running_cnt>0; running_cnt--) { 255 if (*running_dest++ != *running_src++) return(0); 256 running_dest++; 257 } 258 return(1); 259 #endif 260 #endif 261 } 262 263 udopen(io) 264 struct iob *io; 265 { 266 register char *cntaddr; 267 /* 268 * Just clean up any junk in the controller's response buffers. 269 */ 270 #ifndef NOIO 271 #ifndef SIMIO 272 cntaddr = (char *)(udstd[0] + VBIOBASE); /* Booting from cntrlr 0 */ 273 while (cntaddr[IB1] == (char)DEVRDY) { 274 cntaddr[IB1] = (char)0; 275 cntaddr[OB2] = (char)0x06; /* ACK */ 276 cntaddr[INT] = (char)0; /* Force him to listen and to respond */ 277 DELAY(50000); 278 } 279 #endif 280 #endif 281 } 282 #ifdef SIMIO 283 dskio(addr) 284 { 285 asm(".byte 0x2"); 286 } 287 #endif 288