| 1 | /* |
| 2 | * (Free/Net/386)BSD ST01/02, Future Domain TMC-885, TMC-950 SCSI driver for |
| 3 | * Julians SCSI-code |
| 4 | * |
| 5 | * Copyright 1994, Kent Palmkvist (kentp@isy.liu.se) |
| 6 | * Copyright 1994, Robert Knier (rknier@qgraph.com) |
| 7 | * Copyright 1992, 1994 Drew Eckhardt (drew@colorado.edu) |
| 8 | * Copyright 1994, Julian Elischer (julian@tfs.com) |
| 9 | * |
| 10 | * Others that has contributed by example code is |
| 11 | * Glen Overby (overby@cray.com) |
| 12 | * Tatu Yllnen |
| 13 | * Brian E Litzinger |
| 14 | * |
| 15 | * Redistribution and use in source and binary forms, with or without |
| 16 | * modification, are permitted provided that the following conditions |
| 17 | * are met: |
| 18 | * 1. Redistributions of source code must retain the above copyright |
| 19 | * notice, this list of conditions and the following disclaimer. |
| 20 | * 2. Redistributions in binary form must reproduce the above copyright |
| 21 | * notice, this list of conditions and the following disclaimer in the |
| 22 | * documentation and/or other materials provided with the distribution. |
| 23 | * |
| 24 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND |
| 25 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE DEVELOPERS BE LIABLE |
| 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 30 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 31 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 32 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 33 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 34 | * SUCH DAMAGE. |
| 35 | */ |
| 36 | |
| 37 | /* |
| 38 | * |
| 39 | * kentp 940307 alpha version based on newscsi-03 version of Julians SCSI-code |
| 40 | * kentp 940314 Added possibility to not use messages |
| 41 | * rknier 940331 Added fast transfer code |
| 42 | * rknier 940407 Added assembler coded data transfers |
| 43 | * |
| 44 | * $Id: seagate.c,v 1.2 1994/06/13 00:43:26 sean Exp $ |
| 45 | */ |
| 46 | |
| 47 | /* |
| 48 | * What should really be done: |
| 49 | * |
| 50 | * Add missing tests for timeouts |
| 51 | * Restructure interrupt enable/disable code (runs to long with int disabled) |
| 52 | * Find bug? giving problem with tape status |
| 53 | * Add code to handle Future Domain 840, 841, 880 and 881 |
| 54 | * adjust timeouts (startup is very slow) |
| 55 | * add code to use tagged commands in SCSI2 |
| 56 | * Add code to handle slow devices better (sleep if device not disconnecting) |
| 57 | * Fix unnecessary interrupts |
| 58 | */ |
| 59 | |
| 60 | /* Note to users trying to share a disk between DOS and unix: |
| 61 | * The ST01/02 is a translating host-adapter. It is not giving DOS |
| 62 | * the same number of heads/tracks/sectors as specified by the disk. |
| 63 | * It is therefore important to look at what numbers DOS thinks the |
| 64 | * disk has. Use these to disklabel your disk in an appropriate manner |
| 65 | */ |
| 66 | |
| 67 | #include <sys/types.h> |
| 68 | |
| 69 | #ifdef KERNEL /* don't laugh.. look for main() */ |
| 70 | #include <sea.h> |
| 71 | |
| 72 | #include <sys/param.h> |
| 73 | #include <sys/systm.h> |
| 74 | #include <sys/errno.h> |
| 75 | #include <sys/ioctl.h> |
| 76 | #include <sys/malloc.h> |
| 77 | #include <sys/buf.h> |
| 78 | #include <sys/proc.h> |
| 79 | #include <sys/user.h> |
| 80 | #include <i386/isa/isa_device.h> |
| 81 | #endif /* KERNEL */ |
| 82 | #include <scsi/scsi_all.h> |
| 83 | #include <scsi/scsiconf.h> |
| 84 | |
| 85 | #ifdef KERNEL |
| 86 | #include "ddb.h" |
| 87 | #include "kernel.h" |
| 88 | #else /* KERNEL */ |
| 89 | #define NSEA 1 |
| 90 | #endif /* KERNEL */ |
| 91 | |
| 92 | extern int hz; |
| 93 | |
| 94 | #define SEA_SCB_MAX 8 /* allow maximally 8 scsi control blocks */ |
| 95 | #define SCB_TABLE_SIZE 8 /* start with 8 scb entries in table */ |
| 96 | #define BLOCK_SIZE 512 /* size of READ/WRITE areas on SCSI card */ |
| 97 | |
| 98 | /* |
| 99 | * defining PARITY causes parity data to be checked |
| 100 | */ |
| 101 | #define PARITY 1 |
| 102 | |
| 103 | /* |
| 104 | * defining SEA_BLINDTRANSFER will make DATA IN and DATA OUT to be done with |
| 105 | * blind transfers, i.e. no check is done for scsi phase changes. This will |
| 106 | * result in data loss if the scsi device does not send its data using |
| 107 | * BLOCK_SIZE bytes at a time. |
| 108 | * If SEA_BLINDTRANSFER defined and SEA_ASSEMBLER also defined will result in |
| 109 | * the use of blind transfers coded in assembler. SEA_ASSEMBLER is no good |
| 110 | * without SEA_BLINDTRANSFER defined. |
| 111 | */ |
| 112 | #define SEA_BLINDTRANSFER 1 /* do blind transfers */ |
| 113 | #define SEA_ASSEMBLER 1 /* Use assembly code for fast transfers */ |
| 114 | |
| 115 | /* |
| 116 | * defining SEANOMSGS causes messages not to be used (thereby disabling |
| 117 | * disconnects) |
| 118 | */ |
| 119 | /* #define SEANOMSGS 1 */ |
| 120 | |
| 121 | /* |
| 122 | * defining SEA_NODATAOUT makes dataout phase being aborted |
| 123 | */ |
| 124 | /* #define SEA_NODATAOUT 1 */ |
| 125 | |
| 126 | /* |
| 127 | * defining SEA_SENSEFIRST make REQUEST_SENSE opcode to be placed first |
| 128 | */ |
| 129 | /* #define SEA_SENSEFIRST 1 */ |
| 130 | |
| 131 | #define SEA_FREEBSD11 1 /* intermediate def. for FreeBSD 1.1 BETA */ |
| 132 | /* timeout function has changed */ |
| 133 | |
| 134 | /* Debugging definitions. Should not be used unless you want a lot of |
| 135 | printouts even under normal conditions */ |
| 136 | |
| 137 | /* #define SEADEBUG 1 */ /* General info about errors */ |
| 138 | /* #define SEADEBUG1 1 */ /* Info about internal results and errors */ |
| 139 | /* #define SEADEBUG2 1 */ /* Display a lot about timeouts etc */ |
| 140 | /* #define SEADEBUG3 1 */ |
| 141 | /* #define SEADEBUG4 1 */ |
| 142 | /* #define SEADEBUG5 1 */ |
| 143 | /* #define SEADEBUG6 1 */ /* Display info about queue-lengths */ |
| 144 | /* #define SEADEBUG7 1 */ /* Extra check on STATUS before phase check */ |
| 145 | /* #define SEADEBUG8 1 */ /* Disregard non-BSY state in |
| 146 | sea_information_transfer */ |
| 147 | /* #define SEADEBUG9 1 */ /* Enable printouts */ |
| 148 | /* #define SEADEBUG11 1 */ /* stop everything except access to scsi id 1 */ |
| 149 | /* #define SEADEBUG15 1 */ /* Display every byte sent/received */ |
| 150 | |
| 151 | #define NUM_CONCURRENT 1 /* number of concurrent ops per board */ |
| 152 | |
| 153 | /******************************* board definitions **************************/ |
| 154 | /* |
| 155 | * CONTROL defines |
| 156 | */ |
| 157 | |
| 158 | #define CMD_RST 0x01 /* scsi reset */ |
| 159 | #define CMD_SEL 0x02 /* scsi select */ |
| 160 | #define CMD_BSY 0x04 /* scsi busy */ |
| 161 | #define CMD_ATTN 0x08 /* scsi attention */ |
| 162 | #define CMD_START_ARB 0x10 /* start arbitration bit */ |
| 163 | #define CMD_EN_PARITY 0x20 /* enable scsi parity generation */ |
| 164 | #define CMD_INTR 0x40 /* enable scsi interrupts */ |
| 165 | #define CMD_DRVR_ENABLE 0x80 /* scsi enable */ |
| 166 | |
| 167 | /* |
| 168 | * STATUS |
| 169 | */ |
| 170 | |
| 171 | #define STAT_BSY 0x01 /* scsi busy */ |
| 172 | #define STAT_MSG 0x02 /* scsi msg */ |
| 173 | #define STAT_IO 0x04 /* scsi I/O */ |
| 174 | #define STAT_CD 0x08 /* scsi C/D */ |
| 175 | #define STAT_REQ 0x10 /* scsi req */ |
| 176 | #define STAT_SEL 0x20 /* scsi select */ |
| 177 | #define STAT_PARITY 0x40 /* parity error bit */ |
| 178 | #define STAT_ARB_CMPL 0x80 /* arbitration complete bit */ |
| 179 | |
| 180 | /* |
| 181 | * REQUESTS |
| 182 | */ |
| 183 | |
| 184 | #define REQ_MASK (STAT_CD | STAT_IO | STAT_MSG) |
| 185 | #define REQ_DATAOUT 0 |
| 186 | #define REQ_DATAIN STAT_IO |
| 187 | #define REQ_CMDOUT STAT_CD |
| 188 | #define REQ_STATIN (STAT_CD | STAT_IO) |
| 189 | #define REQ_MSGOUT (STAT_MSG | STAT_CD) |
| 190 | #define REQ_MSGIN (STAT_MSG | STAT_CD | STAT_IO) |
| 191 | |
| 192 | #define REQ_UNKNOWN 0xff |
| 193 | |
| 194 | #define SEAGATERAMOFFSET 0x00001800 |
| 195 | |
| 196 | #ifdef PARITY |
| 197 | #define BASE_CMD (CMD_EN_PARITY | CMD_INTR) |
| 198 | #else |
| 199 | #define BASE_CMD (CMD_INTR) |
| 200 | #endif |
| 201 | |
| 202 | #define SEAGATE 1 |
| 203 | #define FD 2 |
| 204 | |
| 205 | /****************************************************************************** |
| 206 | * This should be placed in a more generic file (presume in /sys/scsi) |
| 207 | * Message codes: |
| 208 | */ |
| 209 | #define MSG_ABORT 0x06 |
| 210 | #define MSG_NOP 0x08 |
| 211 | #define MSG_COMMAND_COMPLETE 0x00 |
| 212 | #define MSG_DISCONNECT 0x04 |
| 213 | #define MSG_IDENTIFY 0x80 |
| 214 | #define MSG_BUS_DEV_RESET 0x0c |
| 215 | #define MSG_MESSAGE_REJECT 0x07 |
| 216 | #define MSG_SAVE_POINTERS 0x02 |
| 217 | #define MSG_RESTORE_POINTERS 0x03 |
| 218 | /******************************************************************************/ |
| 219 | |
| 220 | #define IDENTIFY(can_disconnect,lun) (MSG_IDENTIFY | ((can_disconnect) ? \ |
| 221 | 0x40 : 0) | ((lun) & 0x07)) |
| 222 | |
| 223 | /* scsi control block used to keep info about a scsi command */ |
| 224 | struct sea_scb |
| 225 | { |
| 226 | int flags; /* status of the instruction */ |
| 227 | #define SCB_FREE 0 |
| 228 | #define SCB_ACTIVE 1 |
| 229 | #define SCB_ABORTED 2 |
| 230 | #define SCB_TIMEOUT 4 |
| 231 | #define SCB_ERROR 8 |
| 232 | #define SCB_TIMECHK 16 /* We have set a timeout on this one */ |
| 233 | struct sea_scb *next; /* in free list */ |
| 234 | struct scsi_xfer *xfer; /* the scsi_xfer for this cmd */ |
| 235 | u_char * data; /* position in data buffer so far */ |
| 236 | int32 datalen; /* bytes remaining to transfer */; |
| 237 | }; |
| 238 | |
| 239 | /* |
| 240 | * data structure describing current status of the scsi bus. One for each |
| 241 | * controller card. |
| 242 | */ |
| 243 | struct sea_data |
| 244 | { |
| 245 | caddr_t basemaddr; /* Base address for card */ |
| 246 | char ctrl_type; /* FD or SEAGATE */ |
| 247 | caddr_t st0x_cr_sr; /* Address of control and status register */ |
| 248 | caddr_t st0x_dr; /* Address of data register */ |
| 249 | u_short vect; /* interrupt vector for this card */ |
| 250 | int our_id; /* our scsi id */ |
| 251 | int numscb; /* number of scsi control blocks */ |
| 252 | struct scsi_link sc_link; /* struct connecting different data */ |
| 253 | struct sea_scb *connected; /* currently connected command */ |
| 254 | struct sea_scb *issue_queue; /* waiting to be issued */ |
| 255 | struct sea_scb *disconnected_queue; /* waiting to reconnect */ |
| 256 | struct sea_scb scbs[SCB_TABLE_SIZE]; |
| 257 | struct sea_scb *free_scb; /* free scb list */ |
| 258 | volatile unsigned char busy[8]; /* index=target, bit=lun, Keep track of |
| 259 | busy luns at device target */ |
| 260 | } *seadata[NSEA]; |
| 261 | |
| 262 | /* flag showing if main routine is running. */ |
| 263 | static volatile int main_running = 0; |
| 264 | |
| 265 | #define STATUS (*(volatile unsigned char *) sea->st0x_cr_sr) |
| 266 | #define CONTROL STATUS |
| 267 | #define DATA (*(volatile unsigned char *) sea->st0x_dr) |
| 268 | |
| 269 | /* |
| 270 | * These are "special" values for the tag parameter passed to sea_select |
| 271 | * Not implemented right now. |
| 272 | */ |
| 273 | |
| 274 | #define TAG_NEXT -1 /* Use next free tag */ |
| 275 | #define TAG_NONE -2 /* |
| 276 | * Establish I_T_L nexus instead of I_T_L_Q |
| 277 | * even on SCSI-II devices. |
| 278 | */ |
| 279 | |
| 280 | typedef struct { |
| 281 | char *signature ; |
| 282 | unsigned offset; |
| 283 | unsigned length; |
| 284 | unsigned char type; |
| 285 | } BiosSignature; |
| 286 | |
| 287 | /* |
| 288 | * Signatures for automatic recognition of board type |
| 289 | */ |
| 290 | |
| 291 | static const BiosSignature signatures[] = { |
| 292 | {"ST01 v1.7 (C) Copyright 1987 Seagate", 15, 37, SEAGATE}, |
| 293 | {"SCSI BIOS 2.00 (C) Copyright 1987 Seagate", 15, 40, SEAGATE}, |
| 294 | |
| 295 | /* |
| 296 | * The following two lines are NOT mistakes. One detects ROM revision |
| 297 | * 3.0.0, the other 3.2. Since seagate has only one type of SCSI adapter, |
| 298 | * and this is not going to change, the "SEAGATE" and "SCSI" together |
| 299 | * are probably "good enough" |
| 300 | */ |
| 301 | |
| 302 | {"SEAGATE SCSI BIOS ", 16, 17, SEAGATE}, |
| 303 | {"SEAGATE SCSI BIOS ", 17, 17, SEAGATE}, |
| 304 | |
| 305 | /* |
| 306 | * However, future domain makes several incompatible SCSI boards, so specific |
| 307 | * signatures must be used. |
| 308 | */ |
| 309 | |
| 310 | {"FUTURE DOMAIN CORP. (C) 1986-1989 V5.0C2/14/89", 5, 45, FD}, |
| 311 | {"FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/89", 5, 46, FD}, |
| 312 | {"FUTURE DOMAIN CORP. (C) 1986-1990 V6.0105/31/90",5, 47, FD}, |
| 313 | {"FUTURE DOMAIN CORP. (C) 1986-1990 V6.0209/18/90",5, 47, FD}, |
| 314 | {"FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90", 5, 46, FD}, |
| 315 | {"FUTURE DOMAIN CORP. (C) 1992 V8.00.004/02/92", 5, 44, FD}, |
| 316 | {"FUTURE DOMAIN TMC-950", 5, 21, FD}, |
| 317 | }; |
| 318 | |
| 319 | #define NUM_SIGNATURES (sizeof(signatures) / sizeof(BiosSignature)) |
| 320 | |
| 321 | static const char * seagate_bases[] = { |
| 322 | (char *) 0xc8000, (char *) 0xca000, (char *) 0xcc000, |
| 323 | (char *) 0xce000, (char *) 0xdc000, (char *) 0xde000 |
| 324 | }; |
| 325 | |
| 326 | #define NUM_BASES (sizeof(seagate_bases)/sizeof(char *)) |
| 327 | |
| 328 | int sea_probe(struct isa_device *dev); |
| 329 | int sea_attach(struct isa_device *dev); |
| 330 | int seaintr(int unit); |
| 331 | int32 sea_scsi_cmd(struct scsi_xfer *xs); |
| 332 | #ifdef SEA_FREEBSD11 |
| 333 | void sea_timeout(caddr_t, int); |
| 334 | #else |
| 335 | void sea_timeout(struct sea_scb *scb); |
| 336 | #endif |
| 337 | void seaminphys(struct buf *bp); |
| 338 | void sea_done(int unit, struct sea_scb *scb); |
| 339 | u_int32 sea_adapter_info(int unit); |
| 340 | struct sea_scb *sea_get_scb(int unit, int flags); |
| 341 | void sea_free_scb(int unit, struct sea_scb *scb, int flags); |
| 342 | static void sea_main(void); |
| 343 | static void sea_information_transfer(struct sea_data *sea); |
| 344 | int sea_poll(int unit, struct scsi_xfer *xs, struct sea_scb *scb); |
| 345 | int sea_init(int unit); |
| 346 | int sea_send_scb(struct sea_data *sea, struct sea_scb *scb); |
| 347 | int sea_reselect(struct sea_data *sea); |
| 348 | int sea_select(struct sea_data *sea, struct sea_scb *scb); |
| 349 | int sea_transfer_pio(struct sea_data *sea, u_char *phase, int32 *count, |
| 350 | u_char **data); |
| 351 | int sea_abort(int unit, struct sea_scb *scb); |
| 352 | |
| 353 | static sea_unit = 0; |
| 354 | static sea_slot = -1; /* last found board seagate_bases address index */ |
| 355 | #define FAIL 1 |
| 356 | #define SUCCESS 0 |
| 357 | |
| 358 | #ifdef KERNEL |
| 359 | struct scsi_adapter sea_switch = |
| 360 | { |
| 361 | sea_scsi_cmd, |
| 362 | seaminphys, |
| 363 | 0, |
| 364 | 0, |
| 365 | sea_adapter_info, |
| 366 | "sea", |
| 367 | 0,0 |
| 368 | }; |
| 369 | |
| 370 | /* the below structure is so we have a default dev struct for our link struct */ |
| 371 | struct scsi_device sea_dev = |
| 372 | { |
| 373 | NULL, /* use default error handler */ |
| 374 | NULL, /* have a queue, served by this */ |
| 375 | NULL, /* have no async handler */ |
| 376 | NULL, /* Use default 'done' routine */ |
| 377 | "sea", |
| 378 | 0, |
| 379 | 0,0 |
| 380 | }; |
| 381 | |
| 382 | struct isa_driver seadriver = |
| 383 | { |
| 384 | sea_probe, |
| 385 | sea_attach, |
| 386 | "sea" |
| 387 | }; |
| 388 | |
| 389 | #endif /* KERNEL */ |
| 390 | |
| 391 | #ifdef SEADEBUG6 |
| 392 | void sea_queue_length() |
| 393 | { |
| 394 | struct sea_scb *tmp; |
| 395 | int length = 0; |
| 396 | |
| 397 | if(seadata[0]->connected) |
| 398 | length = 1; |
| 399 | for(tmp = seadata[0]->issue_queue; tmp != NULL; tmp = tmp->next, length++); |
| 400 | for(tmp = seadata[0]->disconnected_queue ; tmp != NULL; tmp->next, length++); |
| 401 | printf("length:%d ",length); |
| 402 | } |
| 403 | #endif |
| 404 | |
| 405 | /***********************************************************************\ |
| 406 | * Check if the device can be found at the port given and if so, detect * |
| 407 | * the type of board. Set it up ready for further work. Takes the * |
| 408 | * isa_dev structure from autoconf as an argument. * |
| 409 | * Returns 1 if card recognized, 0 if errors * |
| 410 | \***********************************************************************/ |
| 411 | int |
| 412 | sea_probe(dev) |
| 413 | struct isa_device *dev; |
| 414 | { |
| 415 | int j; |
| 416 | int unit = sea_unit; |
| 417 | struct sea_data *sea; |
| 418 | dev->id_unit = unit; |
| 419 | |
| 420 | #ifdef SEADEBUG2 |
| 421 | printf("sea_probe "); |
| 422 | #endif |
| 423 | |
| 424 | /* find unit and check we have that many defined */ |
| 425 | if(unit >= NSEA) { |
| 426 | printf("sea%d: unit number too high\n",unit); |
| 427 | return(0); |
| 428 | } |
| 429 | dev->id_unit = unit; |
| 430 | #ifdef SEADEBUG2 |
| 431 | printf("unit: %d\n",unit); |
| 432 | printf("dev_addr: 0x%lx\n",dev->id_maddr); |
| 433 | #endif |
| 434 | /* allocate a storage area for us */ |
| 435 | |
| 436 | if (seadata[unit]) { |
| 437 | printf("sea%d: memory already allocated\n", unit); |
| 438 | return(0); |
| 439 | } |
| 440 | #ifdef SEADEBUG2 |
| 441 | printf("Before malloc\n"); |
| 442 | #endif |
| 443 | sea = malloc(sizeof(struct sea_data), M_TEMP, M_NOWAIT); |
| 444 | if (!sea) { |
| 445 | printf("sea%d: cannot malloc!\n", unit); |
| 446 | return(0); |
| 447 | } |
| 448 | |
| 449 | #ifdef SEADEBUG2 |
| 450 | printf("after malloc\n"); |
| 451 | for(j=0;j<32767;j++); |
| 452 | #endif |
| 453 | bzero(sea,sizeof(struct sea_data)); |
| 454 | seadata[unit] = sea; |
| 455 | |
| 456 | /* check for address if no one specified */ |
| 457 | sea->basemaddr = NULL; |
| 458 | |
| 459 | /* Could try to find a board by looking through all possible addresses */ |
| 460 | /* This is not done the right way now, because I have not found a way */ |
| 461 | /* to get a boards virtual memory address given its physical. There is */ |
| 462 | /* a function that returns the physical address for a given virtual */ |
| 463 | /* address, but not the other way around */ |
| 464 | |
| 465 | if(dev->id_maddr == 0) { |
| 466 | /* |
| 467 | for(sea_slot++;sea_slot<NUM_BASES;sea_slot++) |
| 468 | for(j = 0; !sea->basemaddr && j < NUM_SIGNATURES; ++j) |
| 469 | if(!memcmp((void *)(seagate_bases[sea_slot]+signatures[j].offset), |
| 470 | (void *) signatures[j].signature, signatures[j].length)) { |
| 471 | sea->basemaddr = (void *)seagate_bases[sea_slot]; |
| 472 | break; |
| 473 | } |
| 474 | */ |
| 475 | } else { |
| 476 | |
| 477 | #ifdef SEADEBUG2 |
| 478 | printf("id_maddr != 0\n"); |
| 479 | for(j = 0; j < 32767 ; j++); |
| 480 | for(j = 0; j < 32767 ; j++); |
| 481 | #endif |
| 482 | /* find sea_slot position for overridden memory address */ |
| 483 | for(j = 0; ((char *)vtophys(dev->id_maddr) != seagate_bases[j]) && |
| 484 | j<NUM_BASES; ++j); |
| 485 | if(j == NUM_BASES) { |
| 486 | printf("sea: board not expected at address 0x%lx\n",dev->id_maddr); |
| 487 | seadata[unit]=NULL; |
| 488 | free(sea, M_TEMP); |
| 489 | return(0); |
| 490 | } else if(sea_slot > j) { |
| 491 | printf("sea: board address 0x%lx already probed!\n", dev->id_maddr); |
| 492 | seadata[unit]=NULL; |
| 493 | free(sea, M_TEMP); |
| 494 | return(0); |
| 495 | } else { |
| 496 | sea->basemaddr = dev->id_maddr; |
| 497 | } |
| 498 | |
| 499 | } |
| 500 | #ifdef SEADEBUG2 |
| 501 | printf("sea->basemaddr = %lx\n", sea->basemaddr); |
| 502 | #endif |
| 503 | |
| 504 | /* check board type */ /* No way to define this through config */ |
| 505 | for(j = 0; j < NUM_SIGNATURES; j++) |
| 506 | if(!memcmp((void *) (sea->basemaddr + signatures[j].offset), |
| 507 | (void *) signatures[j].signature, signatures[j].length)) { |
| 508 | sea->ctrl_type = signatures[j].type; |
| 509 | break; |
| 510 | } |
| 511 | if(j == NUM_SIGNATURES) { |
| 512 | printf("sea: Board type unknown at address 0x%lx\n", |
| 513 | sea->basemaddr); |
| 514 | seadata[unit]=NULL; |
| 515 | free(sea, M_TEMP); |
| 516 | return(0); |
| 517 | } |
| 518 | |
| 519 | /* Find controller and data memory addresses */ |
| 520 | sea->st0x_cr_sr = (void *) (((unsigned char *) sea->basemaddr) + |
| 521 | ((sea->ctrl_type == SEAGATE) ? 0x1a00 : 0x1c00)); |
| 522 | sea->st0x_dr = (void *) (((unsigned char *) sea->basemaddr) + |
| 523 | ((sea->ctrl_type == SEAGATE) ? 0x1c00 : 0x1e00)); |
| 524 | |
| 525 | /* Test controller RAM (works the same way on future domain cards?) */ |
| 526 | *(sea->basemaddr + SEAGATERAMOFFSET) = 0xa5; |
| 527 | *(sea->basemaddr + SEAGATERAMOFFSET + 1) = 0x5a; |
| 528 | |
| 529 | if((*(sea->basemaddr + SEAGATERAMOFFSET) != (char) 0xa5) || |
| 530 | (*(sea->basemaddr + SEAGATERAMOFFSET + 1) != (char) 0x5a)) { |
| 531 | printf("sea%d: Board RAM failure\n",unit); |
| 532 | } |
| 533 | |
| 534 | if(sea_init(unit) != 0) { |
| 535 | seadata[unit] = NULL; |
| 536 | free(sea,M_TEMP); |
| 537 | return(0); |
| 538 | } |
| 539 | |
| 540 | /* if its there put in it's interrupt vector */ |
| 541 | /* (Doesn't use dma, so no drq is set) */ |
| 542 | sea->vect = dev->id_irq; |
| 543 | |
| 544 | sea_unit++; |
| 545 | return(1); |
| 546 | } |
| 547 | |
| 548 | /***********************************************\ |
| 549 | * Attach all sub-devices we can find * |
| 550 | \***********************************************/ |
| 551 | int |
| 552 | sea_attach(dev) |
| 553 | struct isa_device *dev; |
| 554 | { |
| 555 | int unit = dev->id_unit; |
| 556 | struct sea_data *sea = seadata[unit]; |
| 557 | |
| 558 | #ifdef SEADEBUG2 |
| 559 | printf("sea_attach called\n"); |
| 560 | #endif |
| 561 | |
| 562 | /* fill in the prototype scsi_link */ |
| 563 | sea->sc_link.adapter_unit = unit; |
| 564 | sea->sc_link.adapter_targ = sea->our_id; |
| 565 | sea->sc_link.adapter = &sea_switch; |
| 566 | sea->sc_link.device = &sea_dev; |
| 567 | |
| 568 | /*****************************************************\ |
| 569 | * ask the adapter what subunits are present * |
| 570 | \*****************************************************/ |
| 571 | scsi_attachdevs(&(sea->sc_link)); |
| 572 | return 1; |
| 573 | } |
| 574 | |
| 575 | /***********************************************\ |
| 576 | * Return some information to the caller about * |
| 577 | * the adapter and its capabilities * |
| 578 | \***********************************************/ |
| 579 | u_int32 |
| 580 | sea_adapter_info(unit) |
| 581 | int unit; |
| 582 | { |
| 583 | #ifdef SEADEBUG2 |
| 584 | printf("sea_adapter_info called\n"); |
| 585 | #endif |
| 586 | return 1; |
| 587 | } |
| 588 | |
| 589 | /***********************************************\ |
| 590 | * Catch an interrupt from the adaptor * |
| 591 | \***********************************************/ |
| 592 | int |
| 593 | seaintr(unit) |
| 594 | int unit; |
| 595 | { |
| 596 | int done; |
| 597 | struct sea_data *sea = seadata[unit]; |
| 598 | int oldpri; |
| 599 | |
| 600 | #if SEADEBUG2 |
| 601 | printf(";"); |
| 602 | #endif |
| 603 | |
| 604 | do { |
| 605 | done = 1; |
| 606 | /* dispatch to appropriate routine if found and done=0 */ |
| 607 | /* should check to see that this card really caused the interrupt */ |
| 608 | if ((STATUS & (STAT_SEL | STAT_IO)) == (STAT_SEL | STAT_IO)) { |
| 609 | /* Reselect interrupt */ |
| 610 | #ifdef SEADEBUG2 |
| 611 | printf(";2"); |
| 612 | #endif |
| 613 | done = 0; |
| 614 | /* enable_intr(); */ /* ?? How should this be done ?? */ |
| 615 | sea_reselect(sea); |
| 616 | } else if (STATUS & STAT_PARITY) { |
| 617 | /* Parity error interrupt */ |
| 618 | #ifdef SEADEBUG2 |
| 619 | printf(";3"); |
| 620 | #endif |
| 621 | printf("sea%d: PARITY interrupt\n", unit); |
| 622 | } else { |
| 623 | #ifdef SEADEBUG2 |
| 624 | /* printf("sea%d: unknown interrupt\n",unit); */ |
| 625 | printf(";4%x", STATUS); |
| 626 | #endif |
| 627 | } |
| 628 | if (!done) { |
| 629 | oldpri = splbio(); /* disable_intr(); */ |
| 630 | if (!main_running) { |
| 631 | #ifdef SEADEBUG2 |
| 632 | printf(";5"); |
| 633 | #endif |
| 634 | main_running = 1; |
| 635 | sea_main(); |
| 636 | /* main_running is cleared in sea_main once it can't |
| 637 | * do more work, and sea_main exits with interrupts |
| 638 | * disabled |
| 639 | */ |
| 640 | splx(oldpri); /* enable_intr(); */ |
| 641 | } else { |
| 642 | splx(oldpri); /* enable_intr(); */ |
| 643 | } |
| 644 | } |
| 645 | } while (!done); |
| 646 | return 1; |
| 647 | } |
| 648 | |
| 649 | /***********************************************\ |
| 650 | * Setup data structures, and reset the board * |
| 651 | * and the scsi bus * |
| 652 | \***********************************************/ |
| 653 | int |
| 654 | sea_init(unit) |
| 655 | int unit; |
| 656 | { |
| 657 | long l; |
| 658 | int i; |
| 659 | struct sea_data *sea = seadata[unit]; |
| 660 | |
| 661 | #ifdef SEADEBUG2 |
| 662 | printf("sea_init called\n"); |
| 663 | #endif |
| 664 | /* Reset the scsi bus (I don't know if this is needed */ |
| 665 | CONTROL = BASE_CMD | CMD_DRVR_ENABLE | CMD_RST; |
| 666 | DELAY(25); /* hold reset for at least 25 microseconds */ |
| 667 | CONTROL = BASE_CMD; |
| 668 | DELAY(10); /* wait a Bus Clear Delay (800 ns + bus free delay (800 ns) */ |
| 669 | /* Set our id (don't know anything about this) */ |
| 670 | if(sea->ctrl_type == SEAGATE) |
| 671 | sea->our_id = 7; |
| 672 | else |
| 673 | sea->our_id = 6; |
| 674 | /* init fields used by our routines */ |
| 675 | sea->connected = NULL; |
| 676 | sea->issue_queue = NULL; |
| 677 | sea->disconnected_queue = NULL; |
| 678 | for (i=0; i<8 ; i++) |
| 679 | sea->busy[i] = 0; |
| 680 | |
| 681 | /* link up the free list of scbs */ |
| 682 | sea->numscb = SCB_TABLE_SIZE; |
| 683 | sea->free_scb = (struct sea_scb *) & (sea->scbs[0]); |
| 684 | for(i=1;i< SCB_TABLE_SIZE ; i++) { |
| 685 | sea->scbs[i-1].next = &(sea->scbs[i]); |
| 686 | } |
| 687 | sea->scbs[SCB_TABLE_SIZE - 1].next = NULL; |
| 688 | |
| 689 | return(0); |
| 690 | } |
| 691 | |
| 692 | /***********************************************\ |
| 693 | * * |
| 694 | \***********************************************/ |
| 695 | void seaminphys(bp) |
| 696 | struct buf *bp; |
| 697 | { |
| 698 | #ifdef SEADEBUG2 |
| 699 | /* printf("seaminphys called\n"); */ |
| 700 | printf(","); |
| 701 | #endif |
| 702 | } |
| 703 | |
| 704 | /***********************************************\ |
| 705 | * start a scsi operation given the command and * |
| 706 | * the data address. Also needs the unit, target * |
| 707 | * and lu * |
| 708 | * get a free scb and set it up * |
| 709 | * call send_scb * |
| 710 | * either start timer or wait until done * |
| 711 | \***********************************************/ |
| 712 | int32 sea_scsi_cmd(xs) |
| 713 | struct scsi_xfer *xs; |
| 714 | { |
| 715 | struct scsi_sense_data *s1, *s2; |
| 716 | struct sea_scb *scb; |
| 717 | int i = 0; |
| 718 | int flags; |
| 719 | int unit = xs->sc_link->adapter_unit; |
| 720 | struct sea_data *sea = seadata[unit]; |
| 721 | int s; |
| 722 | unsigned int stat; |
| 723 | int32 result; |
| 724 | |
| 725 | #ifdef SEADEBUG2 |
| 726 | /* printf("scsi_cmd\n"); */ |
| 727 | printf("="); |
| 728 | #endif |
| 729 | |
| 730 | #ifdef SEADEBUG11 |
| 731 | if(xs->sc_link->target != 1) { |
| 732 | xs->flags |= ITSDONE; |
| 733 | xs->error = XS_TIMEOUT; |
| 734 | return(HAD_ERROR); |
| 735 | } |
| 736 | #endif |
| 737 | |
| 738 | flags = xs->flags; |
| 739 | if(xs->bp) flags |= (SCSI_NOSLEEP); |
| 740 | if(flags & ITSDONE) { |
| 741 | printf("sea%d: Already done?", unit); |
| 742 | xs->flags &= ~ITSDONE; |
| 743 | } |
| 744 | if(!(flags & INUSE)) { |
| 745 | printf("sea%d: Not in use?", unit); |
| 746 | xs->flags |= INUSE; |
| 747 | } |
| 748 | if (!(scb = sea_get_scb(unit, flags))) { |
| 749 | #ifdef SEADEBUG2 |
| 750 | printf("=2"); |
| 751 | #endif |
| 752 | xs->error = XS_DRIVER_STUFFUP; |
| 753 | return(TRY_AGAIN_LATER); |
| 754 | } |
| 755 | |
| 756 | /* |
| 757 | * Put all the arguments for the xfer in the scb |
| 758 | */ |
| 759 | scb->xfer = xs; |
| 760 | scb->datalen = xs->datalen; |
| 761 | scb->data = xs->data; |
| 762 | |
| 763 | if(flags & SCSI_RESET) { |
| 764 | /* Try to send a reset command to the card. This is done by calling the |
| 765 | * Reset function. Should then return COMPLETE. Need to take care of the |
| 766 | * possible current connected command. |
| 767 | * Not implemented right now. |
| 768 | */ |
| 769 | printf("sea%d: Got a SCSI_RESET!\n",unit); |
| 770 | } |
| 771 | |
| 772 | /* setup the scb to contain necessary values */ |
| 773 | /* The interresting values can be read from the xs that is saved */ |
| 774 | /* I therefore think that the structure can be kept very small */ |
| 775 | /* the driver doesn't use DMA so the scatter/gather is not needed ? */ |
| 776 | #ifdef SEADEBUG6 |
| 777 | sea_queue_length(); |
| 778 | #endif |
| 779 | if (sea_send_scb(sea, scb) == 0) { |
| 780 | #ifdef SEADEBUG2 |
| 781 | printf("=3"); |
| 782 | #endif |
| 783 | xs->error = XS_DRIVER_STUFFUP; |
| 784 | sea_free_scb(unit, scb, flags); |
| 785 | return (TRY_AGAIN_LATER); |
| 786 | } |
| 787 | |
| 788 | /* |
| 789 | * Usually return SUCCESSFULLY QUEUED |
| 790 | */ |
| 791 | if (!(flags & SCSI_NOMASK)) { |
| 792 | if(xs->flags & ITSDONE) { /* timout timer not started, already finished */ |
| 793 | /* Tried to return COMPLETE but the machine hanged with this */ |
| 794 | #ifdef SEADEBUG2 |
| 795 | printf("=6"); |
| 796 | #endif |
| 797 | return(SUCCESSFULLY_QUEUED); |
| 798 | } |
| 799 | #ifdef SEA_FREEBSD11 |
| 800 | timeout(sea_timeout, (caddr_t)scb, (xs->timeout * hz) / 1000); |
| 801 | #else |
| 802 | timeout(sea_timeout, scb, (xs->timeout * hz) / 1000); |
| 803 | #endif |
| 804 | scb->flags |= SCB_TIMECHK; |
| 805 | #ifdef SEADEBUG2 |
| 806 | printf("=4"); |
| 807 | #endif |
| 808 | return(SUCCESSFULLY_QUEUED); |
| 809 | } |
| 810 | |
| 811 | /* |
| 812 | * If we can't use interrupts, poll on completion |
| 813 | */ |
| 814 | |
| 815 | result = sea_poll(unit, xs, scb); |
| 816 | #ifdef SEADEBUG2 |
| 817 | printf("=5 %lx", result); |
| 818 | #endif |
| 819 | return result; |
| 820 | } |
| 821 | |
| 822 | /* |
| 823 | * Get a free scb. If there are none, see if we can allocate a new one. If so, |
| 824 | * put it in the hash table too, otherwise return an error or sleep. |
| 825 | */ |
| 826 | |
| 827 | struct sea_scb * |
| 828 | sea_get_scb(unit, flags) |
| 829 | int unit; |
| 830 | int flags; |
| 831 | { |
| 832 | struct sea_data *sea = seadata[unit]; |
| 833 | unsigned opri = 0; |
| 834 | struct sea_scb * scbp; |
| 835 | int hashnum; |
| 836 | |
| 837 | #ifdef SEADEBUG2 |
| 838 | /* printf("get_scb\n"); */ |
| 839 | printf("("); |
| 840 | #endif |
| 841 | |
| 842 | if (!(flags & SCSI_NOMASK)) |
| 843 | opri = splbio(); |
| 844 | |
| 845 | #ifdef SEADEBUG3 |
| 846 | printf("(2 %lx ", sea->free_scb); |
| 847 | #endif |
| 848 | |
| 849 | /* |
| 850 | * If we can and have to, sleep waiting for one to come free |
| 851 |