1 /*- 2 * Copyright (c) 2001,2002 S�ren Schmidt <sos@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer, 10 * without modification, immediately at the beginning of the file. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * $FreeBSD$ 29 */ 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/kernel.h> 34 #include <sys/module.h> 35 #include <sys/bus.h> 36 #include <sys/bio.h> 37 #include <sys/conf.h> 38 #include <sys/disk.h> 39 #include <sys/devicestat.h> 40 #include <sys/eventhandler.h> 41 #include <sys/malloc.h> 42 #include <sys/lock.h> 43 #include <sys/mutex.h> 44 #include <vm/vm.h> 45 #include <vm/pmap.h> 46 #include <machine/stdarg.h> 47 #include <machine/resource.h> 48 #include <machine/bus.h> 49 #include <sys/rman.h> 50 #include <pci/pcivar.h> 51 #include <pci/pcireg.h> 52 53 #include "dev/pst/pst-iop.h" 54 55 /* device structures */ 56 static d_strategy_t pststrategy; 57 static struct cdevsw pst_cdevsw = { 58 /* open */ nullopen, 59 /* close */ nullclose, 60 /* read */ physread, 61 /* write */ physwrite, 62 /* ioctl */ noioctl, 63 /* poll */ nopoll, 64 /* mmap */ nommap, 65 /* strat */ pststrategy, 66 /* name */ "pst", 67 /* maj */ 200, 68 /* dump */ nodump, 69 /* psize */ nopsize, 70 /* flags */ D_DISK, 71 }; 72 static struct cdevsw pstdisk_cdevsw; 73 74 struct pst_softc { 75 struct iop_softc *iop; 76 struct i2o_lct_entry *lct; 77 struct i2o_bsa_device *info; 78 dev_t device; 79 struct devstat stats; 80 struct disk disk; 81 struct bio_queue_head queue; 82 struct mtx mtx; 83 int outstanding; 84 }; 85 86 struct pst_request { 87 struct pst_softc *psc; /* pointer to softc */ 88 u_int32_t mfa; /* frame addreess */ 89 struct callout_handle timeout_handle; /* handle for untimeout */ 90 struct bio *bp; /* associated bio ptr */ 91 }; 92 93 /* prototypes */ 94 static int pst_probe(device_t); 95 static int pst_attach(device_t); 96 static int pst_shutdown(device_t); 97 static void pst_start(struct pst_softc *); 98 static void pst_done(struct iop_softc *, u_int32_t, struct i2o_single_reply *); 99 static int pst_rw(struct pst_request *); 100 static void pst_timeout(struct pst_request *); 101 static void bpack(int8_t *, int8_t *, int); 102 103 /* local vars */ 104 static MALLOC_DEFINE(M_PSTRAID, "pst", "Promise SuperTrak RAID driver"); 105 106 int 107 pst_add_raid(struct iop_softc *sc, struct i2o_lct_entry *lct) 108 { 109 struct pst_softc *psc; 110 device_t child = device_add_child(sc->dev, "pst", -1); 111 112 if (!child) 113 return ENOMEM; 114 psc = malloc(sizeof(struct pst_softc), M_PSTRAID, M_NOWAIT | M_ZERO); 115 psc->iop = sc; 116 psc->lct = lct; 117 device_set_softc(child, psc); 118 return bus_generic_attach(sc->dev); 119 } 120 121 static int 122 pst_probe(device_t dev) 123 { 124 device_set_desc(dev, "Promise SuperTrak RAID"); 125 return 0; 126 } 127 128 static int 129 pst_attach(device_t dev) 130 { 131 struct pst_softc *psc = device_get_softc(dev); 132 struct i2o_get_param_reply *reply; 133 struct i2o_device_identity *ident; 134 int lun = device_get_unit(dev); 135 int8_t name [32]; 136 137 if (!(reply = iop_get_util_params(psc->iop, psc->lct->local_tid, 138 I2O_PARAMS_OPERATION_FIELD_GET, 139 I2O_BSA_DEVICE_INFO_GROUP_NO))) 140 return ENODEV; 141 142 if (!(psc->info = (struct i2o_bsa_device *) 143 malloc(sizeof(struct i2o_bsa_device), M_PSTRAID, M_NOWAIT))) { 144 contigfree(reply, PAGE_SIZE, M_PSTRAID); 145 return ENOMEM; 146 } 147 bcopy(reply->result, psc->info, sizeof(struct i2o_bsa_device)); 148 contigfree(reply, PAGE_SIZE, M_PSTRAID); 149 150 if (!(reply = iop_get_util_params(psc->iop, psc->lct->local_tid, 151 I2O_PARAMS_OPERATION_FIELD_GET, 152 I2O_UTIL_DEVICE_IDENTITY_GROUP_NO))) 153 return ENODEV; 154 ident = (struct i2o_device_identity *)reply->result; 155 #ifdef PSTDEBUG 156 printf("pst: vendor=<%.16s> product=<%.16s>\n", 157 ident->vendor, ident->product); 158 printf("pst: description=<%.16s> revision=<%.8s>\n", 159 ident->description, ident->revision); 160 printf("pst: capacity=%lld blocksize=%d\n", 161 psc->info->capacity, psc->info->block_size); 162 #endif 163 bpack(ident->vendor, ident->vendor, 16); 164 bpack(ident->product, ident->product, 16); 165 sprintf(name, "%s %s", ident->vendor, ident->product); 166 contigfree(reply, PAGE_SIZE, M_PSTRAID); 167 168 bioq_init(&psc->queue); 169 mtx_init(&psc->mtx, "pst lock", MTX_DEF, 0); 170 171 psc->device = disk_create(lun, &psc->disk, 0, &pst_cdevsw, &pstdisk_cdevsw); 172 psc->device->si_drv1 = psc; 173 psc->device->si_iosize_max = 64 * 1024; /*I2O_SGL_MAX_SEGS * PAGE_SIZE;*/ 174 175 psc->disk.d_sectorsize = psc->info->block_size; 176 psc->disk.d_mediasize = psc->info->capacity; 177 psc->disk.d_fwsectors = 63; 178 psc->disk.d_fwheads = 255; 179 180 devstat_add_entry(&psc->stats, "pst", lun, psc->info->block_size, 181 DEVSTAT_NO_ORDERED_TAGS, 182 DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_IDE, 183 DEVSTAT_PRIORITY_DISK); 184 185 printf("pst%d: %lluMB <%.40s> [%lld/%d/%d] on %.16s\n", lun, 186 (unsigned long long)psc->info->capacity / (1024 * 1024), 187 name, psc->info->capacity/(512*255*63), 255, 63, 188 device_get_nameunit(psc->iop->dev)); 189 190 EVENTHANDLER_REGISTER(shutdown_post_sync, pst_shutdown, 191 dev, SHUTDOWN_PRI_FIRST); 192 return 0; 193 } 194 195 static int 196 pst_shutdown(device_t dev) 197 { 198 struct pst_softc *psc = device_get_softc(dev); 199 struct i2o_bsa_cache_flush_message *msg; 200 int mfa; 201 202 mfa = iop_get_mfa(psc->iop); 203 msg = (struct i2o_bsa_cache_flush_message *)(psc->iop->ibase + mfa); 204 bzero(msg, sizeof(struct i2o_bsa_cache_flush_message)); 205 msg->version_offset = 0x01; 206 msg->message_flags = 0x0; 207 msg->message_size = sizeof(struct i2o_bsa_cache_flush_message) >> 2; 208 msg->target_address = psc->lct->local_tid; 209 msg->initiator_address = I2O_TID_HOST; 210 msg->function = I2O_BSA_CACHE_FLUSH; 211 msg->control_flags = 0x0; /* 0x80 = post progress reports */ 212 if (iop_queue_wait_msg(psc->iop, mfa, (struct i2o_basic_message *)msg)) 213 printf("pst: shutdown failed!\n"); 214 return 0; 215 } 216 217 static void 218 pststrategy(struct bio *bp) 219 { 220 struct pst_softc *psc = bp->bio_dev->si_drv1; 221 222 mtx_lock(&psc->mtx); 223 bioqdisksort(&psc->queue, bp); 224 pst_start(psc); 225 mtx_unlock(&psc->mtx); 226 } 227 228 static void 229 pst_start(struct pst_softc *psc) 230 { 231 struct pst_request *request; 232 struct bio *bp; 233 u_int32_t mfa; 234 235 if (psc->outstanding < (I2O_IOP_OUTBOUND_FRAME_COUNT - 1) && 236 (bp = bioq_first(&psc->queue))) { 237 if ((mfa = iop_get_mfa(psc->iop)) != 0xffffffff) { 238 if (!(request = malloc(sizeof(struct pst_request), 239 M_PSTRAID, M_NOWAIT | M_ZERO))) { 240 printf("pst: out of memory in start\n"); 241 iop_free_mfa(psc->iop, mfa); 242 return; 243 } 244 psc->outstanding++; 245 request->psc = psc; 246 request->mfa = mfa; 247 request->bp = bp; 248 if (dumping) 249 request->timeout_handle.callout = NULL; 250 else 251 request->timeout_handle = 252 timeout((timeout_t*)pst_timeout, request, 10 * hz); 253 bioq_remove(&psc->queue, bp); 254 devstat_start_transaction(&psc->stats); 255 if (pst_rw(request)) { 256 biofinish(request->bp, &psc->stats, EIO); 257 iop_free_mfa(request->psc->iop, request->mfa); 258 psc->outstanding--; 259 free(request, M_PSTRAID); 260 } 261 } 262 } 263 } 264 265 static void 266 pst_done(struct iop_softc *sc, u_int32_t mfa, struct i2o_single_reply *reply) 267 { 268 struct pst_request *request = 269 (struct pst_request *)reply->transaction_context; 270 struct pst_softc *psc = request->psc; 271 272 untimeout((timeout_t *)pst_timeout, request, request->timeout_handle); 273 request->bp->bio_resid = request->bp->bio_bcount - reply->donecount; 274 biofinish(request->bp, &psc->stats, reply->status ? EIO : 0); 275 free(request, M_PSTRAID); 276 mtx_lock(&psc->mtx); 277 psc->iop->reg->oqueue = mfa; 278 psc->outstanding--; 279 pst_start(psc); 280 mtx_unlock(&psc->mtx); 281 } 282 283 static void 284 pst_timeout(struct pst_request *request) 285 { 286 printf("pst: timeout mfa=0x%08x cmd=0x%02x\n", 287 request->mfa, request->bp->bio_cmd); 288 mtx_lock(&request->psc->mtx); 289 iop_free_mfa(request->psc->iop, request->mfa); 290 if ((request->mfa = iop_get_mfa(request->psc->iop)) == 0xffffffff) { 291 printf("pst: timeout no mfa possible\n"); 292 biofinish(request->bp, &request->psc->stats, EIO); 293 request->psc->outstanding--; 294 mtx_unlock(&request->psc->mtx); 295 return; 296 } 297 if (dumping) 298 request->timeout_handle.callout = NULL; 299 else 300 request->timeout_handle = 301 timeout((timeout_t*)pst_timeout, request, 10 * hz); 302 if (pst_rw(request)) { 303 iop_free_mfa(request->psc->iop, request->mfa); 304 biofinish(request->bp, &request->psc->stats, EIO); 305 request->psc->outstanding--; 306 } 307 mtx_unlock(&request->psc->mtx); 308 } 309 310 int 311 pst_rw(struct pst_request *request) 312 { 313 struct i2o_bsa_rw_block_message *msg; 314 int sgl_flag; 315 316 msg = (struct i2o_bsa_rw_block_message *) 317 (request->psc->iop->ibase + request->mfa); 318 bzero(msg, sizeof(struct i2o_bsa_rw_block_message)); 319 msg->version_offset = 0x81; 320 msg->message_flags = 0x0; 321 msg->message_size = sizeof(struct i2o_bsa_rw_block_message) >> 2; 322 msg->target_address = request->psc->lct->local_tid; 323 msg->initiator_address = I2O_TID_HOST; 324 switch (request->bp->bio_cmd) { 325 case BIO_READ: 326 msg->function = I2O_BSA_BLOCK_READ; 327 msg->control_flags = 0x0; /* 0x0c = read cache + readahead */ 328 msg->fetch_ahead = 0x0; /* 8 Kb */ 329 sgl_flag = 0; 330 break; 331 case BIO_WRITE: 332 msg->function = I2O_BSA_BLOCK_WRITE; 333 msg->control_flags = 0x0; /* 0x10 = write behind cache */ 334 msg->fetch_ahead = 0x0; 335 sgl_flag = I2O_SGL_DIR; 336 break; 337 default: 338 printf("pst: unknown command type\n"); 339 return -1; 340 } 341 msg->initiator_context = (u_int32_t)pst_done; 342 msg->transaction_context = (u_int32_t)request; 343 msg->time_multiplier = 1; 344 msg->bytecount = request->bp->bio_bcount; 345 msg->lba = ((u_int64_t)request->bp->bio_pblkno) * (DEV_BSIZE * 1LL); 346 if (!iop_create_sgl((struct i2o_basic_message *)msg, request->bp->bio_data, 347 request->bp->bio_bcount, sgl_flag)) 348 return -1; 349 request->psc->iop->reg->iqueue = request->mfa; 350 return 0; 351 } 352 353 static void 354 bpack(int8_t *src, int8_t *dst, int len) 355 { 356 int i, j, blank; 357 int8_t *ptr, *buf = dst; 358 359 for (i = j = blank = 0 ; i < len; i++) { 360 if (blank && src[i] == ' ') continue; 361 if (blank && src[i] != ' ') { 362 dst[j++] = src[i]; 363 blank = 0; 364 continue; 365 } 366 if (src[i] == ' ') { 367 blank = 1; 368 if (i == 0) 369 continue; 370 } 371 dst[j++] = src[i]; 372 } 373 if (j < len) 374 dst[j] = 0x00; 375 for (ptr = buf; ptr < buf+len; ++ptr) 376 if (!*ptr) 377 *ptr = ' '; 378 for (ptr = buf + len - 1; ptr >= buf && *ptr == ' '; --ptr) 379 *ptr = 0; 380 } 381 382 static device_method_t pst_methods[] = { 383 DEVMETHOD(device_probe, pst_probe), 384 DEVMETHOD(device_attach, pst_attach), 385 { 0, 0 } 386 }; 387 388 static driver_t pst_driver = { 389 "pst", 390 pst_methods, 391 sizeof(struct pst_softc), 392 }; 393 394 static devclass_t pst_devclass; 395 396 DRIVER_MODULE(pst, pstpci, pst_driver, pst_devclass, 0, 0); 397