|
|
1.1 ! root 1: /* ! 2: * sys/i386/stand/as.c ! 3: * ! 4: * Standalone driver for Adaptech 1542 SCSI ! 5: * ! 6: * Pace Willisson [email protected] April 8, 1992 ! 7: */ ! 8: ! 9: #include "param.h" ! 10: #include "disklabel.h" ! 11: #include "i386/isa/asreg.h" ! 12: #include "saio.h" ! 13: ! 14: #ifdef ASDEBUG ! 15: #define ASPRINT(x) { printf x; DELAY (10000); } ! 16: #else ! 17: #define ASPRINT(x) ! 18: #endif ! 19: ! 20: #define NRETRIES 3 ! 21: ! 22: int as_port = 0x330; ! 23: ! 24: struct mailbox_entry mailbox[2]; ! 25: ! 26: int ! 27: asopen(io) ! 28: struct iob *io; ! 29: { ! 30: struct disklabel *dd; ! 31: char cdb[6]; ! 32: char data[12]; ! 33: int val; ! 34: int oval; ! 35: int i; ! 36: struct iob aio; ! 37: ! 38: if (io->i_unit < 0 || io->i_unit > 8 ! 39: || io->i_part < 0 || io->i_part > 8 ! 40: || io->i_ctlr < 0 || io->i_ctlr > 0) ! 41: return (-1); ! 42: ! 43: /* dma setup: see page 5-31 in the Adaptech manual */ ! 44: outb (0xd6, 0xc1); ! 45: outb (0xd4, 0x01); ! 46: ! 47: ASPRINT (("resetting adaptech card... ")); ! 48: ! 49: outb (as_port + AS_CONTROL, AS_CONTROL_SRST); ! 50: ! 51: /* delay a little */ ! 52: for (i = 0; i < 100; i++) ! 53: inb (0x84); ! 54: ! 55: while (inb (as_port + AS_STATUS) != (AS_STATUS_INIT | AS_STATUS_IDLE)) ! 56: ; ! 57: ! 58: ASPRINT (("reset ok ")); ! 59: ! 60: as_put_byte (AS_CMD_MAILBOX_INIT); ! 61: as_put_byte (1); /* one mailbox out, one in */ ! 62: as_put_byte ((int)mailbox >> 16); ! 63: as_put_byte ((int)mailbox >> 8); ! 64: as_put_byte ((int)mailbox); ! 65: ! 66: while (inb (as_port + AS_STATUS) & AS_STATUS_INIT) ! 67: ; ! 68: ! 69: ASPRINT (("mailbox init ok ")); ! 70: ! 71: /* do mode select to set the logical block size */ ! 72: bzero (cdb, 6); ! 73: cdb[0] = 0x15; /* MODE SELECT */ ! 74: cdb[4] = 12; /* parameter list length */ ! 75: ! 76: bzero (data, 12); ! 77: data[3] = 8; /* block descriptor length */ ! 78: data[9] = DEV_BSIZE >> 16; ! 79: data[10] = DEV_BSIZE >> 8; ! 80: data[11] = DEV_BSIZE; ! 81: ! 82: if (ascmd (io->i_unit, 0, cdb, 6, data, 12, 1) < 0) { ! 83: printf ("as%d: error setting logical block size\n", ! 84: io->i_unit); ! 85: return (-1); ! 86: } ! 87: ! 88: aio = *io; ! 89: aio.i_bn = LABELSECTOR; ! 90: aio.i_cc = DEV_BSIZE; ! 91: /*io->i_ma = buf;*/ ! 92: aio.i_boff = 0; ! 93: ! 94: #ifdef was ! 95: if (asstrategy (&aio, F_READ) == DEV_BSIZE) { ! 96: dd = (struct disklabel *)aio.i_ma; ! 97: io->i_boff = dd->d_partitions[io->i_part].p_offset; ! 98: ASPRINT (("partition offset %d ", io->i_boff)); ! 99: } ! 100: #else ! 101: { ! 102: extern struct disklabel disklabel; ! 103: io->i_boff = disklabel.d_partitions[io->i_part].p_offset; ! 104: ASPRINT (("partition offset %d ", io->i_boff)); ! 105: } ! 106: #endif ! 107: ! 108: ASPRINT (("asopen ok ")); ! 109: return(0); ! 110: } ! 111: ! 112: /* func is F_WRITE or F_READ ! 113: * io->i_unit, io->i_part, io->i_bn is starting block ! 114: * io->i_cc is byte count ! 115: * io->i_ma is memory address ! 116: * io->i_boff is block offset for this partition (set up in asopen) ! 117: */ ! 118: int ! 119: asstrategy(io, func) ! 120: struct iob *io; ! 121: { ! 122: char cdb[6]; ! 123: int blkno; ! 124: int retry; ! 125: ! 126: ASPRINT (("asstrategy(target=%d, block=%d+%d, count=%d) ", ! 127: io->i_unit, io->i_bn, io->i_boff, io->i_cc)); ! 128: ! 129: if (func == F_WRITE) { ! 130: printf ("as%d: write not supported\n", io->i_unit); ! 131: return (0); ! 132: } ! 133: ! 134: if (io->i_cc == 0) ! 135: return (0); ! 136: ! 137: if (io->i_cc % DEV_BSIZE != 0) { ! 138: printf ("as%d: transfer size not multiple of %d\n", ! 139: io->i_unit, DEV_BSIZE); ! 140: return (0); ! 141: } ! 142: ! 143: /* retry in case we get a unit-attention error, which just ! 144: * means the drive has been reset since the last command ! 145: */ ! 146: for (retry = 0; retry < NRETRIES; retry++) { ! 147: blkno = io->i_bn + io->i_boff; ! 148: ! 149: cdb[0] = 8; /* scsi read opcode */ ! 150: cdb[1] = (blkno >> 16) & 0x1f; ! 151: cdb[2] = blkno >> 8; ! 152: cdb[3] = blkno; ! 153: cdb[4] = io->i_cc / DEV_BSIZE; ! 154: cdb[5] = 0; /* control byte (used in linking) */ ! 155: ! 156: if (ascmd (io->i_unit, 1, cdb, 6, io->i_ma, io->i_cc, ! 157: retry == NRETRIES - 1) >= 0) { ! 158: ASPRINT (("asstrategy ok ")); ! 159: return (io->i_cc); ! 160: } ! 161: } ! 162: ! 163: ASPRINT (("asstrategy failed ")); ! 164: return (0); ! 165: } ! 166: ! 167: int ! 168: ascmd (target, readflag, cdb, cdblen, data, datalen, printerr) ! 169: int target; ! 170: int readflag; ! 171: char *cdb; ! 172: int cdblen; ! 173: char *data; ! 174: int datalen; ! 175: int printerr; ! 176: { ! 177: struct ccb ccb; ! 178: int physaddr; ! 179: unsigned char *sp; ! 180: int i; ! 181: ! 182: if (mailbox[0].cmd != 0) ! 183: /* this can't happen, unless the card flakes */ ! 184: _stop ("asstart: mailbox not available\n"); ! 185: ! 186: bzero (&ccb, sizeof ccb); ! 187: ! 188: ccb.ccb_opcode = 3; ! 189: ccb.ccb_addr_and_control = target << 5; ! 190: if (datalen != 0) ! 191: ccb.ccb_addr_and_control |= readflag ? 8 : 0x10; ! 192: else ! 193: ccb.ccb_addr_and_control |= 0x18; ! 194: ! 195: ccb.ccb_data_len_msb = datalen >> 16; ! 196: ccb.ccb_data_len_mid = datalen >> 8; ! 197: ccb.ccb_data_len_lsb = datalen; ! 198: ! 199: ccb.ccb_requst_sense_allocation_len = MAXSENSE; ! 200: ! 201: physaddr = (int)data; ! 202: ccb.ccb_data_ptr_msb = physaddr >> 16; ! 203: ccb.ccb_data_ptr_mid = physaddr >> 8; ! 204: ccb.ccb_data_ptr_lsb = physaddr; ! 205: ! 206: ccb.ccb_scsi_command_len = cdblen; ! 207: bcopy (cdb, ccb.ccb_cdb, cdblen); ! 208: ! 209: #ifdef ASDEBUG ! 210: printf ("ccb: "); ! 211: for (i = 0; i < 48; i++) ! 212: printf ("%x ", ((unsigned char *)&ccb)[i]); ! 213: printf ("\n"); ! 214: /*getchar ();*/ ! 215: #endif ! 216: ! 217: physaddr = (int)&ccb; ! 218: mailbox[0].msb = physaddr >> 16; ! 219: mailbox[0].mid = physaddr >> 8; ! 220: mailbox[0].lsb = physaddr; ! 221: mailbox[0].cmd = 1; ! 222: ! 223: /* tell controller to look in its mailbox */ ! 224: outb (as_port + AS_CONTROL, AS_CONTROL_IRST); ! 225: as_put_byte (AS_CMD_START_SCSI_COMMAND); ! 226: ! 227: /* wait for status */ ! 228: ASPRINT (("waiting for status...")); ! 229: while (mailbox[1].cmd == 0) ! 230: ; ! 231: mailbox[1].cmd = 0; ! 232: ! 233: ! 234: if (ccb.ccb_host_status != 0 || ccb.ccb_target_status != 0) { ! 235: #ifdef ASDEBUG ! 236: printerr = 1; ! 237: #endif ! 238: if (printerr) { ! 239: printf ("as%d error: hst=%x tst=%x sense=", ! 240: target, ! 241: ccb.ccb_host_status, ! 242: ccb.ccb_target_status); ! 243: sp = ccb_sense (&ccb); ! 244: for (i = 0; i < 8; i++) ! 245: printf ("%x ", sp[i]); ! 246: printf ("\n"); ! 247: #ifdef ASDEBUG ! 248: /*getchar ();*/ ! 249: #endif ! 250: } ! 251: return (-1); ! 252: } ! 253: ! 254: ASPRINT (("ascmd ok ")); ! 255: ! 256: return (0); ! 257: } ! 258: ! 259: int ! 260: as_put_byte (val) ! 261: int val; ! 262: { ! 263: while (inb (as_port + AS_STATUS) & AS_STATUS_CDF) ! 264: ; ! 265: outb (as_port + AS_DATA_OUT, val); ! 266: } ! 267:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.