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