1/*-
2 * Copyright (c) 1998,1999 S�ren Schmidt
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 * $Id: ata-all.c,v 1.4 1999/03/07 21:49:14 sos Exp $
29 */
30
31#include "ata.h"
32#if NATA > 0
33#include "isa.h"
34#include "pci.h"
35#include "atadisk.h"
36#include <sys/param.h>
37#include <sys/systm.h>
38#include <sys/kernel.h>
39#include <sys/interrupt.h>
40#include <sys/conf.h>
41#include <sys/buf.h>
42#include <sys/malloc.h>
43#include <sys/devicestat.h>
44#include <vm/vm.h>
45#include <vm/pmap.h>
46#include <machine/clock.h>
47#include <machine/smp.h>
48#include <pci/pcivar.h>
49#include <pci/pcireg.h>
50#include <i386/isa/icu.h>
51#include <i386/isa/isa.h>
52#include <i386/isa/isa_device.h>
53#include <dev/ata/ata-all.h>
54#include <dev/ata/ata-disk.h>
55#include <dev/ata/atapi-all.h>
56
57/* misc defines */
58#define UNIT(dev) (dev>>3 & 0x1f) /* assume 8 minor # per unit */
59#define MIN(a,b) ((a)>(b)?(b):(a))
60#if NSMP == 0
61#define isa_apic_irq(x) x
62#endif
63
64/* prototypes */
65#if NISA > 0
66static int32_t ata_isaprobe(struct isa_device *);
67static int32_t ata_isaattach(struct isa_device *);
68#endif
69#if NPCI > 0
70static const char *ata_pciprobe(pcici_t, pcidi_t);
71static void ata_pciattach(pcici_t, int32_t);
72static void promise_intr(int32_t);
73#endif
74static int32_t ata_probe(int32_t, int32_t, int32_t, pcici_t, int32_t *);
75static void ataintr(int32_t);
76
77static int32_t atanlun = 0, sysctrl = 0;
78struct ata_softc *atadevices[MAXATA];
79struct isa_driver atadriver = { ata_isaprobe, ata_isaattach, "ata" };
80
81#if NISA > 0
82static int32_t
83ata_isaprobe(struct isa_device *devp)
84{
85 int32_t ctlr, res;
86
87 for (ctlr = 0; ctlr < atanlun; ctlr++) {
88 if (atadevices[ctlr]->ioaddr == devp->id_iobase) {
89 printf("ata-isa%d: already registered as ata%d\n",
90 devp->id_unit, ctlr);
91 return 0;
92 }
93 }
94 res = ata_probe(devp->id_iobase, devp->id_iobase + ATA_ALTPORT, 0, 0,
95 &devp->id_unit);
96 if (res)
97 devp->id_intr = (inthand2_t *)ataintr;
98 return res;
99}
100
101static int32_t
102ata_isaattach(struct isa_device *devp)
103{
104 return 1;
105}
106#endif
107
108#if NPCI > 0
109static u_long ata_pcicount;
110static struct pci_device ata_pcidevice = {
111 "ata-pci", ata_pciprobe, ata_pciattach, &ata_pcicount, 0
112};
113
114DATA_SET(pcidevice_set, ata_pcidevice);
115
116static const char *
117ata_pciprobe(pcici_t tag, pcidi_t type)
118{
119 u_int32_t data;
120
121 data = pci_conf_read(tag, PCI_CLASS_REG);
122 if ((data & PCI_CLASS_MASK) == PCI_CLASS_MASS_STORAGE &&
123 ((data & PCI_SUBCLASS_MASK) == 0x00010000 ||
124 ((data & PCI_SUBCLASS_MASK) == 0x00040000))) {
125 switch (type) {
126 case 0x12308086:
127 return "Intel PIIX IDE controller";
128 case 0x70108086:
129 return "Intel PIIX3 IDE controller";
130 case 0x71118086:
131 return "Intel PIIX4 IDE controller";
132 case 0x4d33105a:
133 return "Promise Ultra/33 IDE controller";
134 case 0x522910b9:
135 return "AcerLabs Aladdin IDE controller";
136#if 0
137 case 0x05711106:
138 return "VIA Apollo IDE controller";
139 case 0x01021078:
140 return "Cyrix 5530 IDE controller";
141#endif
142 default:
143 return "Unknown PCI IDE controller";
144 }
145 }
146 return NULL;
147}
148
149static void
150ata_pciattach(pcici_t tag, int32_t unit)
151{
152 pcidi_t type, class, cmd;
153 int32_t iobase_1, iobase_2, altiobase_1, altiobase_2;
154 int32_t bmaddr_1 = 0, bmaddr_2 = 0, irq1, irq2;
155 int32_t lun;
156
157 /* set up vendor-specific stuff */
158 type = pci_conf_read(tag, PCI_ID_REG);
159 class = pci_conf_read(tag, PCI_CLASS_REG);
160 cmd = pci_conf_read(tag, PCI_COMMAND_STATUS_REG);
161
162#ifdef ATA_DEBUG
163 printf("ata%d: type=%08x class=%08x cmd=%08x\n", unit, type, class, cmd);
164#endif
165
166 /* if this is at Promise controller handle it specially */
167 if (type == 0x4d33105a) {
168 iobase_1 = pci_conf_read(tag, 0x10) & 0xfffc;
169 altiobase_1 = pci_conf_read(tag, 0x14) & 0xfffc;
170 iobase_2 = pci_conf_read(tag, 0x18) & 0xfffc;
171 altiobase_2 = pci_conf_read(tag, 0x1c) & 0xfffc;
172 irq1 = irq2 = pci_conf_read(tag, PCI_INTERRUPT_REG) & 0xff;
173 bmaddr_1 = pci_conf_read(tag, 0x20) & 0xfffc;
174 bmaddr_2 = bmaddr_1 + ATA_BM_OFFSET1;
175 sysctrl = (pci_conf_read(tag, 0x20) & 0xfffc) + 0x1c;
176 printf("ata-pci%d: Busmastering DMA supported\n", unit);
177 }
178 /* everybody else seems to do it this way */
179 else {
180 if ((class & 0x100) == 0) {
181 iobase_1 = IO_WD1;
182 altiobase_1 = iobase_1 + ATA_ALTPORT;
183 irq1 = 14;
184 }
185 else {
186 iobase_1 = pci_conf_read(tag, 0x10) & 0xfffc;
187 altiobase_1 = pci_conf_read(tag, 0x14) & 0xfffc;
188 irq1 = pci_conf_read(tag, PCI_INTERRUPT_REG) & 0xff;
189 }
190 if ((class & 0x400) == 0) {
191 iobase_2 = IO_WD2;
192 altiobase_2 = iobase_2 + ATA_ALTPORT;
193 irq2 = 15;
194 }
195 else {
196 iobase_2 = pci_conf_read(tag, 0x18) & 0xfffc;
197 altiobase_2 = pci_conf_read(tag, 0x1c) & 0xfffc;
198 irq2 = pci_conf_read(tag, PCI_INTERRUPT_REG) & 0xff;
199 }
200
201 /* is this controller busmaster capable ? */
202 if (pci_conf_read(tag, PCI_CLASS_REG) & 0x8000) {
203 /* is busmastering support turned on ? */
204 if ((pci_conf_read(tag, PCI_COMMAND_STATUS_REG) & 5) == 5) {
205 /* is there a valid port range to connect to ? */
206 if ((bmaddr_1 = pci_conf_read(tag, 0x20) & 0xfffc)) {
207 bmaddr_2 = bmaddr_1 + ATA_BM_OFFSET1;
208 printf("ata-pci%d: Busmastering DMA supported\n", unit);
209 }
210 else
211 printf("ata-pci%d: Busmastering DMA not configured\n",unit);
212 }
213 else
214 printf("ata-pci%d: Busmastering DMA not enabled\n", unit);
215 }
216 else
217 printf("ata-pci%d: Busmastering DMA not supported\n", unit);
218 }
219
220 /* now probe the addresse found for "real" ATA/ATAPI hardware */
221 lun = 0;
222 if (ata_probe(iobase_1, altiobase_1, bmaddr_1, tag, &lun)) {
223 if (iobase_1 == IO_WD1)
224 register_intr(irq1, (int)"", 0, (inthand2_t *)ataintr,
225 &bio_imask, lun);
226 else {
227 if (sysctrl)
228 pci_map_int(tag, (inthand2_t *)promise_intr,
229 (void *)lun, &bio_imask);
230 else
231 pci_map_int(tag, (inthand2_t *)ataintr, (void *)lun,&bio_imask);
232 }
233 printf("ata%d at 0x%04x irq %d on ata-pci%d\n",
234 lun, iobase_1, isa_apic_irq(irq1), unit);
235 }
236 lun = 1;
237 if (ata_probe(iobase_2, altiobase_2, bmaddr_2, tag, &lun)) {
238 if (iobase_2 == IO_WD2)
239 register_intr(irq2, (int)"", 0, (inthand2_t *)ataintr,
240 &bio_imask, lun);
241 else {
242 if (!sysctrl)
243 pci_map_int(tag, (inthand2_t *)ataintr, (void *)lun,&bio_imask);
244 }
245 printf("ata%d at 0x%04x irq %d on ata-pci%d\n",
246 lun, iobase_2, isa_apic_irq(irq2), unit);
247 }
248}
249
250static void
251promise_intr(int32_t unit)
252{
253 if (inl(sysctrl) & 0x00000400)
254 ataintr(unit);
255 if (inl(sysctrl) & 0x00004000)
256 ataintr(unit+1);
257}
258#endif
259
260static int32_t
261ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t bmaddr,
262 pcici_t tag, int32_t *unit)
263{
264 struct ata_softc *scp = atadevices[atanlun];
265 int32_t mask = 0;
266 int32_t timeout;
267 int32_t lun = atanlun;
268 u_int8_t status0, status1;
269
270#ifdef ATA_STATIC_ID
271 atanlun++;
272#endif
273 if (lun > MAXATA) {
274 printf("ata: unit out of range(%d)\n", lun);
275 return 0;
276 }
277 if (scp) {
278 printf("ata%d: unit already attached\n", lun);
279 return 0;
280 }
281 scp = malloc(sizeof(struct ata_softc), M_DEVBUF, M_NOWAIT);
282 if (scp == NULL) {
283 printf("ata%d: failed to allocate driver storage\n", lun);
284 return 0;
285 }
286 bzero(scp, sizeof(struct ata_softc));
287
288 scp->unit = *unit;
289 scp->lun = lun;
290 scp->ioaddr = ioaddr;
291 scp->altioaddr = altioaddr;
292 scp->active = ATA_IDLE;
293
294#ifdef ATA_DEBUG
295 printf("ata%d: iobase=0x%04x altiobase=0x%04x\n",
296 scp->lun, scp->ioaddr, scp->altioaddr);
297#endif
298
299 /* do we have any signs of ATA/ATAPI HW being present ? */
300 outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
301 DELAY(1);
302 status0 = inb(scp->ioaddr + ATA_STATUS);
303 outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_SLAVE);
304 DELAY(1);
305 status1 = inb(scp->ioaddr + ATA_STATUS);
306 if ((status0 & 0xf8) != 0xf8)
307 mask |= 0x01;
308 if ((status1 & 0xf8) != 0xf8)
309 mask |= 0x02;
310#ifdef ATA_DEBUG
311 printf("ata%d: mask=%02x status0=%02x status1=%02x\n",
312 scp->lun, mask, status0, status1);
313#endif
314 if (!mask) {
315 free(scp, M_DEVBUF);
316 return 0;
317 }
318 /* assert reset for devices and wait for completition */
319 outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
320 DELAY(1);
321 outb(scp->altioaddr, ATA_A_IDS | ATA_A_RESET);
322 DELAY(1000);
323 outb(scp->altioaddr, ATA_A_IDS);
324 DELAY(1000);
325 inb(scp->ioaddr + ATA_ERROR);
326 DELAY(1);
327 outb(scp->altioaddr, ATA_A_4BIT);
328 DELAY(1);
329
330 /* wait for BUSY to go inactive */
331 for (timeout = 0; timeout < 30000*10; timeout++) {
332 outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
333 DELAY(1);
334 status0 = inb(scp->ioaddr + ATA_STATUS);
335 outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_SLAVE);
336 DELAY(1);
337 status1 = inb(scp->ioaddr + ATA_STATUS);
338 if (mask == 0x01) /* wait for master only */
339 if (!(status0 & ATA_S_BSY))
340 break;
341 if (mask == 0x02) /* wait for slave only */
342 if (!(status1 & ATA_S_BSY))
343 break;
344 if (mask == 0x03) /* wait for both master & slave */
345 if (!(status0 & ATA_S_BSY) && !(status1 & ATA_S_BSY))
346 break;
347 DELAY(100);
348 }
349 if (status0 & ATA_S_BSY)
350 mask &= ~0x01;
351 if (status1 & ATA_S_BSY)
352 mask &= ~0x02;
353#ifdef ATA_DEBUG
354 printf("ata%d: mask=%02x status0=%02x status1=%02x\n",
355 scp->lun, mask, status0, status1);
356#endif
357 if (!mask) {
358 free(scp, M_DEVBUF);
359 return 0;
360 }
361 /*
362 * OK, we have at least one device on the chain,
363 * check for ATAPI signatures, if none check if its
364 * a good old ATA device.
365 */
366
367 outb(scp->ioaddr + ATA_DRIVE, (ATA_D_IBM | ATA_MASTER));
368 DELAY(1);
369 if (inb(scp->ioaddr + ATA_CYL_LSB) == ATAPI_MAGIC_LSB &&
370 inb(scp->ioaddr + ATA_CYL_MSB) == ATAPI_MAGIC_MSB) {
371 scp->devices |= ATA_ATAPI_MASTER;
372 }
373 outb(scp->ioaddr + ATA_DRIVE, (ATA_D_IBM | ATA_SLAVE));
374 DELAY(1);
375 if (inb(scp->ioaddr + ATA_CYL_LSB) == ATAPI_MAGIC_LSB &&
376 inb(scp->ioaddr + ATA_CYL_MSB) == ATAPI_MAGIC_MSB) {
377 scp->devices |= ATA_ATAPI_SLAVE;
378 }
379 if (status0 != 0x00 && !(scp->devices & ATA_ATAPI_MASTER)) {
380 outb(scp->ioaddr + ATA_DRIVE, (ATA_D_IBM | ATA_MASTER));
381 DELAY(1);
382 outb(scp->ioaddr + ATA_ERROR, 0x58);
383 outb(scp->ioaddr + ATA_CYL_LSB, 0xa5);
384 if (inb(scp->ioaddr + ATA_ERROR) != 0x58 &&
385 inb(scp->ioaddr + ATA_CYL_LSB) == 0xa5) {
386 scp->devices |= ATA_ATA_MASTER;
387 }
388 }
389 if (status1 != 0x00 && !(scp->devices & ATA_ATAPI_SLAVE)) {
390 outb(scp->ioaddr + ATA_DRIVE, (ATA_D_IBM | ATA_SLAVE));
391 DELAY(1);
392 outb(scp->ioaddr + ATA_ERROR, 0x58);
393 outb(scp->ioaddr + ATA_CYL_LSB, 0xa5);
394 if (inb(scp->ioaddr + ATA_ERROR) != 0x58 &&
395 inb(scp->ioaddr + ATA_CYL_LSB) == 0xa5) {
396 scp->devices |= ATA_ATA_SLAVE;
397 }
398 }
399#ifdef ATA_DEBUG
400 printf("ata%d: devices = 0x%x\n", scp->lun, scp->devices);
401#endif
402 if (!scp->devices) {
403 free(scp, M_DEVBUF);
404 return 0;
405 }
406 bufq_init(&scp->ata_queue);
407 TAILQ_INIT(&scp->atapi_queue);
408 *unit = scp->lun;
409 scp->tag = tag;
410 if (bmaddr)
411 scp->bmaddr = bmaddr;
412 atadevices[scp->lun] = scp;
413#ifndef ATA_STATIC_ID
414 atanlun++;
415#endif
416 return ATA_IOSIZE;
417}
418
419static void
420ataintr(int32_t unit)
421{
422 struct ata_softc *scp;
423 struct atapi_request *atapi_request;
424 struct buf *ata_request;
425 static int32_t intcount = 0;
426
427 if (unit < 0 || unit > atanlun) {
428 printf("ataintr: unit %d unusable\n", unit);
429 return;
430 }
431
432 scp = atadevices[unit];
433
434 /* find & call the responsible driver to process this interrupt */
435 switch (scp->active) {
436#if NATADISK > 0
437 case ATA_ACTIVE_ATA:
438 if ((ata_request = bufq_first(&scp->ata_queue)))
439 if (ad_interrupt(ata_request) == ATA_OP_CONTINUES)
440 return;
441 break;
442#endif
443 case ATA_ACTIVE_ATAPI:
444 if ((atapi_request = TAILQ_FIRST(&scp->atapi_queue)))
445 if (atapi_interrupt(atapi_request) == ATA_OP_CONTINUES)
446 return;
447 break;
448
449 case ATA_WAIT_INTR:
450 wakeup((caddr_t)scp);
451 break;
452
453 case ATA_IGNORE_INTR:
454 break;
455
456 default:
457 case ATA_IDLE:
458 if (intcount++ < 10)
459 printf("ata%d: unwanted interrupt %d\n", unit, intcount);
460 inb(scp->ioaddr + ATA_STATUS);
461 return;
462 }
463 scp->active = ATA_IDLE;
464 ata_start(scp);
465}
466
467void
468ata_start(struct ata_softc *scp)
469{
470 struct buf *ata_request;
471 struct atapi_request *atapi_request;
472
473#ifdef ATA_DEBUG
474 printf("ata_start: entered\n");
475#endif
476 if (scp->active != ATA_IDLE) {
477 printf("ata: unwanted ata_start\n");
478 return;
479 }
480
481#if NATADISK > 0
482 /* find & call the responsible driver if anything on ATA queue */
483 if ((ata_request = bufq_first(&scp->ata_queue))) {
484 scp->active = ATA_ACTIVE_ATA;
485 ad_transfer(ata_request);
486#ifdef ATA_DEBUG
487 printf("ata_start: started ata, leaving\n");
488#endif
489 return;
490 }
491#endif
492
493 /* find & call the responsible driver if anything on ATAPI queue */
494 if ((atapi_request = TAILQ_FIRST(&scp->atapi_queue))) {
495 scp->active = ATA_ACTIVE_ATAPI;
496 atapi_transfer(atapi_request);
497#ifdef ATA_DEBUG
498 printf("ata_start: started atapi, leaving\n");
499#endif
500 return;
501 }
502}
503
504int32_t
505ata_wait(struct ata_softc *scp, int32_t device, u_int8_t mask)
506{
507 u_int8_t status;
508 u_int32_t timeout = 0;
509
510 while (timeout++ <= 500000) { /* timeout 5 secs */
511 status = inb(scp->ioaddr + ATA_STATUS);
512
513 /* if drive fails status, reselect the drive just to be sure */
514 if (status == 0xff) {
515 printf("ata%d: %s: no status, reselecting device\n",
516 scp->lun, device?"slave":"master");
517 outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | device);
518 DELAY(1);
519 status = inb(scp->ioaddr + ATA_STATUS);
520 }
521 if (status == 0xff)
522 return -1;
523 scp->status = status;
524 if (!(status & ATA_S_BSY)) {
525 if (status & ATA_S_ERROR)
526 scp->error = inb(scp->ioaddr + ATA_ERROR);
527 if ((status & mask) == mask)
528 return (status & ATA_S_ERROR);
529 }
530 if (timeout > 1000)
531 DELAY(1000);
532 else
533 DELAY(10);
534 }
535 return -1;
536}
537
538int32_t
539ata_command(struct ata_softc *scp, int32_t device, u_int32_t command,
540 u_int32_t cylinder, u_int32_t head, u_int32_t sector,
541 u_int32_t count, u_int32_t feature, int32_t flags)
542{
543#ifdef ATA_DEBUG
544printf("ata_command: addr=%04x, device=%02x, cmd=%02x, c=%d, h=%d, s=%d, count=%d, flags=%02x\n", scp->ioaddr, device, command, cylinder, head, sector, count, flags);
545#endif
546
547 /* ready to issue command ? */
548 if (ata_wait(scp, device, 0) < 0) {
549 printf("ata%d: %s: timeout waiting to give command s=%02x e=%02x\n",
550 scp->lun, device?"slave":"master", scp->status, scp->error);
551 }
552 outb(scp->ioaddr + ATA_FEATURE, feature);
553 outb(scp->ioaddr + ATA_CYL_LSB, cylinder);
554 outb(scp->ioaddr + ATA_CYL_MSB, cylinder >> 8);
555 outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | device | head);
556 outb(scp->ioaddr + ATA_SECTOR, sector);
557 outb(scp->ioaddr + ATA_COUNT, count);
558
559 if (scp->active != ATA_IDLE && flags != ATA_IMMEDIATE)
560 printf("DANGER active=%d\n", scp->active);
561
562 switch (flags) {
563 case ATA_WAIT_INTR:
564 scp->active = ATA_WAIT_INTR;
565 outb(scp->ioaddr + ATA_CMD, command);
566 if (tsleep((caddr_t)scp, PRIBIO, "atacmd", 500)) {
567 printf("ata_command: timeout waiting for interrupt");
568 scp->active = ATA_IDLE;
569 return -1;
570 }
571 break;
572
573 case ATA_IGNORE_INTR:
574 scp->active = ATA_IGNORE_INTR;
575 outb(scp->ioaddr + ATA_CMD, command);
576 break;
577
578 case ATA_IMMEDIATE:
579 default:
580 outb(scp->ioaddr + ATA_CMD, command);
581 break;
582 }
583#ifdef ATA_DEBUG
584printf("ata_command: leaving\n");
585#endif
586 return 0;
587}
588
589void
590bswap(int8_t *buf, int32_t len)
591{
592 u_int16_t *p = (u_int16_t*)(buf + len);
593
594 while (--p >= (u_int16_t*)buf)
595 *p = ntohs(*p);
596}
597
598void
599btrim(int8_t *buf, int32_t len)
600{
601 int8_t *p;
602
603 for (p = buf; p < buf+len; ++p)
604 if (!*p)
605 *p = ' ';
606 for (p = buf + len - 1; p >= buf && *p == ' '; --p)
607 *p = 0;
608}
609
610void
611bpack(int8_t *src, int8_t *dst, int32_t len)
612{
613 int32_t i, j, blank;
614
615 for (i = j = blank = 0 ; i < len-1; i++) {
616 if (blank && src[i] == ' ') continue;
617 if (blank && src[i] != ' ') {
618 dst[j++] = src[i];
619 blank = 0;
620 continue;
621 }
622 if (src[i] == ' ')
623 blank = 1;
624 dst[j++] = src[i];
625 }
626 dst[j] = 0x00;
627}
628#endif /* NATA > 0 */
2 * Copyright (c) 1998,1999 S�ren Schmidt
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 * $Id: ata-all.c,v 1.4 1999/03/07 21:49:14 sos Exp $
29 */
30
31#include "ata.h"
32#if NATA > 0
33#include "isa.h"
34#include "pci.h"
35#include "atadisk.h"
36#include <sys/param.h>
37#include <sys/systm.h>
38#include <sys/kernel.h>
39#include <sys/interrupt.h>
40#include <sys/conf.h>
41#include <sys/buf.h>
42#include <sys/malloc.h>
43#include <sys/devicestat.h>
44#include <vm/vm.h>
45#include <vm/pmap.h>
46#include <machine/clock.h>
47#include <machine/smp.h>
48#include <pci/pcivar.h>
49#include <pci/pcireg.h>
50#include <i386/isa/icu.h>
51#include <i386/isa/isa.h>
52#include <i386/isa/isa_device.h>
53#include <dev/ata/ata-all.h>
54#include <dev/ata/ata-disk.h>
55#include <dev/ata/atapi-all.h>
56
57/* misc defines */
58#define UNIT(dev) (dev>>3 & 0x1f) /* assume 8 minor # per unit */
59#define MIN(a,b) ((a)>(b)?(b):(a))
60#if NSMP == 0
61#define isa_apic_irq(x) x
62#endif
63
64/* prototypes */
65#if NISA > 0
66static int32_t ata_isaprobe(struct isa_device *);
67static int32_t ata_isaattach(struct isa_device *);
68#endif
69#if NPCI > 0
70static const char *ata_pciprobe(pcici_t, pcidi_t);
71static void ata_pciattach(pcici_t, int32_t);
72static void promise_intr(int32_t);
73#endif
74static int32_t ata_probe(int32_t, int32_t, int32_t, pcici_t, int32_t *);
75static void ataintr(int32_t);
76
77static int32_t atanlun = 0, sysctrl = 0;
78struct ata_softc *atadevices[MAXATA];
79struct isa_driver atadriver = { ata_isaprobe, ata_isaattach, "ata" };
80
81#if NISA > 0
82static int32_t
83ata_isaprobe(struct isa_device *devp)
84{
85 int32_t ctlr, res;
86
87 for (ctlr = 0; ctlr < atanlun; ctlr++) {
88 if (atadevices[ctlr]->ioaddr == devp->id_iobase) {
89 printf("ata-isa%d: already registered as ata%d\n",
90 devp->id_unit, ctlr);
91 return 0;
92 }
93 }
94 res = ata_probe(devp->id_iobase, devp->id_iobase + ATA_ALTPORT, 0, 0,
95 &devp->id_unit);
96 if (res)
97 devp->id_intr = (inthand2_t *)ataintr;
98 return res;
99}
100
101static int32_t
102ata_isaattach(struct isa_device *devp)
103{
104 return 1;
105}
106#endif
107
108#if NPCI > 0
109static u_long ata_pcicount;
110static struct pci_device ata_pcidevice = {
111 "ata-pci", ata_pciprobe, ata_pciattach, &ata_pcicount, 0
112};
113
114DATA_SET(pcidevice_set, ata_pcidevice);
115
116static const char *
117ata_pciprobe(pcici_t tag, pcidi_t type)
118{
119 u_int32_t data;
120
121 data = pci_conf_read(tag, PCI_CLASS_REG);
122 if ((data & PCI_CLASS_MASK) == PCI_CLASS_MASS_STORAGE &&
123 ((data & PCI_SUBCLASS_MASK) == 0x00010000 ||
124 ((data & PCI_SUBCLASS_MASK) == 0x00040000))) {
125 switch (type) {
126 case 0x12308086:
127 return "Intel PIIX IDE controller";
128 case 0x70108086:
129 return "Intel PIIX3 IDE controller";
130 case 0x71118086:
131 return "Intel PIIX4 IDE controller";
132 case 0x4d33105a:
133 return "Promise Ultra/33 IDE controller";
134 case 0x522910b9:
135 return "AcerLabs Aladdin IDE controller";
136#if 0
137 case 0x05711106:
138 return "VIA Apollo IDE controller";
139 case 0x01021078:
140 return "Cyrix 5530 IDE controller";
141#endif
142 default:
143 return "Unknown PCI IDE controller";
144 }
145 }
146 return NULL;
147}
148
149static void
150ata_pciattach(pcici_t tag, int32_t unit)
151{
152 pcidi_t type, class, cmd;
153 int32_t iobase_1, iobase_2, altiobase_1, altiobase_2;
154 int32_t bmaddr_1 = 0, bmaddr_2 = 0, irq1, irq2;
155 int32_t lun;
156
157 /* set up vendor-specific stuff */
158 type = pci_conf_read(tag, PCI_ID_REG);
159 class = pci_conf_read(tag, PCI_CLASS_REG);
160 cmd = pci_conf_read(tag, PCI_COMMAND_STATUS_REG);
161
162#ifdef ATA_DEBUG
163 printf("ata%d: type=%08x class=%08x cmd=%08x\n", unit, type, class, cmd);
164#endif
165
166 /* if this is at Promise controller handle it specially */
167 if (type == 0x4d33105a) {
168 iobase_1 = pci_conf_read(tag, 0x10) & 0xfffc;
169 altiobase_1 = pci_conf_read(tag, 0x14) & 0xfffc;
170 iobase_2 = pci_conf_read(tag, 0x18) & 0xfffc;
171 altiobase_2 = pci_conf_read(tag, 0x1c) & 0xfffc;
172 irq1 = irq2 = pci_conf_read(tag, PCI_INTERRUPT_REG) & 0xff;
173 bmaddr_1 = pci_conf_read(tag, 0x20) & 0xfffc;
174 bmaddr_2 = bmaddr_1 + ATA_BM_OFFSET1;
175 sysctrl = (pci_conf_read(tag, 0x20) & 0xfffc) + 0x1c;
176 printf("ata-pci%d: Busmastering DMA supported\n", unit);
177 }
178 /* everybody else seems to do it this way */
179 else {
180 if ((class & 0x100) == 0) {
181 iobase_1 = IO_WD1;
182 altiobase_1 = iobase_1 + ATA_ALTPORT;
183 irq1 = 14;
184 }
185 else {
186 iobase_1 = pci_conf_read(tag, 0x10) & 0xfffc;
187 altiobase_1 = pci_conf_read(tag, 0x14) & 0xfffc;
188 irq1 = pci_conf_read(tag, PCI_INTERRUPT_REG) & 0xff;
189 }
190 if ((class & 0x400) == 0) {
191 iobase_2 = IO_WD2;
192 altiobase_2 = iobase_2 + ATA_ALTPORT;
193 irq2 = 15;
194 }
195 else {
196 iobase_2 = pci_conf_read(tag, 0x18) & 0xfffc;
197 altiobase_2 = pci_conf_read(tag, 0x1c) & 0xfffc;
198 irq2 = pci_conf_read(tag, PCI_INTERRUPT_REG) & 0xff;
199 }
200
201 /* is this controller busmaster capable ? */
202 if (pci_conf_read(tag, PCI_CLASS_REG) & 0x8000) {
203 /* is busmastering support turned on ? */
204 if ((pci_conf_read(tag, PCI_COMMAND_STATUS_REG) & 5) == 5) {
205 /* is there a valid port range to connect to ? */
206 if ((bmaddr_1 = pci_conf_read(tag, 0x20) & 0xfffc)) {
207 bmaddr_2 = bmaddr_1 + ATA_BM_OFFSET1;
208 printf("ata-pci%d: Busmastering DMA supported\n", unit);
209 }
210 else
211 printf("ata-pci%d: Busmastering DMA not configured\n",unit);
212 }
213 else
214 printf("ata-pci%d: Busmastering DMA not enabled\n", unit);
215 }
216 else
217 printf("ata-pci%d: Busmastering DMA not supported\n", unit);
218 }
219
220 /* now probe the addresse found for "real" ATA/ATAPI hardware */
221 lun = 0;
222 if (ata_probe(iobase_1, altiobase_1, bmaddr_1, tag, &lun)) {
223 if (iobase_1 == IO_WD1)
224 register_intr(irq1, (int)"", 0, (inthand2_t *)ataintr,
225 &bio_imask, lun);
226 else {
227 if (sysctrl)
228 pci_map_int(tag, (inthand2_t *)promise_intr,
229 (void *)lun, &bio_imask);
230 else
231 pci_map_int(tag, (inthand2_t *)ataintr, (void *)lun,&bio_imask);
232 }
233 printf("ata%d at 0x%04x irq %d on ata-pci%d\n",
234 lun, iobase_1, isa_apic_irq(irq1), unit);
235 }
236 lun = 1;
237 if (ata_probe(iobase_2, altiobase_2, bmaddr_2, tag, &lun)) {
238 if (iobase_2 == IO_WD2)
239 register_intr(irq2, (int)"", 0, (inthand2_t *)ataintr,
240 &bio_imask, lun);
241 else {
242 if (!sysctrl)
243 pci_map_int(tag, (inthand2_t *)ataintr, (void *)lun,&bio_imask);
244 }
245 printf("ata%d at 0x%04x irq %d on ata-pci%d\n",
246 lun, iobase_2, isa_apic_irq(irq2), unit);
247 }
248}
249
250static void
251promise_intr(int32_t unit)
252{
253 if (inl(sysctrl) & 0x00000400)
254 ataintr(unit);
255 if (inl(sysctrl) & 0x00004000)
256 ataintr(unit+1);
257}
258#endif
259
260static int32_t
261ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t bmaddr,
262 pcici_t tag, int32_t *unit)
263{
264 struct ata_softc *scp = atadevices[atanlun];
265 int32_t mask = 0;
266 int32_t timeout;
267 int32_t lun = atanlun;
268 u_int8_t status0, status1;
269
270#ifdef ATA_STATIC_ID
271 atanlun++;
272#endif
273 if (lun > MAXATA) {
274 printf("ata: unit out of range(%d)\n", lun);
275 return 0;
276 }
277 if (scp) {
278 printf("ata%d: unit already attached\n", lun);
279 return 0;
280 }
281 scp = malloc(sizeof(struct ata_softc), M_DEVBUF, M_NOWAIT);
282 if (scp == NULL) {
283 printf("ata%d: failed to allocate driver storage\n", lun);
284 return 0;
285 }
286 bzero(scp, sizeof(struct ata_softc));
287
288 scp->unit = *unit;
289 scp->lun = lun;
290 scp->ioaddr = ioaddr;
291 scp->altioaddr = altioaddr;
292 scp->active = ATA_IDLE;
293
294#ifdef ATA_DEBUG
295 printf("ata%d: iobase=0x%04x altiobase=0x%04x\n",
296 scp->lun, scp->ioaddr, scp->altioaddr);
297#endif
298
299 /* do we have any signs of ATA/ATAPI HW being present ? */
300 outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
301 DELAY(1);
302 status0 = inb(scp->ioaddr + ATA_STATUS);
303 outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_SLAVE);
304 DELAY(1);
305 status1 = inb(scp->ioaddr + ATA_STATUS);
306 if ((status0 & 0xf8) != 0xf8)
307 mask |= 0x01;
308 if ((status1 & 0xf8) != 0xf8)
309 mask |= 0x02;
310#ifdef ATA_DEBUG
311 printf("ata%d: mask=%02x status0=%02x status1=%02x\n",
312 scp->lun, mask, status0, status1);
313#endif
314 if (!mask) {
315 free(scp, M_DEVBUF);
316 return 0;
317 }
318 /* assert reset for devices and wait for completition */
319 outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
320 DELAY(1);
321 outb(scp->altioaddr, ATA_A_IDS | ATA_A_RESET);
322 DELAY(1000);
323 outb(scp->altioaddr, ATA_A_IDS);
324 DELAY(1000);
325 inb(scp->ioaddr + ATA_ERROR);
326 DELAY(1);
327 outb(scp->altioaddr, ATA_A_4BIT);
328 DELAY(1);
329
330 /* wait for BUSY to go inactive */
331 for (timeout = 0; timeout < 30000*10; timeout++) {
332 outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
333 DELAY(1);
334 status0 = inb(scp->ioaddr + ATA_STATUS);
335 outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_SLAVE);
336 DELAY(1);
337 status1 = inb(scp->ioaddr + ATA_STATUS);
338 if (mask == 0x01) /* wait for master only */
339 if (!(status0 & ATA_S_BSY))
340 break;
341 if (mask == 0x02) /* wait for slave only */
342 if (!(status1 & ATA_S_BSY))
343 break;
344 if (mask == 0x03) /* wait for both master & slave */
345 if (!(status0 & ATA_S_BSY) && !(status1 & ATA_S_BSY))
346 break;
347 DELAY(100);
348 }
349 if (status0 & ATA_S_BSY)
350 mask &= ~0x01;
351 if (status1 & ATA_S_BSY)
352 mask &= ~0x02;
353#ifdef ATA_DEBUG
354 printf("ata%d: mask=%02x status0=%02x status1=%02x\n",
355 scp->lun, mask, status0, status1);
356#endif
357 if (!mask) {
358 free(scp, M_DEVBUF);
359 return 0;
360 }
361 /*
362 * OK, we have at least one device on the chain,
363 * check for ATAPI signatures, if none check if its
364 * a good old ATA device.
365 */
366
367 outb(scp->ioaddr + ATA_DRIVE, (ATA_D_IBM | ATA_MASTER));
368 DELAY(1);
369 if (inb(scp->ioaddr + ATA_CYL_LSB) == ATAPI_MAGIC_LSB &&
370 inb(scp->ioaddr + ATA_CYL_MSB) == ATAPI_MAGIC_MSB) {
371 scp->devices |= ATA_ATAPI_MASTER;
372 }
373 outb(scp->ioaddr + ATA_DRIVE, (ATA_D_IBM | ATA_SLAVE));
374 DELAY(1);
375 if (inb(scp->ioaddr + ATA_CYL_LSB) == ATAPI_MAGIC_LSB &&
376 inb(scp->ioaddr + ATA_CYL_MSB) == ATAPI_MAGIC_MSB) {
377 scp->devices |= ATA_ATAPI_SLAVE;
378 }
379 if (status0 != 0x00 && !(scp->devices & ATA_ATAPI_MASTER)) {
380 outb(scp->ioaddr + ATA_DRIVE, (ATA_D_IBM | ATA_MASTER));
381 DELAY(1);
382 outb(scp->ioaddr + ATA_ERROR, 0x58);
383 outb(scp->ioaddr + ATA_CYL_LSB, 0xa5);
384 if (inb(scp->ioaddr + ATA_ERROR) != 0x58 &&
385 inb(scp->ioaddr + ATA_CYL_LSB) == 0xa5) {
386 scp->devices |= ATA_ATA_MASTER;
387 }
388 }
389 if (status1 != 0x00 && !(scp->devices & ATA_ATAPI_SLAVE)) {
390 outb(scp->ioaddr + ATA_DRIVE, (ATA_D_IBM | ATA_SLAVE));
391 DELAY(1);
392 outb(scp->ioaddr + ATA_ERROR, 0x58);
393 outb(scp->ioaddr + ATA_CYL_LSB, 0xa5);
394 if (inb(scp->ioaddr + ATA_ERROR) != 0x58 &&
395 inb(scp->ioaddr + ATA_CYL_LSB) == 0xa5) {
396 scp->devices |= ATA_ATA_SLAVE;
397 }
398 }
399#ifdef ATA_DEBUG
400 printf("ata%d: devices = 0x%x\n", scp->lun, scp->devices);
401#endif
402 if (!scp->devices) {
403 free(scp, M_DEVBUF);
404 return 0;
405 }
406 bufq_init(&scp->ata_queue);
407 TAILQ_INIT(&scp->atapi_queue);
408 *unit = scp->lun;
409 scp->tag = tag;
410 if (bmaddr)
411 scp->bmaddr = bmaddr;
412 atadevices[scp->lun] = scp;
413#ifndef ATA_STATIC_ID
414 atanlun++;
415#endif
416 return ATA_IOSIZE;
417}
418
419static void
420ataintr(int32_t unit)
421{
422 struct ata_softc *scp;
423 struct atapi_request *atapi_request;
424 struct buf *ata_request;
425 static int32_t intcount = 0;
426
427 if (unit < 0 || unit > atanlun) {
428 printf("ataintr: unit %d unusable\n", unit);
429 return;
430 }
431
432 scp = atadevices[unit];
433
434 /* find & call the responsible driver to process this interrupt */
435 switch (scp->active) {
436#if NATADISK > 0
437 case ATA_ACTIVE_ATA:
438 if ((ata_request = bufq_first(&scp->ata_queue)))
439 if (ad_interrupt(ata_request) == ATA_OP_CONTINUES)
440 return;
441 break;
442#endif
443 case ATA_ACTIVE_ATAPI:
444 if ((atapi_request = TAILQ_FIRST(&scp->atapi_queue)))
445 if (atapi_interrupt(atapi_request) == ATA_OP_CONTINUES)
446 return;
447 break;
448
449 case ATA_WAIT_INTR:
450 wakeup((caddr_t)scp);
451 break;
452
453 case ATA_IGNORE_INTR:
454 break;
455
456 default:
457 case ATA_IDLE:
458 if (intcount++ < 10)
459 printf("ata%d: unwanted interrupt %d\n", unit, intcount);
460 inb(scp->ioaddr + ATA_STATUS);
461 return;
462 }
463 scp->active = ATA_IDLE;
464 ata_start(scp);
465}
466
467void
468ata_start(struct ata_softc *scp)
469{
470 struct buf *ata_request;
471 struct atapi_request *atapi_request;
472
473#ifdef ATA_DEBUG
474 printf("ata_start: entered\n");
475#endif
476 if (scp->active != ATA_IDLE) {
477 printf("ata: unwanted ata_start\n");
478 return;
479 }
480
481#if NATADISK > 0
482 /* find & call the responsible driver if anything on ATA queue */
483 if ((ata_request = bufq_first(&scp->ata_queue))) {
484 scp->active = ATA_ACTIVE_ATA;
485 ad_transfer(ata_request);
486#ifdef ATA_DEBUG
487 printf("ata_start: started ata, leaving\n");
488#endif
489 return;
490 }
491#endif
492
493 /* find & call the responsible driver if anything on ATAPI queue */
494 if ((atapi_request = TAILQ_FIRST(&scp->atapi_queue))) {
495 scp->active = ATA_ACTIVE_ATAPI;
496 atapi_transfer(atapi_request);
497#ifdef ATA_DEBUG
498 printf("ata_start: started atapi, leaving\n");
499#endif
500 return;
501 }
502}
503
504int32_t
505ata_wait(struct ata_softc *scp, int32_t device, u_int8_t mask)
506{
507 u_int8_t status;
508 u_int32_t timeout = 0;
509
510 while (timeout++ <= 500000) { /* timeout 5 secs */
511 status = inb(scp->ioaddr + ATA_STATUS);
512
513 /* if drive fails status, reselect the drive just to be sure */
514 if (status == 0xff) {
515 printf("ata%d: %s: no status, reselecting device\n",
516 scp->lun, device?"slave":"master");
517 outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | device);
518 DELAY(1);
519 status = inb(scp->ioaddr + ATA_STATUS);
520 }
521 if (status == 0xff)
522 return -1;
523 scp->status = status;
524 if (!(status & ATA_S_BSY)) {
525 if (status & ATA_S_ERROR)
526 scp->error = inb(scp->ioaddr + ATA_ERROR);
527 if ((status & mask) == mask)
528 return (status & ATA_S_ERROR);
529 }
530 if (timeout > 1000)
531 DELAY(1000);
532 else
533 DELAY(10);
534 }
535 return -1;
536}
537
538int32_t
539ata_command(struct ata_softc *scp, int32_t device, u_int32_t command,
540 u_int32_t cylinder, u_int32_t head, u_int32_t sector,
541 u_int32_t count, u_int32_t feature, int32_t flags)
542{
543#ifdef ATA_DEBUG
544printf("ata_command: addr=%04x, device=%02x, cmd=%02x, c=%d, h=%d, s=%d, count=%d, flags=%02x\n", scp->ioaddr, device, command, cylinder, head, sector, count, flags);
545#endif
546
547 /* ready to issue command ? */
548 if (ata_wait(scp, device, 0) < 0) {
549 printf("ata%d: %s: timeout waiting to give command s=%02x e=%02x\n",
550 scp->lun, device?"slave":"master", scp->status, scp->error);
551 }
552 outb(scp->ioaddr + ATA_FEATURE, feature);
553 outb(scp->ioaddr + ATA_CYL_LSB, cylinder);
554 outb(scp->ioaddr + ATA_CYL_MSB, cylinder >> 8);
555 outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | device | head);
556 outb(scp->ioaddr + ATA_SECTOR, sector);
557 outb(scp->ioaddr + ATA_COUNT, count);
558
559 if (scp->active != ATA_IDLE && flags != ATA_IMMEDIATE)
560 printf("DANGER active=%d\n", scp->active);
561
562 switch (flags) {
563 case ATA_WAIT_INTR:
564 scp->active = ATA_WAIT_INTR;
565 outb(scp->ioaddr + ATA_CMD, command);
566 if (tsleep((caddr_t)scp, PRIBIO, "atacmd", 500)) {
567 printf("ata_command: timeout waiting for interrupt");
568 scp->active = ATA_IDLE;
569 return -1;
570 }
571 break;
572
573 case ATA_IGNORE_INTR:
574 scp->active = ATA_IGNORE_INTR;
575 outb(scp->ioaddr + ATA_CMD, command);
576 break;
577
578 case ATA_IMMEDIATE:
579 default:
580 outb(scp->ioaddr + ATA_CMD, command);
581 break;
582 }
583#ifdef ATA_DEBUG
584printf("ata_command: leaving\n");
585#endif
586 return 0;
587}
588
589void
590bswap(int8_t *buf, int32_t len)
591{
592 u_int16_t *p = (u_int16_t*)(buf + len);
593
594 while (--p >= (u_int16_t*)buf)
595 *p = ntohs(*p);
596}
597
598void
599btrim(int8_t *buf, int32_t len)
600{
601 int8_t *p;
602
603 for (p = buf; p < buf+len; ++p)
604 if (!*p)
605 *p = ' ';
606 for (p = buf + len - 1; p >= buf && *p == ' '; --p)
607 *p = 0;
608}
609
610void
611bpack(int8_t *src, int8_t *dst, int32_t len)
612{
613 int32_t i, j, blank;
614
615 for (i = j = blank = 0 ; i < len-1; i++) {
616 if (blank && src[i] == ' ') continue;
617 if (blank && src[i] != ' ') {
618 dst[j++] = src[i];
619 blank = 0;
620 continue;
621 }
622 if (src[i] == ' ')
623 blank = 1;
624 dst[j++] = src[i];
625 }
626 dst[j] = 0x00;
627}
628#endif /* NATA > 0 */